public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { var retNode = new ReturnEntry(); if (context.Method.HasReturnType) { var returnType = context.Method.ReturnType; var value = importer.PopExpression(); if (returnType.IsStruct()) { // Record return buffer argument index // so that code gen can generate code to // copy struct on top of stack to the // return buffer. retNode.ReturnBufferArgIndex = context.Method.HasThis ? 1 : 0; retNode.ReturnTypeExactSize = returnType.GetExactSize(); } else if (value.Kind != StackValueKind.Int32) { throw new NotSupportedException($"Unsupported Return type {value.Kind}"); } retNode.Return = value; } importer.ImportAppendTree(retNode); context.StopImporting = true; }
public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { var fieldDef = instruction.OperandAs <FieldDef>(); var value = importer.PopExpression(); var addr = importer.PopExpression(); var kind = fieldDef.FieldType.GetStackValueKind(); if (value.Kind != StackValueKind.Int32 && value.Kind != StackValueKind.ValueType && value.Kind != StackValueKind.NativeInt) { throw new NotSupportedException($"Storing to field of type {value.Kind} not supported"); } // Ensure fields have all offsets calculated if (fieldDef.FieldOffset == null) { fieldDef.DeclaringType.ToTypeSig().GetExactSize(); } // TODO: Can this be removed var fieldSize = fieldDef.FieldType.GetExactSize(); var fieldOffset = fieldDef.FieldOffset ?? 0; importer.ImportAppendTree(new StoreIndEntry(addr, value, WellKnownType.Int32, fieldOffset, fieldSize)); }
public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { var fallthroughBlock = context.FallThroughBlock; var op1 = importer.PopExpression(); var targets = instruction.Operand as Instruction[]; var jumpTable = new List <string>(targets?.Length ?? 0); if (targets != null) { foreach (var target in targets) { var targetBlock = importer.BasicBlocks[(int)target.Offset]; jumpTable.Add(targetBlock.Label); importer.ImportFallThrough(targetBlock); } } var switchNode = new SwitchEntry(op1, jumpTable); importer.ImportAppendTree(switchNode); // TODO: Can this ever be null? if (fallthroughBlock != null) { importer.ImportFallThrough(fallthroughBlock); } context.StopImporting = true; }
public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { var op1 = importer.PopExpression(); // Need to spill result removed from stack to a temp that will never be used var lclNum = importer.GrabTemp(op1.Kind, op1.ExactSize); var node = new StoreLocalVariableEntry(lclNum, false, op1); // ctor has no return type so just append the tree importer.ImportAppendTree(node); }
public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { var value = importer.PopExpression(); if (value.Kind != StackValueKind.Int32 && value.Kind != StackValueKind.ObjRef) { throw new NotSupportedException("Storing to argument other than short, int32 or object refs not supported yet"); } var node = new StoreLocalVariableEntry((instruction.OperandAs <Parameter>()).Index, true, value); importer.ImportAppendTree(node); }
public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { int index = GetIndex(instruction); var value = importer.PopExpression(); if (value.Kind != StackValueKind.Int32 && value.Kind != StackValueKind.ObjRef && value.Kind != StackValueKind.ValueType && value.Kind != StackValueKind.NativeInt) { throw new NotSupportedException("Storing variables other than short, int32 ,object refs, or valuetypes not supported yet"); } var localNumber = importer.ParameterCount + index; var node = new StoreLocalVariableEntry(localNumber, false, value); importer.ImportAppendTree(node, true); }
public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { var value = importer.PopExpression(); var addr = importer.PopExpression(); if (value.Kind != StackValueKind.Int32) { throw new NotSupportedException(); } // TODO: Can this be optimised to copy less data if Stind_I1, Stind_I2??? WellKnownType type = WellKnownType.Int32; int exactSize = type.GetWellKnownTypeSize(); importer.ImportAppendTree(new StoreIndEntry(addr, value, type, fieldOffset: 0, exactSize)); }
public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { var methodDefOrRef = instruction.Operand as IMethodDefOrRef; var methodToCall = methodDefOrRef.ResolveMethodDefThrow(); var declType = methodToCall.DeclaringType; var objType = declType.ToTypeSig(); var objKind = objType.GetStackValueKind(); var objSize = objType.GetExactSize(); if (declType.IsValueType) { // Allocate memory on the stack for the value type as a temp local variable var lclNum = importer.GrabTemp(objKind, objSize); var newObjThisPtr = new LocalVariableAddressEntry(lclNum); // Call the valuetype constructor CallImporter.ImportCall(instruction, context, importer, newObjThisPtr); var node = new LocalVariableEntry(lclNum, objKind, objSize); importer.PushExpression(node); } else { // Allocate memory for object var op1 = new AllocObjEntry((int)declType.ClassSize, objKind); // Store allocated memory address into a temp local variable var lclNum = importer.GrabTemp(objKind, objSize); var asg = new StoreLocalVariableEntry(lclNum, false, op1); importer.ImportAppendTree(asg); // Call the constructor var newObjThisPtr = new LocalVariableEntry(lclNum, objKind, objSize); CallImporter.ImportCall(instruction, context, importer, newObjThisPtr); // Push a local variable entry corresponding to the object here var node = new LocalVariableEntry(lclNum, objKind, objSize); importer.PushExpression(node); } }
private static bool ImportIntrinsicCall(MethodDef methodToCall, IList <StackEntry> arguments, IILImporterProxy importer) { // Not yet implemented methods with non void return type if (methodToCall.HasReturnType) { throw new NotSupportedException(); } // Map method name to string that code generator will understand var targetMethodName = ""; switch (methodToCall.Name) { // TODO: Suspect this won't stay as an intrinsic but at least we have the mechanism for instrincs case "Write": if (IsTypeName(methodToCall, "System", "Console")) { var argtype = methodToCall.Parameters[0].Type; targetMethodName = argtype.FullName switch { "System.String" => "WriteString", "System.Int32" => "WriteInt32", "System.UInt32" => "WriteUInt32", "System.Char" => "WriteChar", _ => throw new NotSupportedException(), }; } break; default: return(false); } var callNode = new IntrinsicEntry(targetMethodName, arguments, StackValueKind.Unknown); importer.ImportAppendTree(callNode); return(true); }
public static void ImportCall(Instruction instruction, ImportContext context, IILImporterProxy importer, StackEntry?newObjThis = null) { var methodDefOrRef = instruction.Operand as IMethodDefOrRef; var methodToCall = methodDefOrRef.ResolveMethodDefThrow(); var arguments = new List <StackEntry>(); var firstArgIndex = newObjThis != null ? 1 : 0; for (var i = firstArgIndex; i < methodToCall.Parameters.Count; i++) { var argument = importer.PopExpression(); arguments.Add(argument); } // Add the this pointer if required, e.g. if part of newobj if (newObjThis != null) { arguments.Add(newObjThis); } arguments.Reverse(); // Intrinsic calls if (methodToCall.IsIntrinsic()) { if (!ImportIntrinsicCall(methodToCall, arguments, importer)) { throw new NotSupportedException("Unknown intrinsic"); } return; } string targetMethod; if (methodToCall.IsPinvokeImpl) { targetMethod = methodToCall.ImplMap.Name; } else { targetMethod = context.NameMangler.GetMangledMethodName(methodToCall); } int returnBufferArgIndex = 0; var returnType = methodToCall.ReturnType; if (methodToCall.HasReturnType) { if (returnType.IsStruct()) { returnBufferArgIndex = FixupCallStructReturn(returnType, arguments, importer, methodToCall.HasThis); } } int?returnTypeSize = methodToCall.HasReturnType ? returnType.GetExactSize() : null; var callNode = new CallEntry(targetMethod, arguments, returnType.GetStackValueKind(), returnTypeSize); if (!methodToCall.HasReturnType) { importer.ImportAppendTree(callNode); } else { if (returnType.IsStruct()) { importer.ImportAppendTree(callNode); // Load return buffer to stack var loadTemp = new LocalVariableEntry(returnBufferArgIndex, returnType.GetStackValueKind(), returnType.GetExactSize()); importer.PushExpression(loadTemp); } else { importer.PushExpression(callNode); } } }
public void Import(Instruction instruction, ImportContext context, IILImporterProxy importer) { var code = instruction.OpCode.Code; switch (code) { case Code.Br_S: case Code.Blt_S: case Code.Bgt_S: case Code.Ble_S: case Code.Bge_S: case Code.Beq_S: case Code.Bne_Un_S: case Code.Brfalse_S: case Code.Brtrue_S: code += (Code.Br - Code.Br_S); break; } var target = instruction.OperandAs <Instruction>(); var targetBlock = importer.BasicBlocks[(int)target.Offset]; var fallthroughBlock = (code != Code.Br) ? context.FallThroughBlock : null; if (code != Code.Br) { var op2 = importer.PopExpression(); if (op2.Kind != StackValueKind.Int32 && op2.Kind != StackValueKind.NativeInt) { throw new NotSupportedException("Boolean comparisons only supported using int and nativeint as underlying type"); } StackEntry op1; Operation op; if (code != Code.Brfalse && code != Code.Brtrue) { op1 = importer.PopExpression(); op = Operation.Eq + (code - Code.Beq); // If one of the values is a native int then cast the other to be native int too if (op1.Kind == StackValueKind.NativeInt && op2.Kind == StackValueKind.Int32) { op2 = new CastEntry(Common.TypeSystem.WellKnownType.Object, op2, op1.Kind); } else if (op1.Kind == StackValueKind.Int32 && op2.Kind == StackValueKind.NativeInt) { op1 = new CastEntry(Common.TypeSystem.WellKnownType.Object, op1, op2.Kind); } } else { op1 = new Int32ConstantEntry(0); op = (code == Code.Brfalse) ? Operation.Eq : Operation.Ne; } op1 = new BinaryOperator(op, isComparison: true, op1, op2, op1.Kind); importer.ImportAppendTree(new JumpTrueEntry(targetBlock.Label, op1)); } else { importer.ImportAppendTree(new JumpEntry(targetBlock.Label)); } // Fall through handling importer.ImportFallThrough(targetBlock); if (fallthroughBlock != null) { importer.ImportFallThrough(fallthroughBlock); } context.StopImporting = true; }