diff options
| author | Timon Kruiper <timonkruiper@gmail.com> | 2021-01-06 00:34:11 +0100 |
|---|---|---|
| committer | Timon Kruiper <timonkruiper@gmail.com> | 2021-01-06 10:52:20 +0100 |
| commit | 31d1ec4c2fd0d1e07e0020b19b7bca8196d7879c (patch) | |
| tree | dac56ed37e0a825de481088993ccc5bce25bdf7a /src | |
| parent | 5d5db833f277518bab152b743d6a4cfaa1e3fd8d (diff) | |
| download | zig-31d1ec4c2fd0d1e07e0020b19b7bca8196d7879c.tar.gz zig-31d1ec4c2fd0d1e07e0020b19b7bca8196d7879c.zip | |
stage2: make use of `llvm.Context` in LLVM backend
This for example allows for multiple LLVM instances to run in parallel.
Also rename some functions in llvm_bindings.zig.
Fixes #7688
Diffstat (limited to 'src')
| -rw-r--r-- | src/llvm_backend.zig | 55 | ||||
| -rw-r--r-- | src/llvm_bindings.zig | 85 |
2 files changed, 74 insertions, 66 deletions
diff --git a/src/llvm_backend.zig b/src/llvm_backend.zig index 2e7615d6ed..2bac4523c9 100644 --- a/src/llvm_backend.zig +++ b/src/llvm_backend.zig @@ -140,6 +140,7 @@ pub fn targetTriple(allocator: *Allocator, target: std.Target) ![:0]u8 { pub const LLVMIRModule = struct { module: *Module, llvm_module: *const llvm.Module, + context: *const llvm.Context, target_machine: *const llvm.TargetMachine, builder: *const llvm.Builder, @@ -181,19 +182,22 @@ pub const LLVMIRModule = struct { const object_path = try o_directory.join(gpa, &[_][]const u8{obj_basename}); errdefer gpa.free(object_path); + const context = llvm.Context.create(); + errdefer context.dispose(); + initializeLLVMTargets(); const root_nameZ = try gpa.dupeZ(u8, options.root_name); defer gpa.free(root_nameZ); - const llvm_module = llvm.Module.createWithName(root_nameZ.ptr); - errdefer llvm_module.disposeModule(); + const llvm_module = llvm.Module.createWithName(root_nameZ.ptr, context); + errdefer llvm_module.dispose(); const llvm_target_triple = try targetTriple(gpa, options.target); defer gpa.free(llvm_target_triple); var error_message: [*:0]const u8 = undefined; var target: *const llvm.Target = undefined; - if (llvm.Target.getTargetFromTriple(llvm_target_triple.ptr, &target, &error_message)) { + if (llvm.Target.getFromTriple(llvm_target_triple.ptr, &target, &error_message)) { defer llvm.disposeMessage(error_message); const stderr = std.io.getStdErr().outStream(); @@ -213,7 +217,7 @@ pub const LLVMIRModule = struct { } const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug) .None else .Aggressive; - const target_machine = llvm.TargetMachine.createTargetMachine( + const target_machine = llvm.TargetMachine.create( target, llvm_target_triple.ptr, "", @@ -222,14 +226,15 @@ pub const LLVMIRModule = struct { .Static, .Default, ); - errdefer target_machine.disposeTargetMachine(); + errdefer target_machine.dispose(); - const builder = llvm.Builder.createBuilder(); - errdefer builder.disposeBuilder(); + const builder = context.createBuilder(); + errdefer builder.dispose(); self.* = .{ .module = options.module.?, .llvm_module = llvm_module, + .context = context, .target_machine = target_machine, .builder = builder, .object_path = object_path, @@ -239,9 +244,10 @@ pub const LLVMIRModule = struct { } pub fn deinit(self: *LLVMIRModule, allocator: *Allocator) void { - self.builder.disposeBuilder(); - self.target_machine.disposeTargetMachine(); - self.llvm_module.disposeModule(); + self.builder.dispose(); + self.target_machine.dispose(); + self.llvm_module.dispose(); + self.context.dispose(); self.func_inst_table.deinit(self.gpa); self.gpa.free(self.object_path); @@ -271,7 +277,7 @@ pub const LLVMIRModule = struct { // verifyModule always allocs the error_message even if there is no error defer llvm.disposeMessage(error_message); - if (self.llvm_module.verifyModule(.ReturnStatus, &error_message)) { + if (self.llvm_module.verify(.ReturnStatus, &error_message)) { const stderr = std.io.getStdErr().outStream(); try stderr.print("broken LLVM module found: {s}\nThis is a bug in the Zig compiler.", .{error_message}); return error.BrokenLLVMModule; @@ -340,7 +346,7 @@ pub const LLVMIRModule = struct { bb.deleteBasicBlock(); } - self.entry_block = llvm_func.appendBasicBlock("Entry"); + self.entry_block = self.context.appendBasicBlock(llvm_func, "Entry"); self.builder.positionBuilderAtEnd(self.entry_block); self.latest_alloca_inst = null; @@ -606,7 +612,7 @@ pub const LLVMIRModule = struct { return self.fail(src, "TODO handle other sentinel values", .{}); } else false; - return llvm.constString(payload.data.ptr, @intCast(c_uint, payload.data.len), !zero_sentinel); + return self.context.constString(payload.data.ptr, @intCast(c_uint, payload.data.len), !zero_sentinel); } else { return self.fail(src, "TODO handle more array values", .{}); } @@ -617,13 +623,13 @@ pub const LLVMIRModule = struct { fn getLLVMType(self: *LLVMIRModule, t: Type, src: usize) error{ OutOfMemory, CodegenFail }!*const llvm.Type { switch (t.zigTypeTag()) { - .Void => return llvm.voidType(), - .NoReturn => return llvm.voidType(), + .Void => return self.context.voidType(), + .NoReturn => return self.context.voidType(), .Int => { const info = t.intInfo(self.module.getTarget()); - return llvm.intType(info.bits); + return self.context.intType(info.bits); }, - .Bool => return llvm.intType(1), + .Bool => return self.context.intType(1), .Pointer => { if (t.isSlice()) { return self.fail(src, "TODO: LLVM backend: implement slices", .{}); @@ -688,12 +694,25 @@ pub const LLVMIRModule = struct { const llvm_fn = self.llvm_module.addFunction(func.name, fn_type); if (return_type.tag() == .noreturn) { - llvm_fn.addFnAttr("noreturn"); + self.addFnAttr(llvm_fn, "noreturn"); } return llvm_fn; } + // Helper functions + fn addAttr(self: LLVMIRModule, val: *const llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { + const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len); + assert(kind_id != 0); + const llvm_attr = self.context.createEnumAttribute(kind_id, 0); + val.addAttributeAtIndex(index, llvm_attr); + } + + fn addFnAttr(self: *LLVMIRModule, val: *const llvm.Value, attr_name: []const u8) void { + // TODO: improve this API, `addAttr(-1, attr_name)` + self.addAttr(val, std.math.maxInt(llvm.AttributeIndex), attr_name); + } + pub fn fail(self: *LLVMIRModule, src: usize, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } { @setCold(true); assert(self.err_msg == null); diff --git a/src/llvm_bindings.zig b/src/llvm_bindings.zig index 4a3c37cef7..1af64e85f6 100644 --- a/src/llvm_bindings.zig +++ b/src/llvm_bindings.zig @@ -5,35 +5,44 @@ const std = @import("std"); const assert = std.debug.assert; const LLVMBool = bool; -pub const LLVMAttributeIndex = c_uint; +pub const AttributeIndex = c_uint; + +/// Make sure to use the *InContext functions instead of the global ones. +pub const Context = opaque { + pub const create = LLVMContextCreate; + extern fn LLVMContextCreate() *const Context; + + pub const dispose = LLVMContextDispose; + extern fn LLVMContextDispose(C: *const Context) void; + + pub const createEnumAttribute = LLVMCreateEnumAttribute; + extern fn LLVMCreateEnumAttribute(*const Context, KindID: c_uint, Val: u64) *const Attribute; + + pub const intType = LLVMIntTypeInContext; + extern fn LLVMIntTypeInContext(C: *const Context, NumBits: c_uint) *const Type; + + pub const voidType = LLVMVoidTypeInContext; + extern fn LLVMVoidTypeInContext(C: *const Context) *const Type; + + pub const constString = LLVMConstStringInContext; + extern fn LLVMConstStringInContext(C: *const Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: LLVMBool) *const Value; + + pub const appendBasicBlock = LLVMAppendBasicBlockInContext; + extern fn LLVMAppendBasicBlockInContext(C: *const Context, Fn: *const Value, Name: [*:0]const u8) *const BasicBlock; + + pub const createBuilder = LLVMCreateBuilderInContext; + extern fn LLVMCreateBuilderInContext(C: *const Context) *const Builder; +}; pub const Value = opaque { pub const addAttributeAtIndex = LLVMAddAttributeAtIndex; - extern fn LLVMAddAttributeAtIndex(*const Value, Idx: LLVMAttributeIndex, A: *const Attribute) void; - - pub const appendBasicBlock = LLVMAppendBasicBlock; - extern fn LLVMAppendBasicBlock(Fn: *const Value, Name: [*:0]const u8) *const BasicBlock; + extern fn LLVMAddAttributeAtIndex(*const Value, Idx: AttributeIndex, A: *const Attribute) void; pub const getFirstBasicBlock = LLVMGetFirstBasicBlock; extern fn LLVMGetFirstBasicBlock(Fn: *const Value) ?*const BasicBlock; pub const getNextInstruction = LLVMGetNextInstruction; extern fn LLVMGetNextInstruction(Inst: *const Value) ?*const Value; - - // Helper functions - // TODO: Do we want to put these functions here? It allows for convienient function calls - // on Value: llvm_fn.addFnAttr("noreturn") - fn addAttr(val: *const Value, index: LLVMAttributeIndex, name: []const u8) void { - const kind_id = getEnumAttributeKindForName(name.ptr, name.len); - assert(kind_id != 0); - const llvm_attr = Context.getGlobal().createEnumAttribute(kind_id, 0); - val.addAttributeAtIndex(index, llvm_attr); - } - - pub fn addFnAttr(val: *const Value, attr_name: []const u8) void { - // TODO: improve this API, `addAttr(-1, attr_name)` - val.addAttr(std.math.maxInt(LLVMAttributeIndex), attr_name); - } }; pub const Type = opaque { @@ -63,13 +72,13 @@ pub const Type = opaque { }; pub const Module = opaque { - pub const createWithName = LLVMModuleCreateWithName; - extern fn LLVMModuleCreateWithName(ModuleID: [*:0]const u8) *const Module; + pub const createWithName = LLVMModuleCreateWithNameInContext; + extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*:0]const u8, C: *const Context) *const Module; - pub const disposeModule = LLVMDisposeModule; + pub const dispose = LLVMDisposeModule; extern fn LLVMDisposeModule(*const Module) void; - pub const verifyModule = LLVMVerifyModule; + pub const verify = LLVMVerifyModule; extern fn LLVMVerifyModule(*const Module, Action: VerifierFailureAction, OutMessage: *[*:0]const u8) LLVMBool; pub const addFunction = LLVMAddFunction; @@ -106,15 +115,9 @@ pub const VerifierFailureAction = extern enum { pub const constNeg = LLVMConstNeg; extern fn LLVMConstNeg(ConstantVal: *const Value) *const Value; -pub const constString = LLVMConstString; -extern fn LLVMConstString(Str: [*]const u8, Length: c_uint, DontNullTerminate: LLVMBool) *const Value; - pub const setInitializer = LLVMSetInitializer; extern fn LLVMSetInitializer(GlobalVar: *const Value, ConstantVal: *const Value) void; -pub const voidType = LLVMVoidType; -extern fn LLVMVoidType() *const Type; - pub const getParam = LLVMGetParam; extern fn LLVMGetParam(Fn: *const Value, Index: c_uint) *const Value; @@ -123,22 +126,8 @@ extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint pub const Attribute = opaque {}; -pub const Context = opaque { - pub const createEnumAttribute = LLVMCreateEnumAttribute; - extern fn LLVMCreateEnumAttribute(*const Context, KindID: c_uint, Val: u64) *const Attribute; - - pub const getGlobal = LLVMGetGlobalContext; - extern fn LLVMGetGlobalContext() *const Context; -}; - -pub const intType = LLVMIntType; -extern fn LLVMIntType(NumBits: c_uint) *const Type; - pub const Builder = opaque { - pub const createBuilder = LLVMCreateBuilder; - extern fn LLVMCreateBuilder() *const Builder; - - pub const disposeBuilder = LLVMDisposeBuilder; + pub const dispose = LLVMDisposeBuilder; extern fn LLVMDisposeBuilder(Builder: *const Builder) void; pub const positionBuilder = LLVMPositionBuilder; @@ -208,7 +197,7 @@ pub const BasicBlock = opaque { }; pub const TargetMachine = opaque { - pub const createTargetMachine = LLVMCreateTargetMachine; + pub const create = LLVMCreateTargetMachine; extern fn LLVMCreateTargetMachine( T: *const Target, Triple: [*:0]const u8, @@ -219,7 +208,7 @@ pub const TargetMachine = opaque { CodeModel: CodeMode, ) *const TargetMachine; - pub const disposeTargetMachine = LLVMDisposeTargetMachine; + pub const dispose = LLVMDisposeTargetMachine; extern fn LLVMDisposeTargetMachine(T: *const TargetMachine) void; pub const emitToFile = LLVMTargetMachineEmitToFile; @@ -259,7 +248,7 @@ pub const CodeGenFileType = extern enum { }; pub const Target = opaque { - pub const getTargetFromTriple = LLVMGetTargetFromTriple; + pub const getFromTriple = LLVMGetTargetFromTriple; extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **const Target, ErrorMessage: *[*:0]const u8) LLVMBool; }; |
