protected override ExprAST VisitPrototypeAST(PrototypeAST node) { // Make the function type: double(double,double) etc. var argumentCount = (uint)node.Arguments.Count; var arguments = new LLVMTypeRef[Math.Max(argumentCount, 1)]; var function = LLVM.GetNamedFunction(this.module, node.Name); // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (function.Pointer != IntPtr.Zero) { // If F already has a body, reject this. if (LLVM.CountBasicBlocks(function) != 0) { throw new Exception("redefinition of function."); } // If F took a different number of args, reject. if (LLVM.CountParams(function) != argumentCount) { throw new Exception("redefinition of function with different # args"); } } else { for (int i = 0; i < argumentCount; ++i) { arguments[i] = LLVM.DoubleType(); } function = LLVM.AddFunction(this.module, node.Name, LLVM.FunctionType(LLVM.DoubleType(), arguments, LLVMBoolFalse)); LLVM.SetLinkage(function, LLVMLinkage.LLVMExternalLinkage); } for (int i = 0; i < argumentCount; ++i) { var argumentName = node.Arguments[i]; LLVMValueRef param = LLVM.GetParam(function, (uint)i); LLVM.SetValueName(param, argumentName); this.namedValues[argumentName] = param; } this.valueStack.Push(function); return(node); }
private void EmitNativeMain() { LLVMValueRef shadowStackTop = LLVM.GetNamedGlobal(Module, "t_pShadowStackTop"); LLVMBuilderRef builder = LLVM.CreateBuilder(); var mainSignature = LLVM.FunctionType(LLVM.Int32Type(), new LLVMTypeRef[] { LLVM.Int32Type(), LLVM.PointerType(LLVM.Int8Type(), 0) }, false); var mainFunc = LLVM.AddFunction(Module, "__managed__Main", mainSignature); var mainEntryBlock = LLVM.AppendBasicBlock(mainFunc, "entry"); LLVM.PositionBuilderAtEnd(builder, mainEntryBlock); LLVMValueRef managedMain = LLVM.GetNamedFunction(Module, "StartupCodeMain"); if (managedMain.Pointer == IntPtr.Zero) { throw new Exception("Main not found"); } LLVMTypeRef reversePInvokeFrameType = LLVM.StructType(new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.PointerType(LLVM.Int8Type(), 0) }, false); LLVMValueRef reversePinvokeFrame = LLVM.BuildAlloca(builder, reversePInvokeFrameType, "ReversePInvokeFrame"); LLVMValueRef RhpReversePInvoke2 = LLVM.GetNamedFunction(Module, "RhpReversePInvoke2"); if (RhpReversePInvoke2.Pointer == IntPtr.Zero) { RhpReversePInvoke2 = LLVM.AddFunction(Module, "RhpReversePInvoke2", LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(reversePInvokeFrameType, 0) }, false)); } LLVM.BuildCall(builder, RhpReversePInvoke2, new LLVMValueRef[] { reversePinvokeFrame }, ""); var shadowStack = LLVM.BuildMalloc(builder, LLVM.ArrayType(LLVM.Int8Type(), 1000000), String.Empty); var castShadowStack = LLVM.BuildPointerCast(builder, shadowStack, LLVM.PointerType(LLVM.Int8Type(), 0), String.Empty); LLVM.BuildStore(builder, castShadowStack, shadowStackTop); // Pass on main arguments LLVMValueRef argc = LLVM.GetParam(mainFunc, 0); LLVMValueRef argv = LLVM.GetParam(mainFunc, 1); LLVMValueRef mainReturn = LLVM.BuildCall(builder, managedMain, new LLVMValueRef[] { castShadowStack, argc, argv, }, "returnValue"); LLVM.BuildRet(builder, mainReturn); LLVM.SetLinkage(mainFunc, LLVMLinkage.LLVMExternalLinkage); }
private static LLVMValueRef ReadSReg(string name, IRBuilder builder, LLVMModuleRef module) { var fName = "llvm.nvvm.read.ptx.sreg." + name; var fun = LLVM.GetNamedFunction(module, name); if (fun.Pointer == IntPtr.Zero) { fun = LLVM.AddFunction( module, fName, LLVM.FunctionType( LLVM.Int32TypeInContext(LLVM.GetModuleContext(module)), EmptyArray <LLVMTypeRef> .Value, false)); } return(builder.CreateCall(fun, EmptyArray <LLVMValueRef> .Value, "")); }
/// <summary> /// Creates the declaration for a method. /// </summary> /// <param name="methodDef">The method definition.</param> public void CreateDeclaration(MethodDefinition methodDef) { string methodName = NameHelper.CreateMethodName(methodDef); int paramCount = methodDef.Parameters.Count; // CIL runtime method? if (methodDef.IsRuntime && !mRuntimeCompiler.MustHandleMethod(methodDef)) { return; } // If we expect an instance reference as first argument, then we need to make sure our for loop has an offset. int offset = 0; if (methodDef.HasThis) { paramCount++; offset = 1; } // Fill in arguments. TypeRef[] argTypes = new TypeRef[paramCount]; for (int i = offset; i < paramCount; i++) { TypeReference type = methodDef.Parameters[i - offset].ParameterType; argTypes[i] = TypeHelper.GetTypeRefFromType(type); } // If needed, fill in the instance reference. if (methodDef.HasThis) { argTypes[0] = TypeHelper.GetTypeRefFromType(methodDef.DeclaringType); // We need to pass the valuetype as a pointer because we need to modify its contents in the constructor. if (methodDef.DeclaringType.IsValueType) { argTypes[0] = LLVM.PointerType(argTypes[0], 0); } } // Create LLVM function type and add function to the lookup table. TypeRef functionType = LLVM.FunctionType(TypeHelper.GetTypeRefFromType(methodDef.ReturnType), argTypes, false); ValueRef function = LLVM.AddFunction(mCompiler.Module, methodName, functionType); mCompiler.Lookup.AddFunction(methodName, function); }
/// <summary> /// Compiles the init cctors method. /// </summary> private void compileInitCctorsMethod() { TypeRef type = LLVM.FunctionType(TypeHelper.Void, new TypeRef[0], false); ValueRef func = LLVM.AddFunction(Module, "initCctors", type); BuilderRef builder = LLVM.CreateBuilderInContext(ModuleContext); LLVM.PositionBuilderAtEnd(builder, LLVM.AppendBasicBlockInContext(ModuleContext, func, string.Empty)); MethodDefinition[] cctors = Lookup.GetStaticConstructors(); foreach (MethodDefinition method in cctors) { LLVM.BuildCall(builder, Lookup.GetFunction(NameHelper.CreateMethodName(method)).Value, new ValueRef[0], string.Empty); } LLVM.BuildRetVoid(builder); LLVM.DisposeBuilder(builder); }
public IMethodRegister CreateMethod(string className, bool isStatic, ClepsType functionType, string functionName) { string fullFunctionName = className + "." + functionName; FunctionClepsType functionClepsType = functionType as FunctionClepsType; LLVMTypeRef returnLLVMType = GetLLVMType(functionClepsType.ReturnType); LLVMTypeRef[] parameterLLVMTypes = functionClepsType.ParameterTypes.Select(c => GetLLVMType(c)).ToArray(); LLVMTypeRef functionLLVMType = LLVM.FunctionType(returnLLVMType, parameterLLVMTypes, false /* var args */); LLVMValueRef functionRef = LLVM.AddFunction(Module, fullFunctionName, functionLLVMType); LLVMBasicBlockRef block = LLVM.AppendBasicBlockInContext(Context, functionRef, "entry"); LLVM.PositionBuilderAtEnd(Builder, block); var ret = new LLVMMethod(block); return(ret); }
public void FunctionPrototype(Stmt.FunctionDeclaration func) { uint argc = (uint)func.Parameters.Count; var argv = new LLVMTypeRef[argc]; var function = LLVM.GetNamedFunction(_module, func.Identifier.Source); if (function.Pointer != IntPtr.Zero) { if (LLVM.CountBasicBlocks(function) != 0) { throw new Exception("redefinition of function."); } if (LLVM.CountParams(function) != argc) { throw new Exception("redefinition of function with different # args"); } } else { for (int i = 0; i < argc; i++) { argv[i] = GetParameterType(func.Parameters[i].Type); } function = LLVM.AddFunction(_module, func.Identifier.Source, LLVM.FunctionType(GetParameterType(func.ReturnType), argv, false)); LLVM.SetLinkage(function, LLVMLinkage.LLVMExternalLinkage); } for (int i = 0; i < argc; i++) { string argName = func.Parameters[i].Identifier; LLVMValueRef param = LLVM.GetParam(function, (uint)i); LLVM.SetValueName(param, argName); //_namedValues[argName] = new LLVMSymbol { Binding = null, IsFunction = false, KtsType = stmt.Parameters[i].Type, Value = param }; } _functions.Add(func.Identifier.Source, new FunctionSymbol { ReturnType = func.ReturnType, Parameters = func.Parameters }); }
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); }
private void ImportRawPInvoke(MethodDesc method) { LLVMValueRef nativeFunc = LLVM.GetNamedFunction(Module, method.Name); // Create an import if we haven't already if (nativeFunc.Pointer == IntPtr.Zero) { // Set up native parameter types LLVMTypeRef[] paramTypes = new LLVMTypeRef[method.Signature.Length]; for (int i = 0; i < paramTypes.Length; i++) { paramTypes[i] = GetLLVMTypeForTypeDesc(method.Signature[i]); } // Define the full signature LLVMTypeRef nativeFuncType = LLVM.FunctionType(GetLLVMTypeForTypeDesc(method.Signature.ReturnType), paramTypes, LLVMMisc.False); nativeFunc = LLVM.AddFunction(Module, method.Name, nativeFuncType); LLVM.SetLinkage(nativeFunc, LLVMLinkage.LLVMDLLImportLinkage); } LLVMValueRef[] arguments = new LLVMValueRef[method.Signature.Length]; for (int i = 0; i < arguments.Length; i++) { LLVMValueRef argValue = _stack.Pop().LLVMValue; // Arguments are reversed on the stack // Coerce pointers to the native type TypeDesc signatureType = method.Signature[arguments.Length - i - 1]; LLVMValueRef typedValue = argValue; if (signatureType.IsPointer) { LLVMTypeRef signatureLlvmType = GetLLVMTypeForTypeDesc(signatureType); typedValue = LLVM.BuildPointerCast(_builder, argValue, signatureLlvmType, String.Empty); } arguments[arguments.Length - i - 1] = typedValue; } var returnValue = LLVM.BuildCall(_builder, nativeFunc, arguments, "call"); // TODO: void returns PushExpression(GetStackValueKind(method.Signature.ReturnType), String.Empty, returnValue, method.Signature.ReturnType); }
// Init is the rule that defines our entire program. public VisitResult VisitInit([Antlr4.Runtime.Misc.NotNull] BFParser.InitContext context) { // Create our builder. builder = LLVM.CreateBuilder(); // Define all the functions we need to make a BF program. This includes input, output, and memory management programs to get our initial block of memory. outputFunc = LLVM.AddFunction(mod, "putchar", LLVM.FunctionType(LLVM.Int32Type(), new LLVMTypeRef[] { LLVM.Int8Type() }, false)); inputFunc = LLVM.AddFunction(mod, "getchar", LLVM.FunctionType(LLVM.Int8Type(), new LLVMTypeRef[] {}, false)); var malloc = LLVM.AddFunction(mod, "malloc", LLVM.FunctionType(LLVM.PointerType(LLVM.Int32Type(), 0), new LLVMTypeRef[] { LLVM.Int32Type() }, false)); var memset = LLVM.AddFunction(mod, "memset", LLVM.FunctionType(LLVM.PointerType(LLVM.Int32Type(), 0), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int32Type(), 0), LLVM.Int32Type(), LLVM.Int32Type() }, false)); var free = LLVM.AddFunction(mod, "free", LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int32Type(), 0) }, false)); main = LLVM.AddFunction(mod, "main", LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] {}, false)); // Start the entry point. var entry = LLVM.AppendBasicBlock(main, "entry"); LLVM.PositionBuilderAtEnd(builder, entry); // Call malloc to get a void* (which is actually a int32*) that points to our program memory. We will just allocate a chunk to play with. basePtr = LLVM.BuildCall(builder, malloc, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), memSize, false) }, "basePtr"); // Set memory to 0 (otherwise BF would almost never work). LLVM.BuildCall(builder, memset, new LLVMValueRef[] { basePtr, LLVM.ConstInt(LLVM.Int32Type(), 0, true), LLVM.ConstInt(LLVM.Int32Type(), memSize, false) }, "callMemset"); // Due to how LLVM works, once creating pointer we wouldn't be able to use it again. To counter this, we create a pointer to our pointer. ptr = LLVM.BuildAlloca(builder, LLVM.PointerType(LLVM.Int8Type(), 0), "ptr"); // Cast our void* as a int8* and set our pointer value to it. SetValue(ptr, LLVM.BuildPointerCast(builder, basePtr, LLVM.PointerType(LLVM.Int8Type(), 0), "tempPtr")); // This is where we actually start adding our program instructions. for (int i = 0; i < context.ChildCount; i++) { context.GetChild(i).Accept(visitor); } // Free our malloc'd memory and return nothing. LLVM.BuildFree(builder, basePtr); LLVM.BuildRetVoid(builder); return(null); }
/// <summary> /// Initializes runtime functions. /// </summary> /// <param name="module">The module.</param> public static void ImportFunctions(ModuleRef module) { // Newarr. TypeRef newarrType = LLVM.FunctionType(TypeHelper.VoidPtr, new TypeRef[] { TypeHelper.Int32, TypeHelper.NativeIntType }, false); Newarr = LLVM.AddFunction(module, "newarr", newarrType); LLVM.SetLinkage(Newarr, Linkage.ExternalLinkage); // Memcpy. TypeRef memcpyType = LLVM.FunctionType(TypeHelper.VoidPtr, new TypeRef[] { TypeHelper.VoidPtr, TypeHelper.VoidPtr, TypeHelper.NativeIntType }, false); Memcpy = LLVM.AddFunction(module, "memcpy", memcpyType); LLVM.SetLinkage(Memcpy, Linkage.ExternalLinkage); // Memcpy. TypeRef memsetType = LLVM.FunctionType(TypeHelper.VoidPtr, new TypeRef[] { TypeHelper.VoidPtr, TypeHelper.Int32, TypeHelper.NativeIntType }, false); Memset = LLVM.AddFunction(module, "memset", memsetType); LLVM.SetLinkage(Memset, Linkage.ExternalLinkage); }
public LLVMValueRef Emit(LLVMModuleRef context) { // Ensure body was provided or created. if (Body == null) { throw new Exception("Unexpected function body to be null"); } // Ensure prototype is set. else if (Prototype == null) { throw new Exception("Unexpected function prototype to be null"); } // Emit the argument types. var args = Prototype.Args.Emit(); // Emit the return type LLVMTypeRef returnType = Prototype.ReturnType.Emit(); // Emit the function type. LLVMTypeRef type = LLVM.FunctionType(returnType, args, Prototype.Args.Continuous); // Create the function. LLVMValueRef function = LLVM.AddFunction(context, Prototype.Name, type); // Apply the body. Body.Emit(function); // Ensures the function does not already exist if (SymbolTable.functions.ContainsKey(Prototype.Name)) { throw new Exception($@"Function with that name ""{Prototype.Name}"" already exists."); } else { // Register the function in the symbol table. SymbolTable.functions.Add(Prototype.Name, function); } return(function); }
private void AddEntryPoint(ClassManager classManager, CompileStatus status, LLVMContextRef context, LLVMModuleRef module, LLVMBuilderRef builder) { LLVMTypeRef functionType = LLVM.FunctionType(LLVM.Int32TypeInContext(context), new LLVMTypeRef[] { }, false); LLVMValueRef functionValue = LLVM.AddFunction(module, "main", functionType); LLVMBasicBlockRef blockValue = LLVM.AppendBasicBlockInContext(context, functionValue, "entry"); LLVM.PositionBuilderAtEnd(builder, blockValue); LLVMValueRef intRet = LLVM.ConstInt(LLVM.Int32Type(), 0, false); if (classManager.MainFunctionFullNames.Count < 1) { status.AddError(new CompilerError("", 0, 0, "No main functions found in the program")); } else if (classManager.MainFunctionFullNames.Count > 1) { status.AddError(new CompilerError("", 0, 0, "Multiple main functions found in the program: " + String.Join(",", classManager.MainFunctionFullNames))); } else { LLVMValueRef functionToCall = LLVM.GetNamedFunction(module, classManager.MainFunctionFullNames.First()); LLVMValueRef intOrIntMappedTypeRet = LLVM.BuildCall(builder, functionToCall, new LLVMValueRef[0], "entryPointCall"); LLVMTypeRef returnType = LLVM.TypeOf(intOrIntMappedTypeRet); if (returnType.TypeKind == LLVMTypeKind.LLVMIntegerTypeKind && returnType.GetIntTypeWidth() == 32) { intRet = intOrIntMappedTypeRet; } else { LLVMValueRef intMappedTypeRetPtr = LLVM.BuildAlloca(builder, LLVM.TypeOf(intOrIntMappedTypeRet), "intMappedType"); LLVM.BuildStore(builder, intOrIntMappedTypeRet, intMappedTypeRetPtr); //Extract the first field to get the int value from the mapped type //See rawtypemap for more details LLVMValueRef fieldPtr = LLVM.BuildStructGEP(builder, intMappedTypeRetPtr, 0, "returnIntFieldPtr"); intRet = LLVM.BuildLoad(builder, fieldPtr, "returnValue"); } } LLVM.BuildRet(builder, intRet); }
public void Visit(AST.Module module) { moduleLLVM = LLVM.ModuleCreateWithName(module.Name); var triple = Marshal.PtrToStringAnsi(LLVM.GetDefaultTargetTriple()); LLVM.SetTarget(moduleLLVM, triple); builtIns = new BuiltInsLLVM(builder, moduleLLVM); mainFuncLLVM = LLVM.AddFunction(moduleLLVM, "main", LLVM.FunctionType(LLVM.Int32Type(), new LLVMTypeRef[] { }, false)); var varBlock = LLVM.AppendBasicBlock(mainFuncLLVM, "var"); var codeBlock = LLVM.AppendBasicBlock(mainFuncLLVM, "begin"); varBlocks.Push(varBlock); codeBlocks.Push(codeBlock); foreach (var statement in module.Statements) { statement.Accept(this); if (returns) { break; } } LLVM.PositionBuilderAtEnd(builder, varBlock); LLVM.BuildBr(builder, codeBlock); if (!returns) { LLVM.PositionBuilderAtEnd(builder, codeBlocks.Peek()); LLVM.BuildRet(builder, LLVM.ConstInt(LLVM.Int32Type(), 0, false)); } codeBlocks.Pop(); varBlocks.Pop(); LLVM.WriteBitcodeToFile(moduleLLVM, $"{module.Name}.bc"); LLVM.PrintModuleToFile(moduleLLVM, $"{module.Name}.ll", out var _); }
/// <summary> /// Declares a method. /// </summary> /// <param name="methodDef">The CIL method definition</param> /// <returns>The LLVM value reference</returns> public LLVMValueRef DeclareMethod(MethodDefinition methodDef) { int offset = methodDef.HasThis ? 1 : 0; var paramTypes = new LLVMTypeRef[methodDef.Parameters.Count + offset]; for (int i = 0; i < paramTypes.Length - offset; ++i) { paramTypes[i + offset] = typeLookup.GetLLVMTypeRef(methodDef.Parameters[i].ParameterType); } if (methodDef.HasThis) { paramTypes[0] = typeLookup.GetLLVMTypeRef(methodDef.DeclaringType); if (methodDef.DeclaringType.IsValueType) { paramTypes[0] = LLVM.PointerType(paramTypes[0], 0); } } var fnType = LLVM.FunctionType( typeLookup.GetLLVMTypeRef(methodDef.MethodReturnType.ReturnType), paramTypes, false ); var valueRef = LLVM.AddFunction(moduleRef, methodDef.FullName, fnType); methodMap.Add(methodDef.FullName, valueRef); if (methodDef.IsConstructor && methodDef.IsStatic) { LLVM.SetLinkage(valueRef, LLVMLinkage.LLVMInternalLinkage); LLVM.BuildCall(cctorCallBuilder, valueRef, new LLVMValueRef[0], string.Empty); } return(valueRef); }
private void createSystemObjectCtor() { var paramTypes = new LLVMTypeRef[] { LLVM.PointerType(LLVM.VoidType(), 0) }; var fnType = LLVM.FunctionType(LLVM.VoidType(), paramTypes, false); var valueRef = LLVM.AddFunction(moduleRef, string.Empty, fnType); // TODO: maybe put this somewhere else? // TODO: this is somewhat a workaround? /*var asmDef = AssemblyDefinition.ReadAssembly(typeof(object).Assembly.Location); * var sysObj = asmDef.MainModule.GetTypes().Where(typeDef => typeDef.FullName == "System.Object").Single(); * var methodDef = sysObj.Methods.Where(methodDef => methodDef.Name == ".ctor").Single(); * System.Console.WriteLine(methodDef); * methodMap.Add(methodDef., valueRef);*/ methodMap.Add("System.Void System.Object::.ctor()", valueRef); var builder = LLVM.CreateBuilder(); var block = LLVM.AppendBasicBlock(valueRef, string.Empty); LLVM.PositionBuilderAtEnd(builder, block); LLVM.BuildRetVoid(builder); LLVM.DisposeBuilder(builder); }
private void EmitNativeMain() { LLVMBuilderRef builder = LLVM.CreateBuilder(); var mainSignature = LLVM.FunctionType(LLVM.Int32Type(), new LLVMTypeRef[0], false); var mainFunc = LLVM.AddFunction(Module, "main", mainSignature); var mainEntryBlock = LLVM.AppendBasicBlock(mainFunc, "entry"); LLVM.PositionBuilderAtEnd(builder, mainEntryBlock); LLVMValueRef managedMain = LLVM.GetNamedFunction(Module, "Main"); var shadowStack = LLVM.BuildMalloc(builder, LLVM.ArrayType(LLVM.Int8Type(), 1000000), String.Empty); var castShadowStack = LLVM.BuildPointerCast(builder, shadowStack, LLVM.PointerType(LLVM.Int8Type(), 0), String.Empty); LLVM.BuildCall(builder, managedMain, new LLVMValueRef[] { castShadowStack, LLVM.ConstPointerNull(LLVM.PointerType(LLVM.Int8Type(), 0)) }, String.Empty); LLVM.BuildRet(builder, LLVM.ConstInt(LLVM.Int32Type(), 42, LLVMMisc.False)); LLVM.SetLinkage(mainFunc, LLVMLinkage.LLVMExternalLinkage); }
public LLVMValueRef Emit(LLVMModuleRef context) { // Ensure prototype is set. if (Prototype == null) { throw new Exception("Unexpected external definition's prototype to be null"); } // Emit the formal arguments. var args = Prototype.Args.Emit(); // Emit the return type. LLVMTypeRef returnType = Prototype.ReturnType.Emit(); // Emit the function type. LLVMTypeRef type = LLVM.FunctionType(returnType, args, Prototype.Args.Continuous); // Emit the external definition to context and capture the LLVM value reference. LLVMValueRef external = LLVM.AddFunction(context, Prototype.Name, type); // Return the resulting LLVM value reference. return(external); }
public LLVMValueRef Emit(PipeContext <Module> context) { // Ensure prototype is set. if (this.Prototype == null) { throw new Exception("Unexpected external definition's prototype to be null"); } // Emit the formal arguments. LLVMTypeRef[] args = this.Prototype.Args.Emit(context); // Emit the return type. LLVMTypeRef returnType = this.Prototype.ReturnType.Emit(); // Emit the function type. LLVMTypeRef type = LLVM.FunctionType(returnType, args, this.Prototype.Args.Continuous); // Emit the external definition to context and capture the LLVM value reference. LLVMValueRef external = LLVM.AddFunction(context.Target.Target, this.Prototype.Identifier, type); // Determine if should be registered on the symbol table. if (!context.SymbolTable.functions.Contains(this.Prototype.Identifier)) { // Register the external definition as a function in the symbol table. context.SymbolTable.functions.Add(new FunctionSymbol(this.Prototype.Identifier, external, this.Prototype.Args.Continuous)); } // Otherwise, issue a warning. else { // TODO System.Console.WriteLine($"Warning: Extern definition '{this.Prototype.Identifier}' being re-defined"); } // Return the resulting LLVM value reference. return(external); }
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(); } }
private static void declareCFunctions() { LLVMTypeRef PutCharType = LLVMTypeRef.FunctionType(LLVM.Int32Type(), new LLVMTypeRef[] { LLVM.Int32Type() }, false); LLVM.AddFunction(module, "putchar", PutCharType); }
private void VisitStmt(Statement stmt, out bool terminate) { terminate = false; if (stmt == null) { return; } LoadTypes(stmt.ScopeSymbols); switch (stmt) { case FunctionDeclarationStmt fd: { break; } case FunctionStmt f: { FunctionSymbol funcSym = f.Symbol; TypeSymbol returnSym = funcSym.Signature.Return.Symbol; LLVMTypeRef funcTy = LLVM.FunctionType( ReturnType: m_Types[returnSym], ParamTypes: funcSym.Signature.Arguments.Select(arg => m_Types[arg.Type.Symbol]).ToArray(), IsVarArg: false); m_Function = LLVM.AddFunction(m_Module, f.Declaration.Name, funcTy); m_FunctionPointers.Add(funcSym, m_Function); LLVMBasicBlockRef bb = LLVM.AppendBasicBlock(m_Function, "entry"); LLVM.PositionBuilderAtEnd(m_Builder, bb); int paramIndex = 0; foreach (var param in m_Function.GetParams()) { LLVMValueRef ptrArg = LLVM.BuildAlloca(m_Builder, LLVM.TypeOf(param), "arg"); LLVM.BuildStore(m_Builder, param, ptrArg); m_VariablePointers.Add(funcSym.Signature.Arguments[paramIndex].Symbol, ptrArg); paramIndex++; } VisitStmt(f.Body, out bool term); if (!term) { if (returnSym.IsPrimitive) { CPrimitiveType prim = returnSym.Primitive.Value; if (prim == CPrimitiveType.Void) { LLVM.BuildRetVoid(m_Builder); } else { LLVM.BuildRet(m_Builder, m_PrimitiveLookup[prim].Default.Value); } } else { throw new NotImplementedException(); } } break; } case BlockStmt block: { foreach (var childStmt in block.Statements) { VisitStmt(childStmt, out bool term); if (term) { terminate = true; break; } } break; } case VariableDeclarationStmt vd: { if (vd.Symbol.IsGlobal) { throw new NotImplementedException(); } else { LLVMValueRef ptr = LLVM.BuildAlloca(m_Builder, m_Types[vd.Type.Symbol], vd.Name); m_VariablePointers.Add(vd.Symbol, ptr); if (vd.Assignment != null) { LLVMValueRef value = VisitExpr(vd.Assignment); LLVM.BuildStore(m_Builder, value, ptr); } } break; } case IfStmt ifs: { LLVMValueRef i32 = VisitExpr(ifs.Condition); LLVMValueRef cond = I32ToCond(i32); LLVMBasicBlockRef bbTrue = LLVM.AppendBasicBlock(m_Function, "if_true"); LLVMBasicBlockRef bbFalse = LLVM.AppendBasicBlock(m_Function, "if_false"); LLVMBasicBlockRef bbSucc = LLVM.AppendBasicBlock(m_Function, "if_succ"); LLVM.BuildCondBr(m_Builder, cond, bbTrue, bbFalse); LLVM.PositionBuilderAtEnd(m_Builder, bbTrue); VisitStmt(ifs.True, out bool termTrue); if (!termTrue) { LLVM.BuildBr(m_Builder, bbSucc); } LLVM.PositionBuilderAtEnd(m_Builder, bbFalse); VisitStmt(ifs.False, out bool termFalse); if (!termFalse) { LLVM.BuildBr(m_Builder, bbSucc); } LLVM.PositionBuilderAtEnd(m_Builder, bbSucc); break; } case ReturnStmt ret: { if (ret.Value == null) { LLVM.BuildRetVoid(m_Builder); } else { LLVMValueRef value = VisitExpr(ret.Value); LLVM.BuildRet(m_Builder, value); } terminate = true; break; } case WhileStmt wh: { LLVMBasicBlockRef bbCond = LLVM.AppendBasicBlock(m_Function, "while_cond"); LLVMBasicBlockRef bbBody = LLVM.AppendBasicBlock(m_Function, "while_body"); LLVMBasicBlockRef bbSucc = LLVM.AppendBasicBlock(m_Function, "while_succ"); m_BreakableStatementSuccessor.Add(wh, bbSucc); LLVM.BuildBr(m_Builder, bbCond); LLVM.PositionBuilderAtEnd(m_Builder, bbCond); LLVMValueRef i32 = VisitExpr(wh.Condition); LLVMValueRef cond = I32ToCond(i32); LLVM.BuildCondBr(m_Builder, cond, bbBody, bbSucc); LLVM.PositionBuilderAtEnd(m_Builder, bbBody); VisitStmt(wh.Body, out bool term); if (!term) { LLVM.BuildBr(m_Builder, bbCond); } LLVM.PositionBuilderAtEnd(m_Builder, bbSucc); break; } case BreakStmt brk: { terminate = true; LLVM.BuildBr(m_Builder, m_BreakableStatementSuccessor[brk.Host]); break; } case ExpressionStmt exprStmt: { VisitExpr(exprStmt.Expression); break; } default: { throw new ArgumentException("Unrecognizable statement type."); } } }
public ModuleRef CompileAssembly(AssemblyDefinition assembly) { this.assembly = assembly; corlib = assembly.MainModule.Import(typeof(void)).Resolve().Module.Assembly; module = LLVM.ModuleCreateWithName(assembly.Name.Name); allocObjectFunction = RuntimeInline.Runtime.define_allocObject(module); context = LLVM.GetModuleContext(module); builder = LLVM.CreateBuilderInContext(context); intPtrType = LLVM.PointerType(LLVM.Int8TypeInContext(context), 0); int32Type = LLVM.Int32TypeInContext(context); int64Type = LLVM.Int64TypeInContext(context); intPtrSize = 4; // Or 8? nativeIntType = int32Type; // Or int64Type? builderPhi = LLVM.CreateBuilderInContext(context); intPtr = GetType(corlib.MainModule.GetType(typeof(IntPtr).FullName)); int32 = GetType(corlib.MainModule.GetType(typeof(int).FullName)); int64 = GetType(corlib.MainModule.GetType(typeof(long).FullName)); // struct IMTSlot { i8* functionPtr, i32 functionId, IMTEntry* nextEntry } imtEntryType = LLVM.StructCreateNamed(context, "IMTEntry"); LLVM.StructSetBody(imtEntryType, new[] { intPtrType, int32Type, LLVM.PointerType(imtEntryType, 0) }, false); // Process types foreach (var assemblyModule in assembly.Modules) { var typeReferences = assemblyModule.GetTypeReferences(); foreach (var type in typeReferences) { CreateType(type); } var memberReferences = assemblyModule.GetMemberReferences(); foreach (var member in memberReferences) { var method = member as MethodReference; if (member.DeclaringType.ContainsGenericParameter()) { continue; } CreateType(member.DeclaringType); if (method != null) { if (!method.HasGenericParameters) { CreateFunction(method); } } } foreach (var type in assemblyModule.Types) { if (!type.HasGenericParameters && type.FullName != typeof(void).FullName) { GetClass(type); } foreach (var nestedType in type.NestedTypes) { if (!nestedType.HasGenericParameters) { GetClass(nestedType); } } } } // Process methods foreach (var @class in classes) { CompileClassMethods(@class.Value); } // Generate code while (methodsToCompile.Count > 0) { var methodToCompile = methodsToCompile.Dequeue(); CompileFunction(methodToCompile.Key, methodToCompile.Value); } // Emit "main" which will call the assembly entry point (if any) Function entryPoint; if (assembly.EntryPoint != null && functions.TryGetValue(assembly.EntryPoint, out entryPoint)) { var mainFunctionType = LLVM.FunctionType(int32Type, new TypeRef[0], false); var mainFunction = LLVM.AddFunction(module, "main", mainFunctionType); LLVM.SetLinkage(mainFunction, Linkage.ExternalLinkage); LLVM.PositionBuilderAtEnd(builder, LLVM.AppendBasicBlockInContext(context, mainFunction, string.Empty)); var parameters = (entryPoint.ParameterTypes.Length > 0) ? new[] { LLVM.ConstPointerNull(entryPoint.ParameterTypes[0].DefaultType) } : new ValueRef[0]; LLVM.BuildCall(builder, entryPoint.GeneratedValue, parameters, string.Empty); LLVM.BuildRet(builder, LLVM.ConstInt(int32Type, 0, false)); } LLVM.DisposeBuilder(builder); // Verify module #if VERIFY_LLVM string message; if (LLVM.VerifyModule(module, VerifierFailureAction.PrintMessageAction, out message)) { throw new InvalidOperationException(message); } #endif return(module); }
public LLVMValueRef EmitMethodHeader(string pName, Syntax.MethodSyntax pMethod, out string pNewName) { //Get method return type LLVMTypeRef ret; if (pMethod.ReturnValues.Count == 0) { ret = LLVMTypeRef.VoidType(); } else if (pMethod.ReturnValues.Count == 1) { ret = SmallTypeCache.GetLLVMType(pMethod.Type, this); } else { LLVMTypeRef[] types = new LLVMTypeRef[pMethod.ReturnValues.Count]; for (int i = 0; i < types.Length; i++) { types[i] = SmallTypeCache.GetLLVMType(pMethod.ReturnValues[i].Type, this); } ret = LLVM.StructType(types, false); Cache.SetLLVMType(pMethod.Type.Name, ret); } //If we are emitting a struct method we need to add "self" as a parameter SmallType[] originalTypes = new SmallType[pMethod.Parameters.Count]; LLVMTypeRef[] parmTypes = null; int start = 0; if (CurrentStruct != null) { parmTypes = new LLVMTypeRef[pMethod.Parameters.Count + 1]; parmTypes[0] = LLVMTypeRef.PointerType(SmallTypeCache.GetLLVMType(CurrentStruct, this), 0); start = 1; } else { parmTypes = new LLVMTypeRef[pMethod.Parameters.Count]; } //Get parameter types for (int i = 0; i < pMethod.Parameters.Count; i++) { var parmType = pMethod.Parameters[i].Type; if (parmType.IsGenericParameter) { originalTypes[i] = TypeMappings[parmType.Name]; } else { originalTypes[i] = parmType; } //For calling external methods with strings, we only want to pass the character array if (pMethod.External && parmType == SmallTypeCache.String) { parmType = parmType.GetElementType(); } parmTypes[start + i] = SmallTypeCache.GetLLVMType(parmType, this); if (pMethod.Parameters[i].Type.IsStruct || pMethod.Parameters[i].Type.IsArray) { parmTypes[start + i] = LLVMTypeRef.PointerType(parmTypes[start + i], 0); } } var result = Cache.FindMethod(out MethodDefinition pDefinition, null, CurrentStruct, pName, originalTypes); Debug.Assert(result == Compiler.FindResult.Found); pNewName = pDefinition.MangledName; //Method header var func = LLVM.GetNamedFunction(CurrentModule, pNewName); if (func.Pointer == IntPtr.Zero) { func = LLVM.AddFunction(CurrentModule, pNewName, LLVM.FunctionType(ret, parmTypes, false)); LLVM.SetLinkage(func, LLVMLinkage.LLVMExternalLinkage); } if (pMethod.External) { //Create attribute so we can find it later when executing var attribute = LLVM.CreateStringAttribute(_context, "external", 8, pMethod.Annotation.Value, (uint)pMethod.Annotation.Value.Length); LLVM.AddAttributeAtIndex(func, LLVMAttributeIndex.LLVMAttributeFunctionIndex, attribute); } return(func); }
private unsafe static void Main(string[] args) { LLVMBool Success = new LLVMBool(0); LLVMModuleRef mod = LLVM.ModuleCreateWithName("LLVMSharpIntro"); LLVMTypeRef[] param_types = { LLVM.Int32Type(), LLVM.Int32Type() }; LLVMTypeRef ret_type = LLVM.FunctionType(LLVM.Int32Type(), param_types, false); LLVMValueRef sum = LLVM.AddFunction(mod, "sum", ret_type); LLVMBasicBlockRef entry = LLVM.AppendBasicBlock(sum, "entry"); LLVMBuilderRef builder = LLVM.CreateBuilder(); LLVM.PositionBuilderAtEnd(builder, entry); LLVMValueRef tmp = LLVM.BuildAdd(builder, LLVM.GetParam(sum, 0), LLVM.GetParam(sum, 1), "tmp"); LLVM.BuildRet(builder, tmp); LLVM.SetLinkage(sum, LLVMLinkage.LLVMExternalLinkage); LLVM.SetDLLStorageClass(sum, LLVMDLLStorageClass.LLVMDLLExportStorageClass); if (LLVM.VerifyModule(mod, LLVMVerifierFailureAction.LLVMPrintMessageAction, out var error) != Success) { Console.WriteLine($"Error: {error}"); } //LLVM.LinkInMCJIT(); LLVM.InitializeX86TargetMC(); LLVM.InitializeX86Target(); LLVM.InitializeX86TargetInfo(); LLVM.InitializeX86AsmParser(); LLVM.InitializeX86AsmPrinter(); /*LLVMMCJITCompilerOptions options = new LLVMMCJITCompilerOptions { NoFramePointerElim = 1 }; * LLVM.InitializeMCJITCompilerOptions(options); * if (LLVM.CreateMCJITCompilerForModule(out var engine, mod, options, out error) != Success) * { * Console.WriteLine($"Error: {error}"); * } * * var addMethod = (Add)Marshal.GetDelegateForFunctionPointer(LLVM.GetPointerToGlobal(engine, sum), 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);*/ var aa = LLVM.GetLinkage(sum); LLVM.DumpModule(mod); if (LLVM.GetTargetFromTriple("x86_64-pc-win32", out var target, out error) == Success) { var targetMachine = LLVM.CreateTargetMachine(target, "x86_64-pc-win32", "generic", "", LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault, LLVMRelocMode.LLVMRelocDefault, LLVMCodeModel.LLVMCodeModelDefault); var dl = LLVM.CreateTargetDataLayout(targetMachine); LLVM.SetModuleDataLayout(mod, dl); LLVM.SetTarget(mod, "x86_64-pc-win32"); byte[] buffer = System.Text.Encoding.Default.GetBytes("test.o\0"); fixed(byte *ptr = buffer) { LLVM.TargetMachineEmitToFile(targetMachine, mod, new IntPtr(ptr), LLVMCodeGenFileType.LLVMObjectFile, out error); } } }
private LLVMValueRef CreateLLVMFunction(string mangledName) { LLVMTypeRef universalSignature = LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.PointerType(LLVM.Int8Type(), 0) }, false); return(LLVM.AddFunction(Module, mangledName, universalSignature)); }
public PrototypeAST PrototypeASTVisit(PrototypeAST node) { var argumentCount = (uint)node.Args.Count; var arguments = new LLVMTypeRef[Math.Max(argumentCount, 1)]; var function = LLVM.GetNamedFunction(this.module, node.Name); if (function.Pointer != IntPtr.Zero) { if (LLVM.CountBasicBlocks(function) != 0) { throw new Exception("Redefinition Of Function"); } if (LLVM.CountParams(function) != argumentCount) { throw new Exception("Redefinition of function with diff args num."); } return(node); } else { for (int i = 0; i < argumentCount; i++) { switch (node.Args[i].Type) { case Type.Bool: arguments[i] = LLVM.Int8Type(); break; case Type.Double: arguments[i] = LLVM.DoubleType(); break; //Function Type Goes Here!! case Type.Integer: arguments[i] = LLVM.Int64Type(); break; case Type.Void: arguments[i] = LLVM.VoidType(); break; //String type as well //And the others. :) } } LLVMTypeRef ret = LLVM.VoidType(); switch (node.ReturnType) { case Type.Bool: ret = LLVM.Int8Type(); break; case Type.Double: ret = LLVM.DoubleType(); break; //Function Type Goes Here!! case Type.Integer: ret = LLVM.Int64Type(); break; case Type.Void: ret = LLVM.VoidType(); break; } function = LLVM.AddFunction(module, node.Name, LLVM.FunctionType(ret, arguments, LLVMBoolFalse)); LLVM.SetLinkage(function, LLVMLinkage.LLVMExternalLinkage); var funcEntry = LLVM.AppendBasicBlock(function, "entry"); LLVM.PositionBuilderAtEnd(this.builder, funcEntry); for (int i = 0; i < argumentCount; i++) { string argumentName = node.Args[i].Name; LLVMValueRef param = LLVM.GetParam(function, (uint)i); LLVM.SetValueName(param, argumentName); LLVMValueRef Alloca = CreateEntryBlockAlloca(function, arguments[i], argumentName); LLVM.BuildStore(builder, param, Alloca); this.namedValues[argumentName] = Alloca; } this.valueStack.Push(function); return(node); } }
private ValueRef GenerateMulticastInvokeThunk(Class declaringClass) { // Reuse same signature as Invoke var delegateType = corlib.MainModule.GetType(typeof(Delegate).FullName); var invokeMethod = declaringClass.Functions.Single(x => x.MethodReference.Name == "Invoke"); var invokeMethodHelper = LLVM.AddFunction(module, LLVM.GetValueName(invokeMethod.GeneratedValue) + "_MulticastHelper", invokeMethod.FunctionType); ApplyFunctionAttributes(invokeMethod.Signature, invokeMethodHelper); LLVM.SetLinkage(invokeMethodHelper, declaringClass.Type.Linkage); LLVM.PositionBuilderAtEnd(builder, LLVM.AppendBasicBlockInContext(context, invokeMethodHelper, string.Empty)); var invokeFunctionType = LLVM.GetElementType(LLVM.TypeOf(invokeMethodHelper)); bool hasRetValue = LLVM.GetReturnType(invokeFunctionType) != LLVM.VoidTypeInContext(context); var delegateArrayType = GetType(new ArrayType(delegateType), TypeState.TypeComplete); // Prepare basic blocks var forCodeBlock = LLVM.AppendBasicBlockInContext(context, invokeMethodHelper, string.Empty); var exitBlock = LLVM.AppendBasicBlockInContext(context, invokeMethodHelper, string.Empty); var stack = new FunctionStack(); // Load first argument and cast as Delegate[] var @this = LLVM.GetParam(invokeMethodHelper, 0); @this = LLVM.BuildPointerCast(builder, @this, delegateArrayType.DefaultTypeLLVM, string.Empty); // Create index (i = 0) var locals = new List <StackValue>(); locals.Add(new StackValue(StackValueType.Int32, int32, LLVM.BuildAlloca(builder, int32.DefaultTypeLLVM, "i"))); EmitI4(stack, 0); EmitStloc(stack, locals, 0); // length = invocationList.Length var delegateArray = new StackValue(StackValueType.Object, delegateArrayType, @this); stack.Add(delegateArray); EmitLdlen(stack); EmitConv(stack, Code.Conv_I4); var invocationCount = stack.Pop(); // Iterate over each element in array LLVM.BuildBr(builder, forCodeBlock); LLVM.PositionBuilderAtEnd(builder, forCodeBlock); // Get delegateArray[i] stack.Add(delegateArray); EmitLdloc(stack, locals, 0); EmitLdelem(stack); // Call var helperArgs = new ValueRef[LLVM.CountParams(invokeMethodHelper)]; var thisIndex = invokeMethod.Signature.GetParameterIndexForThis(); helperArgs[thisIndex] = LLVM.BuildPointerCast(builder, stack.Pop().Value, declaringClass.Type.DefaultTypeLLVM, string.Empty); for (int i = 0; i < helperArgs.Length; ++i) { if (i == thisIndex) { continue; } helperArgs[i] = LLVM.GetParam(invokeMethodHelper, (uint)i); } var retValue = LLVM.BuildCall(builder, invokeMethod.GeneratedValue, helperArgs, string.Empty); ApplyCallAttributes(invokeMethod.Signature, retValue); // i++ EmitLdloc(stack, locals, 0); var lastStack = stack[stack.Count - 1]; var incrementedValue = LLVM.BuildAdd(builder, lastStack.Value, LLVM.ConstInt(int32LLVM, 1, false), string.Empty); lastStack = new StackValue(StackValueType.Int32, int32, incrementedValue); stack[stack.Count - 1] = lastStack; EmitStloc(stack, locals, 0); // if (i < length) // goto forCodeBlock // else // return lastReturnValue; EmitLdloc(stack, locals, 0); stack.Add(invocationCount); EmitConditionalBranch(stack, forCodeBlock, exitBlock, Code.Blt_S); LLVM.PositionBuilderAtEnd(builder, exitBlock); // Return value if (hasRetValue) { LLVM.BuildRet(builder, retValue); } else { LLVM.BuildRetVoid(builder); } return(invokeMethodHelper); }
internal void DeclareFunctionPrototype(FunctionDeclaration funcdecl) { // Prepare argument type array var argumentCount = funcdecl.Parameters.Count; var arguments = new LLVMTypeRef [Math.Max(argumentCount, 0)]; // Check if the function is already defined Symbol sym; if ((Table.TopScope.IsFunction && Table.TopScope.FindSymbol(funcdecl.Name, out sym)) || (!Table.TopScope.IsFunction && Table.FindSymbol(funcdecl.Name, out sym))) { var e = LoreException.Create(funcdecl.Location).Describe($"Redefinition of function '{funcdecl.Name}'!"); e.Describe($"Previous declaration was at {sym.Location}."); e.Resolve($"Rename the function to avoid a collision."); throw e; } // Add function parameter types to array for (var i = 0; i < funcdecl.Parameters.Count; i++) { arguments [i] = Helper.GetBuiltinTypeFromString(funcdecl.Parameters [i].Type.Name); } // Check if the function returns multiple values var returnType = LLVM.VoidType(); var tupleReturnTypes = new LLVMTypeRef [0]; if (funcdecl.ReturnsTuple) { var count = funcdecl.TupleReturnTypes.Count; tupleReturnTypes = new LLVMTypeRef [count]; for (var i = 0; i < count; i++) { var current = funcdecl.TupleReturnTypes [i]; tupleReturnTypes [i] = Helper.GetBuiltinTypeFromString(current.Name); } returnType = LLVM.StructType(tupleReturnTypes, true); } // Create the return type else if (funcdecl.HasReturnType) { returnType = Helper.GetBuiltinTypeFromString(funcdecl.ReturnType.Name); } // Create the function type var functionType = LLVM.FunctionType( ReturnType: returnType, ParamTypes: arguments, IsVarArg: LLVMFalse ); // Create the actual function var functionRef = LLVM.AddFunction(LLVMModule, funcdecl.Name, functionType); LLVM.SetLinkage(functionRef, LLVMLinkage.LLVMExternalLinkage); // Add the function prototype as a symbol Table.AddSymbol(Symbol.CreatePrototype(funcdecl.Name, functionRef, funcdecl.Location)); }
public LLVMValueRef Emit(PipeContext <CodeGeneration.Module> context) { // Ensure body was provided or created. if (this.Body == null) { throw new Exception("Unexpected function body to be null"); } // Ensure prototype is set. else if (this.Prototype == null) { throw new Exception("Unexpected function prototype to be null"); } // Ensure that body returns a value if applicable. else if (!this.Prototype.ReturnType.IsVoid && !this.Body.HasReturnExpr) { throw new Exception("Functions that do not return void must return a value"); } // Emit the argument types. LLVMTypeRef[] args = this.Prototype.Args.Emit(context); // Emit the return type LLVMTypeRef returnType = this.Prototype.ReturnType.Emit(); // Emit the function type. LLVMTypeRef type = LLVM.FunctionType(returnType, args, this.Prototype.Args.Continuous); // Create the function. LLVMValueRef function = LLVM.AddFunction(context.Target.Target, this.Prototype.Identifier, type); // Create the argument index counter. uint argIndexCounter = 0; // Name arguments. foreach (FormalArg arg in this.Prototype.Args.Values) { // Name the argument. LLVM.SetValueName(LLVM.GetParam(function, argIndexCounter), arg.Identifier); // Increment the index counter for next iteration. argIndexCounter++; } // Create the function context. PipeContext <LLVMValueRef> functionContext = context.Derive <LLVMValueRef>(function); // Emit the body to its corresponding context. LLVMBasicBlockRef body = this.Body.Emit(functionContext); // Create a new builder reference for the body. LLVMBuilderRef bodyBuilder = body.CreateBuilder(false); // Derive a context for the body's builder. PipeContext <LLVMBuilderRef> bodyContext = context.Derive <LLVMBuilderRef>(bodyBuilder); // TODO: Missing support for native attribute emission. // Emit attributes as first-class instructions if applicable. foreach (Attribute attribute in this.Attributes) { // Emit the attribute onto the body's builder context. attribute.Emit(bodyContext); } // Ensures the function does not already exist if (context.SymbolTable.functions.Contains(this.Prototype.Identifier)) { throw new Exception($"A function with the identifier '{this.Prototype.Identifier}' already exists"); } // Register the function on the symbol table. context.SymbolTable.functions.Add(new FunctionSymbol(this.Prototype.Identifier, function, this.Prototype.Args.Continuous)); // Return the function entity. return(function); }