public object Walk(FormalParameter node) { if (Enter(node)) { node.Identifier.Accept(this); } Exit(node); return null; }
public object Walk(FormalParameter node) { if (Enter(node)) { node.Identifier.Accept(this); } Exit(node); return(null); }
public override bool VisitFormalParameter(FormalParameter formalParameter) { var other = _other as FormalParameter; if (other == null) { return(false); } return(other.Name == formalParameter.Name && other.TypeIdentifier == formalParameter.TypeIdentifier); }
private bool ParseParameters(Lexer lexer, Environment environment) { var successfullyParsed = true; do { var token = lexer.GetNextToken(); if (token.Is(TokenType.RightParenthesis)) { return(true); } var parameter = new FormalParameter(); if (token.Is(TokenType.ByVal) || token.Is(TokenType.ByRef)) { parameter.ParameterType = token.Is(TokenType.ByVal) ? ParameterType.ByVal : ParameterType.ByRef; token = lexer.GetNextToken(); ValidateToken(token, TokenType.Identifier); } else { parameter.ParameterType = ParameterType.ByVal; ValidateToken(token, TokenType.Identifier); } parameter.Identifier = token.Lexeme; // SEM: Validar que no haya parametros con nombres duplicados. if (environment.FormalParameters.Exists(parameter.Identifier)) { LogDuplicateIdentifierFound(parameter.Identifier, token); successfullyParsed = false; } ValidateToken(lexer.GetNextToken(), TokenType.IdTypeSeparator); token = lexer.GetNextToken(); ValidateToken(token, TokenType.IntegerDataType, TokenType.BooleanDataType); parameter.DataType = token.Type == TokenType.IntegerDataType ? DataType.Integer : DataType.Boolean; environment.FormalParameters.AddParameter(parameter); } while (lexer.GetNextToken().Is(TokenType.ListSeparator)); return(successfullyParsed); }
// Actual Parameters // Always returns null. Uses the given FormalParameter. public Void VisitValueParameter(ValueParameter ast, FormalParameter arg) { TypeDenoter expressionType = ast.Expression.Visit(this, null); if (arg is ConstFormalParameter param) { CheckAndReportError(expressionType.Equals(param.Type), "wrong type for const actual parameter", ast.Expression); } else { ReportError("const actual parameter not expected here", ast); } return(null); }
public FunctionDeclaration(string name, Type returnType, FormalParameter[] formalParameters, Scope scope) : base(name, scope) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("The name is blank!", "name"); if (returnType == null) ThrowHelper.ThrowArgumentNullException(() => returnType); if (formalParameters == null) ThrowHelper.ThrowArgumentNullException(() => formalParameters); Name = name; ReturnType = returnType; FormalParameters = formalParameters; }
public Void VisitVarParameter(VarParameter ast, FormalParameter arg) { Declaration actualType = ast.Identifier.Visit(this, null); if (!ast.Identifier.IsVariable) { ReportError("parameter is not a variable", ast.Identifier); } else if (arg is VarFormalParameter parameter) { CheckAndReportError(actualType.Equals(parameter.Type), "wrong type for var parameter", ast.Identifier); } else { ReportError("var parameter not expected here", ast.Identifier); } return(null); }
private List <FormalParameter> ParseFormalParameterList() { var list = new List <FormalParameter>(); Match(TokenType.LeftParen); while (Next().Is(TokenType.Multiply) || Next().Is(TokenType.Identifier)) { var parameter = new FormalParameter() { Token = Next() }; if (Next().Is(TokenType.Multiply)) { Match(TokenType.Multiply); parameter.IsParams = true; } parameter.Identifier = ParseIdentifier(); if (list.Any(param => param.Identifier.Equals(parameter.Identifier))) { throw Error("Duplicated parameter name", Next()); } list.Add(parameter); if (Next().Is(TokenType.Comma)) { Match(TokenType.Comma); continue; } if (Next().Is(TokenType.RightParen)) { break; } throw Error("Unexpected token", Next()); } if (list.Any(p => p.IsParams && list.IndexOf(p) != list.Count - 1)) { throw Error("Var-arg parameter must be the last parameter", Next()); } Match(TokenType.RightParen); return(list); }
public virtual void Exit(FormalParameter node) { }
public virtual bool Enter(FormalParameter node) { return true; }
public virtual bool Enter(FormalParameter node) { return(true); }
private List<FormalParameter> ParseFormalParameterList() { var list = new List<FormalParameter>(); Match(TokenType.LeftParen); while (Next().Is(TokenType.Multiply) || Next().Is(TokenType.Identifier)) { var parameter = new FormalParameter() {Token = Next()}; if (Next().Is(TokenType.Multiply)) { Match(TokenType.Multiply); parameter.IsParams = true; } parameter.Identifier = ParseIdentifier(); if (list.Any(param => param.Identifier.Equals(parameter.Identifier))) throw Error("Duplicated parameter name", Next()); list.Add(parameter); if (Next().Is(TokenType.Comma)) { Match(TokenType.Comma); continue; } if (Next().Is(TokenType.RightParen)) break; throw Error("Unexpected token", Next()); } if (list.Any(p => p.IsParams && list.IndexOf(p) != list.Count - 1)) throw Error("Var-arg parameter must be the last parameter", Next()); Match(TokenType.RightParen); return list; }
public static Subprogram BuildIR(this MethodInfo method, IList <SpecialRegister> srpool, IDictionary <MethodInfo, Subprogram> spmap, bool anonymousKernel = false) { if (!method.IsStatic) { throw new ArgumentException("Only static methods are supported", "method"); } bool kernel = anonymousKernel || Attribute.GetCustomAttribute(method, typeof(KernelAttribute)) != null; bool result = method.ReturnType != typeof(void); if (kernel && result) { throw new ArgumentException("Kernels can not have return parameter", "method"); } List <FormalParameter> formalParameters = new List <FormalParameter>(method.GetParameters().Select(pi => { PassingStyles ps = pi.ParameterType.IsByRef ? pi.IsOut ? PassingStyles.OUT : PassingStyles.REF : PassingStyles.VAL; Type pt = pi.ParameterType.IsByRef ? pi.ParameterType.GetElementType() : pi.ParameterType; FormalParameter fp = pt.IsArray ? new FormalParameter(pt.GetElementType(), anonymousKernel ? StateSpaces.GLOBAL : (Attribute.GetCustomAttribute(pi, typeof(StateSpaceAttribute)) as StateSpaceAttribute).StateSpace, ps) : new Argument(pt, ps); fp.Name = pi.Name; return(fp); })); if (result) { FormalParameter returnParameter = method.ReturnType.IsArray ? new FormalParameter(method.ReturnType.GetElementType(), (Attribute.GetCustomAttribute(method.ReturnParameter, typeof(StateSpaceAttribute)) as StateSpaceAttribute).StateSpace, PassingStyles.OUT) : new Argument(method.ReturnType, PassingStyles.OUT); returnParameter.Name = method.Name; formalParameters.Add(returnParameter); } IList <FormalParameter> formalParametersRO = formalParameters.AsReadOnly(); IList <VirtualRegister> localVariablesRO = new List <VirtualRegister>(method.GetMethodBody().LocalVariables.Select(lvi => new VirtualRegister(InstructionSelector.UpconvertMapping[lvi.LocalType.IsArray ? typeof(int) : lvi.LocalType]))).AsReadOnly(); Subprogram subprogram = kernel ? new Kernel(formalParametersRO) : new Subprogram(formalParametersRO); subprogram.Name = method.Name; spmap.Add(method, subprogram); Func <Type, StateSpaces, InstructionSelector.DynamicRegister> regalloc = IRBuildOptions.WasteRegisters ? (Func <Type, StateSpaces, InstructionSelector.DynamicRegister>)RegisterAllocator.Waste : new RegisterAllocator().Allocate; subprogram.CFGRoot = BuildIRCFG(BuildCILCFG(method.GetInstructions().First()), new Stack <Tuple <Tuple <GenericOperand, bool>, InstructionSelector> >(), new Dictionary <CILBB, List <CILBBImplementation> >(), formalParametersRO, localVariablesRO, result, srpool, spmap, regalloc).AsBasicBlock; if (regalloc.Target != null && !(regalloc.Target as RegisterAllocator).FinishTest()) { throw new Exception("There is a bug in instruction selecting phase: we have live registers"); } return(subprogram); }
public Setter(string propertyName, FormalParameter setParameter, FunctionStatementList functionBody) { this.propertyName = propertyName; this.setParameter = setParameter; this.functionBody = functionBody; }
public override Statement EmitStatement(EmitMode mode) { if (mode == EmitMode.ForStorage) { SaveObjectID(); SaveLocator(); } else { RemoveObjectID(); RemoveLocator(); } try { IMetaData result; if ((mode != EmitMode.ForRemote) && (DeclarationText != null)) { SourceStatement statement = new SourceStatement(); statement.Source = DeclarationText + InitializationText + AggregationText + FinalizationText; result = statement; } else { CreateAggregateOperatorStatement statement = new CreateAggregateOperatorStatement(); statement.OperatorName = Schema.Object.EnsureRooted(OperatorName); foreach (Operand operand in Operands) { FormalParameter formalParameter = new FormalParameter(); formalParameter.Identifier = operand.Name; formalParameter.TypeSpecifier = operand.DataType.EmitSpecifier(mode); formalParameter.Modifier = operand.Modifier; statement.FormalParameters.Add(formalParameter); } statement.ReturnType = ReturnDataType.EmitSpecifier(mode); #if USEVIRTUAL statement.IsVirtual = IsVirtual; statement.IsAbstract = IsAbstract; statement.IsOverride = IsOverride; statement.IsReintroduced = IsReintroduced; #endif if ((mode == EmitMode.ForRemote) && !IsRemotable) { statement.Initialization.Block = new Block(); statement.Aggregation.Block = new Block(); statement.Finalization.Block = new Block(); } else { Initialization.EmitStatement(mode, statement.Initialization); Aggregation.EmitStatement(mode, statement.Aggregation); Finalization.EmitStatement(mode, statement.Finalization); } result = statement; } result.MetaData = MetaData == null ? null : MetaData.Copy(); if (SessionObjectName != null) { if (result.MetaData == null) { result.MetaData = new MetaData(); } result.MetaData.Tags.AddOrUpdate("DAE.GlobalObjectName", OperatorName, true); } return((Statement)result); } finally { if (mode == EmitMode.ForStorage) { RemoveObjectID(); RemoveLocator(); } } }
public virtual T VisitFormalParameter(FormalParameter formalParameter) { return(default(T)); }
public InstructionSelector(IList <Instruction> cilbbcode, Stack <Tuple <Tuple <GenericOperand, bool>, InstructionSelector> > stack, IList <FormalParameter> parameters, IList <VirtualRegister> variables, bool result, IList <SpecialRegister> srpool, IDictionary <MethodInfo, Subprogram> spmap, Func <Type, StateSpaces, DynamicRegister> regalloc) { this.stack = stack; this.regalloc = regalloc; bool skipnext = false; foreach (Instruction cilinstr in cilbbcode) { if (skipnext) { skipnext = false; continue; } if (Trailer != null) { throw new ArgumentException("No instruction is permitted after trailing control flow one", "cilbbcode"); } GenericOperand left = null; GenericOperand right = null; GenericOperand extra = null; VirtualRegister regleft = null; VirtualRegister regright = null; VirtualRegister target = null; FormalParameter arg = null; VirtualRegister loc = null; CILOpCodes cilopcode = (CILOpCodes)cilinstr.OpCode.Value; bool isArithmetic = cilopcode >= CILOpCodes.Add && cilopcode <= CILOpCodes.Xor; bool isCompare = cilopcode >= CILOpCodes.Ceq && cilopcode <= CILOpCodes.Clt_Un; bool isCompBranch = cilopcode >= CILOpCodes.Beq_S && cilopcode <= CILOpCodes.Blt_Un_S || cilopcode >= CILOpCodes.Beq && cilopcode <= CILOpCodes.Blt_Un; if (isArithmetic || isCompare || isCompBranch) { right = RetrieveOperand(); left = RetrieveOperand(); if (cilopcode == CILOpCodes.Mul && cilinstr.Next != null && (CILOpCodes)cilinstr.Next.OpCode.Value == CILOpCodes.Add) { extra = RetrieveOperand(); } Type targetType = ArithmeticMapping[left.DataType][right.DataType]; right = ConvertOperand(right, targetType); left = ConvertOperand(left, targetType); if (extra != null) { extra = ConvertOperand(extra, targetType); } ReleaseOperand(right); ReleaseOperand(left); if (extra != null) { ReleaseOperand(extra); } target = AllocateRegister(isArithmetic ? targetType : typeof(int)); if (!isCompBranch) { PushByVal(target); } } switch (cilopcode) { // Method arguments loading case CILOpCodes.Ldarg_0: case CILOpCodes.Ldarg_1: case CILOpCodes.Ldarg_2: case CILOpCodes.Ldarg_3: case CILOpCodes.Ldarg_S: case CILOpCodes.Ldarg: arg = parameters[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Ldarg_0) : (cilinstr.Operand as ParameterInfo).Position]; if (arg.PassingStyle == PassingStyles.VAL) { target = AllocateRegister(arg.StateSpace != StateSpaces.REG ? arg.UnderlyingType : arg.DataType, arg.StateSpace); code.Add(new UnaryOperation(IROpCodes.MOV, target, arg)); PushByVal(target); } else { PushByRef(arg); } break; case CILOpCodes.Ldarga_S: case CILOpCodes.Ldarga: arg = parameters[(cilinstr.Operand as ParameterInfo).Position]; PushByRef(arg); break; // Local variables loading case CILOpCodes.Ldloc_0: case CILOpCodes.Ldloc_1: case CILOpCodes.Ldloc_2: case CILOpCodes.Ldloc_3: case CILOpCodes.Ldloc_S: case CILOpCodes.Ldloc: loc = variables[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Ldloc_0) : (cilinstr.Operand as LocalVariableInfo).LocalIndex]; target = AllocateRegister(loc.UnderlyingType, loc.StateSpace); code.Add(new UnaryOperation(IROpCodes.MOV, target, loc)); PushByVal(target); break; case CILOpCodes.Ldloca_S: case CILOpCodes.Ldloca: loc = variables[(cilinstr.Operand as LocalVariableInfo).LocalIndex]; PushByRef(loc); break; // Method arguments storing case CILOpCodes.Starg_S: case CILOpCodes.Starg: arg = parameters[(cilinstr.Operand as ParameterInfo).Position]; right = RetrieveOperand(); if (arg.DataType != right.DataType) { code.Add(new UnaryOperation(IROpCodes.CVT, arg, right)); } else { code.Add(new UnaryOperation(IROpCodes.MOV, arg, right)); } ReleaseOperand(right); break; // Local variables storing case CILOpCodes.Stloc_0: case CILOpCodes.Stloc_1: case CILOpCodes.Stloc_2: case CILOpCodes.Stloc_3: case CILOpCodes.Stloc_S: case CILOpCodes.Stloc: loc = variables[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Stloc_0) : (cilinstr.Operand as LocalVariableInfo).LocalIndex]; right = RetrieveOperand(); if (loc.DataType != right.DataType) { code.Add(new UnaryOperation(IROpCodes.CVT, loc, right)); } else { code.Add(new UnaryOperation(IROpCodes.MOV, loc, right)); } ReleaseOperand(right); break; // Constants storing case CILOpCodes.Ldnull: PushByRef(new ImmediateValue((int)0)); break; case CILOpCodes.Ldc_I4_M1: case CILOpCodes.Ldc_I4_0: case CILOpCodes.Ldc_I4_1: case CILOpCodes.Ldc_I4_2: case CILOpCodes.Ldc_I4_3: case CILOpCodes.Ldc_I4_4: case CILOpCodes.Ldc_I4_5: case CILOpCodes.Ldc_I4_6: case CILOpCodes.Ldc_I4_7: case CILOpCodes.Ldc_I4_8: case CILOpCodes.Ldc_I4_S: case CILOpCodes.Ldc_I4: case CILOpCodes.Ldc_I8: case CILOpCodes.Ldc_R4: case CILOpCodes.Ldc_R8: PushByRef(new ImmediateValue((cilinstr.Operand == null) ? (int)(cilopcode - CILOpCodes.Ldc_I4_0) : (ValueType)Convert.ChangeType(cilinstr.Operand, UpconvertMapping[cilinstr.Operand.GetType()]))); break; // Array elements loading case CILOpCodes.Ldelem_I1: case CILOpCodes.Ldelem_U1: case CILOpCodes.Ldelem_I2: case CILOpCodes.Ldelem_U2: case CILOpCodes.Ldelem_I4: case CILOpCodes.Ldelem_U4: case CILOpCodes.Ldelem_I8: case CILOpCodes.Ldelem_R4: case CILOpCodes.Ldelem_R8: case CILOpCodes.Ldelem: regright = MapToRegister(RetrieveOperand()); // index regleft = RetrieveOperand() as VirtualRegister; // array VirtualRegister address = CalculateAddress(regleft, regright); target = AllocateRegister(UpconvertMapping[regleft.UnderlyingType]); code.Add(new LDInstruction(target, address)); ReleaseOperand(address); PushByVal(target); break; case CILOpCodes.Ldelema: regright = MapToRegister(RetrieveOperand()); // index regleft = RetrieveOperand() as VirtualRegister; // array PushByVal(CalculateAddress(regleft, regright)); break; // Array elements storing case CILOpCodes.Stelem_I1: case CILOpCodes.Stelem_I2: case CILOpCodes.Stelem_I4: case CILOpCodes.Stelem_I8: case CILOpCodes.Stelem_R4: case CILOpCodes.Stelem_R8: case CILOpCodes.Stelem: GenericOperand val = RetrieveOperand(); // value regright = MapToRegister(RetrieveOperand()); // index regleft = RetrieveOperand() as VirtualRegister; // array IEnumerable <Type> compatible = regleft.UnderlyingType.CompatibleTypes().Where(type => type.SizeOf() >= sizeof(int)); target = !compatible.Contains(val.DataType) ? ConvertOperand(val, compatible.First()) as VirtualRegister : MapToRegister(val); address = CalculateAddress(regleft, regright); code.Add(new STInstruction(address, target)); ReleaseOperand(address); ReleaseOperand(target); break; // Indirect loads case CILOpCodes.Ldobj: case CILOpCodes.Ldind_I1: case CILOpCodes.Ldind_U1: case CILOpCodes.Ldind_I2: case CILOpCodes.Ldind_U2: case CILOpCodes.Ldind_I4: case CILOpCodes.Ldind_U4: case CILOpCodes.Ldind_I8: case CILOpCodes.Ldind_R4: case CILOpCodes.Ldind_R8: // pointer (induced by ldelema) / variable (induced by ldloca) / parameter (induced by ldarga or pass-by-ref ldarg) regright = RetrieveOperand() as VirtualRegister; if (regright.StateSpace == StateSpaces.REG) { target = AllocateRegister(regright.DataType); code.Add(new UnaryOperation(IROpCodes.MOV, target, regright)); } else { target = AllocateRegister(UpconvertMapping[regright.UnderlyingType]); code.Add(new LDInstruction(target, regright)); } ReleaseOperand(regright); PushByVal(target); break; case CILOpCodes.Ldind_Ref: regright = RetrieveOperand() as VirtualRegister; // pointer (induced by pass-by-ref ldarg) target = AllocateRegister(regright.UnderlyingType, regright.StateSpace); code.Add(new UnaryOperation(IROpCodes.MOV, target, regright)); ReleaseOperand(regright); PushByVal(target); break; // Indirect stores case CILOpCodes.Stobj: case CILOpCodes.Stind_I1: case CILOpCodes.Stind_I2: case CILOpCodes.Stind_I4: case CILOpCodes.Stind_I8: case CILOpCodes.Stind_R4: case CILOpCodes.Stind_R8: right = RetrieveOperand(); // value // pointer (induced by ldelema) / variable (induced by ldloca) / parameter (induced by ldarga or pass-by-ref ldarg) regleft = RetrieveOperand() as VirtualRegister; if (regleft.StateSpace == StateSpaces.REG) { if (regleft.DataType != right.DataType) { code.Add(new UnaryOperation(IROpCodes.CVT, regleft, right)); } else { code.Add(new UnaryOperation(IROpCodes.MOV, regleft, right)); } ReleaseOperand(right); } else { compatible = regleft.UnderlyingType.CompatibleTypes().Where(type => type.SizeOf() >= sizeof(int)); regright = !compatible.Contains(right.DataType) ? ConvertOperand(right, compatible.First()) as VirtualRegister : MapToRegister(right); code.Add(new STInstruction(regleft, regright)); ReleaseOperand(regright); } ReleaseOperand(regleft); break; case CILOpCodes.Stind_Ref: regright = RetrieveOperand() as VirtualRegister; // source pointer (induced by ldarg or pass-by-ref ldarg) regleft = RetrieveOperand() as VirtualRegister; // target pointer (induced by pass-by-ref ldarg) code.Add(new UnaryOperation(IROpCodes.MOV, regleft, regright)); ReleaseOperand(regleft); ReleaseOperand(regright); break; // Comparison branches case CILOpCodes.Beq: case CILOpCodes.Beq_S: code.Add(new BinaryOperation(IROpCodes.EQ, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Bne_Un: case CILOpCodes.Bne_Un_S: code.Add(new BinaryOperation(IROpCodes.NE, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Bge_S: case CILOpCodes.Bge_Un_S: case CILOpCodes.Bge: case CILOpCodes.Bge_Un: code.Add(new BinaryOperation(IROpCodes.GE, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Bgt_S: case CILOpCodes.Bgt_Un_S: case CILOpCodes.Bgt: case CILOpCodes.Bgt_Un: code.Add(new BinaryOperation(IROpCodes.GT, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Ble_S: case CILOpCodes.Ble_Un_S: case CILOpCodes.Ble: case CILOpCodes.Ble_Un: code.Add(new BinaryOperation(IROpCodes.LE, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Blt_S: case CILOpCodes.Blt_Un_S: case CILOpCodes.Blt: case CILOpCodes.Blt_Un: code.Add(new BinaryOperation(IROpCodes.LT, target, left, right)); goto case CILOpCodes.Brtrue; // Basic branches (the last instructions in basic block) case CILOpCodes.Br_S: case CILOpCodes.Br: Trailer = new JMPInstruction(); break; case CILOpCodes.Brfalse_S: case CILOpCodes.Brfalse: regleft = MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int))); Trailer = new JFInstruction(regleft); ReleaseOperand(regleft); break; case CILOpCodes.Brtrue_S: case CILOpCodes.Brtrue: regleft = isCompBranch ? target : MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int))); Trailer = new JTInstruction(regleft); ReleaseOperand(regleft); break; // Call stuff. case CILOpCodes.Call: MethodInfo method = cilinstr.Operand as MethodInfo; PropertyInfo property = method.DeclaringType.GetProperty(method.Name.Replace("get_", "")); if (property != null) { // Handle predefined value access. PredefinedValueAttribute pva = Attribute.GetCustomAttribute(property, typeof(PredefinedValueAttribute)) as PredefinedValueAttribute; if (pva != null) { PushByVal(MapToRegister(srpool.Single(sr => sr.Value == pva.Value))); } else { throw new NotSupportedException(method.DeclaringType.FullName + "." + property.Name); } } else { // Handle intrinsic function call. IntrinsicFunctionAttribute ifa = Attribute.GetCustomAttribute(method, typeof(IntrinsicFunctionAttribute)) as IntrinsicFunctionAttribute; if (ifa != null) { switch (ifa.OpCode) { case IROpCodes.SYNC: code.Add(new SYNCInstruction()); break; case IROpCodes.ABS: case IROpCodes.SQRT: case IROpCodes.RSQRT: case IROpCodes.SIN: case IROpCodes.COS: case IROpCodes.LG2: case IROpCodes.EX2: right = ConvertOperand(RetrieveOperand(), UpconvertMapping[method.ReturnType]); ReleaseOperand(right); target = AllocateRegister(right.DataType); code.Add(new UnaryOperation(ifa.OpCode, target, right)); PushByVal(target); break; case IROpCodes.MIN: case IROpCodes.MAX: right = ConvertOperand(RetrieveOperand(), UpconvertMapping[method.ReturnType]); left = ConvertOperand(RetrieveOperand(), right.DataType); ReleaseOperand(right); ReleaseOperand(left); target = AllocateRegister(right.DataType); code.Add(new BinaryOperation(ifa.OpCode, target, left, right)); PushByVal(target); break; default: throw new NotSupportedException(ifa.OpCode.ToString()); } } else { // Handle subprogram call. Subprogram sp; spmap.TryGetValue(method, out sp); if (sp == null) { sp = method.BuildIR(srpool, spmap); } List <GenericOperand> actualParameters = new List <GenericOperand>(); List <Tuple <VirtualRegister, VirtualRegister> > wrappedRefElements = new List <Tuple <VirtualRegister, VirtualRegister> >(); if (method.ReturnType != typeof(void)) { arg = sp.FormalParameters.Last(); target = AllocateRegister(arg.StateSpace != StateSpaces.REG ? arg.UnderlyingType : arg.DataType, arg.StateSpace); PushByVal(target); } foreach (FormalParameter fp in sp.FormalParameters.Reverse()) { GenericOperand ap = RetrieveOperand(); if (fp.StateSpace == StateSpaces.REG) { VirtualRegister regap = ap as VirtualRegister; if (regap != null && regap.StateSpace != StateSpaces.REG) { // Passing array element by reference. // Create wrapping register. regright = AllocateRegister(fp.DataType); // Load array element value to wrapping register. if (fp.PassingStyle == PassingStyles.REF) { code.Add(new LDInstruction(regright, regap)); } // Remember address-to-register mapping. wrappedRefElements.Add(new Tuple <VirtualRegister, VirtualRegister>(regap, regright)); // Replace original actual parameter with wrapping register. ap = regright; } else if (fp.PassingStyle == PassingStyles.VAL) { // Perform implicit parameter conversion. ap = ConvertOperand(ap, fp.DataType); } } actualParameters.Insert(0, ap); } code.Add(new CALLInstruction(sp, actualParameters)); // Update values of wrapped array elements. code.AddRange(wrappedRefElements.Select(we => new STInstruction(we.Item1, we.Item2))); foreach (VirtualRegister ap in actualParameters) { ReleaseOperand(ap); } foreach (Tuple <VirtualRegister, VirtualRegister> we in wrappedRefElements) { ReleaseOperand(we.Item1); } if (method.ReturnType != typeof(void)) { PushByVal(target); (target as DynamicRegister).Live = true; } } } break; // Arithmetic operations case CILOpCodes.Add: code.Add(new BinaryOperation(IROpCodes.ADD, target, left, right)); break; case CILOpCodes.Sub: code.Add(new BinaryOperation(IROpCodes.SUB, target, left, right)); break; case CILOpCodes.Mul: if (extra != null) { code.Add(new MADOperation(target, left, right, extra)); skipnext = true; } else { code.Add(new BinaryOperation(IROpCodes.MUL, target, left, right)); } break; case CILOpCodes.Div: case CILOpCodes.Div_Un: code.Add(new BinaryOperation(IROpCodes.DIV, target, left, right)); break; case CILOpCodes.Rem: case CILOpCodes.Rem_Un: code.Add(new BinaryOperation(IROpCodes.REM, target, left, right)); break; case CILOpCodes.And: code.Add(new BinaryOperation(IROpCodes.AND, target, left, right)); break; case CILOpCodes.Or: code.Add(new BinaryOperation(IROpCodes.OR, target, left, right)); break; case CILOpCodes.Xor: code.Add(new BinaryOperation(IROpCodes.XOR, target, left, right)); break; case CILOpCodes.Neg: right = RetrieveOperand(); right = ConvertOperand(right, NegMapping[right.DataType]); ReleaseOperand(right); target = AllocateRegister(right.DataType); code.Add(new UnaryOperation(IROpCodes.NEG, target, right)); PushByVal(target); break; case CILOpCodes.Not: right = RetrieveOperand(); right = ConvertOperand(right, NotMapping[right.DataType]); ReleaseOperand(right); target = AllocateRegister(right.DataType); code.Add(new UnaryOperation(IROpCodes.NOT, target, right)); PushByVal(target); break; // Convert operations case CILOpCodes.Conv_I1: case CILOpCodes.Conv_Ovf_I1: case CILOpCodes.Conv_Ovf_I1_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(sbyte)))); break; case CILOpCodes.Conv_I2: case CILOpCodes.Conv_Ovf_I2: case CILOpCodes.Conv_Ovf_I2_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(short)))); break; case CILOpCodes.Conv_I: case CILOpCodes.Conv_Ovf_I: case CILOpCodes.Conv_Ovf_I_Un: case CILOpCodes.Conv_U: case CILOpCodes.Conv_Ovf_U: case CILOpCodes.Conv_Ovf_U_Un: case CILOpCodes.Conv_I4: case CILOpCodes.Conv_Ovf_I4: case CILOpCodes.Conv_Ovf_I4_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int)))); break; case CILOpCodes.Conv_I8: case CILOpCodes.Conv_Ovf_I8: case CILOpCodes.Conv_Ovf_I8_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(long)))); break; case CILOpCodes.Conv_U1: case CILOpCodes.Conv_Ovf_U1: case CILOpCodes.Conv_Ovf_U1_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(byte)))); break; case CILOpCodes.Conv_U2: case CILOpCodes.Conv_Ovf_U2: case CILOpCodes.Conv_Ovf_U2_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(ushort)))); break; case CILOpCodes.Conv_U4: case CILOpCodes.Conv_Ovf_U4: case CILOpCodes.Conv_Ovf_U4_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(uint)))); break; case CILOpCodes.Conv_U8: case CILOpCodes.Conv_Ovf_U8: case CILOpCodes.Conv_Ovf_U8_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(ulong)))); break; case CILOpCodes.Conv_R4: case CILOpCodes.Conv_R_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(float)))); break; case CILOpCodes.Conv_R8: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(double)))); break; // Compare operations case CILOpCodes.Ceq: code.Add(new BinaryOperation(IROpCodes.EQ, target, left, right)); break; case CILOpCodes.Cgt: case CILOpCodes.Cgt_Un: code.Add(new BinaryOperation(IROpCodes.GT, target, left, right)); break; case CILOpCodes.Clt: case CILOpCodes.Clt_Un: code.Add(new BinaryOperation(IROpCodes.LT, target, left, right)); break; // Stack manipulation case CILOpCodes.Pop: ReleaseOperand(RetrieveOperand()); break; case CILOpCodes.Dup: bool byref = stack.Peek().Item1.Item2; right = RetrieveOperand(); if (byref) { PushByRef(right); PushByRef(right); } else { regright = right as VirtualRegister; PushByVal(regright); target = AllocateRegister(regright.UnderlyingType, regright.StateSpace); code.Add(new UnaryOperation(IROpCodes.MOV, target, regright)); PushByVal(target); } break; case CILOpCodes.Ret: if (result) { arg = parameters.Last(); right = RetrieveOperand(); if (arg.DataType != right.DataType) { code.Add(new UnaryOperation(IROpCodes.CVT, arg, right)); } else { code.Add(new UnaryOperation(IROpCodes.MOV, arg, right)); } ReleaseOperand(right); } Trailer = new RETInstruction(); break; case CILOpCodes.Nop: break; default: throw new NotSupportedException(cilinstr.OpCode.Name); } if (isCompare) { code.Add(new UnaryOperation(IROpCodes.NEG, target, target)); } } if (Trailer == null) { Trailer = new JMPInstruction(); } }