/// <summary>
        /// Creates the System.String::get_Chars(int32) function.
        /// </summary>
        /// <param name="builder">The builder.</param>
        private void createStringGetCharsFunction(BuilderRef builder)
        {
            const string funcName = "System_Char_System_String_get_Chars_System_Int32";

            // Create function and set linkage.
            TypeRef  type = LLVM.FunctionType(TypeHelper.Int8, new TypeRef[] { TypeHelper.String, TypeHelper.Int32 }, false);
            ValueRef func = LLVM.AddFunction(mCompiler.Module, funcName, type);

            LLVM.SetLinkage(func, Linkage.LinkOnceAnyLinkage);
            LLVM.AddAttributeAtIndex(func, (uint)LLVM.AttributeFunctionIndex, LLVM.CreateEnumAttribute(mCompiler.ModuleContext, LLVM.GetEnumAttributeKindForName("alwaysinline", 12), 1));

            // Arguments.
            ValueRef str   = LLVM.GetParam(func, 0);
            ValueRef index = LLVM.GetParam(func, 1);

            // Create function body.
            BasicBlockRef entry = LLVM.AppendBasicBlock(func, string.Empty);

            LLVM.PositionBuilderAtEnd(builder, entry);
            ValueRef ch        = LLVM.BuildGEP(builder, str, new ValueRef[] { index }, "charptr");
            ValueRef returnVal = LLVM.BuildLoad(builder, ch, "character");

            LLVM.BuildRet(builder, returnVal);

            mCompiler.Lookup.AddFunction(funcName, func);
        }
示例#2
0
        /// <summary>
        /// Helper function for Brfalse/Brtrue: compare stack value with zero using zeroPredicate,
        /// and accordingly jump to either target or next block.
        /// </summary>
        private void EmitBrCommon(StackValue stack, IntPredicate zeroPredicate, BasicBlockRef targetBasicBlock, BasicBlockRef nextBasicBlock)
        {
            // Compare stack value with zero, and accordingly jump to either target or next block
            ValueRef cmpInst;

            switch (stack.StackType)
            {
            case StackValueType.NativeInt:
            {
                var zero = LLVM.ConstPointerNull(LLVM.TypeOf(stack.Value));
                cmpInst = LLVM.BuildICmp(builder, zeroPredicate, stack.Value, zero, string.Empty);
                break;
            }

            case StackValueType.Int32:
            {
                var zero = LLVM.ConstInt(int32Type, 0, false);
                cmpInst = LLVM.BuildICmp(builder, zeroPredicate, stack.Value, zero, string.Empty);
                break;
            }

            case StackValueType.Object:
            {
                var zero = LLVM.ConstPointerNull(LLVM.TypeOf(stack.Value));
                cmpInst = LLVM.BuildICmp(builder, zeroPredicate, stack.Value, zero, string.Empty);
                break;
            }

            default:
                throw new NotImplementedException();
            }

            LLVM.BuildCondBr(builder, cmpInst, targetBasicBlock, nextBasicBlock);
        }
示例#3
0
        public void TestORC()
        {
            LLVM.InitializeAllTargets();
            LLVM.InitializeAllTargetMCs();
            LLVM.InitializeAllTargetInfos();
            LLVM.InitializeAllAsmPrinters();

            // See http://www.doof.me.uk/2017/05/11/using-orc-with-llvms-c-api/
            ModuleRef mod = LLVM.ModuleCreateWithName("LLVMSharpIntro");

            TypeRef[]     param_types = { LLVM.Int32Type(), LLVM.Int32Type() };
            TypeRef       ret_type    = LLVM.FunctionType(LLVM.Int32Type(), param_types, false);
            ValueRef      sum         = LLVM.AddFunction(mod, "sum", ret_type);
            BasicBlockRef entry       = LLVM.AppendBasicBlock(sum, "entry");
            BuilderRef    builder     = LLVM.CreateBuilder();

            LLVM.PositionBuilderAtEnd(builder, entry);
            ValueRef tmp = LLVM.BuildAdd(builder, LLVM.GetParam(sum, 0), LLVM.GetParam(sum, 1), "tmp");

            LLVM.BuildRet(builder, tmp);
            MyString the_error = new MyString();

            LLVM.VerifyModule(mod, VerifierFailureAction.AbortProcessAction, the_error);

            //LLVM.DisposeMessage(error);
            TargetRef t2;
            string    tr2      = LLVM.GetDefaultTargetTriple();
            var       b        = LLVM.GetTargetFromTriple(tr2, out t2, the_error);
            string    triple   = "";
            string    cpu      = "";
            string    features = "";

            TargetMachineRef tmr = LLVM.CreateTargetMachine(t2, tr2, cpu, features,
                                                            CodeGenOptLevel.CodeGenLevelDefault,
                                                            RelocMode.RelocDefault,
                                                            CodeModel.CodeModelDefault);

            OrcJITStackRef ojsr = LLVM.OrcCreateInstance(tmr);
            MyString       ms   = new MyString();

            LLVM.OrcGetMangledSymbol(ojsr, ms, "sum");
            IntPtr ctx = IntPtr.Zero;

            SharedModuleRef smr       = LLVM.OrcMakeSharedModule(mod);
            OrcErrorCode    xx        = LLVM.OrcAddLazilyCompiledIR(ojsr, out uint omh, smr, null, ctx);
            OrcErrorCode    p         = LLVM.OrcGetSymbolAddress(ojsr, out IntPtr RetAddr, "sum");
            Add             addMethod = (Add)Marshal.GetDelegateForFunctionPointer(RetAddr, typeof(Add));
            int             result    = addMethod(10, 10);

            Console.WriteLine("Result of sum is: " + result);
            if (result != 20)
            {
                throw new Exception("Failed.");
            }
            LLVM.DumpModule(mod);
            LLVM.DisposeBuilder(builder);
        }
示例#4
0
        /// <summary>
        /// Creates the "newobj" method for a type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>The function.</returns>
        private ValueRef createNewobjMethod(TypeDefinition type)
        {
            string     name    = string.Format("newobj_{0}", type.FullName);
            BuilderRef builder = LLVM.CreateBuilderInContext(mCompiler.ModuleContext);

            // Create method type.
            TypeRef  funcType = LLVM.FunctionType(TypeHelper.GetTypeRefFromType(type), new TypeRef[0], false);
            ValueRef func     = LLVM.AddFunction(mCompiler.Module, name, funcType);

            LLVM.SetLinkage(func, Linkage.InternalLinkage);

            BasicBlockRef entry = LLVM.AppendBasicBlockInContext(mCompiler.ModuleContext, func, string.Empty);

            LLVM.PositionBuilderAtEnd(builder, entry);

            // Allocate space on the heap for this object.
            TypeRef  typeRef = mCompiler.Lookup.GetTypeRef(type);
            ValueRef objPtr  = LLVM.BuildMalloc(builder, typeRef, "newobj");

            // Initialize class VTables.
            Lookup lookup = mCompiler.Lookup;

            if (lookup.NeedsVirtualCall(type))
            {
                VTable vtable = lookup.GetVTable(type);
                KeyValuePair <TypeDefinition, Tuple <TypeRef, ValueRef> >[] others = vtable.GetAllClassEntries();
                foreach (KeyValuePair <TypeDefinition, Tuple <TypeRef, ValueRef> > pair in others)
                {
                    uint     index     = lookup.GetClassVTableIndex(pair.Key);
                    ValueRef vTableGep = LLVM.BuildInBoundsGEP(builder, objPtr, new ValueRef[] { LLVM.ConstInt(TypeHelper.Int32, 0, false), LLVM.ConstInt(TypeHelper.Int32, index, false) }, "vtabledst");
                    LLVM.BuildStore(builder, pair.Value.Item2, vTableGep);
                }
            }

            // Initialize interface indirection table.
            if (type.HasInterfaces)
            {
                ValueRef indirectionTable = mLookup.GetInterfaceIndirectionTable(type);
                ValueRef gep = LLVM.BuildInBoundsGEP(builder, objPtr, new ValueRef[] { LLVM.ConstInt(TypeHelper.Int32, 0, false), LLVM.ConstInt(TypeHelper.Int32, 0, false) }, "interfaceindirectiontablegep");
                LLVM.BuildStore(builder, LLVM.BuildPointerCast(builder, indirectionTable, TypeHelper.VoidPtr, string.Empty), gep);
            }

            // Return object pointer.
            LLVM.BuildRet(builder, objPtr);

            LLVM.DisposeBuilder(builder);

            return(func);
        }
示例#5
0
        /// <summary>
        /// Helper function for Brfalse/Brtrue: compare stack value with zero using zeroPredicate,
        /// and accordingly jump to either target or next block.
        /// </summary>
        private void EmitBrCommon(StackValue stack, IntPredicate zeroPredicate, BasicBlockRef targetBasicBlock, BasicBlockRef nextBasicBlock)
        {
            // Zero constant
            var zero = LLVM.ConstInt(int32Type, 0, false);

            switch (stack.StackType)
            {
            case StackValueType.Int32:
                // Compare stack value with zero, and accordingly jump to either target or next block
                var cmpInst = LLVM.BuildICmp(builder, zeroPredicate, stack.Value, zero, string.Empty);
                LLVM.BuildCondBr(builder, cmpInst, targetBasicBlock, nextBasicBlock);
                break;

            default:
                throw new NotImplementedException();
            }
        }
示例#6
0
        static void Main(string[] args)
        {
            Swigged.LLVM.Helper.Adjust.Path();
            LLVM.InitializeAllTargets();
            LLVM.InitializeAllTargetMCs();
            LLVM.InitializeAllTargetInfos();
            LLVM.InitializeAllAsmPrinters();

            ModuleRef mod = LLVM.ModuleCreateWithName("LLVMSharpIntro");

            TypeRef[]     param_types = { LLVM.Int32Type(), LLVM.Int32Type() };
            TypeRef       ret_type    = LLVM.FunctionType(LLVM.Int32Type(), param_types, false);
            ValueRef      sum         = LLVM.AddFunction(mod, "sum", ret_type);
            BasicBlockRef entry       = LLVM.AppendBasicBlock(sum, "entry");
            BuilderRef    builder     = LLVM.CreateBuilder();

            LLVM.PositionBuilderAtEnd(builder, entry);
            ValueRef tmp = LLVM.BuildAdd(builder, LLVM.GetParam(sum, 0), LLVM.GetParam(sum, 1), "tmp");

            LLVM.BuildRet(builder, tmp);
            MyString the_error = new MyString();

            LLVM.VerifyModule(mod, VerifierFailureAction.AbortProcessAction, the_error);
            //LLVM.DisposeMessage(error);
            ExecutionEngineRef   engine;
            MCJITCompilerOptions options = new MCJITCompilerOptions();
            var optionsSize = (4 * sizeof(int)) + IntPtr.Size; // LLVMMCJITCompilerOptions has 4 ints and a pointer

            LLVM.InitializeMCJITCompilerOptions(options, (uint)optionsSize);
            LLVM.CreateMCJITCompilerForModule(out engine, mod, options, (uint)optionsSize, the_error);
            var    ptr       = LLVM.GetPointerToGlobal(engine, sum);
            IntPtr p         = (IntPtr)ptr;
            Add    addMethod = (Add)Marshal.GetDelegateForFunctionPointer(p, typeof(Add));
            int    result    = addMethod(10, 10);

            Console.WriteLine("Result of sum is: " + result);
            if (LLVM.WriteBitcodeToFile(mod, "sum.bc") != 0)
            {
                Console.WriteLine("error writing bitcode to file, skipping");
            }
            LLVM.DumpModule(mod);
            LLVM.DisposeBuilder(builder);
            LLVM.DisposeExecutionEngine(engine);
        }
示例#7
0
 public unsafe static ValueRef BuildSwitch(BuilderRef arg0, ValueRef V, BasicBlockRef Else, uint NumCases) {
   ValueRef ret = new ValueRef(LLVMPINVOKE.BuildSwitch(arg0.Value, V.Value, Else.Value, NumCases));
   return ret;
 }
示例#8
0
 public unsafe static ValueRef BuildBr(BuilderRef arg0, BasicBlockRef Dest) {
   ValueRef ret = new ValueRef(LLVMPINVOKE.BuildBr(arg0.Value, Dest.Value));
   return ret;
 }
示例#9
0
 public unsafe static void PositionBuilderAtEnd(BuilderRef Builder, BasicBlockRef Block) {
   LLVMPINVOKE.PositionBuilderAtEnd(Builder.Value, Block.Value);
 }
示例#10
0
 public unsafe static BasicBlockRef GetIncomingBlock(ValueRef PhiNode, uint Index) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetIncomingBlock(PhiNode.Value, Index));
   return ret;
 }
示例#11
0
 public unsafe static BasicBlockRef GetSwitchDefaultDest(ValueRef SwitchInstr) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetSwitchDefaultDest(SwitchInstr.Value));
   return ret;
 }
示例#12
0
        private void GenerateLeave(List<ExceptionHandlerInfo> activeTryHandlers, Instruction targetInstruction, ValueRef endfinallyJumpTarget, BasicBlockRef[] basicBlocks)
        {
            // Check if we need to go through a finally handler
            for (int index = activeTryHandlers.Count - 1; index >= 0; index--)
            {
                var exceptionHandler = activeTryHandlers[index];

                // Jumping inside that exception clause?
                if (targetInstruction.Offset >= exceptionHandler.Source.TryStart.Offset
                    && targetInstruction.Offset < exceptionHandler.Source.TryEnd.Offset)
                    break;

                // Leaving through a finally clause
                if (exceptionHandler.Source.HandlerType == ExceptionHandlerType.Finally)
                {
                    // Find or insert index of this instruction
                    var leaveTargetIndex = exceptionHandler.LeaveTargets.IndexOf(targetInstruction);
                    if (leaveTargetIndex == -1)
                    {
                        leaveTargetIndex = exceptionHandler.LeaveTargets.Count;
                        exceptionHandler.LeaveTargets.Add(targetInstruction);
                    }

                    // Update desired jump target
                    LLVM.BuildStore(builder, LLVM.ConstInt(int32Type, (ulong)leaveTargetIndex, false), endfinallyJumpTarget);

                    // Actual jump will be to finally clause
                    targetInstruction = exceptionHandler.Source.HandlerStart;
                    break;
                }
            }

            EmitBr(basicBlocks[targetInstruction.Offset]);
        }
示例#13
0
 private void EmitBrtrue(List <StackValue> stack, BasicBlockRef targetBasicBlock, BasicBlockRef nextBasicBlock)
 {
     // Stack element should be different from zero.
     EmitBrCommon(stack.Pop(), IntPredicate.IntNE, targetBasicBlock, nextBasicBlock);
 }
示例#14
0
 private void EmitBrfalse(List <StackValue> stack, BasicBlockRef targetBasicBlock, BasicBlockRef nextBasicBlock)
 {
     // Stack element should be equal to zero.
     EmitBrCommon(stack.Pop(), IntPredicate.IntEQ, targetBasicBlock, nextBasicBlock);
 }
示例#15
0
 private void EmitBr(BasicBlockRef targetBasicBlock)
 {
     // Unconditional branch
     LLVM.BuildBr(builder, targetBasicBlock);
 }
示例#16
0
        public void TestMultiModules()
        {
            LLVM.InitializeAllTargets();
            LLVM.InitializeAllTargetMCs();
            LLVM.InitializeAllTargetInfos();
            LLVM.InitializeAllAsmPrinters();

            // First module contains add.
            ModuleRef mod1 = LLVM.ModuleCreateWithName("LLVMSharpIntro");

            TypeRef[]     param_types1 = { LLVM.Int32Type(), LLVM.Int32Type() };
            TypeRef       ret_type1    = LLVM.FunctionType(LLVM.Int32Type(), param_types1, false);
            ValueRef      add          = LLVM.AddFunction(mod1, "add", ret_type1);
            BasicBlockRef entry1       = LLVM.AppendBasicBlock(add, "entry");
            BuilderRef    builder1     = LLVM.CreateBuilder();

            LLVM.PositionBuilderAtEnd(builder1, entry1);
            ValueRef tmp1 = LLVM.BuildAdd(builder1, LLVM.GetParam(add, 0), LLVM.GetParam(add, 1), "tmp");

            LLVM.BuildRet(builder1, tmp1);
            MyString the_error = new MyString();

            LLVM.VerifyModule(mod1, VerifierFailureAction.PrintMessageAction, the_error);
            LLVM.DumpModule(mod1);

            // Second module contains sub.
            ModuleRef mod2 = LLVM.ModuleCreateWithName("LLVMSharpIntro");

            TypeRef[]     param_types2 = { LLVM.Int32Type(), LLVM.Int32Type() };
            TypeRef       ret_type2    = LLVM.FunctionType(LLVM.Int32Type(), param_types2, false);
            ValueRef      sub          = LLVM.AddFunction(mod2, "sub", ret_type2);
            BasicBlockRef entry2       = LLVM.AppendBasicBlock(sub, "entry");
            BuilderRef    builder2     = LLVM.CreateBuilder();

            LLVM.PositionBuilderAtEnd(builder2, entry2);
            ValueRef tmp2 = LLVM.BuildSub(builder2, LLVM.GetParam(sub, 0), LLVM.GetParam(sub, 1), "tmp");

            LLVM.BuildRet(builder2, tmp2);
            LLVM.VerifyModule(mod2, VerifierFailureAction.PrintMessageAction, the_error);
            LLVM.DumpModule(mod2);

            // Third module contains uses of add and sub.
            ModuleRef mod3 = LLVM.ModuleCreateWithName("LLVMSharpIntro");

            TypeRef[]     param_types3 = { };
            TypeRef       ret_type3    = LLVM.FunctionType(LLVM.Int32Type(), param_types3, false);
            ValueRef      comb         = LLVM.AddFunction(mod3, "comb", ret_type3);
            ValueRef      add1         = LLVM.AddFunction(mod3, "add", ret_type1);
            ValueRef      sub2         = LLVM.AddFunction(mod3, "sub", ret_type1);
            BasicBlockRef entry3       = LLVM.AppendBasicBlock(comb, "entry");
            BuilderRef    builder3     = LLVM.CreateBuilder();

            LLVM.PositionBuilderAtEnd(builder3, entry3);
            ValueRef tmpa3 = LLVM.ConstInt(LLVM.Int32Type(), 1, false);
            ValueRef tmpb3 = LLVM.ConstInt(LLVM.Int32Type(), 2, false);
            ValueRef tmpc3 = LLVM.ConstInt(LLVM.Int32Type(), 3, false);
            var      tmpd3 = LLVM.BuildCall(builder3, add1, new ValueRef[] { tmpa3, tmpc3 }, "");
            var      tmpe3 = LLVM.BuildCall(builder3, sub2, new ValueRef[] { tmpd3, tmpb3 }, "");

            LLVM.BuildRet(builder3, tmpe3);

            LLVM.VerifyModule(mod3, VerifierFailureAction.PrintMessageAction, the_error);
            LLVM.DumpModule(mod3);

            //LLVM.DisposeMessage(error);
            TargetRef t2;
            string    tr2      = LLVM.GetDefaultTargetTriple();
            var       b        = LLVM.GetTargetFromTriple(tr2, out t2, the_error);
            string    triple   = "";
            string    cpu      = "";
            string    features = "";

            TargetMachineRef tmr = LLVM.CreateTargetMachine(t2, tr2, cpu, features,
                                                            CodeGenOptLevel.CodeGenLevelDefault,
                                                            RelocMode.RelocDefault,
                                                            CodeModel.CodeModelDefault);

            OrcJITStackRef ojsr = LLVM.OrcCreateInstance(tmr);
            MyString       ms   = new MyString();

            LLVM.OrcGetMangledSymbol(ojsr, ms, "comb");
            IntPtr          ctx  = IntPtr.Zero;
            SharedModuleRef smr1 = LLVM.OrcMakeSharedModule(mod1);
            var             xx   = LLVM.OrcAddLazilyCompiledIR(ojsr, out uint omh1, smr1, null, ctx);
            SharedModuleRef smr2 = LLVM.OrcMakeSharedModule(mod2);

            xx = LLVM.OrcAddLazilyCompiledIR(ojsr, out uint omh2, smr2, null, ctx);
            SharedModuleRef smr3 = LLVM.OrcMakeSharedModule(mod3);

            xx = LLVM.OrcAddLazilyCompiledIR(ojsr, out uint omh3, smr3, null, ctx);
            var  p          = LLVM.OrcGetSymbolAddress(ojsr, out IntPtr RetAddr, "comb");
            Comb combMethod = (Comb)Marshal.GetDelegateForFunctionPointer(RetAddr, typeof(Comb));
            int  result     = combMethod();

            Console.WriteLine("Result of comb is: " + result);
            if (result != 2)
            {
                throw new Exception();
            }
        }
示例#17
0
        public void TestFact()
        {
            ModuleRef Module = LLVM.ModuleCreateWithName("fac_module");

            TypeRef[] fac_args = { LLVM.Int32Type() };
            ValueRef  fac      = LLVM.AddFunction(Module, "fac", LLVM.FunctionType(LLVM.Int32Type(), fac_args, false));

            LLVM.SetFunctionCallConv(fac, (uint)Swigged.LLVM.CallConv.CCallConv);
            ValueRef n = LLVM.GetParam(fac, 0);

            BasicBlockRef entry   = LLVM.AppendBasicBlock(fac, "entry");
            BasicBlockRef iftrue  = LLVM.AppendBasicBlock(fac, "iftrue");
            BasicBlockRef iffalse = LLVM.AppendBasicBlock(fac, "iffalse");
            BasicBlockRef end     = LLVM.AppendBasicBlock(fac, "end");
            BuilderRef    builder = LLVM.CreateBuilder();

            LLVM.PositionBuilderAtEnd(builder, entry);
            ValueRef If = LLVM.BuildICmp(builder, Swigged.LLVM.IntPredicate.IntEQ, n, LLVM.ConstInt(LLVM.Int32Type(), 0, false), "n == 0");

            LLVM.BuildCondBr(builder, If, iftrue, iffalse);

            LLVM.PositionBuilderAtEnd(builder, iftrue);
            ValueRef res_iftrue = LLVM.ConstInt(LLVM.Int32Type(), 1, false);

            LLVM.BuildBr(builder, end);

            LLVM.PositionBuilderAtEnd(builder, iffalse);
            ValueRef n_minus = LLVM.BuildSub(builder, n, LLVM.ConstInt(LLVM.Int32Type(), 1, false), "n - 1");

            ValueRef[] call_fac_args = { n_minus };
            ValueRef   call_fac      = LLVM.BuildCall(builder, fac, call_fac_args, "fac(n - 1)");
            ValueRef   res_iffalse   = LLVM.BuildMul(builder, n, call_fac, "n * fac(n - 1)");

            LLVM.BuildBr(builder, end);

            LLVM.PositionBuilderAtEnd(builder, end);
            ValueRef res = LLVM.BuildPhi(builder, LLVM.Int32Type(), "result");

            ValueRef[]      phi_vals   = { res_iftrue, res_iffalse };
            BasicBlockRef[] phi_blocks = { iftrue, iffalse };
            LLVM.AddIncoming(res, phi_vals, phi_blocks);
            LLVM.BuildRet(builder, res);

            MyString error = new MyString();

            LLVM.VerifyModule(Module, VerifierFailureAction.PrintMessageAction, error);
            if (error.ToString() != "")
            {
                throw new Exception("Failed");
            }

            ExecutionEngineRef engine;
            ModuleProviderRef  provider = LLVM.CreateModuleProviderForExistingModule(Module);

            LLVM.CreateJITCompilerForModule(out engine, Module, 0, error);

            PassManagerRef pass = LLVM.CreatePassManager();

            // LLVM.AddTargetData(LLVM.GetExecutionEngineTargetData(engine), pass);
            LLVM.AddConstantPropagationPass(pass);
            LLVM.AddInstructionCombiningPass(pass);
            LLVM.AddPromoteMemoryToRegisterPass(pass);
            // LLVMAddDemoteMemoryToRegisterPass(pass); // Demotes every possible value to memory
            LLVM.AddGVNPass(pass);
            LLVM.AddCFGSimplificationPass(pass);
            LLVM.RunPassManager(pass, Module);
            LLVM.DumpModule(Module);

            ulong input = 10;

            for (ulong i = 0; i < input; ++i)
            {
                GenericValueRef exec_args                 = LLVM.CreateGenericValueOfInt(LLVM.Int32Type(), input, false);
                GenericValueRef exec_res                  = LLVM.RunFunction(engine, fac, 1, out exec_args);
                var             result_of_function        = LLVM.GenericValueToInt(exec_res, false);
                var             result_of_csharp_function = Factorial(input);
                if (result_of_csharp_function != result_of_function)
                {
                    throw new Exception("Results not the same.");
                }
            }

            LLVM.DisposePassManager(pass);
            LLVM.DisposeBuilder(builder);
            LLVM.DisposeExecutionEngine(engine);
        }
示例#18
0
        public void TestPTX()
        {
            LLVM.InitializeAllTargets();
            LLVM.InitializeAllTargetMCs();
            LLVM.InitializeAllTargetInfos();
            LLVM.InitializeAllAsmPrinters();
            ModuleRef mod = LLVM.ModuleCreateWithName("llvmptx");
            var       pt  = LLVM.PointerType(LLVM.Int64Type(), 1);

            TypeRef[]     param_types = { pt };
            TypeRef       ret_type    = LLVM.FunctionType(LLVM.VoidType(), param_types, false);
            ValueRef      sum         = LLVM.AddFunction(mod, "sum", ret_type);
            BasicBlockRef entry       = LLVM.AppendBasicBlock(sum, "entry");
            BuilderRef    builder     = LLVM.CreateBuilder();

            LLVM.PositionBuilderAtEnd(builder, entry);
            var      v   = LLVM.BuildLoad(builder, LLVM.GetParam(sum, 0), "");
            ValueRef tmp = LLVM.BuildAdd(builder, v, LLVM.ConstInt(LLVM.Int64Type(), 1, false), "tmp");

            LLVM.BuildStore(builder, tmp, LLVM.GetParam(sum, 0));
            LLVM.BuildRetVoid(builder);
            MyString the_error = new MyString();

            LLVM.VerifyModule(mod, VerifierFailureAction.PrintMessageAction, the_error);

            string    triple = "nvptx64-nvidia-cuda";
            TargetRef t2;
            var       b = LLVM.GetTargetFromTriple(triple, out t2, the_error);

            string cpu      = "";
            string features = "";

            TargetMachineRef tmr = LLVM.CreateTargetMachine(t2, triple, cpu, features,
                                                            CodeGenOptLevel.CodeGenLevelDefault,
                                                            RelocMode.RelocDefault,
                                                            CodeModel.CodeModelKernel);
            ContextRef context_ref = LLVM.ContextCreate();
            ValueRef   kernelMd    = LLVM.MDNodeInContext(context_ref, new ValueRef[3]
            {
                sum,
                LLVM.MDStringInContext(context_ref, "kernel", 6),
                LLVM.ConstInt(LLVM.Int32TypeInContext(context_ref), 1, false)
            });

            LLVM.AddNamedMetadataOperand(mod, "nvvm.annotations", kernelMd);
            var y1 = LLVM.TargetMachineEmitToMemoryBuffer(
                tmr,
                mod,
                Swigged.LLVM.CodeGenFileType.AssemblyFile,
                the_error,
                out MemoryBufferRef buffer);
            string ptx = null;

            try
            {
                ptx = LLVM.GetBufferStart(buffer);
                uint length = LLVM.GetBufferSize(buffer);
                // Output the PTX assembly code. We can run this using the CUDA Driver API
                System.Console.WriteLine(ptx);
            }
            finally
            {
                LLVM.DisposeMemoryBuffer(buffer);
            }


            // RUN THE MF.

            Int64[]     h_C             = new Int64[100];
            CudaContext ctx             = new CudaContext(CudaContext.GetMaxGflopsDeviceId());
            CudaKernel  kernel          = ctx.LoadKernelPTX(Encoding.ASCII.GetBytes(ptx), "sum");
            var         d_C             = new CudaDeviceVariable <Int64>(100);
            int         N               = 1;
            int         threadsPerBlock = 256;

            kernel.BlockDimensions = threadsPerBlock;
            kernel.GridDimensions  = (N + threadsPerBlock - 1) / threadsPerBlock;
            kernel.Run(d_C.DevicePointer);
            h_C = d_C;
            System.Console.WriteLine("Result " + h_C[0]);
            if (h_C[0] != 1)
            {
                throw new Exception("Failed.");
            }
            LLVM.DumpModule(mod);
            LLVM.DisposeBuilder(builder);
        }
示例#19
0
 public unsafe static void AddCase(ValueRef Switch, ValueRef OnVal, BasicBlockRef Dest) {
   LLVMPINVOKE.AddCase(Switch.Value, OnVal.Value, Dest.Value);
 }
示例#20
0
 public unsafe static ValueRef DIBuilderInsertDeclareAtEnd(DIBuilderRef Builder, ValueRef Val, DIDescriptor VarInfo, DIDescriptor Expr, BasicBlockRef InsertAtEnd) {
   ValueRef ret = new ValueRef(LLVMPINVOKE.DIBuilderInsertDeclareAtEnd(Builder.Value, Val.Value, VarInfo.Value, Expr.Value, InsertAtEnd.Value));
   return ret;
 }
示例#21
0
 public unsafe static BasicBlockRef GetPreviousBasicBlock(BasicBlockRef BB) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetPreviousBasicBlock(BB.Value));
   return ret;
 }
示例#22
0
        private void UpdateExceptionHandlers(FunctionCompilerContext functionContext, Instruction instruction)
        {
            var functionGlobal = functionContext.Function.GeneratedValue;
            var exceptionHandlers = functionContext.ExceptionHandlers;
            var activeTryHandlers = functionContext.ActiveTryHandlers;
            var methodReference = functionContext.MethodReference;
            bool exceptionHandlersChanged = false;

            // Exit finished exception handlers
            for (int index = activeTryHandlers.Count - 1; index >= 0; index--)
            {
                var exceptionHandler = activeTryHandlers[index];
                if (instruction == exceptionHandler.Source.TryEnd)
                {
                    activeTryHandlers.RemoveAt(index);
                    exceptionHandlersChanged = true;
                }
                else
                    break;
            }

            // Add new exception handlers
            for (int index = exceptionHandlers.Count - 1; index >= 0; index--)
            {
                var exceptionHandler = exceptionHandlers[index];
                if (instruction == exceptionHandler.Source.TryStart)
                {
                    var catchDispatchBlock = new BasicBlockRef();

                    if (exceptionHandler.Source.HandlerType == ExceptionHandlerType.Catch)
                    {
                        catchDispatchBlock = LLVM.AppendBasicBlockInContext(context, functionGlobal, "catch.dispatch");
                        LLVM.PositionBuilderAtEnd(builder2, catchDispatchBlock);

                        var catchBlock = functionContext.BasicBlocks[exceptionHandler.Source.HandlerStart.Offset];
                        var catchClass = GetClass(ResolveGenericsVisitor.Process(methodReference, exceptionHandler.Source.CatchType));

                        // Compare exception type
                        var ehselectorValue = LLVM.BuildLoad(builder2, functionContext.ExceptionHandlerSelectorSlot, "sel");

                        var ehtypeIdFor = LLVM.IntrinsicGetDeclaration(module, (uint)Intrinsics.eh_typeid_for, new TypeRef[0]);
                        var ehtypeid = LLVM.BuildCall(builder2, ehtypeIdFor, new[] { LLVM.ConstBitCast(catchClass.GeneratedRuntimeTypeInfoGlobal, intPtrType) }, string.Empty);

                        // Jump to catch clause if type matches.
                        // Otherwise, go to next exception handler dispatch block (if any), or resume exception block (TODO)
                        var ehtypeComparisonResult = LLVM.BuildICmp(builder2, IntPredicate.IntEQ, ehselectorValue, ehtypeid, string.Empty);
                        LLVM.BuildCondBr(builder2, ehtypeComparisonResult, catchBlock, activeTryHandlers.Count > 0 ? activeTryHandlers.Last().CatchDispatch : functionContext.ResumeExceptionBlock);
                    }
                    else if (exceptionHandler.Source.HandlerType == ExceptionHandlerType.Finally)
                    {
                        catchDispatchBlock = functionContext.BasicBlocks[exceptionHandler.Source.HandlerStart.Offset];
                    }

                    exceptionHandler.CatchDispatch = catchDispatchBlock;
                    activeTryHandlers.Add(exceptionHandler);
                    exceptionHandlersChanged = true;
                }
            }

            if (exceptionHandlersChanged)
            {
                // Need to generate a new landing pad
                for (int index = activeTryHandlers.Count - 1; index >= 0; index--)
                {
                    var exceptionHandler = activeTryHandlers[index];
                    switch (exceptionHandler.Source.HandlerType)
                    {
                        case ExceptionHandlerType.Catch:
                            break;
                    }
                }

                if (activeTryHandlers.Count > 0)
                {
                    //var handlerStart = exceptionHandlers.Last().HandlerStart.Offset;
                    //functionContext.LandingPadBlock = basicBlocks[handlerStart];

                    // Prepare landing pad block
                    functionContext.LandingPadBlock = LLVM.AppendBasicBlockInContext(context, functionGlobal, "landingpad");
                    LLVM.PositionBuilderAtEnd(builder2, functionContext.LandingPadBlock);
                    var landingPad = LLVM.BuildLandingPad(builder2, caughtResultType, sharpPersonalityFunction, 1, string.Empty);

                    // Extract exception, and store it in exn.slot
                    var exceptionObject = LLVM.BuildExtractValue(builder2, landingPad, 0, string.Empty);
                    exceptionObject = LLVM.BuildPointerCast(builder2, exceptionObject, @object.Class.Type.DefaultType, string.Empty);
                    LLVM.BuildStore(builder2, exceptionObject, functionContext.ExceptionSlot);

                    // Extract selector slot, and store it in ehselector.slot
                    var exceptionType = LLVM.BuildExtractValue(builder2, landingPad, 1, string.Empty);
                    LLVM.BuildStore(builder2, exceptionType, functionContext.ExceptionHandlerSelectorSlot);

                    // Let future finally clause know that we need to propage exception after they are executed
                    // A future Leave instruction should clear that if necessary
                    LLVM.BuildStore(builder2, LLVM.ConstInt(int32Type, unchecked((ulong)-1), true), functionContext.EndfinallyJumpTarget);

                    // Add jump to catch dispatch block or finally block
                    var lastActiveTryHandler = activeTryHandlers.Last();
                    LLVM.BuildBr(builder2, lastActiveTryHandler.CatchDispatch);

                    // Filter exceptions type by type
                    for (int index = activeTryHandlers.Count - 1; index >= 0; index--)
                    {
                        var exceptionHandler = activeTryHandlers[index];

                        // Add landing pad type clause
                        if (exceptionHandler.Source.HandlerType == ExceptionHandlerType.Catch)
                        {
                            var catchClass = GetClass(ResolveGenericsVisitor.Process(methodReference, exceptionHandler.Source.CatchType));
                            LLVM.AddClause(landingPad, LLVM.ConstBitCast(catchClass.GeneratedRuntimeTypeInfoGlobal, intPtrType));
                        }
                        else if (exceptionHandler.Source.HandlerType == ExceptionHandlerType.Finally)
                        {
                            LLVM.SetCleanup(landingPad, true);
                        }
                    }
                }
                else
                {
                    functionContext.LandingPadBlock = new BasicBlockRef();
                }
            }
        }
示例#23
0
 public unsafe static BasicBlockRef GetEntryBasicBlock(ValueRef Fn) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetEntryBasicBlock(Fn.Value));
   return ret;
 }
示例#24
0
 public unsafe static void SetSuccessor(ValueRef Term, uint i, BasicBlockRef block) {
   LLVMPINVOKE.SetSuccessor(Term.Value, i, block.Value);
 }
示例#25
0
 public unsafe static BasicBlockRef AppendBasicBlockInContext(ContextRef C, ValueRef Fn, string Name) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.AppendBasicBlockInContext(C.Value, Fn.Value, Name));
   return ret;
 }
示例#26
0
 public unsafe static void AddIncoming(ValueRef PhiNode, ValueRef[] IncomingValues, BasicBlockRef[] IncomingBlocks) {
   fixed (ValueRef* swig_ptrTo_IncomingValues = IncomingValues)
   fixed (BasicBlockRef* swig_ptrTo_IncomingBlocks = IncomingBlocks)
   {
     LLVMPINVOKE.AddIncoming(PhiNode.Value, (System.IntPtr)swig_ptrTo_IncomingValues, (System.IntPtr)swig_ptrTo_IncomingBlocks, (uint)IncomingBlocks.Length);
   }
 }
示例#27
0
 public unsafe static BasicBlockRef AppendBasicBlock(ValueRef Fn, string Name) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.AppendBasicBlock(Fn.Value, Name));
   return ret;
 }
示例#28
0
 public unsafe static void PositionBuilder(BuilderRef Builder, BasicBlockRef Block, ValueRef Instr) {
   LLVMPINVOKE.PositionBuilder(Builder.Value, Block.Value, Instr.Value);
 }
示例#29
0
 public unsafe static BasicBlockRef InsertBasicBlockInContext(ContextRef C, BasicBlockRef BB, string Name) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.InsertBasicBlockInContext(C.Value, BB.Value, Name));
   return ret;
 }
示例#30
0
 public unsafe static BasicBlockRef GetInsertBlock(BuilderRef Builder) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetInsertBlock(Builder.Value));
   return ret;
 }
示例#31
0
 public unsafe static BasicBlockRef InsertBasicBlock(BasicBlockRef InsertBeforeBB, string Name) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.InsertBasicBlock(InsertBeforeBB.Value, Name));
   return ret;
 }
示例#32
0
 public unsafe static ValueRef BuildCondBr(BuilderRef arg0, ValueRef If, BasicBlockRef Then, BasicBlockRef Else) {
   ValueRef ret = new ValueRef(LLVMPINVOKE.BuildCondBr(arg0.Value, If.Value, Then.Value, Else.Value));
   return ret;
 }
示例#33
0
 public unsafe static void DeleteBasicBlock(BasicBlockRef BB) {
   LLVMPINVOKE.DeleteBasicBlock(BB.Value);
 }
示例#34
0
 public unsafe static ValueRef BuildInvoke(BuilderRef arg0, ValueRef Fn, ValueRef[] Args, BasicBlockRef Then, BasicBlockRef Catch, string Name) {
   fixed (ValueRef* swig_ptrTo_Args = Args)
   {
     ValueRef ret = new ValueRef(LLVMPINVOKE.BuildInvoke(arg0.Value, Fn.Value, (System.IntPtr)swig_ptrTo_Args, (uint)Args.Length, Then.Value, Catch.Value, Name));
     return ret;
   }
 }
示例#35
0
 public unsafe static void RemoveBasicBlockFromParent(BasicBlockRef BB) {
   LLVMPINVOKE.RemoveBasicBlockFromParent(BB.Value);
 }
示例#36
0
 public unsafe static void AddDestination(ValueRef IndirectBr, BasicBlockRef Dest) {
   LLVMPINVOKE.AddDestination(IndirectBr.Value, Dest.Value);
 }
示例#37
0
 public unsafe static void MoveBasicBlockAfter(BasicBlockRef BB, BasicBlockRef MovePos) {
   LLVMPINVOKE.MoveBasicBlockAfter(BB.Value, MovePos.Value);
 }
示例#38
0
        /// <summary>
        /// Compiles the given method definition.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="function">The function.</param>
        /// <exception cref="System.NotSupportedException"></exception>
        /// <exception cref="System.NotImplementedException"></exception>
        /// <exception cref="System.InvalidOperationException">Backward jump with a non-empty stack unknown target.</exception>
        private void CompileFunction(MethodReference methodReference, Function function)
        {
            var method = methodReference.Resolve();

            var body = method.Body;
            var codeSize = body != null ? body.CodeSize : 0;
            var functionGlobal = function.GeneratedValue;

            var functionContext = new FunctionCompilerContext(function);
            functionContext.BasicBlock = LLVM.AppendBasicBlockInContext(context, functionGlobal, string.Empty);
            LLVM.PositionBuilderAtEnd(builder, functionContext.BasicBlock);

            if (body == null && (method.ImplAttributes & MethodImplAttributes.Runtime) != 0)
            {
                var declaringClass = GetClass(function.DeclaringType);

                // Generate IL for various methods
                if (declaringClass.BaseType != null &&
                    declaringClass.BaseType.Type.TypeReference.FullName == typeof(MulticastDelegate).FullName)
                {
                    body = GenerateDelegateMethod(method, declaringClass);
                    if (body == null)
                        return;

                    codeSize = UpdateOffsets(body);
                }
            }

            if (body == null)
                return;

            var numParams = method.Parameters.Count;

            // Create stack, locals and args
            var stack = new List<StackValue>(body.MaxStackSize);
            var locals = new List<StackValue>(body.Variables.Count);
            var args = new List<StackValue>(numParams);
            var exceptionHandlers = new List<ExceptionHandlerInfo>();
            var activeTryHandlers = new List<ExceptionHandlerInfo>();

            functionContext.Stack = stack;
            functionContext.Locals = locals;
            functionContext.Arguments = args;
            functionContext.ExceptionHandlers = exceptionHandlers;
            functionContext.ActiveTryHandlers = activeTryHandlers;

            // Process locals
            foreach (var local in body.Variables)
            {
                // TODO: Anything to do on pinned objects?
                //if (local.IsPinned)
                //    throw new NotSupportedException();

                var type = CreateType(ResolveGenericsVisitor.Process(methodReference, local.VariableType));
                locals.Add(new StackValue(type.StackType, type, LLVM.BuildAlloca(builder, type.DefaultType, local.Name)));
            }

            // Process args
            for (int index = 0; index < function.ParameterTypes.Length; index++)
            {
                var argType = function.ParameterTypes[index];
                var arg = LLVM.GetParam(functionGlobal, (uint)index);

                // Copy argument on stack
                var storage = LLVM.BuildAlloca(builder, argType.DefaultType, "arg" + index.ToString());
                LLVM.BuildStore(builder, arg, storage);

                args.Add(new StackValue(argType.StackType, argType, storage));
            }

            // Some wasted space due to unused offsets, but we only keep one so it should be fine.
            // TODO: Reuse same allocated instance per thread, and grow it only if necessary
            var branchTargets = new bool[codeSize];
            var basicBlocks = new BasicBlockRef[codeSize];
            var forwardStacks = new StackValue[codeSize][];

            functionContext.BasicBlocks = basicBlocks;
            functionContext.ForwardStacks = forwardStacks;

            // Find branch targets (which will require PHI node for stack merging)
            for (int index = 0; index < body.Instructions.Count; index++)
            {
                var instruction = body.Instructions[index];

                var flowControl = instruction.OpCode.FlowControl;

                // Process branch targets
                if (flowControl == FlowControl.Cond_Branch
                    || flowControl == FlowControl.Branch)
                {
                    var targets = instruction.Operand is Instruction[] ? (Instruction[])instruction.Operand : new[] { (Instruction)instruction.Operand };

                    foreach (var target in targets)
                    {
                        // Operand Target can be reached
                        branchTargets[target.Offset] = true;
                    }
                }

                // Need to enforce a block to be created for the next instruction after a conditional branch
                // TODO: Break?
                if (flowControl == FlowControl.Cond_Branch)
                {
                    if (instruction.Next != null)
                        branchTargets[instruction.Next.Offset] = true;
                }
            }

            // Setup exception handling
            if (body.HasExceptionHandlers)
            {
                // Add an "ehselector.slot" i32 local, and a "exn.slot" Object reference local
                functionContext.ExceptionHandlerSelectorSlot = LLVM.BuildAlloca(builder, int32Type, "ehselector.slot");
                functionContext.ExceptionSlot = LLVM.BuildAlloca(builder, @object.DefaultType, "exn.slot");
                functionContext.EndfinallyJumpTarget = LLVM.BuildAlloca(builder, int32Type, "endfinally.jumptarget");

                // Create resume exception block
                functionContext.ResumeExceptionBlock = LLVM.AppendBasicBlockInContext(context, functionGlobal, "eh.resume");
                LLVM.PositionBuilderAtEnd(builder2, functionContext.ResumeExceptionBlock);
                var exceptionObject = LLVM.BuildLoad(builder2, functionContext.ExceptionSlot, "exn");
                var ehselectorValue = LLVM.BuildLoad(builder2, functionContext.ExceptionHandlerSelectorSlot, "sel");

                exceptionObject = LLVM.BuildPointerCast(builder2, exceptionObject, intPtrType, "exn");
                var landingPadValue = LLVM.BuildInsertValue(builder2, LLVM.GetUndef(caughtResultType), exceptionObject, 0, "lpad.val");
                landingPadValue = LLVM.BuildInsertValue(builder2, landingPadValue, ehselectorValue, 1, "lpad.val");

                LLVM.BuildResume(builder2, landingPadValue);

                // Exception handlers blocks are also branch targets
                foreach (var exceptionHandler in body.ExceptionHandlers)
                {
                    branchTargets[exceptionHandler.HandlerStart.Offset] = true;
                }
            }

            // Create basic block
            // TODO: Could be done during previous pass
            for (int offset = 0; offset < branchTargets.Length; offset++)
            {
                // Create a basic block if this was a branch target or an instruction after a conditional branch
                if (branchTargets[offset])
                {
                    basicBlocks[offset] = LLVM.AppendBasicBlockInContext(context, functionGlobal, string.Format("L_{0:x4}", offset));
                }
            }

            // Create catch clause stack
            if (body.HasExceptionHandlers)
            {
                // Exception handlers blocks are also branch targets
                foreach (var exceptionHandler in body.ExceptionHandlers)
                {
                    exceptionHandlers.Add(new ExceptionHandlerInfo(exceptionHandler));

                    if (exceptionHandler.HandlerType != ExceptionHandlerType.Catch)
                        continue;

                    var handlerStart = exceptionHandler.HandlerStart.Offset;

                    var catchBlock = basicBlocks[handlerStart];
                    var catchClass = GetClass(ResolveGenericsVisitor.Process(methodReference, exceptionHandler.CatchType));

                    // Extract exception
                    LLVM.PositionBuilderAtEnd(builder2, catchBlock);
                    var exceptionObject = LLVM.BuildLoad(builder2, functionContext.ExceptionSlot, string.Empty);
                    exceptionObject = LLVM.BuildPointerCast(builder2, exceptionObject, catchClass.Type.DefaultType, string.Empty);

                    // Erase exception from exn.slot (it has been handled)
                    LLVM.BuildStore(builder2, LLVM.ConstNull(@object.DefaultType), functionContext.ExceptionSlot);
                    LLVM.BuildStore(builder2, LLVM.ConstInt(int32Type, 0, false), functionContext.ExceptionHandlerSelectorSlot);
                     
                    forwardStacks[handlerStart] = new[]
                    {
                        new StackValue(catchClass.Type.StackType, catchClass.Type, exceptionObject)
                    };
                }
            }

            foreach (var instruction in body.Instructions)
            {
                try
                {
                    // Check if any exception handlers might have changed
                    if (body.HasExceptionHandlers)
                        UpdateExceptionHandlers(functionContext, instruction);

                    if (branchTargets[instruction.Offset])
                        UpdateBranching(functionContext, instruction);

                    // Reset states
                    functionContext.FlowingNextInstructionMode = FlowingNextInstructionMode.Implicit;

                    EmitInstruction(functionContext, instruction);

                    // If we do a jump, let's merge stack
                    var flowControl = instruction.OpCode.FlowControl;
                    if (flowControl == FlowControl.Cond_Branch
                        || flowControl == FlowControl.Branch)
                        MergeStacks(functionContext, instruction);
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException(string.Format("Error while processing instruction {0} of method {1}", instruction, methodReference), e);
                }
            }
        }
示例#39
0
 public unsafe static BasicBlockRef GetInstructionParent(ValueRef Inst) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetInstructionParent(Inst.Value));
   return ret;
 }
示例#40
0
        /// <summary>
        /// Merges the stack.
        /// </summary>
        /// <param name="sourceStack">The source stack.</param>
        /// <param name="sourceBasicBlock">The source basic block.</param>
        /// <param name="targetStack">The target stack.</param>
        /// <param name="targetBasicBlock">The target basic block.</param>
        private void MergeStack(List<StackValue> sourceStack, BasicBlockRef sourceBasicBlock, ref StackValue[] targetStack, BasicBlockRef targetBasicBlock)
        {
            // First time? Need to create stack and position builder
            if (targetStack == null)
            {
                targetStack = new StackValue[sourceStack.Count];
                if (LLVM.GetLastInstruction(targetBasicBlock).Value != IntPtr.Zero && sourceStack.Count != 0)
                    throw new InvalidOperationException("Target basic block should have no instruction yet, or stack should be empty.");
            }

            for (int index = 0; index < sourceStack.Count; index++)
            {
                var stackValue = sourceStack[index];

                var mergedStackValue = targetStack[index];

                // First time? Need to create PHI node
                if (mergedStackValue == null)
                {
                    // TODO: Check stack type during merging?
                    LLVM.PositionBuilderAtEnd(builder2, targetBasicBlock);
                    mergedStackValue = new StackValue(stackValue.StackType, stackValue.Type, LLVM.BuildPhi(builder2, LLVM.TypeOf(stackValue.Value), string.Empty));
                    targetStack[index] = mergedStackValue;
                }

                // Convert type (if necessary)
                // TOOD: Reuse common code with cast/conversion code
                var value = stackValue.Value;
                if (LLVM.TypeOf(value) != LLVM.TypeOf(mergedStackValue.Value) && LLVM.GetTypeKind(LLVM.TypeOf(mergedStackValue.Value)) == TypeKind.PointerTypeKind)
                {
                    // Position before last instruction (which should be a branching instruction)
                    LLVM.PositionBuilderBefore(builder2, LLVM.GetLastInstruction(sourceBasicBlock));
                    value = LLVM.BuildPointerCast(builder2, value, LLVM.TypeOf(mergedStackValue.Value), string.Empty);
                }

                // Add values from previous stack value
                LLVM.AddIncoming(mergedStackValue.Value, new[] { value }, new[] { sourceBasicBlock });
            }
        }
示例#41
0
 public unsafe static BasicBlockRef GetSuccessor(ValueRef Term, uint i) {
   BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetSuccessor(Term.Value, i));
   return ret;
 }
示例#42
0
 public unsafe static ValueRef GetLastInstruction(BasicBlockRef BB) {
   ValueRef ret = new ValueRef(LLVMPINVOKE.GetLastInstruction(BB.Value));
   return ret;
 }
示例#43
0
        /// <summary>
        /// Update stack with phi nodes.
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <param name="srcStack">The source stack.</param>
        /// <param name="oldBlock">The old block.</param>
        /// <param name="newBlock">The new block.</param>
        /// <param name="refers">The amount of references to the new block.</param>
        public void Update(BuilderRef builder, ILStack srcStack, BasicBlockRef oldBlock, BasicBlockRef newBlock, int refers)
        {
            // If there's only one reference to this branch, there's only one way to get here.
            // That means the stack elements only depend on one other branch, therefor we don't need to build phi nodes.
            if (refers == 1)
            {
                for (int i = 0; i < srcStack.Count; i++)
                {
                    Push(new StackElement(srcStack[i]));
                }
            }
            // Multiple references.
            else
            {
                // We got three possible cases here:
                // 1. #deststack = #srcstack => build phi nodes for every element.
                // 2. #deststack > #srcstack => build phi nodes for the top elements of the srcstack.
                // 3. #deststack < #srcstack => build phi nodes for the top elements and put the rest on the stack as independent values.

                int dstOffset  = Count - 1;
                int difference = 0;

                // Case 3.
                if (Count < srcStack.Count)
                {
                    difference = srcStack.Count - Count;

                    // Push independent values on the stack start.
                    for (int i = difference - 1; i >= 0; i--)
                    {
                        InsertAtStart(srcStack[i]);
                        oldBlocks.Insert(0, oldBlock);
                    }
                }

                difference += srcStack.GetDependentCount();

                for (int i = srcStack.Count - 1; i >= difference; i--)
                {
                    // Not a phi node yet. Transform to a phi node.
                    if (mPhi[dstOffset] == 0)
                    {
                        StackElement element  = mStack[dstOffset];
                        ValueRef     oldValue = element.Value;

                        LLVM.PositionBuilderAtEnd(builder, newBlock);
                        element.Value = LLVM.BuildPhi(builder, element.Type, "phi");
                        LLVM.PositionBuilderAtEnd(builder, oldBlock);
                        LLVM.AddIncoming(element.Value, new ValueRef[] { oldValue }, new BasicBlockRef[] { oldBlocks[i] });
                    }

                    ValueRef phi = mStack[dstOffset].Value;

                    // We might need to cast the incoming value to the phi type.
                    // This is because it is possible that an integer type of a smaller type is pushed on the stack.
                    // by IL, for example in "branch on condition".
                    TypeRef  phiType       = LLVM.TypeOf(phi);
                    ValueRef incomingValue = srcStack[i].Value;

                    // Cast if not the same type.
                    if (srcStack[i].Type != phiType)
                    {
                        CastHelper.HelpIntAndPtrCast(builder, ref incomingValue, ref srcStack[i].Type, phiType, "phicast");
                    }

                    // Add new incoming from source stack.
                    LLVM.AddIncoming(phi, new ValueRef[] { incomingValue }, new BasicBlockRef[] { oldBlock });

                    mPhi[dstOffset]++;
                    dstOffset--;
                }
            }
        }