Exemple #1
0
        private LLVM.FunctionType ConstructType()
        {
            LLVM.Type retTy = Cil2Llvm.GetType(_method.ReturnType);
            if (_method.ReturnType.MetadataType == MetadataType.Class)
            {
                retTy = retTy.GetPointerTo();
            }

            List <LLVM.Type> paramsTy = new List <LLVM.Type>();

            if (_method.HasThis)
            {
                paramsTy.Add(Cil2Llvm.GetType(_method.DeclaringType).GetPointerTo());
            }

            if (_method.HasParameters)
            {
                foreach (ParameterDefinition p in _method.Parameters)
                {
                    LLVM.Type ty = Cil2Llvm.GetType(p.ParameterType);
                    if (p.ParameterType.MetadataType == MetadataType.Class)
                    {
                        ty = ty.GetPointerTo();
                    }
                    paramsTy.Add(ty);
                }
            }

            // TODO false -> varArg
            return(LLVM.FunctionType.Get(retTy, paramsTy.ToArray(), false));
        }
Exemple #2
0
        private void EmitOpCodeNewobj(MethodReference method)
        {
            Trace.Assert(method != null);
            TypeReference type = method.DeclaringType;

            Trace.Assert(type != null); // cannot be null, we are creating an obj

            LLVM.Type  ty     = Cil2Llvm.GetType(type);
            LLVM.Value size   = ConvertInteger(ty.Size, CLR.Native);
            LLVM.Value newobj = _builder.CreateCall(CLR.Newobj, size, "newobj");
            newobj.Dump();
            LLVM.Value obj = ConvertPointer(newobj, ty.GetPointerTo());
//obj.dump();

            _stack.Push(obj);
            //TODO: Trace.Assert(method.ReturnType == Void);
            EmitOpCodeCall(method);
            _stack.Push(obj);

/*
 *  // Cast to object type, call ctor and push on the stack
 *  //
 *  convertValue(newobj, PointerType::get(ClassTy, 0), bb);
 *  callMethod(newobj, token, bb);
 *  _Stack.push_back(newobj);
 */
        }
Exemple #3
0
        private void EmitOpCodeStfld(FieldReference field)
        {
            Trace.Assert(field != null);
            Trace.Assert(_stack.Count >= 2);
            Trace.Assert(field.IsDefinition);

            CodeGenType     ty = Cil2Llvm.GetCodeGenType(field.DeclaringType);
            FieldDefinition f  = field as FieldDefinition;

            uint offset = ty.GetFieldOffset(f);

            LLVM.Value val = _stack.Pop();
            LLVM.Value obj = ConvertToType(_stack.Pop(), ty.Type.GetPointerTo());
            LLVM.Value ptr = _builder.CreateStructGEP(obj, offset, field.Name + " pointer");
            _builder.CreateStore(val, ptr);
        }
Exemple #4
0
        private void EmitOpCodeCall(MethodReference method)
        {
            Trace.Assert(method != null);

            List <LLVM.Type> argsTy = new List <LLVM.Type>();

            if (method.HasThis)
            {
                argsTy.Add(Cil2Llvm.GetType(method.DeclaringType).GetPointerTo());
            }

            if (method.HasParameters)
            {
                foreach (ParameterDefinition p in method.Parameters)
                {
                    argsTy.Add(Cil2Llvm.GetType(p.ParameterType));
                }
            }

            Trace.Assert(_stack.Count >= argsTy.Count);
            LLVM.Value[] args = new LLVM.Value[argsTy.Count];

            for (int i = argsTy.Count - 1; i >= 0; i--)
            {
                args[i] = ConvertToType(_stack.Pop(), argsTy[i]);
            }

            LLVM.Value ret   = _builder.CreateCall(Cil2Llvm.GetMethod(method), args);
            LLVM.Type  retTy = Cil2Llvm.GetType(method.ReturnType);

            if (!retTy.Equals(CLR.Void))
            {
                _stack.Push(ret);
            }

/*
 *  // Cast to object type, call ctor and push on the stack
 *  //
 *  convertValue(newobj, PointerType::get(ClassTy, 0), bb);
 *  callMethod(newobj, token, bb);
 *  _Stack.push_back(newobj);
 */
        }
Exemple #5
0
        public void EmitBody()
        {
            uint             hasThis = 0;
            MethodDefinition meth    = _method.Method as MethodDefinition;

            LLVM.Function func = _method.Function;

            // Process parameters
            //
            if (meth.HasThis)
            {
                LLVM.Value val = func.GetParam(0);
                val.Name = "this";
                _params.Add(val);
                hasThis = 1;
            }
            for (uint i = 0; i < meth.Parameters.Count; i++)
            {
                LLVM.Value val = func.GetParam(i + hasThis);
                val.Name = meth.Parameters[(int)i].Name;
                _params.Add(val);
            }

            MethodBody body = meth.Body;

            if (body == null)
            {
                // Method may not have a body. For instance in the case of
                // external methods
                return; // end here
            }
            LLVM.BasicBlock bb = new LLVM.BasicBlock(func, "IL_0000");
            _builder.PositionAtEnd(bb);

            // Process local variables
            //
            if (body.HasVariables)
            {
                _variables = new List <LLVM.Value>();
                foreach (VariableDefinition variable in body.Variables)
                {
                    LLVM.Type ty = Cil2Llvm.GetType(variable.VariableType);

                    // FIXME: check when we want to use pointers and when we
                    // want to use primitive type. Do we want to use struct
                    // for ValueTypes ?
                    //
                    if (!variable.VariableType.IsPrimitive &&
                        !variable.VariableType.IsValueType)
                    {
                        ty = ty.GetPointerTo();
                    }
                    string name = "V_";
                    if (variable.Name.Length != 0)
                    {
                        name = variable.Name;
                    }
                    LLVM.Value val = _builder.CreateAlloca(ty, name);
                    _variables.Add(val);
                }
            }

            // parse all flowcontrol instructions a first time to create
            // basic blocks with the labels these instructions point to.
            //
            List <int> labels = new List <int>();

            foreach (Instruction inst in body.Instructions)
            {
                if (inst.OpCode.OperandType == OperandType.InlineBrTarget ||
                    inst.OpCode.OperandType == OperandType.ShortInlineBrTarget)
                {
                    if (inst.OpCode.FlowControl == FlowControl.Cond_Branch)
                    {
                        labels.Add(inst.Next.Offset);
                    }
                    Instruction br = inst.Operand as Instruction;
                    labels.Add(br.Offset);
                }
            }
            labels.Sort();

            foreach (int offset in labels)
            {
                LLVM.BasicBlock lbl = func.AppendBasicBlock("IL_" + offset.ToString("x4"));
                _labels[offset] = lbl;
            }

            var  lEnum     = labels.GetEnumerator();
            bool hasLabels = lEnum.MoveNext();

            foreach (Instruction inst in body.Instructions)
            {
                Console.WriteLine("{0}", inst);

                if (hasLabels && lEnum.Current == inst.Offset)
                {
                    LLVM.BasicBlock lbl = _labels[inst.Offset];
                    Console.WriteLine("offset " + inst.Offset);
                    if (!bb.HasTerminator)
                    {
                        _builder.CreateBr(lbl);
                    }
                    _builder.PositionAtEnd(lbl);
                    bb = lbl;
                    while (lEnum.Current == inst.Offset &&
                           (hasLabels = lEnum.MoveNext()))
                    {
                    }
                }

//TODO: pre-select instruction by type (flowcontrol, ...)

                if (inst.OpCode == OpCodes.Nop)
                {
                }                               /* Nothing */
                else if (inst.OpCode == OpCodes.Break)
                {
                    EmitUnimplemented();
                }
                else if (inst.OpCode == OpCodes.Ldarg_0)
                {
                    EmitOpCodeLdarg(0);
                }
                else if (inst.OpCode == OpCodes.Ldarg_1)
                {
                    EmitOpCodeLdarg(1);
                }
                else if (inst.OpCode == OpCodes.Ldarg_2)
                {
                    EmitOpCodeLdarg(2);
                }
                else if (inst.OpCode == OpCodes.Ldarg_3)
                {
                    EmitOpCodeLdarg(3);
                }
                else if (inst.OpCode == OpCodes.Ldloc_0)
                {
                    EmitOpCodeLdloc(0);
                }
                else if (inst.OpCode == OpCodes.Ldloc_1)
                {
                    EmitOpCodeLdloc(1);
                }
                else if (inst.OpCode == OpCodes.Ldloc_2)
                {
                    EmitOpCodeLdloc(2);
                }
                else if (inst.OpCode == OpCodes.Ldloc_3)
                {
                    EmitOpCodeLdloc(3);
                }
                else if (inst.OpCode == OpCodes.Stloc_0)
                {
                    EmitOpCodeStloc(0);
                }
                else if (inst.OpCode == OpCodes.Stloc_1)
                {
                    EmitOpCodeStloc(1);
                }
                else if (inst.OpCode == OpCodes.Stloc_2)
                {
                    EmitOpCodeStloc(2);
                }
                else if (inst.OpCode == OpCodes.Stloc_3)
                {
                    EmitOpCodeStloc(3);
                }
                else if (inst.OpCode == OpCodes.Ldnull)
                {
                    EmitUnimplemented();
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_M1)
                {
                    EmitOpCodeLdc(4, Convert.ToInt64(-1));
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_0)
                {
                    EmitOpCodeLdc(4, 0);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_1)
                {
                    EmitOpCodeLdc(4, 1);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_2)
                {
                    EmitOpCodeLdc(4, 2);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_3)
                {
                    EmitOpCodeLdc(4, 3);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_4)
                {
                    EmitOpCodeLdc(4, 4);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_5)
                {
                    EmitOpCodeLdc(4, 5);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_6)
                {
                    EmitOpCodeLdc(4, 6);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_7)
                {
                    EmitOpCodeLdc(4, 7);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_8)
                {
                    EmitOpCodeLdc(4, 8);
                }
                else if (inst.OpCode == OpCodes.Dup)
                {
                    EmitOpCodeDup();
                }
                else if (inst.OpCode == OpCodes.Pop)
                {
                    EmitOpCodePop();
                }
                else if (inst.OpCode == OpCodes.Ret)
                {
                    EmitOpCodeRet();
                }

/*
 *          case 0x46:  // ldind.i1
 *          case 0x47:  // ldind.u1
 *          case 0x48:  // ldind.i2
 *          case 0x49:  // ldind.u2
 *          case 0x4A:  // ldind.i4
 *          case 0x4B:  // ldind.u4
 *          case 0x4C:  // ldind.i8,u8
 *          case 0x4D:  // ldind.i
 *          case 0x4E:  // ldind.r4
 *          case 0x4F:  // ldind.r8
 *          case 0x50:  // ldind.ref
 *          case 0x51:  // stind.ref
 *          case 0x52:  // stind.i1
 *          case 0x53:  // stind.i2
 *          case 0x54:  // stind.i4
 *          case 0x55:  // stind.i8
 *          case 0x56:  // stind.r4
 *          case 0x57:  // stind.r8
 */
                else if (inst.OpCode == OpCodes.Call)
                {
                    EmitOpCodeCall(inst.Operand as MethodReference);
                }

                else if (inst.OpCode == OpCodes.Add)
                {
                    EmitOpCodeAdd();
                }
                else if (inst.OpCode == OpCodes.Sub)
                {
                    EmitOpCodeSub();
                }
                else if (inst.OpCode == OpCodes.Mul)
                {
                    EmitOpCodeMul();
                }
                else if (inst.OpCode == OpCodes.Div)
                {
                    EmitOpCodeDiv();
                }
                else if (inst.OpCode == OpCodes.Div_Un)
                {
                    EmitOpCodeDivUn();
                }

                else if (inst.OpCode == OpCodes.And)
                {
                    EmitOpCodeAnd();
                }
                else if (inst.OpCode == OpCodes.Or)
                {
                    EmitOpCodeOr();
                }
                else if (inst.OpCode == OpCodes.Xor)
                {
                    EmitOpCodeXor();
                }
                else if (inst.OpCode == OpCodes.Not)
                {
                    EmitOpCodeNot();
                }

                else if (inst.OpCode == OpCodes.Ldfld)
                {
                    EmitOpCodeLdfld(inst.Operand as FieldReference);
                }
                else if (inst.OpCode == OpCodes.Stfld)
                {
                    EmitOpCodeStfld(inst.Operand as FieldReference);
                }

                else if (inst.OpCode == OpCodes.Bge)
                {
                    EmitOpCodeBge(inst);
                }
                else if (inst.OpCode == OpCodes.Ble)
                {
                    EmitOpCodeBle(inst);
                }
#if UNIMPLEMENTED
/*
 *          case 0x5D:  // rem
 *          case 0x5E:  // rem.un
 *          case 0x62:  // shl
 *          case 0x63:  // shr
 *          case 0x64:  // shr.un
 *          case 0x65:  // neg
 *          case 0x67:  // conv.i1
 *          case 0x68:  // conv.i2
 *          case 0x69:  // conv.i4
 *          case 0x6A:  // conv.i8
 *          case 0x6B:  // conv.r4
 *          case 0x6C:  // conv.r8
 *          case 0x6D:  // conv.u4
 *          case 0x6E:  // conv.u8
 *          case 0x76:  // conv.r.un
 *          case 0x82:  // conv.ovf.i1.un
 *          case 0x83:  // conv.ovfi.i2.un
 *          case 0x84:  // conv.ovf.i4.un
 *          case 0x85:  // conv.ovf.i8.un
 *          case 0x86:  // conv.ovf.u1.un
 *          case 0x87:  // conv.ovf.u2.un
 *          case 0x88:  // conv.ovf.u4.un
 *          case 0x89:  // conv.ovf.u8.un
 *          case 0x8A:  // conv.ovf.i.un
 *          case 0x8B:  // conv.ovf.u.un
 *          case 0xB3:  // conv.ovf.i1
 *          case 0xB4:  // conv.ovf.u1
 *          case 0xB5:  // conv.ovfi.i2
 *          case 0xB6:  // conv.ovf.u2
 *          case 0xB7:  // conv.ovf.i4
 *          case 0xB8:  // conv.ovf.u4
 *          case 0xB9:  // conv.ovf.i8
 *          case 0xBA:  // conv.ovf.u8
 *          case 0xC3:  // ckfinite
 *          case 0xD1:  // conv.u2
 *          case 0xD2:  // conv.u1
 *          case 0xD3:  // conv.i (native int)
 *          case 0xD4:  // conv.ovf.i
 *          case 0xD5:  // conv.ovf.u
 *          case 0xD6:  // add.ovf
 *          case 0xD7:  // add.ovf.un
 *          case 0xD8:  // mul.ovf
 *          case 0xD9:  // mul.ovf.un
 *          case 0xDA:  // sub.ovf
 *          case 0xDB:  // sub.ovf.un
 *          case 0xDC:  // endfault, endfinally
 *          case 0xDD:  // leave
 *          case 0xDE:  // leave.s
 *          case 0xDF:  // stind.i
 *          case 0xE0:  // conv.u (native int)
 *
 */
#endif
                else if (inst.OpCode == OpCodes.Newobj)
                {
                    EmitOpCodeNewobj(inst.Operand as MethodReference);
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_S)
                {
                    EmitOpCodeLdc(4, Convert.ToInt64(inst.Operand));
                }
                else if (inst.OpCode == OpCodes.Ldc_I4)
                {
                    EmitOpCodeLdc(4, Convert.ToInt64(inst.Operand));
                }
                else
                {
                    EmitUnimplemented();
                }
            }
        }