Example #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;
        }
Example #2
0
        // Internal generation logic for a subroutine or function call.
        SymType InternalGenerate(CodeGenerator cg, SymClass callType, string callName)
        {
            Symbol sym = ProcName.Symbol;
            SymType thisType = SymType.NONE;

            if (!sym.Defined) {
                cg.Error(sym.RefLine, String.Format("Undefined {0} {1}", callName, sym.Name));
            }
            if (sym.Class != callType) {
                cg.Error(sym.RefLine, String.Format("{0} is not a {1}", sym.Name, callName));
            }

            Type[] paramTypes = Parameters.Generate(cg, sym);

            if (sym.IsParameter) {
                ProcName.Generate(cg);
                cg.Emitter.CallIndirect(sym.Type, paramTypes);
                thisType = sym.Type;
            } else {
                if (sym.Info != null) {
                    Debug.Assert(sym.Info is MethodInfo);
                    cg.Emitter.Call((MethodInfo)sym.Info);
                    thisType = sym.Type;
                }
            }

            // Sanity check, make sure alternate return labels are only specified
            // for subroutines.
            if (AlternateReturnLabels.Count > 0 && sym.Class != SymClass.SUBROUTINE) {
                throw new CodeGeneratorException("Codegen error: Alternate return labels only permitted for subroutines");
            }

            // Post-alternate return branching
            if (AlternateReturnLabels.Count > 0) {
                Label [] jumpTable = new Label[AlternateReturnLabels.Count];
                for (int c = 0; c < AlternateReturnLabels.Count; ++c) {
                    Symbol symLabel = AlternateReturnLabels[c];
                    jumpTable[c] = (Label)symLabel.Info;
                }
                cg.Emitter.LoadInteger(1);
                cg.Emitter.Sub(SymType.INTEGER);
                cg.Emitter.Switch(jumpTable);
            }

            Parameters.FreeLocalDescriptors();
            return thisType;
        }
Example #3
0
 /// <summary>
 /// Generate the code to emit a procedure.
 /// </summary>
 /// <param name="cg">A CodeGenerator object</param>
 public override void Generate(CodeGenerator cg)
 {
     if (cg == null) {
         throw new ArgumentNullException("cg");
     }
     Symbol retVal = cg.CurrentProcedure.ProcedureSymbol.RetVal;
     if (retVal != null) {
         if (ReturnExpression != null) {
             SymType thisType = cg.GenerateExpression(SymType.NONE, ReturnExpression);
             cg.Emitter.ConvertType(thisType, retVal.Type);
         }
         else {
             if (retVal.Index == null) {
                 cg.Error(string.Format("Function {0} does not return a value", cg.CurrentProcedure.ProcedureSymbol.Name));
             }
             cg.Emitter.LoadLocal(retVal.Index);
         }
     } else {
         // For alternate return, if the method is marked as supporting
         // them then it will be compiled as a function. So it must always
         // have a return value. A value of 0 means the default behaviour
         // (i.e. none of the labels specified are picked).
         if (cg.CurrentProcedure.AlternateReturnCount > 0) {
             if (ReturnExpression != null) {
                 cg.GenerateExpression(SymType.INTEGER, ReturnExpression);
             } else {
                 cg.Emitter.LoadInteger(0);
             }
         }
     }
     cg.Emitter.Return();
 }