예제 #1
0
        /// <summary>
        /// Declares a method.
        /// </summary>
        /// <param name="methodDef">The CIL method definition</param>
        /// <returns>The LLVM value reference</returns>
        public LLVMValueRef DeclareMethod(MethodDefinition methodDef)
        {
            int offset = methodDef.HasThis ? 1 : 0;

            var paramTypes = new LLVMTypeRef[methodDef.Parameters.Count + offset];

            for (int i = 0; i < paramTypes.Length - offset; ++i)
            {
                paramTypes[i + offset] = typeLookup.GetLLVMTypeRef(methodDef.Parameters[i].ParameterType);
            }

            if (methodDef.HasThis)
            {
                paramTypes[0] = typeLookup.GetLLVMTypeRef(methodDef.DeclaringType);
                if (methodDef.DeclaringType.IsValueType)
                {
                    paramTypes[0] = LLVM.PointerType(paramTypes[0], 0);
                }
            }

            var fnType = LLVM.FunctionType(
                typeLookup.GetLLVMTypeRef(methodDef.MethodReturnType.ReturnType),
                paramTypes,
                false
                );

            var valueRef = LLVM.AddFunction(moduleRef, methodDef.FullName, fnType);

            methodMap.Add(methodDef.FullName, valueRef);

            if (methodDef.IsConstructor && methodDef.IsStatic)
            {
                LLVM.SetLinkage(valueRef, LLVMLinkage.LLVMInternalLinkage);
                LLVM.BuildCall(cctorCallBuilder, valueRef, new LLVMValueRef[0], string.Empty);
            }

            return(valueRef);
        }
예제 #2
0
        /// <summary>
        /// Declares a static field.
        /// </summary>
        /// <param name="fieldDef">The static field definition</param>
        public void DeclareField(FieldDefinition fieldDef)
        {
            var globalType  = typeLookup.GetLLVMTypeRef(fieldDef.FieldType);
            var globalValue = LLVM.AddGlobal(moduleRef, globalType, fieldDef.FullName);

            fieldMap.Add(fieldDef, globalValue);

            // TODO: optimize using InitialValue?

            /*System.Console.WriteLine(fieldDef.InitialValue);
             * foreach(byte b in fieldDef.InitialValue)
             *  System.Console.WriteLine(b);*/

            LLVM.SetInitializer(globalValue, LLVM.ConstNull(globalType));
        }
예제 #3
0
        public void Compile()
        {
            if (offsetToBasicBlock.Count > 0)
            {
                throw new InvalidOperationException("This method is already compiled.");
            }

            LLVMBuilderRef builder = LLVM.CreateBuilder();

            // Add the entry point as the first basic block.
            {
                var it = MethodDef.Body.Instructions.GetEnumerator();
                it.MoveNext();
                AddBasicBlockAt(it.Current);
            }

            // Generate the entry point code for arguments.
            LLVM.PositionBuilderAtEnd(builder, offsetToBasicBlock[0].LLVMBlock);
            uint paramCount = LLVM.CountParams(FunctionValueRef);

            ArgumentValues = new EmulatedStateValue[paramCount];
            int offset = MethodDef.HasThis ? 1 : 0;

            for (uint i = 0; i < paramCount; ++i)
            {
                LLVMValueRef param    = LLVM.GetParam(FunctionValueRef, i);
                var          valueRef = LLVM.BuildAlloca(builder, LLVM.TypeOf(param), "arg" + i);

                TypeInfo typeInfo;
                if (MethodDef.HasThis && i == 0)
                {
                    typeInfo = TypeInfo.Reference;
                }
                else
                {
                    typeInfo = MethodDef.Parameters[(int)i - offset].ParameterType.GetTypeInfo();
                }

                ArgumentValues[i] = new EmulatedStateValue(valueRef, typeInfo);
                LLVM.BuildStore(builder, param, valueRef);
            }

            // Generate the entry point code for locals.
            {
                var locals = MethodDef.Body.Variables;
                LocalValues = new EmulatedStateValue[locals.Count];
                for (int i = 0; i < locals.Count; ++i)
                {
                    var cilType  = locals[i].VariableType;
                    var valueRef = LLVM.BuildAlloca(builder, TypeLookup.GetLLVMTypeRef(cilType), "local" + i);
                    LocalValues[i] = new EmulatedStateValue(valueRef, cilType.GetTypeInfo());
                }
            }

            // Now, find the basic blocks.
            {
                int currentBlockIndex = 0;
                foreach (Instruction insn in MethodDef.Body.Instructions)
                {
                    if (HasBasicBlock(insn.Offset))
                    {
                        // This is a fallthrough?
                        if (currentBlockIndex != insn.Offset)
                        {
                            // Can't be fallthrough if previous instruction was an unconditional branch.
                            if (!insn.Previous.IsUnconditionalBranchInstruction())
                            {
                                AddOutgoingEdge(currentBlockIndex, insn.Offset);
                            }
                        }

                        currentBlockIndex = insn.Offset;
                    }

                    if (insn.IsBranchInstruction())
                    {
                        AddBasicBlockAt((Instruction)insn.Operand);
                        AddOutgoingEdge(currentBlockIndex, ((Instruction)insn.Operand).Offset);
                        AddBasicBlockAt(insn.Next);
                        // Can't be fallthrough if current instruction was an unconditional branch.
                        if (!insn.IsUnconditionalBranchInstruction())
                        {
                            AddOutgoingEdge(currentBlockIndex, insn.Next.Offset);
                        }
                    }
                }
            }

            compileBasicBlock(builder, 0);

            LLVM.DisposeBuilder(builder);
        }