コード例 #1
0
ファイル: RetImporter.cs プロジェクト: drcjt/CSharp-80
        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;
        }
コード例 #2
0
ファイル: StoreFieldImporter.cs プロジェクト: drcjt/CSharp-80
        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));
        }
コード例 #3
0
ファイル: SwitchImporter.cs プロジェクト: drcjt/CSharp-80
        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;
        }
コード例 #4
0
ファイル: PopImporter.cs プロジェクト: drcjt/CSharp-80
        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);
        }
コード例 #5
0
ファイル: StoreArgImporter.cs プロジェクト: drcjt/CSharp-80
        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);
        }
コード例 #6
0
ファイル: StoreVarImporter.cs プロジェクト: drcjt/CSharp-80
        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);
        }
コード例 #7
0
        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));
        }
コード例 #8
0
ファイル: NewobjImporter.cs プロジェクト: drcjt/CSharp-80
        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);
            }
        }
コード例 #9
0
ファイル: CallImporter.cs プロジェクト: drcjt/CSharp-80
        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);
        }
コード例 #10
0
ファイル: CallImporter.cs プロジェクト: drcjt/CSharp-80
        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);
                }
            }
        }
コード例 #11
0
ファイル: BranchImporter.cs プロジェクト: drcjt/CSharp-80
        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;
        }