authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-08-29 06:08:19+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-09-20 02:29:04+02:00
logea393b2bca7587955df81d149caecc5522944d15
tree1391b7c5e6a462e86c8730e9a74c046b2d95a827
parente09465fc49d86cc4aa9338106862d3e059ae3303

Address Spaces: Implement in LLVM codegen


9 files changed, 91 insertions(+), 21 deletions(-)

src/Module.zig+1-1
...@@ -4761,7 +4761,7 @@ pub fn populateTestFunctions(mod: *Module) !void {...@@ -4761,7 +4761,7 @@ pub fn populateTestFunctions(mod: *Module) !void {
4761 const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;4761 const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;
4762 const builtin_namespace = builtin_file.root_decl.?.namespace;4762 const builtin_namespace = builtin_file.root_decl.?.namespace;
4763 const decl = builtin_namespace.decls.get("test_functions").?;4763 const decl = builtin_namespace.decls.get("test_functions").?;
4764 var buf: Type.Payload.ElemType = undefined;4764 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
4765 const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType();4765 const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType();
47664766
4767 const array_decl = d: {4767 const array_decl = d: {
src/Sema.zig+1-1
...@@ -8390,7 +8390,7 @@ fn fieldVal(...@@ -8390,7 +8390,7 @@ fn fieldVal(
8390 .Pointer => switch (object_ty.ptrSize()) {8390 .Pointer => switch (object_ty.ptrSize()) {
8391 .Slice => {8391 .Slice => {
8392 if (mem.eql(u8, field_name, "ptr")) {8392 if (mem.eql(u8, field_name, "ptr")) {
8393 const buf = try arena.create(Type.Payload.ElemType);8393 const buf = try arena.create(Type.SlicePtrFieldTypeBuffer);
8394 const result_ty = object_ty.slicePtrFieldType(buf);8394 const result_ty = object_ty.slicePtrFieldType(buf);
8395 if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| {8395 if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| {
8396 if (val.isUndef()) return sema.addConstUndef(result_ty);8396 if (val.isUndef()) return sema.addConstUndef(result_ty);
src/codegen.zig+1-1
...@@ -4873,7 +4873,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -4873,7 +4873,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
4873 switch (typed_value.ty.zigTypeTag()) {4873 switch (typed_value.ty.zigTypeTag()) {
4874 .Pointer => switch (typed_value.ty.ptrSize()) {4874 .Pointer => switch (typed_value.ty.ptrSize()) {
4875 .Slice => {4875 .Slice => {
4876 var buf: Type.Payload.ElemType = undefined;4876 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
4877 const ptr_type = typed_value.ty.slicePtrFieldType(&buf);4877 const ptr_type = typed_value.ty.slicePtrFieldType(&buf);
4878 const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val });4878 const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val });
4879 const slice_len = typed_value.val.sliceLen();4879 const slice_len = typed_value.val.sliceLen();
src/codegen/c.zig+1-1
...@@ -251,7 +251,7 @@ pub const DeclGen = struct {...@@ -251,7 +251,7 @@ pub const DeclGen = struct {
251 try writer.writeByte('(');251 try writer.writeByte('(');
252 try dg.renderType(writer, t);252 try dg.renderType(writer, t);
253 try writer.writeAll("){");253 try writer.writeAll("){");
254 var buf: Type.Payload.ElemType = undefined;254 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
255 try dg.renderValue(writer, t.slicePtrFieldType(&buf), val);255 try dg.renderValue(writer, t.slicePtrFieldType(&buf), val);
256 try writer.writeAll(", ");256 try writer.writeAll(", ");
257 try writer.print("{d}", .{val.sliceLen()});257 try writer.print("{d}", .{val.sliceLen()});
src/codegen/llvm.zig+32-8
...@@ -554,7 +554,8 @@ pub const DeclGen = struct {...@@ -554,7 +554,8 @@ pub const DeclGen = struct {
554 @intCast(c_uint, fn_param_len),554 @intCast(c_uint, fn_param_len),
555 .False,555 .False,
556 );556 );
557 const llvm_fn = self.llvmModule().addFunction(decl.name, fn_type);557 const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace");
558 const llvm_fn = self.llvmModule().addFunctionInAddressSpace(decl.name, fn_type, llvm_addrspace);
558559
559 const is_extern = decl.val.tag() == .extern_fn;560 const is_extern = decl.val.tag() == .extern_fn;
560 if (!is_extern) {561 if (!is_extern) {
...@@ -576,7 +577,27 @@ pub const DeclGen = struct {...@@ -576,7 +577,27 @@ pub const DeclGen = struct {
576 if (llvm_module.getNamedGlobal(decl.name)) |val| return val;577 if (llvm_module.getNamedGlobal(decl.name)) |val| return val;
577 // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`.578 // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`.
578 const llvm_type = try self.llvmType(decl.ty);579 const llvm_type = try self.llvmType(decl.ty);
579 return llvm_module.addGlobal(llvm_type, decl.name);580 const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace");
581 return llvm_module.addGlobalInAddressSpace(llvm_type, decl.name, llvm_addrspace);
582 }
583
584 fn llvmAddressSpace(self: DeclGen, address_space: std.builtin.AddressSpace) c_uint {
585 const target = self.module.getTarget();
586 return switch (address_space) {
587 .generic => llvm.address_space.default,
588 .gs => switch (target.cpu.arch) {
589 .i386, .x86_64 => llvm.address_space.x86.gs,
590 else => unreachable,
591 },
592 .fs => switch (target.cpu.arch) {
593 .i386, .x86_64 => llvm.address_space.x86.fs,
594 else => unreachable,
595 },
596 .ss => switch (target.cpu.arch) {
597 .i386, .x86_64 => llvm.address_space.x86.ss,
598 else => unreachable,
599 },
600 };
580 }601 }
581602
582 fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type {603 fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type {
...@@ -605,7 +626,7 @@ pub const DeclGen = struct {...@@ -605,7 +626,7 @@ pub const DeclGen = struct {
605 .Bool => return self.context.intType(1),626 .Bool => return self.context.intType(1),
606 .Pointer => {627 .Pointer => {
607 if (t.isSlice()) {628 if (t.isSlice()) {
608 var buf: Type.Payload.ElemType = undefined;629 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
609 const ptr_type = t.slicePtrFieldType(&buf);630 const ptr_type = t.slicePtrFieldType(&buf);
610631
611 const fields: [2]*const llvm.Type = .{632 const fields: [2]*const llvm.Type = .{
...@@ -615,7 +636,8 @@ pub const DeclGen = struct {...@@ -615,7 +636,8 @@ pub const DeclGen = struct {
615 return self.context.structType(&fields, fields.len, .False);636 return self.context.structType(&fields, fields.len, .False);
616 } else {637 } else {
617 const elem_type = try self.llvmType(t.elemType());638 const elem_type = try self.llvmType(t.elemType());
618 return elem_type.pointerType(0);639 const llvm_addrspace = self.llvmAddressSpace(t.ptrAddressSpace());
640 return elem_type.pointerType(llvm_addrspace);
619 }641 }
620 },642 },
621 .Array => {643 .Array => {
...@@ -681,7 +703,8 @@ pub const DeclGen = struct {...@@ -681,7 +703,8 @@ pub const DeclGen = struct {
681 @intCast(c_uint, llvm_params.len),703 @intCast(c_uint, llvm_params.len),
682 llvm.Bool.fromBool(is_var_args),704 llvm.Bool.fromBool(is_var_args),
683 );705 );
684 return llvm_fn_ty.pointerType(0);706 const llvm_addrspace = self.llvmAddressSpace(t.fnAddressSpace());
707 return llvm_fn_ty.pointerType(llvm_addrspace);
685 },708 },
686 .ComptimeInt => unreachable,709 .ComptimeInt => unreachable,
687 .ComptimeFloat => unreachable,710 .ComptimeFloat => unreachable,
...@@ -749,7 +772,7 @@ pub const DeclGen = struct {...@@ -749,7 +772,7 @@ pub const DeclGen = struct {
749 .Pointer => switch (tv.val.tag()) {772 .Pointer => switch (tv.val.tag()) {
750 .decl_ref => {773 .decl_ref => {
751 if (tv.ty.isSlice()) {774 if (tv.ty.isSlice()) {
752 var buf: Type.Payload.ElemType = undefined;775 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
753 const ptr_ty = tv.ty.slicePtrFieldType(&buf);776 const ptr_ty = tv.ty.slicePtrFieldType(&buf);
754 var slice_len: Value.Payload.U64 = .{777 var slice_len: Value.Payload.U64 = .{
755 .base = .{ .tag = .int_u64 },778 .base = .{ .tag = .int_u64 },
...@@ -779,12 +802,13 @@ pub const DeclGen = struct {...@@ -779,12 +802,13 @@ pub const DeclGen = struct {
779 decl.alive = true;802 decl.alive = true;
780 const val = try self.resolveGlobalDecl(decl);803 const val = try self.resolveGlobalDecl(decl);
781 const llvm_var_type = try self.llvmType(tv.ty);804 const llvm_var_type = try self.llvmType(tv.ty);
782 const llvm_type = llvm_var_type.pointerType(0);805 const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace");
806 const llvm_type = llvm_var_type.pointerType(llvm_addrspace);
783 return val.constBitCast(llvm_type);807 return val.constBitCast(llvm_type);
784 },808 },
785 .slice => {809 .slice => {
786 const slice = tv.val.castTag(.slice).?.data;810 const slice = tv.val.castTag(.slice).?.data;
787 var buf: Type.Payload.ElemType = undefined;811 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
788 const fields: [2]*const llvm.Value = .{812 const fields: [2]*const llvm.Value = .{
789 try self.genTypedValue(.{813 try self.genTypedValue(.{
790 .ty = tv.ty.slicePtrFieldType(&buf),814 .ty = tv.ty.slicePtrFieldType(&buf),
src/codegen/llvm/bindings.zig+8
...@@ -197,6 +197,9 @@ pub const Module = opaque {...@@ -197,6 +197,9 @@ pub const Module = opaque {
197 pub const addFunction = LLVMAddFunction;197 pub const addFunction = LLVMAddFunction;
198 extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value;198 extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value;
199199
200 pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace;
201 extern fn ZigLLVMAddFunctionInAddressSpace(*const Module, Name: [*:0]const u8, FunctionTy: *const Type, AddressSpace: c_uint) *const Value;
202
200 pub const getNamedFunction = LLVMGetNamedFunction;203 pub const getNamedFunction = LLVMGetNamedFunction;
201 extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value;204 extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value;
202205
...@@ -209,6 +212,9 @@ pub const Module = opaque {...@@ -209,6 +212,9 @@ pub const Module = opaque {
209 pub const addGlobal = LLVMAddGlobal;212 pub const addGlobal = LLVMAddGlobal;
210 extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value;213 extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value;
211214
215 pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace;
216 extern fn LLVMAddGlobalInAddressSpace(M: *const Module, Ty: *const Type, Name: [*:0]const u8, AddressSpace: c_uint) *const Value;
217
212 pub const getNamedGlobal = LLVMGetNamedGlobal;218 pub const getNamedGlobal = LLVMGetNamedGlobal;
213 extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value;219 extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value;
214220
...@@ -975,6 +981,8 @@ pub const TypeKind = enum(c_int) {...@@ -975,6 +981,8 @@ pub const TypeKind = enum(c_int) {
975};981};
976982
977pub const address_space = struct {983pub const address_space = struct {
984 pub const default = 0;
985
978 // See llvm/lib/Target/X86/X86.h986 // See llvm/lib/Target/X86/X86.h
979 pub const x86_64 = x86;987 pub const x86_64 = x86;
980 pub const x86 = struct {988 pub const x86 = struct {
src/type.zig+39-9
...@@ -2161,42 +2161,72 @@ pub const Type = extern union {...@@ -2161,42 +2161,72 @@ pub const Type = extern union {
2161 };2161 };
2162 }2162 }
21632163
2164 pub fn slicePtrFieldType(self: Type, buffer: *Payload.ElemType) Type {2164 pub const SlicePtrFieldTypeBuffer = union {
2165 elem_type: Payload.ElemType,
2166 pointer: Payload.Pointer,
2167 };
2168
2169 pub fn slicePtrFieldType(self: Type, buffer: *SlicePtrFieldTypeBuffer) Type {
2165 switch (self.tag()) {2170 switch (self.tag()) {
2166 .const_slice_u8 => return Type.initTag(.manyptr_const_u8),2171 .const_slice_u8 => return Type.initTag(.manyptr_const_u8),
21672172
2168 .const_slice => {2173 .const_slice => {
2169 const elem_type = self.castTag(.const_slice).?.data;2174 const elem_type = self.castTag(.const_slice).?.data;
2170 buffer.* = .{2175 buffer.elem_type = .{
2171 .base = .{ .tag = .many_const_pointer },2176 .base = .{ .tag = .many_const_pointer },
2172 .data = elem_type,2177 .data = elem_type,
2173 };2178 };
2174 return Type.initPayload(&buffer.base);2179 return Type.initPayload(&buffer.elem_type.base);
2175 },2180 },
2176 .mut_slice => {2181 .mut_slice => {
2177 const elem_type = self.castTag(.mut_slice).?.data;2182 const elem_type = self.castTag(.mut_slice).?.data;
2178 buffer.* = .{2183 buffer.elem_type = .{
2179 .base = .{ .tag = .many_mut_pointer },2184 .base = .{ .tag = .many_mut_pointer },
2180 .data = elem_type,2185 .data = elem_type,
2181 };2186 };
2182 return Type.initPayload(&buffer.base);2187 return Type.initPayload(&buffer.elem_type.base);
2183 },2188 },
21842189
2185 .pointer => {2190 .pointer => {
2186 const payload = self.castTag(.pointer).?.data;2191 const payload = self.castTag(.pointer).?.data;
2187 assert(payload.size == .Slice);2192 assert(payload.size == .Slice);
2188 if (payload.mutable) {2193
2189 buffer.* = .{2194 if (payload.sentinel != null or
2195 payload.@"align" != 0 or
2196 payload.@"addrspace" != .generic or
2197 payload.bit_offset != 0 or
2198 payload.host_size != 0 or
2199 payload.@"allowzero" or
2200 payload.@"volatile"
2201 ) {
2202 buffer.pointer = .{
2203 .data = .{
2204 .pointee_type = payload.pointee_type,
2205 .sentinel = payload.sentinel,
2206 .@"align" = payload.@"align",
2207 .@"addrspace" = payload.@"addrspace",
2208 .bit_offset = payload.bit_offset,
2209 .host_size = payload.host_size,
2210 .@"allowzero" = payload.@"allowzero",
2211 .mutable = payload.mutable,
2212 .@"volatile" = payload.@"volatile",
2213 .size = .Many
2214 },
2215 };
2216 return Type.initPayload(&buffer.pointer.base);
2217 } else if (payload.mutable) {
2218 buffer.elem_type = .{
2190 .base = .{ .tag = .many_mut_pointer },2219 .base = .{ .tag = .many_mut_pointer },
2191 .data = payload.pointee_type,2220 .data = payload.pointee_type,
2192 };2221 };
2222 return Type.initPayload(&buffer.elem_type.base);
2193 } else {2223 } else {
2194 buffer.* = .{2224 buffer.elem_type = .{
2195 .base = .{ .tag = .many_const_pointer },2225 .base = .{ .tag = .many_const_pointer },
2196 .data = payload.pointee_type,2226 .data = payload.pointee_type,
2197 };2227 };
2228 return Type.initPayload(&buffer.elem_type.base);
2198 }2229 }
2199 return Type.initPayload(&buffer.base);
2200 },2230 },
22012231
2202 else => unreachable,2232 else => unreachable,
src/zig_llvm.cpp+5
...@@ -416,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {...@@ -416,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {
416 return wrap(Type::getTokenTy(*unwrap(context_ref)));416 return wrap(Type::getTokenTy(*unwrap(context_ref)));
417}417}
418418
419LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, LLVMTypeRef FunctionTy, unsigned AddressSpace) {
420 Function* func = Function::Create(unwrap<FunctionType>(FunctionTy), GlobalValue::ExternalLinkage, AddressSpace, Name, unwrap(M));
421 return wrap(func);
422}
423
419LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,424LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
420 unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name)425 unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name)
421{426{
src/zig_llvm.h+3
...@@ -65,6 +65,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co...@@ -65,6 +65,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
6565
66ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);66ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
6767
68ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
69 LLVMTypeRef FunctionTy, unsigned AddressSpace);
70
68enum ZigLLVM_CallingConv {71enum ZigLLVM_CallingConv {
69 ZigLLVM_C = 0,72 ZigLLVM_C = 0,
70 ZigLLVM_Fast = 8,73 ZigLLVM_Fast = 8,