/// <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); }
/// <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); }
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); }
/// <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); }
/// <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(); } }
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); }
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; }
public unsafe static ValueRef BuildBr(BuilderRef arg0, BasicBlockRef Dest) { ValueRef ret = new ValueRef(LLVMPINVOKE.BuildBr(arg0.Value, Dest.Value)); return ret; }
public unsafe static void PositionBuilderAtEnd(BuilderRef Builder, BasicBlockRef Block) { LLVMPINVOKE.PositionBuilderAtEnd(Builder.Value, Block.Value); }
public unsafe static BasicBlockRef GetIncomingBlock(ValueRef PhiNode, uint Index) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetIncomingBlock(PhiNode.Value, Index)); return ret; }
public unsafe static BasicBlockRef GetSwitchDefaultDest(ValueRef SwitchInstr) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetSwitchDefaultDest(SwitchInstr.Value)); return ret; }
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]); }
private void EmitBrtrue(List <StackValue> stack, BasicBlockRef targetBasicBlock, BasicBlockRef nextBasicBlock) { // Stack element should be different from zero. EmitBrCommon(stack.Pop(), IntPredicate.IntNE, targetBasicBlock, nextBasicBlock); }
private void EmitBrfalse(List <StackValue> stack, BasicBlockRef targetBasicBlock, BasicBlockRef nextBasicBlock) { // Stack element should be equal to zero. EmitBrCommon(stack.Pop(), IntPredicate.IntEQ, targetBasicBlock, nextBasicBlock); }
private void EmitBr(BasicBlockRef targetBasicBlock) { // Unconditional branch LLVM.BuildBr(builder, targetBasicBlock); }
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(); } }
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); }
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); }
public unsafe static void AddCase(ValueRef Switch, ValueRef OnVal, BasicBlockRef Dest) { LLVMPINVOKE.AddCase(Switch.Value, OnVal.Value, Dest.Value); }
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; }
public unsafe static BasicBlockRef GetPreviousBasicBlock(BasicBlockRef BB) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetPreviousBasicBlock(BB.Value)); return ret; }
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(); } } }
public unsafe static BasicBlockRef GetEntryBasicBlock(ValueRef Fn) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetEntryBasicBlock(Fn.Value)); return ret; }
public unsafe static void SetSuccessor(ValueRef Term, uint i, BasicBlockRef block) { LLVMPINVOKE.SetSuccessor(Term.Value, i, block.Value); }
public unsafe static BasicBlockRef AppendBasicBlockInContext(ContextRef C, ValueRef Fn, string Name) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.AppendBasicBlockInContext(C.Value, Fn.Value, Name)); return ret; }
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); } }
public unsafe static BasicBlockRef AppendBasicBlock(ValueRef Fn, string Name) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.AppendBasicBlock(Fn.Value, Name)); return ret; }
public unsafe static void PositionBuilder(BuilderRef Builder, BasicBlockRef Block, ValueRef Instr) { LLVMPINVOKE.PositionBuilder(Builder.Value, Block.Value, Instr.Value); }
public unsafe static BasicBlockRef InsertBasicBlockInContext(ContextRef C, BasicBlockRef BB, string Name) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.InsertBasicBlockInContext(C.Value, BB.Value, Name)); return ret; }
public unsafe static BasicBlockRef GetInsertBlock(BuilderRef Builder) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetInsertBlock(Builder.Value)); return ret; }
public unsafe static BasicBlockRef InsertBasicBlock(BasicBlockRef InsertBeforeBB, string Name) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.InsertBasicBlock(InsertBeforeBB.Value, Name)); return ret; }
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; }
public unsafe static void DeleteBasicBlock(BasicBlockRef BB) { LLVMPINVOKE.DeleteBasicBlock(BB.Value); }
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; } }
public unsafe static void RemoveBasicBlockFromParent(BasicBlockRef BB) { LLVMPINVOKE.RemoveBasicBlockFromParent(BB.Value); }
public unsafe static void AddDestination(ValueRef IndirectBr, BasicBlockRef Dest) { LLVMPINVOKE.AddDestination(IndirectBr.Value, Dest.Value); }
public unsafe static void MoveBasicBlockAfter(BasicBlockRef BB, BasicBlockRef MovePos) { LLVMPINVOKE.MoveBasicBlockAfter(BB.Value, MovePos.Value); }
/// <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); } } }
public unsafe static BasicBlockRef GetInstructionParent(ValueRef Inst) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetInstructionParent(Inst.Value)); return ret; }
/// <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 }); } }
public unsafe static BasicBlockRef GetSuccessor(ValueRef Term, uint i) { BasicBlockRef ret = new BasicBlockRef(LLVMPINVOKE.GetSuccessor(Term.Value, i)); return ret; }
public unsafe static ValueRef GetLastInstruction(BasicBlockRef BB) { ValueRef ret = new ValueRef(LLVMPINVOKE.GetLastInstruction(BB.Value)); return ret; }
/// <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--; } } }