Esempio n. 1
0
        /// <summary>
        /// Generate the code to push the specified parameters onto the caller
        /// stack. Unless the called function or subroutine is being called
        /// indirectly (and thus we may not have knowledge of its parameter
        /// count or types), the number of parameters in the caller and callee
        /// must agree.
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <param name="sym">Symbol entry for the called function</param>
        /// <returns>A list of system types corresponding to the computed parameters.</returns>
        public Type[] Generate(CodeGenerator cg, Symbol sym)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            if (sym == null) {
                throw new ArgumentNullException("sym");
            }

            int callerParameterCount = Nodes.Count;
            int calleeParameterCount = (sym.Parameters != null) ? sym.Parameters.Count : 0;

            if (!sym.IsParameter && callerParameterCount != calleeParameterCount) {
                cg.Error(String.Format("Parameter count mismatch for {0}", sym.Name));
            }

            _locals = new Temporaries(cg.Emitter);

            Type [] paramTypes = new Type[callerParameterCount];
            for (int c = 0; c < Nodes.Count; ++c) {
                ParameterParseNode paramNode = Nodes[c];
                Symbol symParam = (sym.Parameters != null) ? sym.Parameters[c] : null;
                paramTypes[c] = paramNode.Generate(cg, symParam, _locals);
            }
            return paramTypes;
        }
Esempio n. 2
0
        /// <summary>
        /// Generate the code to push the specified parameters onto the caller
        /// stack. Unless the called function or subroutine is being called
        /// indirectly (and thus we may not have knowledge of its parameter
        /// count or types), the number of parameters in the caller and callee
        /// must agree.
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <returns>A list of system types corresponding to the computed parameters.</returns>
        public new Type[] Generate(CodeGenerator cg)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }

            _locals = new Temporaries(cg.Emitter);

            Type [] paramTypes = new Type[Nodes.Count];
            for (int c = 0; c < Nodes.Count; ++c) {
                ParameterParseNode paramNode = Nodes[c];
                paramTypes[c] = paramNode.Generate(cg, _locals);
            }
            return paramTypes;
        }
Esempio n. 3
0
        /// <summary>
        /// Generate the code to push one parameter onto the caller stack. There are
        /// three different approaches here:
        /// 
        /// 1. Passing a defined variable. We either pass the address of the
        ///    variable (which may be local, parameter or static) if the corresponding
        ///    argument is BYREF, or we pass the value.
        /// 2. Passing a computed value. A computed value has no storage so if the
        ///    corresponding argument is BYREF, we need to allocate storage for it
        ///    and pass the address of the storage.
        /// 3. Finally, a computed value where the argument is BYVAL is passed on
        ///    the stack.
        /// 
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <param name="symParam">Symbol entry for the called function</param>
        /// <param name="locals">A Temporaries collection for any local temporaries</param>
        /// <returns>The system type corresponding to this parameter.</returns>
        public Type Generate(CodeGenerator cg, Symbol symParam, Temporaries locals)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            if (locals == null) {
                throw new ArgumentNullException("locals");
            }

            // Set some flags up-front
            bool isByRef = (symParam != null) ? symParam.IsByRef : IsByRef;
            bool isArray = (symParam != null) && symParam.IsArray;

            // The argument is an array, so the source must either be an array or
            // an array reference.
            if (isArray && _paramNode.ID == ParseID.IDENT) {
                IdentifierParseNode identNode = (IdentifierParseNode)_paramNode;
                Symbol symIdent = identNode.Symbol;
                if (symIdent.IsArray) {
                    GenerateLoadSubArray(cg, identNode, symParam, locals);
                    return symIdent.SystemType;
                }
            }

            // Parameter is an identifier. If passing by reference, pass the address
            // of the identifier in the local context. Otherwise extract and pass the
            // value.
            if (_paramNode.ID == ParseID.IDENT) {
                IdentifierParseNode identNode = (IdentifierParseNode)_paramNode;
                SymType identType = identNode.Type;
                Symbol symIdent = identNode.Symbol;

                if (!symIdent.IsInline && !identNode.HasSubstring) {
                    // If we're passing an existing parameter, it is already
                    // a reference so don't double it up.
                    if (symIdent.IsParameter) {
                        cg.Emitter.LoadParameter(symIdent.ParameterIndex);
                        if (!isByRef && symIdent.IsValueType) {
                            cg.Emitter.LoadIndirect(identType);
                        }
                    } else {
                        if (symIdent.IsArray && !identNode.HasIndexes) {
                            cg.GenerateLoadArray(identNode, false);
                            return symIdent.SystemType;
                        }
                        if (isByRef) {
                            cg.LoadAddress(identNode);
                        } else {
                            identNode.Generate(cg);
                            if (symParam != null) {
                                if (!symParam.IsMethod) {
                                    cg.Emitter.ConvertType(identNode.Type, symParam.Type);
                                }
                                identType = symParam.Type;
                            }
                        }
                    }
                    Type paramType = Symbol.SymTypeToSystemType(identType);
                    if (isByRef) {
                        paramType = paramType.MakeByRefType();
                    }
                    return paramType;
                }
            }

            // For reference function parameters, if this argument is not an
            // addressable object, such as a literal value or an expression,
            // then we need to generate local storage for the result and pass
            // the address of that.
            if (isByRef) {
                LocalDescriptor index = locals.New(_paramNode.Type);

                SymType exprType = cg.GenerateExpression(_paramNode.Type, _paramNode);
                cg.Emitter.StoreLocal(index);
                cg.Emitter.LoadLocalAddress(index);
                return Symbol.SymTypeToSystemType(exprType).MakeByRefType();
            }

            // Byval argument passing
            SymType neededType = (symParam != null) ? symParam.Type : Type;
            SymType thisType = cg.GenerateExpression(neededType, _paramNode);
            if (symParam != null) {
                thisType = symParam.Type;
            }
            return Symbol.SymTypeToSystemType(thisType);
        }
Esempio n. 4
0
        // Emit the code that loads part of an entire array by making a copy of
        // the array to the destination array dimensions and copying from the
        // given offset.
        void GenerateLoadSubArray(CodeGenerator cg, IdentifierParseNode identNode, Symbol symParam, Temporaries locals)
        {
            if (!identNode.HasIndexes) {
                cg.GenerateLoadArray(identNode, false);
                return;
            }

            LocalDescriptor index = locals.New(symParam.SystemType);

            cg.GenerateLoadArrayAddress(identNode);
            cg.Emitter.CreateSimpleArray(symParam.ArraySize, Symbol.SymTypeToSystemType(symParam.Type));
            cg.Emitter.Dup();
            cg.Emitter.StoreLocal(index);
            cg.Emitter.LoadInteger(0);
            cg.Emitter.LoadInteger(symParam.ArraySize);
            cg.Emitter.Call(typeof(Array).GetMethod("Copy", new [] { typeof(Array), typeof(int), typeof(Array), typeof(int), typeof(int) }));
            cg.Emitter.LoadLocal(index);
        }
Esempio n. 5
0
 /// <summary>
 /// Generate the code to push one parameter onto the caller stack using the
 /// symbol specified in the constructor.
 /// </summary>
 /// <param name="cg">A CodeGenerator object</param>
 /// <param name="locals">A Temporaries collection for any local temporaries</param>
 /// <returns>The system type corresponding to this parameter.</returns>
 public Type Generate(CodeGenerator cg, Temporaries locals)
 {
     return Generate(cg, _symbol, locals);
 }