From e09465fc49d86cc4aa9338106862d3e059ae3303 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 29 Aug 2021 03:18:23 +0200 Subject: Address Spaces: Chaining tests --- src/codegen/llvm/bindings.zig | 59 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'src/codegen/llvm') diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index db1dcd22f2..67b39784b1 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -973,3 +973,62 @@ pub const TypeKind = enum(c_int) { BFloat, X86_AMX, }; + +pub const address_space = struct { + // See llvm/lib/Target/X86/X86.h + pub const x86_64 = x86; + pub const x86 = struct { + pub const gs = 256; + pub const fs = 257; + pub const ss = 258; + + pub const ptr32_sptr = 270; + pub const ptr32_uptr = 271; + pub const ptr64 = 272; + }; + + // See llvm/lib/Target/AVR/AVR.h + pub const avr = struct { + pub const data_memory = 0; + pub const program_memory = 1; + }; + + // See llvm/lib/Target/NVPTX/NVPTX.h + pub const nvptx = struct { + pub const generic = 0; + pub const global = 1; + pub const constant = 2; + pub const shared = 3; + pub const param = 4; + pub const local = 5; + }; + + // See llvm/lib/Target/AMDGPU/AMDGPU.h + pub const amdgpu = struct { + pub const flat = 0; + pub const global = 1; + pub const region = 2; + pub const local = 3; + pub const constant = 4; + pub const constant_32bit = 6; + pub const buffer_fat_pointer = 7; + pub const param_d = 6; + pub const param_i = 7; + pub const constant_buffer_0 = 8; + pub const constant_buffer_1 = 9; + pub const constant_buffer_2 = 10; + pub const constant_buffer_3 = 11; + pub const constant_buffer_4 = 12; + pub const constant_buffer_5 = 13; + pub const constant_buffer_6 = 14; + pub const constant_buffer_7 = 15; + pub const constant_buffer_8 = 16; + pub const constant_buffer_9 = 17; + pub const constant_buffer_10 = 18; + pub const constant_buffer_11 = 19; + pub const constant_buffer_12 = 20; + pub const constant_buffer_13 = 21; + pub const constant_buffer_14 = 22; + pub const constant_buffer_15 = 23; + }; +}; -- cgit v1.2.3 From ea393b2bca7587955df81d149caecc5522944d15 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 29 Aug 2021 06:08:19 +0200 Subject: Address Spaces: Implement in LLVM codegen --- src/Module.zig | 2 +- src/Sema.zig | 2 +- src/codegen.zig | 2 +- src/codegen/c.zig | 2 +- src/codegen/llvm.zig | 40 ++++++++++++++++++++++++++++-------- src/codegen/llvm/bindings.zig | 8 ++++++++ src/type.zig | 48 +++++++++++++++++++++++++++++++++++-------- src/zig_llvm.cpp | 5 +++++ src/zig_llvm.h | 3 +++ 9 files changed, 91 insertions(+), 21 deletions(-) (limited to 'src/codegen/llvm') diff --git a/src/Module.zig b/src/Module.zig index b2cef0792a..1f9b5abcb9 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -4761,7 +4761,7 @@ pub fn populateTestFunctions(mod: *Module) !void { const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; const builtin_namespace = builtin_file.root_decl.?.namespace; const decl = builtin_namespace.decls.get("test_functions").?; - var buf: Type.Payload.ElemType = undefined; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); const array_decl = d: { diff --git a/src/Sema.zig b/src/Sema.zig index 4b75cc4c43..d6e926e604 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8390,7 +8390,7 @@ fn fieldVal( .Pointer => switch (object_ty.ptrSize()) { .Slice => { if (mem.eql(u8, field_name, "ptr")) { - const buf = try arena.create(Type.Payload.ElemType); + const buf = try arena.create(Type.SlicePtrFieldTypeBuffer); const result_ty = object_ty.slicePtrFieldType(buf); if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| { if (val.isUndef()) return sema.addConstUndef(result_ty); diff --git a/src/codegen.zig b/src/codegen.zig index e0047de1f7..cbee79f139 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -4873,7 +4873,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { switch (typed_value.ty.zigTypeTag()) { .Pointer => switch (typed_value.ty.ptrSize()) { .Slice => { - var buf: Type.Payload.ElemType = undefined; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; const ptr_type = typed_value.ty.slicePtrFieldType(&buf); const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); const slice_len = typed_value.val.sliceLen(); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 5eb4388a9e..7a2dc343f7 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -251,7 +251,7 @@ pub const DeclGen = struct { try writer.writeByte('('); try dg.renderType(writer, t); try writer.writeAll("){"); - var buf: Type.Payload.ElemType = undefined; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; try dg.renderValue(writer, t.slicePtrFieldType(&buf), val); try writer.writeAll(", "); try writer.print("{d}", .{val.sliceLen()}); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 53e57ee219..8b7282160e 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -554,7 +554,8 @@ pub const DeclGen = struct { @intCast(c_uint, fn_param_len), .False, ); - const llvm_fn = self.llvmModule().addFunction(decl.name, fn_type); + const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); + const llvm_fn = self.llvmModule().addFunctionInAddressSpace(decl.name, fn_type, llvm_addrspace); const is_extern = decl.val.tag() == .extern_fn; if (!is_extern) { @@ -576,7 +577,27 @@ pub const DeclGen = struct { if (llvm_module.getNamedGlobal(decl.name)) |val| return val; // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`. const llvm_type = try self.llvmType(decl.ty); - return llvm_module.addGlobal(llvm_type, decl.name); + const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); + return llvm_module.addGlobalInAddressSpace(llvm_type, decl.name, llvm_addrspace); + } + + fn llvmAddressSpace(self: DeclGen, address_space: std.builtin.AddressSpace) c_uint { + const target = self.module.getTarget(); + return switch (address_space) { + .generic => llvm.address_space.default, + .gs => switch (target.cpu.arch) { + .i386, .x86_64 => llvm.address_space.x86.gs, + else => unreachable, + }, + .fs => switch (target.cpu.arch) { + .i386, .x86_64 => llvm.address_space.x86.fs, + else => unreachable, + }, + .ss => switch (target.cpu.arch) { + .i386, .x86_64 => llvm.address_space.x86.ss, + else => unreachable, + }, + }; } fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type { @@ -605,7 +626,7 @@ pub const DeclGen = struct { .Bool => return self.context.intType(1), .Pointer => { if (t.isSlice()) { - var buf: Type.Payload.ElemType = undefined; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; const ptr_type = t.slicePtrFieldType(&buf); const fields: [2]*const llvm.Type = .{ @@ -615,7 +636,8 @@ pub const DeclGen = struct { return self.context.structType(&fields, fields.len, .False); } else { const elem_type = try self.llvmType(t.elemType()); - return elem_type.pointerType(0); + const llvm_addrspace = self.llvmAddressSpace(t.ptrAddressSpace()); + return elem_type.pointerType(llvm_addrspace); } }, .Array => { @@ -681,7 +703,8 @@ pub const DeclGen = struct { @intCast(c_uint, llvm_params.len), llvm.Bool.fromBool(is_var_args), ); - return llvm_fn_ty.pointerType(0); + const llvm_addrspace = self.llvmAddressSpace(t.fnAddressSpace()); + return llvm_fn_ty.pointerType(llvm_addrspace); }, .ComptimeInt => unreachable, .ComptimeFloat => unreachable, @@ -749,7 +772,7 @@ pub const DeclGen = struct { .Pointer => switch (tv.val.tag()) { .decl_ref => { if (tv.ty.isSlice()) { - var buf: Type.Payload.ElemType = undefined; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; const ptr_ty = tv.ty.slicePtrFieldType(&buf); var slice_len: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, @@ -779,12 +802,13 @@ pub const DeclGen = struct { decl.alive = true; const val = try self.resolveGlobalDecl(decl); const llvm_var_type = try self.llvmType(tv.ty); - const llvm_type = llvm_var_type.pointerType(0); + const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); + const llvm_type = llvm_var_type.pointerType(llvm_addrspace); return val.constBitCast(llvm_type); }, .slice => { const slice = tv.val.castTag(.slice).?.data; - var buf: Type.Payload.ElemType = undefined; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; const fields: [2]*const llvm.Value = .{ try self.genTypedValue(.{ .ty = tv.ty.slicePtrFieldType(&buf), diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 67b39784b1..e50589dee1 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -197,6 +197,9 @@ pub const Module = opaque { pub const addFunction = LLVMAddFunction; extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value; + pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace; + extern fn ZigLLVMAddFunctionInAddressSpace(*const Module, Name: [*:0]const u8, FunctionTy: *const Type, AddressSpace: c_uint) *const Value; + pub const getNamedFunction = LLVMGetNamedFunction; extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value; @@ -209,6 +212,9 @@ pub const Module = opaque { pub const addGlobal = LLVMAddGlobal; extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value; + pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace; + extern fn LLVMAddGlobalInAddressSpace(M: *const Module, Ty: *const Type, Name: [*:0]const u8, AddressSpace: c_uint) *const Value; + pub const getNamedGlobal = LLVMGetNamedGlobal; extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value; @@ -975,6 +981,8 @@ pub const TypeKind = enum(c_int) { }; pub const address_space = struct { + pub const default = 0; + // See llvm/lib/Target/X86/X86.h pub const x86_64 = x86; pub const x86 = struct { diff --git a/src/type.zig b/src/type.zig index b15026b595..9cda4aacf7 100644 --- a/src/type.zig +++ b/src/type.zig @@ -2161,42 +2161,72 @@ pub const Type = extern union { }; } - pub fn slicePtrFieldType(self: Type, buffer: *Payload.ElemType) Type { + pub const SlicePtrFieldTypeBuffer = union { + elem_type: Payload.ElemType, + pointer: Payload.Pointer, + }; + + pub fn slicePtrFieldType(self: Type, buffer: *SlicePtrFieldTypeBuffer) Type { switch (self.tag()) { .const_slice_u8 => return Type.initTag(.manyptr_const_u8), .const_slice => { const elem_type = self.castTag(.const_slice).?.data; - buffer.* = .{ + buffer.elem_type = .{ .base = .{ .tag = .many_const_pointer }, .data = elem_type, }; - return Type.initPayload(&buffer.base); + return Type.initPayload(&buffer.elem_type.base); }, .mut_slice => { const elem_type = self.castTag(.mut_slice).?.data; - buffer.* = .{ + buffer.elem_type = .{ .base = .{ .tag = .many_mut_pointer }, .data = elem_type, }; - return Type.initPayload(&buffer.base); + return Type.initPayload(&buffer.elem_type.base); }, .pointer => { const payload = self.castTag(.pointer).?.data; assert(payload.size == .Slice); - if (payload.mutable) { - buffer.* = .{ + + if (payload.sentinel != null or + payload.@"align" != 0 or + payload.@"addrspace" != .generic or + payload.bit_offset != 0 or + payload.host_size != 0 or + payload.@"allowzero" or + payload.@"volatile" + ) { + buffer.pointer = .{ + .data = .{ + .pointee_type = payload.pointee_type, + .sentinel = payload.sentinel, + .@"align" = payload.@"align", + .@"addrspace" = payload.@"addrspace", + .bit_offset = payload.bit_offset, + .host_size = payload.host_size, + .@"allowzero" = payload.@"allowzero", + .mutable = payload.mutable, + .@"volatile" = payload.@"volatile", + .size = .Many + }, + }; + return Type.initPayload(&buffer.pointer.base); + } else if (payload.mutable) { + buffer.elem_type = .{ .base = .{ .tag = .many_mut_pointer }, .data = payload.pointee_type, }; + return Type.initPayload(&buffer.elem_type.base); } else { - buffer.* = .{ + buffer.elem_type = .{ .base = .{ .tag = .many_const_pointer }, .data = payload.pointee_type, }; + return Type.initPayload(&buffer.elem_type.base); } - return Type.initPayload(&buffer.base); }, else => unreachable, diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index e1ab74f423..6e136161a6 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -416,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) { return wrap(Type::getTokenTy(*unwrap(context_ref))); } +LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, LLVMTypeRef FunctionTy, unsigned AddressSpace) { + Function* func = Function::Create(unwrap(FunctionTy), GlobalValue::ExternalLinkage, AddressSpace, Name, unwrap(M)); + return wrap(func); +} + LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name) { diff --git a/src/zig_llvm.h b/src/zig_llvm.h index be279d86e1..49a4c0e8fd 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -65,6 +65,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); +ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, + LLVMTypeRef FunctionTy, unsigned AddressSpace); + enum ZigLLVM_CallingConv { ZigLLVM_C = 0, ZigLLVM_Fast = 8, -- cgit v1.2.3 From e4ac063297fc9210ae3a97fa370ea8c6c216ec43 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Fri, 3 Sep 2021 04:36:56 +0200 Subject: Address Spaces: Restructure llvmAddressSpace a bit --- src/codegen/llvm.zig | 19 +++++----- src/codegen/llvm/bindings.zig | 81 ++++++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 51 deletions(-) (limited to 'src/codegen/llvm') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 8b7282160e..ce79d43fac 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -583,18 +583,15 @@ pub const DeclGen = struct { fn llvmAddressSpace(self: DeclGen, address_space: std.builtin.AddressSpace) c_uint { const target = self.module.getTarget(); - return switch (address_space) { - .generic => llvm.address_space.default, - .gs => switch (target.cpu.arch) { - .i386, .x86_64 => llvm.address_space.x86.gs, - else => unreachable, - }, - .fs => switch (target.cpu.arch) { - .i386, .x86_64 => llvm.address_space.x86.fs, - else => unreachable, + return switch (target.cpu.arch) { + .i386, .x86_64 => switch (address_space) { + .generic => llvm.address_space.default, + .gs => llvm.address_space.x86.gs, + .fs => llvm.address_space.x86.fs, + .ss => llvm.address_space.x86.ss, }, - .ss => switch (target.cpu.arch) { - .i386, .x86_64 => llvm.address_space.x86.ss, + else => switch (address_space) { + .generic => llvm.address_space.default, else => unreachable, }, }; diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index e50589dee1..ebb84cb05b 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -981,62 +981,63 @@ pub const TypeKind = enum(c_int) { }; pub const address_space = struct { - pub const default = 0; + pub const default: c_uint = 0; // See llvm/lib/Target/X86/X86.h pub const x86_64 = x86; pub const x86 = struct { - pub const gs = 256; - pub const fs = 257; - pub const ss = 258; + pub const gs: c_uint = 256; + pub const fs: c_uint = 257; + pub const ss: c_uint = 258; - pub const ptr32_sptr = 270; - pub const ptr32_uptr = 271; - pub const ptr64 = 272; + pub const ptr32_sptr: c_uint = 270; + pub const ptr32_uptr: c_uint = 271; + pub const ptr64: c_uint = 272; }; // See llvm/lib/Target/AVR/AVR.h pub const avr = struct { - pub const data_memory = 0; - pub const program_memory = 1; + pub const data_memory: c_uint = 0; + pub const program_memory: c_uint = 1; }; // See llvm/lib/Target/NVPTX/NVPTX.h pub const nvptx = struct { - pub const generic = 0; - pub const global = 1; - pub const constant = 2; - pub const shared = 3; - pub const param = 4; - pub const local = 5; + pub const generic: c_uint = 0; + pub const global: c_uint = 1; + pub const constant: c_uint = 2; + pub const shared: c_uint = 3; + pub const param: c_uint = 4; + pub const local: c_uint = 5; }; // See llvm/lib/Target/AMDGPU/AMDGPU.h pub const amdgpu = struct { - pub const flat = 0; - pub const global = 1; - pub const region = 2; - pub const local = 3; - pub const constant = 4; - pub const constant_32bit = 6; - pub const buffer_fat_pointer = 7; - pub const param_d = 6; - pub const param_i = 7; - pub const constant_buffer_0 = 8; - pub const constant_buffer_1 = 9; - pub const constant_buffer_2 = 10; - pub const constant_buffer_3 = 11; - pub const constant_buffer_4 = 12; - pub const constant_buffer_5 = 13; - pub const constant_buffer_6 = 14; - pub const constant_buffer_7 = 15; - pub const constant_buffer_8 = 16; - pub const constant_buffer_9 = 17; - pub const constant_buffer_10 = 18; - pub const constant_buffer_11 = 19; - pub const constant_buffer_12 = 20; - pub const constant_buffer_13 = 21; - pub const constant_buffer_14 = 22; - pub const constant_buffer_15 = 23; + pub const flat: c_uint = 0; + pub const global: c_uint = 1; + pub const region: c_uint = 2; + pub const local: c_uint = 3; + pub const constant: c_uint = 4; + pub const private: c_uint = 5; + pub const constant_32bit: c_uint = 6; + pub const buffer_fat_pointer: c_uint = 7; + pub const param_d: c_uint = 6; + pub const param_i: c_uint = 7; + pub const constant_buffer_0: c_uint = 8; + pub const constant_buffer_1: c_uint = 9; + pub const constant_buffer_2: c_uint = 10; + pub const constant_buffer_3: c_uint = 11; + pub const constant_buffer_4: c_uint = 12; + pub const constant_buffer_5: c_uint = 13; + pub const constant_buffer_6: c_uint = 14; + pub const constant_buffer_7: c_uint = 15; + pub const constant_buffer_8: c_uint = 16; + pub const constant_buffer_9: c_uint = 17; + pub const constant_buffer_10: c_uint = 18; + pub const constant_buffer_11: c_uint = 19; + pub const constant_buffer_12: c_uint = 20; + pub const constant_buffer_13: c_uint = 21; + pub const constant_buffer_14: c_uint = 22; + pub const constant_buffer_15: c_uint = 23; }; }; -- cgit v1.2.3