| author | |
| committer | |
| log | ea393b2bca7587955df81d149caecc5522944d15 |
| tree | 1391b7c5e6a462e86c8730e9a74c046b2d95a827 |
| parent | e09465fc49d86cc4aa9338106862d3e059ae3303 |
9 files changed, 91 insertions(+), 21 deletions(-)
src/Module.zig+1-1| ... | ... | @@ -4761,7 +4761,7 @@ pub fn populateTestFunctions(mod: *Module) !void { |
| 4761 | 4761 | const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; |
| 4762 | 4762 | const builtin_namespace = builtin_file.root_decl.?.namespace; |
| 4763 | 4763 | const decl = builtin_namespace.decls.get("test_functions").?; |
| 4764 | var buf: Type.Payload.ElemType = undefined; | |
| 4764 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 4765 | 4765 | const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); |
| 4766 | 4766 | |
| 4767 | 4767 | const array_decl = d: { |
src/Sema.zig+1-1| ... | ... | @@ -8390,7 +8390,7 @@ fn fieldVal( |
| 8390 | 8390 | .Pointer => switch (object_ty.ptrSize()) { |
| 8391 | 8391 | .Slice => { |
| 8392 | 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 | 8394 | const result_ty = object_ty.slicePtrFieldType(buf); |
| 8395 | 8395 | if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| { |
| 8396 | 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 | 4873 | switch (typed_value.ty.zigTypeTag()) { |
| 4874 | 4874 | .Pointer => switch (typed_value.ty.ptrSize()) { |
| 4875 | 4875 | .Slice => { |
| 4876 | var buf: Type.Payload.ElemType = undefined; | |
| 4876 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 4877 | 4877 | const ptr_type = typed_value.ty.slicePtrFieldType(&buf); |
| 4878 | 4878 | const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); |
| 4879 | 4879 | const slice_len = typed_value.val.sliceLen(); |
src/codegen/c.zig+1-1| ... | ... | @@ -251,7 +251,7 @@ pub const DeclGen = struct { |
| 251 | 251 | try writer.writeByte('('); |
| 252 | 252 | try dg.renderType(writer, t); |
| 253 | 253 | try writer.writeAll("){"); |
| 254 | var buf: Type.Payload.ElemType = undefined; | |
| 254 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 255 | 255 | try dg.renderValue(writer, t.slicePtrFieldType(&buf), val); |
| 256 | 256 | try writer.writeAll(", "); |
| 257 | 257 | try writer.print("{d}", .{val.sliceLen()}); |
src/codegen/llvm.zig+32-8| ... | ... | @@ -554,7 +554,8 @@ pub const DeclGen = struct { |
| 554 | 554 | @intCast(c_uint, fn_param_len), |
| 555 | 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); | |
| 558 | 559 | |
| 559 | 560 | const is_extern = decl.val.tag() == .extern_fn; |
| 560 | 561 | if (!is_extern) { |
| ... | ... | @@ -576,7 +577,27 @@ pub const DeclGen = struct { |
| 576 | 577 | if (llvm_module.getNamedGlobal(decl.name)) |val| return val; |
| 577 | 578 | // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`. |
| 578 | 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 | } |
| 581 | 602 | |
| 582 | 603 | fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type { |
| ... | ... | @@ -605,7 +626,7 @@ pub const DeclGen = struct { |
| 605 | 626 | .Bool => return self.context.intType(1), |
| 606 | 627 | .Pointer => { |
| 607 | 628 | if (t.isSlice()) { |
| 608 | var buf: Type.Payload.ElemType = undefined; | |
| 629 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 609 | 630 | const ptr_type = t.slicePtrFieldType(&buf); |
| 610 | 631 | |
| 611 | 632 | const fields: [2]*const llvm.Type = .{ |
| ... | ... | @@ -615,7 +636,8 @@ pub const DeclGen = struct { |
| 615 | 636 | return self.context.structType(&fields, fields.len, .False); |
| 616 | 637 | } else { |
| 617 | 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 | 643 | .Array => { |
| ... | ... | @@ -681,7 +703,8 @@ pub const DeclGen = struct { |
| 681 | 703 | @intCast(c_uint, llvm_params.len), |
| 682 | 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 | 709 | .ComptimeInt => unreachable, |
| 687 | 710 | .ComptimeFloat => unreachable, |
| ... | ... | @@ -749,7 +772,7 @@ pub const DeclGen = struct { |
| 749 | 772 | .Pointer => switch (tv.val.tag()) { |
| 750 | 773 | .decl_ref => { |
| 751 | 774 | if (tv.ty.isSlice()) { |
| 752 | var buf: Type.Payload.ElemType = undefined; | |
| 775 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 753 | 776 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); |
| 754 | 777 | var slice_len: Value.Payload.U64 = .{ |
| 755 | 778 | .base = .{ .tag = .int_u64 }, |
| ... | ... | @@ -779,12 +802,13 @@ pub const DeclGen = struct { |
| 779 | 802 | decl.alive = true; |
| 780 | 803 | const val = try self.resolveGlobalDecl(decl); |
| 781 | 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 | 807 | return val.constBitCast(llvm_type); |
| 784 | 808 | }, |
| 785 | 809 | .slice => { |
| 786 | 810 | const slice = tv.val.castTag(.slice).?.data; |
| 787 | var buf: Type.Payload.ElemType = undefined; | |
| 811 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 788 | 812 | const fields: [2]*const llvm.Value = .{ |
| 789 | 813 | try self.genTypedValue(.{ |
| 790 | 814 | .ty = tv.ty.slicePtrFieldType(&buf), |
src/codegen/llvm/bindings.zig+8| ... | ... | @@ -197,6 +197,9 @@ pub const Module = opaque { |
| 197 | 197 | pub const addFunction = LLVMAddFunction; |
| 198 | 198 | extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value; |
| 199 | 199 | |
| 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 | 203 | pub const getNamedFunction = LLVMGetNamedFunction; |
| 201 | 204 | extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value; |
| 202 | 205 | |
| ... | ... | @@ -209,6 +212,9 @@ pub const Module = opaque { |
| 209 | 212 | pub const addGlobal = LLVMAddGlobal; |
| 210 | 213 | extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value; |
| 211 | 214 | |
| 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 | 218 | pub const getNamedGlobal = LLVMGetNamedGlobal; |
| 213 | 219 | extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value; |
| 214 | 220 | |
| ... | ... | @@ -975,6 +981,8 @@ pub const TypeKind = enum(c_int) { |
| 975 | 981 | }; |
| 976 | 982 | |
| 977 | 983 | pub const address_space = struct { |
| 984 | pub const default = 0; | |
| 985 | ||
| 978 | 986 | // See llvm/lib/Target/X86/X86.h |
| 979 | 987 | pub const x86_64 = x86; |
| 980 | 988 | pub const x86 = struct { |
src/type.zig+39-9| ... | ... | @@ -2161,42 +2161,72 @@ pub const Type = extern union { |
| 2161 | 2161 | }; |
| 2162 | 2162 | } |
| 2163 | 2163 | |
| 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 | 2170 | switch (self.tag()) { |
| 2166 | 2171 | .const_slice_u8 => return Type.initTag(.manyptr_const_u8), |
| 2167 | 2172 | |
| 2168 | 2173 | .const_slice => { |
| 2169 | 2174 | const elem_type = self.castTag(.const_slice).?.data; |
| 2170 | buffer.* = .{ | |
| 2175 | buffer.elem_type = .{ | |
| 2171 | 2176 | .base = .{ .tag = .many_const_pointer }, |
| 2172 | 2177 | .data = elem_type, |
| 2173 | 2178 | }; |
| 2174 | return Type.initPayload(&buffer.base); | |
| 2179 | return Type.initPayload(&buffer.elem_type.base); | |
| 2175 | 2180 | }, |
| 2176 | 2181 | .mut_slice => { |
| 2177 | 2182 | const elem_type = self.castTag(.mut_slice).?.data; |
| 2178 | buffer.* = .{ | |
| 2183 | buffer.elem_type = .{ | |
| 2179 | 2184 | .base = .{ .tag = .many_mut_pointer }, |
| 2180 | 2185 | .data = elem_type, |
| 2181 | 2186 | }; |
| 2182 | return Type.initPayload(&buffer.base); | |
| 2187 | return Type.initPayload(&buffer.elem_type.base); | |
| 2183 | 2188 | }, |
| 2184 | 2189 | |
| 2185 | 2190 | .pointer => { |
| 2186 | 2191 | const payload = self.castTag(.pointer).?.data; |
| 2187 | 2192 | assert(payload.size == .Slice); |
| 2188 | if (payload.mutable) { | |
| 2189 | buffer.* = .{ | |
| 2193 | ||
| 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 | 2219 | .base = .{ .tag = .many_mut_pointer }, |
| 2191 | 2220 | .data = payload.pointee_type, |
| 2192 | 2221 | }; |
| 2222 | return Type.initPayload(&buffer.elem_type.base); | |
| 2193 | 2223 | } else { |
| 2194 | buffer.* = .{ | |
| 2224 | buffer.elem_type = .{ | |
| 2195 | 2225 | .base = .{ .tag = .many_const_pointer }, |
| 2196 | 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 | }, |
| 2201 | 2231 | |
| 2202 | 2232 | else => unreachable, |
src/zig_llvm.cpp+5| ... | ... | @@ -416,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) { |
| 416 | 416 | return wrap(Type::getTokenTy(*unwrap(context_ref))); |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | LLVMValueRef 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 | ||
| 419 | 424 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, |
| 420 | 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 | 65 | |
| 66 | 66 | ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); |
| 67 | 67 | |
| 68 | ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, | |
| 69 | LLVMTypeRef FunctionTy, unsigned AddressSpace); | |
| 70 | ||
| 68 | 71 | enum ZigLLVM_CallingConv { |
| 69 | 72 | ZigLLVM_C = 0, |
| 70 | 73 | ZigLLVM_Fast = 8, |