authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-15 23:32:02-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-16 00:09:00-07:00
logc3663f2617fd317f458bfa013ea94efb7dbcfee5
tree21f88c80bd8279909a3f65abd3bc01c87eb3ca0d
parentcfc31b5bbdf67632626eb934886cdeaefe40e595

LLVM: implement debug info for structs

This involved some significant reworking in order to introduce the concept of "forward declarations" to the system to break dependency loops. The `lowerDebugType` function now takes an `enum { full, fwd }` and is moved from `DeclGen` to `Object` so that it can be called from `flushModule`. `DITypeMap` is now an `ArrayHashMap` instead of a `HashMap` so that we can iterate over the entries in `flushModule` and finalize the forward decl DITypes into full DITypes. `DITypeMap` now stores `AnnotatedDITypePtr` values instead of `*DIType` values. This is an abstraction around a `usize` which assumes the pointers will be at least 2 bytes aligned and uses the least significant bit to store whether it is forward decl or a fully resolved debug info type. `lowerDebugTypeImpl` is extracted out from `lowerDebugType` and it has a mechanism for completing a forward decl DIType to a fully resolved one. The function now contains lowering for struct types. Closes #11095. There is a workaround for struct types which have not had `resolveFieldTypes` called in Sema, even by the time `flushModule` is called. This is a deficiency of Sema that should be addressed, and the workaround removed. I think Sema needs a new mechanism to queue up type resolution work instead of doing it in-line, so that it does not cause false dependency loops. We already have one failing behavior test because of a false dependency loop.

1 files changed, 1908 insertions(+), 1773 deletions(-)

src/codegen/llvm.zig+1908-1773
...@@ -160,6 +160,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 {...@@ -160,6 +160,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 {
160}160}
161161
162pub const Object = struct {162pub const Object = struct {
163 gpa: Allocator,
163 llvm_module: *const llvm.Module,164 llvm_module: *const llvm.Module,
164 di_builder: ?*llvm.DIBuilder,165 di_builder: ?*llvm.DIBuilder,
165 /// One of these mappings:166 /// One of these mappings:
...@@ -171,6 +172,7 @@ pub const Object = struct {...@@ -171,6 +172,7 @@ pub const Object = struct {
171 context: *const llvm.Context,172 context: *const llvm.Context,
172 target_machine: *const llvm.TargetMachine,173 target_machine: *const llvm.TargetMachine,
173 target_data: *const llvm.TargetData,174 target_data: *const llvm.TargetData,
175 target: std.Target,
174 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,176 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,
175 /// but that has some downsides:177 /// but that has some downsides:
176 /// * we have to compute the fully qualified name every time we want to do the lookup178 /// * we have to compute the fully qualified name every time we want to do the lookup
...@@ -202,11 +204,13 @@ pub const Object = struct {...@@ -202,11 +204,13 @@ pub const Object = struct {
202 std.hash_map.default_max_load_percentage,204 std.hash_map.default_max_load_percentage,
203 );205 );
204206
205 pub const DITypeMap = std.HashMapUnmanaged(207 /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we
208 /// want to iterate over it while adding entries to it.
209 pub const DITypeMap = std.ArrayHashMapUnmanaged(
206 Type,210 Type,
207 *llvm.DIType,211 AnnotatedDITypePtr,
208 Type.HashContext64,212 Type.HashContext32,
209 std.hash_map.default_max_load_percentage,213 true,
210 );214 );
211215
212 pub fn create(gpa: Allocator, options: link.Options) !*Object {216 pub fn create(gpa: Allocator, options: link.Options) !*Object {
...@@ -335,6 +339,7 @@ pub const Object = struct {...@@ -335,6 +339,7 @@ pub const Object = struct {
335 llvm_module.setModuleDataLayout(target_data);339 llvm_module.setModuleDataLayout(target_data);
336340
337 return Object{341 return Object{
342 .gpa = gpa,
338 .llvm_module = llvm_module,343 .llvm_module = llvm_module,
339 .di_map = .{},344 .di_map = .{},
340 .di_builder = opt_di_builder,345 .di_builder = opt_di_builder,
...@@ -342,6 +347,7 @@ pub const Object = struct {...@@ -342,6 +347,7 @@ pub const Object = struct {
342 .context = context,347 .context = context,
343 .target_machine = target_machine,348 .target_machine = target_machine,
344 .target_data = target_data,349 .target_data = target_data,
350 .target = options.target,
345 .decl_map = .{},351 .decl_map = .{},
346 .type_map = .{},352 .type_map = .{},
347 .type_map_arena = std.heap.ArenaAllocator.init(gpa),353 .type_map_arena = std.heap.ArenaAllocator.init(gpa),
...@@ -437,7 +443,25 @@ pub const Object = struct {...@@ -437,7 +443,25 @@ pub const Object = struct {
437 pub fn flushModule(self: *Object, comp: *Compilation) !void {443 pub fn flushModule(self: *Object, comp: *Compilation) !void {
438 try self.genErrorNameTable(comp);444 try self.genErrorNameTable(comp);
439445
440 if (self.di_builder) |dib| dib.finalize();446 if (self.di_builder) |dib| {
447 // When lowering debug info for pointers, we emitted the element types as
448 // forward decls. Now we must go flesh those out.
449 // Here we iterate over a hash map while modifying it but it is OK because
450 // we never add or remove entries during this loop.
451 var i: usize = 0;
452 while (i < self.di_type_map.count()) : (i += 1) {
453 const value_ptr = &self.di_type_map.values()[i];
454 const annotated = value_ptr.*;
455 if (!annotated.isFwdOnly()) continue;
456 const entry: Object.DITypeMap.Entry = .{
457 .key_ptr = &self.di_type_map.keys()[i],
458 .value_ptr = value_ptr,
459 };
460 _ = try self.lowerDebugTypeImpl(entry, .full, annotated.toDIType());
461 }
462
463 dib.finalize();
464 }
441465
442 if (comp.verbose_llvm_ir) {466 if (comp.verbose_llvm_ir) {
443 self.llvm_module.dump();467 self.llvm_module.dump();
...@@ -503,7 +527,7 @@ pub const Object = struct {...@@ -503,7 +527,7 @@ pub const Object = struct {
503 }527 }
504528
505 pub fn updateFunc(529 pub fn updateFunc(
506 self: *Object,530 o: *Object,
507 module: *Module,531 module: *Module,
508 func: *Module.Fn,532 func: *Module.Fn,
509 air: Air,533 air: Air,
...@@ -512,8 +536,8 @@ pub const Object = struct {...@@ -512,8 +536,8 @@ pub const Object = struct {
512 const decl = func.owner_decl;536 const decl = func.owner_decl;
513537
514 var dg: DeclGen = .{538 var dg: DeclGen = .{
515 .context = self.context,539 .context = o.context,
516 .object = self,540 .object = o,
517 .module = module,541 .module = module,
518 .decl = decl,542 .decl = decl,
519 .err_msg = null,543 .err_msg = null,
...@@ -584,7 +608,7 @@ pub const Object = struct {...@@ -584,7 +608,7 @@ pub const Object = struct {
584 llvm_func.getValueName(),608 llvm_func.getValueName(),
585 di_file.?,609 di_file.?,
586 line_number,610 line_number,
587 try dg.lowerDebugType(decl.ty),611 try o.lowerDebugType(decl.ty, .full),
588 is_internal_linkage,612 is_internal_linkage,
589 true, // is definition613 true, // is definition
590 line_number + func.lbrace_line, // scope line614 line_number + func.lbrace_line, // scope line
...@@ -631,7 +655,7 @@ pub const Object = struct {...@@ -631,7 +655,7 @@ pub const Object = struct {
631 };655 };
632656
633 const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{};657 const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{};
634 try self.updateDeclExports(module, decl, decl_exports);658 try o.updateDeclExports(module, decl, decl_exports);
635 }659 }
636660
637 pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void {661 pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void {
...@@ -773,622 +797,811 @@ pub const Object = struct {...@@ -773,622 +797,811 @@ pub const Object = struct {
773 gop.value_ptr.* = di_file.toNode();797 gop.value_ptr.* = di_file.toNode();
774 return di_file;798 return di_file;
775 }799 }
776};
777800
778pub const DeclGen = struct {801 const DebugResolveStatus = enum { fwd, full };
779 context: *const llvm.Context,
780 object: *Object,
781 module: *Module,
782 decl: *Module.Decl,
783 gpa: Allocator,
784 err_msg: ?*Module.ErrorMsg,
785802
786 fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error {803 /// In the implementation of this function, it is required to store a forward decl
787 @setCold(true);804 /// into `gop` before making any recursive calls (even directly).
788 assert(self.err_msg == null);805 fn lowerDebugType(
789 const src_loc = @as(LazySrcLoc, .{ .node_offset = 0 }).toSrcLoc(self.decl);806 o: *Object,
790 self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args);807 ty: Type,
791 return error.CodegenFail;808 resolve: DebugResolveStatus,
792 }809 ) Allocator.Error!*llvm.DIType {
810 const gpa = o.gpa;
811 // Be careful not to reference this `gop` variable after any recursive calls
812 // to `lowerDebugType`.
813 const gop = try o.di_type_map.getOrPut(gpa, ty);
814 if (gop.found_existing) {
815 const annotated = gop.value_ptr.*;
816 const di_type = annotated.toDIType();
817 if (!annotated.isFwdOnly() or resolve == .fwd) {
818 return di_type;
819 }
820 const entry: Object.DITypeMap.Entry = .{
821 .key_ptr = gop.key_ptr,
822 .value_ptr = gop.value_ptr,
823 };
824 return o.lowerDebugTypeImpl(entry, resolve, di_type);
825 }
826 errdefer assert(o.di_type_map.orderedRemove(ty));
827 // The Type memory is ephemeral; since we want to store a longer-lived
828 // reference, we need to copy it here.
829 gop.key_ptr.* = try ty.copy(o.type_map_arena.allocator());
830 const entry: Object.DITypeMap.Entry = .{
831 .key_ptr = gop.key_ptr,
832 .value_ptr = gop.value_ptr,
833 };
834 return o.lowerDebugTypeImpl(entry, resolve, null);
835 }
836
837 /// This is a helper function used by `lowerDebugType`.
838 fn lowerDebugTypeImpl(
839 o: *Object,
840 gop: Object.DITypeMap.Entry,
841 resolve: DebugResolveStatus,
842 opt_fwd_decl: ?*llvm.DIType,
843 ) Allocator.Error!*llvm.DIType {
844 const ty = gop.key_ptr.*;
845 const gpa = o.gpa;
846 const target = o.target;
847 const dib = o.di_builder.?;
848 switch (ty.zigTypeTag()) {
849 .Void, .NoReturn => {
850 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
851 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
852 return di_type;
853 },
854 .Int => {
855 const info = ty.intInfo(target);
856 assert(info.bits != 0);
857 const name = try ty.nameAlloc(gpa);
858 defer gpa.free(name);
859 const dwarf_encoding: c_uint = switch (info.signedness) {
860 .signed => DW.ATE.signed,
861 .unsigned => DW.ATE.unsigned,
862 };
863 const di_type = dib.createBasicType(name, info.bits, dwarf_encoding);
864 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
865 return di_type;
866 },
867 .Enum => {
868 const owner_decl = ty.getOwnerDecl();
793869
794 fn llvmModule(self: *DeclGen) *const llvm.Module {870 if (!ty.hasRuntimeBitsIgnoreComptime()) {
795 return self.object.llvm_module;871 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
796 }872 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
873 // means we can't use `gop` anymore.
874 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty));
875 return enum_di_ty;
876 }
797877
798 fn genDecl(dg: *DeclGen) !void {878 const field_names = ty.enumFields().keys();
799 const decl = dg.decl;
800 assert(decl.has_tv);
801879
802 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val });880 const enumerators = try gpa.alloc(*llvm.DIEnumerator, field_names.len);
881 defer gpa.free(enumerators);
803882
804 if (decl.val.castTag(.function)) |func_payload| {883 var buf_field_index: Value.Payload.U32 = .{
805 _ = func_payload;884 .base = .{ .tag = .enum_field_index },
806 @panic("TODO llvm backend genDecl function pointer");885 .data = undefined,
807 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {886 };
808 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);887 const field_index_val = Value.initPayload(&buf_field_index.base);
809 } else {888
810 const target = dg.module.getTarget();889 for (field_names) |field_name, i| {
811 var global = try dg.resolveGlobalDecl(decl);890 const field_name_z = try gpa.dupeZ(u8, field_name);
812 global.setAlignment(decl.getAlignment(target));891 defer gpa.free(field_name_z);
813 assert(decl.has_tv);892
814 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {893 buf_field_index.data = @intCast(u32, i);
815 const variable = payload.data;894 var buf_u64: Value.Payload.U64 = undefined;
816 break :init_val variable.init;895 const field_int_val = field_index_val.enumToInt(ty, &buf_u64);
817 } else init_val: {896 // See https://github.com/ziglang/zig/issues/645
818 global.setGlobalConstant(.True);897 const field_int = field_int_val.toSignedInt();
819 break :init_val decl.val;898 enumerators[i] = dib.createEnumerator(field_name_z, field_int);
820 };
821 if (init_val.tag() != .unreachable_value) {
822 const llvm_init = try dg.genTypedValue(.{ .ty = decl.ty, .val = init_val });
823 if (global.globalGetValueType() == llvm_init.typeOf()) {
824 global.setInitializer(llvm_init);
825 } else {
826 // LLVM does not allow us to change the type of globals. So we must
827 // create a new global with the correct type, copy all its attributes,
828 // and then update all references to point to the new global,
829 // delete the original, and rename the new one to the old one's name.
830 // This is necessary because LLVM does not support const bitcasting
831 // a struct with padding bytes, which is needed to lower a const union value
832 // to LLVM, when a field other than the most-aligned is active. Instead,
833 // we must lower to an unnamed struct, and pointer cast at usage sites
834 // of the global. Such an unnamed struct is the cause of the global type
835 // mismatch, because we don't have the LLVM type until the *value* is created,
836 // whereas the global needs to be created based on the type alone, because
837 // lowering the value may reference the global as a pointer.
838 const new_global = dg.object.llvm_module.addGlobalInAddressSpace(
839 llvm_init.typeOf(),
840 "",
841 dg.llvmAddressSpace(decl.@"addrspace"),
842 );
843 new_global.setLinkage(global.getLinkage());
844 new_global.setUnnamedAddr(global.getUnnamedAddress());
845 new_global.setAlignment(global.getAlignment());
846 new_global.setInitializer(llvm_init);
847 // replaceAllUsesWith requires the type to be unchanged. So we bitcast
848 // the new global to the old type and use that as the thing to replace
849 // old uses.
850 const new_global_ptr = new_global.constBitCast(global.typeOf());
851 global.replaceAllUsesWith(new_global_ptr);
852 dg.object.decl_map.putAssumeCapacity(decl, new_global);
853 new_global.takeName(global);
854 global.deleteGlobal();
855 global = new_global;
856 }899 }
857 }
858900
859 if (dg.object.di_builder) |dib| {901 const di_file = try o.getDIFile(gpa, owner_decl.src_namespace.file_scope);
860 const di_file = try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope);902 const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
861903
862 const line_number = decl.src_line + 1;904 const name = try ty.nameAlloc(gpa);
863 const is_internal_linkage = !dg.module.decl_exports.contains(decl);905 defer gpa.free(name);
864 const di_global = dib.createGlobalVariable(906 var buffer: Type.Payload.Bits = undefined;
865 di_file.toScope(),907 const int_ty = ty.intTagType(&buffer);
866 decl.name,908
867 global.getValueName(),909 const enum_di_ty = dib.createEnumerationType(
910 di_scope,
911 name,
868 di_file,912 di_file,
869 line_number,913 owner_decl.src_node + 1,
870 try dg.lowerDebugType(decl.ty),914 ty.abiSize(target) * 8,
871 is_internal_linkage,915 ty.abiAlignment(target) * 8,
916 enumerators.ptr,
917 @intCast(c_int, enumerators.len),
918 try o.lowerDebugType(int_ty, .full),
919 "",
872 );920 );
921 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
922 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty));
923 return enum_di_ty;
924 },
925 .Float => {
926 const bits = ty.floatBits(target);
927 const name = try ty.nameAlloc(gpa);
928 defer gpa.free(name);
929 const di_type = dib.createBasicType(name, bits, DW.ATE.float);
930 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
931 return di_type;
932 },
933 .Bool => {
934 const di_type = dib.createBasicType("bool", 1, DW.ATE.boolean);
935 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
936 return di_type;
937 },
938 .Pointer => {
939 // Normalize everything that the debug info does not represent.
940 const ptr_info = ty.ptrInfo().data;
873941
874 try dg.object.di_map.put(dg.gpa, dg.decl, di_global.toNode());942 if (ptr_info.sentinel != null or
875 }943 ptr_info.@"addrspace" != .generic or
876 }944 ptr_info.bit_offset != 0 or
877 }945 ptr_info.host_size != 0 or
946 ptr_info.@"allowzero" or
947 !ptr_info.mutable or
948 ptr_info.@"volatile" or
949 ptr_info.size == .Many or ptr_info.size == .C or
950 !ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime())
951 {
952 var payload: Type.Payload.Pointer = .{
953 .data = .{
954 .pointee_type = ptr_info.pointee_type,
955 .sentinel = null,
956 .@"align" = ptr_info.@"align",
957 .@"addrspace" = .generic,
958 .bit_offset = 0,
959 .host_size = 0,
960 .@"allowzero" = false,
961 .mutable = true,
962 .@"volatile" = false,
963 .size = switch (ptr_info.size) {
964 .Many, .C, .One => .One,
965 .Slice => .Slice,
966 },
967 },
968 };
969 if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) {
970 payload.data.pointee_type = Type.anyopaque;
971 }
972 const bland_ptr_ty = Type.initPayload(&payload.base);
973 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);
974 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
975 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty));
976 return ptr_di_ty;
977 }
878978
879 /// If the llvm function does not exist, create it.979 if (ty.isSlice()) {
880 /// Note that this can be called before the function's semantic analysis has980 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
881 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.981 const ptr_ty = ty.slicePtrFieldType(&buf);
882 fn resolveLlvmFunction(dg: *DeclGen, decl: *Module.Decl) !*const llvm.Value {982 const len_ty = Type.usize;
883 const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl);
884 if (gop.found_existing) return gop.value_ptr.*;
885983
886 assert(decl.has_tv);984 const name = try ty.nameAlloc(gpa);
887 const zig_fn_type = decl.ty;985 defer gpa.free(name);
888 const fn_info = zig_fn_type.fnInfo();986 const di_file: ?*llvm.DIFile = null;
889 const target = dg.module.getTarget();987 const line = 0;
890 const sret = firstParamSRet(fn_info, target);988 const compile_unit_scope = o.di_compile_unit.?.toScope();
891989
892 const fn_type = try dg.llvmType(zig_fn_type);990 const fwd_decl = opt_fwd_decl orelse blk: {
991 const fwd_decl = dib.createReplaceableCompositeType(
992 DW.TAG.structure_type,
993 name.ptr,
994 compile_unit_scope,
995 di_file,
996 line,
997 );
998 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
999 if (resolve == .fwd) return fwd_decl;
1000 break :blk fwd_decl;
1001 };
8931002
894 const fqn = try decl.getFullyQualifiedName(dg.gpa);1003 const ptr_size = ptr_ty.abiSize(target);
895 defer dg.gpa.free(fqn);1004 const ptr_align = ptr_ty.abiAlignment(target);
1005 const len_size = len_ty.abiSize(target);
1006 const len_align = len_ty.abiAlignment(target);
8961007
897 const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");1008 var offset: u64 = 0;
898 const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(fqn, fn_type, llvm_addrspace);1009 offset += ptr_size;
899 gop.value_ptr.* = llvm_fn;1010 offset = std.mem.alignForwardGeneric(u64, offset, len_align);
1011 const len_offset = offset;
9001012
901 const is_extern = decl.isExtern();1013 const fields: [2]*llvm.DIType = .{
902 if (!is_extern) {1014 dib.createMemberType(
903 llvm_fn.setLinkage(.Internal);1015 fwd_decl.toScope(),
904 llvm_fn.setUnnamedAddr(.True);1016 "ptr",
905 } else if (dg.module.getTarget().isWasm()) {1017 di_file,
906 dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0));1018 line,
907 if (decl.getExternFn().?.lib_name) |lib_name| {1019 ptr_size * 8, // size in bits
908 const module_name = std.mem.sliceTo(lib_name, 0);1020 ptr_align * 8, // align in bits
909 if (!std.mem.eql(u8, module_name, "c")) {1021 0, // offset in bits
910 dg.addFnAttrString(llvm_fn, "wasm-import-module", module_name);1022 0, // flags
1023 try o.lowerDebugType(ptr_ty, .full),
1024 ),
1025 dib.createMemberType(
1026 fwd_decl.toScope(),
1027 "len",
1028 di_file,
1029 line,
1030 len_size * 8, // size in bits
1031 len_align * 8, // align in bits
1032 len_offset * 8, // offset in bits
1033 0, // flags
1034 try o.lowerDebugType(len_ty, .full),
1035 ),
1036 };
1037
1038 const full_di_ty = dib.createStructType(
1039 compile_unit_scope,
1040 name.ptr,
1041 di_file,
1042 line,
1043 ty.abiSize(target) * 8, // size in bits
1044 ty.abiAlignment(target) * 8, // align in bits
1045 0, // flags
1046 null, // derived from
1047 &fields,
1048 fields.len,
1049 0, // run time lang
1050 null, // vtable holder
1051 "", // unique id
1052 );
1053 dib.replaceTemporary(fwd_decl, full_di_ty);
1054 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1055 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty));
1056 return full_di_ty;
911 }1057 }
912 }
913 }
9141058
915 if (sret) {1059 const elem_di_ty = try o.lowerDebugType(ptr_info.pointee_type, .fwd);
916 dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 01060 const name = try ty.nameAlloc(gpa);
917 dg.addArgAttr(llvm_fn, 0, "noalias");1061 defer gpa.free(name);
1062 const ptr_di_ty = dib.createPointerType(
1063 elem_di_ty,
1064 target.cpu.arch.ptrBitWidth(),
1065 ty.ptrAlignment(target) * 8,
1066 name,
1067 );
1068 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1069 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty));
1070 return ptr_di_ty;
1071 },
1072 .Opaque => {
1073 if (ty.tag() == .anyopaque) {
1074 const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed);
1075 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
1076 return di_ty;
1077 }
1078 const name = try ty.nameAlloc(gpa);
1079 defer gpa.free(name);
1080 const owner_decl = ty.getOwnerDecl();
1081 const opaque_di_ty = dib.createForwardDeclType(
1082 DW.TAG.structure_type,
1083 name,
1084 try o.namespaceToDebugScope(owner_decl.src_namespace),
1085 try o.getDIFile(gpa, owner_decl.src_namespace.file_scope),
1086 owner_decl.src_node + 1,
1087 );
1088 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`
1089 // means we can't use `gop` anymore.
1090 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(opaque_di_ty));
1091 return opaque_di_ty;
1092 },
1093 .Array => {
1094 const array_di_ty = dib.createArrayType(
1095 ty.abiSize(target) * 8,
1096 ty.abiAlignment(target) * 8,
1097 try o.lowerDebugType(ty.childType(), .full),
1098 @intCast(c_int, ty.arrayLen()),
1099 );
1100 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1101 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(array_di_ty));
1102 return array_di_ty;
1103 },
1104 .Vector => {
1105 const vector_di_ty = dib.createVectorType(
1106 ty.abiSize(target) * 8,
1107 ty.abiAlignment(target) * 8,
1108 try o.lowerDebugType(ty.childType(), .full),
1109 ty.vectorLen(),
1110 );
1111 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1112 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(vector_di_ty));
1113 return vector_di_ty;
1114 },
1115 .Optional => {
1116 const name = try ty.nameAlloc(gpa);
1117 defer gpa.free(name);
1118 var buf: Type.Payload.ElemType = undefined;
1119 const child_ty = ty.optionalChild(&buf);
1120 if (!child_ty.hasRuntimeBitsIgnoreComptime()) {
1121 const di_ty = dib.createBasicType(name, 1, DW.ATE.boolean);
1122 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
1123 return di_ty;
1124 }
1125 if (ty.isPtrLikeOptional()) {
1126 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);
1127 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1128 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty));
1129 return ptr_di_ty;
1130 }
9181131
919 const raw_llvm_ret_ty = try dg.llvmType(fn_info.return_type);1132 const di_file: ?*llvm.DIFile = null;
920 llvm_fn.addSretAttr(0, raw_llvm_ret_ty);1133 const line = 0;
921 }1134 const compile_unit_scope = o.di_compile_unit.?.toScope();
1135 const fwd_decl = opt_fwd_decl orelse blk: {
1136 const fwd_decl = dib.createReplaceableCompositeType(
1137 DW.TAG.structure_type,
1138 name.ptr,
1139 compile_unit_scope,
1140 di_file,
1141 line,
1142 );
1143 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
1144 if (resolve == .fwd) return fwd_decl;
1145 break :blk fwd_decl;
1146 };
9221147
923 // Set parameter attributes.1148 const non_null_ty = Type.bool;
924 var llvm_param_i: c_uint = @boolToInt(sret);1149 const payload_size = child_ty.abiSize(target);
925 for (fn_info.param_types) |param_ty| {1150 const payload_align = child_ty.abiAlignment(target);
926 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;1151 const non_null_size = non_null_ty.abiSize(target);
1152 const non_null_align = non_null_ty.abiAlignment(target);
9271153
928 if (isByRef(param_ty)) {1154 var offset: u64 = 0;
929 dg.addArgAttr(llvm_fn, llvm_param_i, "nonnull");1155 offset += payload_size;
930 // TODO readonly, noalias, align1156 offset = std.mem.alignForwardGeneric(u64, offset, non_null_align);
931 }1157 const non_null_offset = offset;
932 llvm_param_i += 1;
933 }
9341158
935 // TODO: more attributes. see codegen.cpp `make_fn_llvm_value`.1159 const fields: [2]*llvm.DIType = .{
936 if (fn_info.cc == .Naked) {1160 dib.createMemberType(
937 dg.addFnAttr(llvm_fn, "naked");1161 fwd_decl.toScope(),
938 } else {1162 "data",
939 llvm_fn.setFunctionCallConv(toLlvmCallConv(fn_info.cc, target));1163 di_file,
940 }1164 line,
1165 payload_size * 8, // size in bits
1166 payload_align * 8, // align in bits
1167 0, // offset in bits
1168 0, // flags
1169 try o.lowerDebugType(child_ty, .full),
1170 ),
1171 dib.createMemberType(
1172 fwd_decl.toScope(),
1173 "some",
1174 di_file,
1175 line,
1176 non_null_size * 8, // size in bits
1177 non_null_align * 8, // align in bits
1178 non_null_offset * 8, // offset in bits
1179 0, // flags
1180 try o.lowerDebugType(non_null_ty, .full),
1181 ),
1182 };
9411183
942 if (fn_info.alignment != 0) {1184 const full_di_ty = dib.createStructType(
943 llvm_fn.setAlignment(fn_info.alignment);1185 compile_unit_scope,
944 }1186 name.ptr,
1187 di_file,
1188 line,
1189 ty.abiSize(target) * 8, // size in bits
1190 ty.abiAlignment(target) * 8, // align in bits
1191 0, // flags
1192 null, // derived from
1193 &fields,
1194 fields.len,
1195 0, // run time lang
1196 null, // vtable holder
1197 "", // unique id
1198 );
1199 dib.replaceTemporary(fwd_decl, full_di_ty);
1200 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1201 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty));
1202 return full_di_ty;
1203 },
1204 .ErrorUnion => {
1205 const err_set_ty = ty.errorUnionSet();
1206 const payload_ty = ty.errorUnionPayload();
1207 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1208 const err_set_di_ty = try o.lowerDebugType(err_set_ty, .full);
1209 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1210 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty));
1211 return err_set_di_ty;
1212 }
1213 const name = try ty.nameAlloc(gpa);
1214 defer gpa.free(name);
1215 const di_file: ?*llvm.DIFile = null;
1216 const line = 0;
1217 const compile_unit_scope = o.di_compile_unit.?.toScope();
1218 const fwd_decl = opt_fwd_decl orelse blk: {
1219 const fwd_decl = dib.createReplaceableCompositeType(
1220 DW.TAG.structure_type,
1221 name.ptr,
1222 compile_unit_scope,
1223 di_file,
1224 line,
1225 );
1226 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
1227 if (resolve == .fwd) return fwd_decl;
1228 break :blk fwd_decl;
1229 };
9451230
946 // Function attributes that are independent of analysis results of the function body.1231 const err_set_size = err_set_ty.abiSize(target);
947 dg.addCommonFnAttributes(llvm_fn);1232 const err_set_align = err_set_ty.abiAlignment(target);
1233 const payload_size = payload_ty.abiSize(target);
1234 const payload_align = payload_ty.abiAlignment(target);
9481235
949 if (fn_info.return_type.isNoReturn()) {1236 var offset: u64 = 0;
950 dg.addFnAttr(llvm_fn, "noreturn");1237 offset += err_set_size;
951 }1238 offset = std.mem.alignForwardGeneric(u64, offset, payload_align);
1239 const payload_offset = offset;
9521240
953 return llvm_fn;1241 const fields: [2]*llvm.DIType = .{
954 }1242 dib.createMemberType(
1243 fwd_decl.toScope(),
1244 "tag",
1245 di_file,
1246 line,
1247 err_set_size * 8, // size in bits
1248 err_set_align * 8, // align in bits
1249 0, // offset in bits
1250 0, // flags
1251 try o.lowerDebugType(err_set_ty, .full),
1252 ),
1253 dib.createMemberType(
1254 fwd_decl.toScope(),
1255 "value",
1256 di_file,
1257 line,
1258 payload_size * 8, // size in bits
1259 payload_align * 8, // align in bits
1260 payload_offset * 8, // offset in bits
1261 0, // flags
1262 try o.lowerDebugType(payload_ty, .full),
1263 ),
1264 };
9551265
956 fn addCommonFnAttributes(dg: *DeclGen, llvm_fn: *const llvm.Value) void {1266 const full_di_ty = dib.createStructType(
957 if (!dg.module.comp.bin_file.options.red_zone) {1267 compile_unit_scope,
958 dg.addFnAttr(llvm_fn, "noredzone");1268 name.ptr,
959 }1269 di_file,
960 if (dg.module.comp.bin_file.options.omit_frame_pointer) {1270 line,
961 dg.addFnAttrString(llvm_fn, "frame-pointer", "none");1271 ty.abiSize(target) * 8, // size in bits
962 } else {1272 ty.abiAlignment(target) * 8, // align in bits
963 dg.addFnAttrString(llvm_fn, "frame-pointer", "all");1273 0, // flags
964 }1274 null, // derived from
965 dg.addFnAttr(llvm_fn, "nounwind");1275 &fields,
966 if (dg.module.comp.unwind_tables) {1276 fields.len,
967 dg.addFnAttr(llvm_fn, "uwtable");1277 0, // run time lang
968 }1278 null, // vtable holder
969 if (dg.module.comp.bin_file.options.skip_linker_dependencies) {1279 "", // unique id
970 // The intent here is for compiler-rt and libc functions to not generate1280 );
971 // infinite recursion. For example, if we are compiling the memcpy function,1281 dib.replaceTemporary(fwd_decl, full_di_ty);
972 // and llvm detects that the body is equivalent to memcpy, it may replace the1282 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
973 // body of memcpy with a call to memcpy, which would then cause a stack1283 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty));
974 // overflow instead of performing memcpy.1284 return full_di_ty;
975 dg.addFnAttr(llvm_fn, "nobuiltin");
976 }
977 if (dg.module.comp.bin_file.options.optimize_mode == .ReleaseSmall) {
978 dg.addFnAttr(llvm_fn, "minsize");
979 dg.addFnAttr(llvm_fn, "optsize");
980 }
981 if (dg.module.comp.bin_file.options.tsan) {
982 dg.addFnAttr(llvm_fn, "sanitize_thread");
983 }
984 // TODO add target-cpu and target-features fn attributes
985 }
986
987 fn resolveGlobalDecl(dg: *DeclGen, decl: *Module.Decl) Error!*const llvm.Value {
988 const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl);
989 if (gop.found_existing) return gop.value_ptr.*;
990 errdefer assert(dg.object.decl_map.remove(decl));
991
992 const fqn = try decl.getFullyQualifiedName(dg.gpa);
993 defer dg.gpa.free(fqn);
994
995 const llvm_type = try dg.llvmType(decl.ty);
996 const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");
997 const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace(llvm_type, fqn, llvm_addrspace);
998 gop.value_ptr.* = llvm_global;
999
1000 // This is needed for declarations created by `@extern`.
1001 if (decl.isExtern()) {
1002 llvm_global.setValueName(decl.name);
1003 llvm_global.setUnnamedAddr(.False);
1004 llvm_global.setLinkage(.External);
1005 if (decl.val.castTag(.variable)) |variable| {
1006 const single_threaded = dg.module.comp.bin_file.options.single_threaded;
1007 if (variable.data.is_threadlocal and !single_threaded) {
1008 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1009 } else {
1010 llvm_global.setThreadLocalMode(.NotThreadLocal);
1011 }
1012 if (variable.data.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);
1013 }
1014 } else {
1015 llvm_global.setLinkage(.Internal);
1016 llvm_global.setUnnamedAddr(.True);
1017 }
1018
1019 return llvm_global;
1020 }
1021
1022 fn llvmAddressSpace(self: DeclGen, address_space: std.builtin.AddressSpace) c_uint {
1023 const target = self.module.getTarget();
1024 return switch (target.cpu.arch) {
1025 .i386, .x86_64 => switch (address_space) {
1026 .generic => llvm.address_space.default,
1027 .gs => llvm.address_space.x86.gs,
1028 .fs => llvm.address_space.x86.fs,
1029 .ss => llvm.address_space.x86.ss,
1030 else => unreachable,
1031 },
1032 .nvptx, .nvptx64 => switch (address_space) {
1033 .generic => llvm.address_space.default,
1034 .global => llvm.address_space.nvptx.global,
1035 .constant => llvm.address_space.nvptx.constant,
1036 .param => llvm.address_space.nvptx.param,
1037 .shared => llvm.address_space.nvptx.shared,
1038 .local => llvm.address_space.nvptx.local,
1039 else => unreachable,
1040 },
1041 else => switch (address_space) {
1042 .generic => llvm.address_space.default,
1043 else => unreachable,
1044 },
1045 };
1046 }
1047
1048 fn isUnnamedType(dg: *DeclGen, ty: Type, val: *const llvm.Value) bool {
1049 // Once `llvmType` succeeds, successive calls to it with the same Zig type
1050 // are guaranteed to succeed. So if a call to `llvmType` fails here it means
1051 // it is the first time lowering the type, which means the value can't possible
1052 // have that type.
1053 const llvm_ty = dg.llvmType(ty) catch return true;
1054 return val.typeOf() != llvm_ty;
1055 }
1056
1057 fn llvmType(dg: *DeclGen, t: Type) Allocator.Error!*const llvm.Type {
1058 const gpa = dg.gpa;
1059 const target = dg.module.getTarget();
1060 switch (t.zigTypeTag()) {
1061 .Void, .NoReturn => return dg.context.voidType(),
1062 .Int => {
1063 const info = t.intInfo(target);
1064 assert(info.bits != 0);
1065 return dg.context.intType(info.bits);
1066 },
1067 .Enum => {
1068 var buffer: Type.Payload.Bits = undefined;
1069 const int_ty = t.intTagType(&buffer);
1070 const bit_count = int_ty.intInfo(target).bits;
1071 assert(bit_count != 0);
1072 return dg.context.intType(bit_count);
1073 },
1074 .Float => switch (t.floatBits(target)) {
1075 16 => return dg.context.halfType(),
1076 32 => return dg.context.floatType(),
1077 64 => return dg.context.doubleType(),
1078 80 => return if (backendSupportsF80(target)) dg.context.x86FP80Type() else dg.context.intType(80),
1079 128 => return dg.context.fp128Type(),
1080 else => unreachable,
1081 },1285 },
1082 .Bool => return dg.context.intType(1),1286 .ErrorSet => {
1083 .Pointer => {1287 // TODO make this a proper enum with all the error codes in it.
1084 if (t.isSlice()) {1288 // will need to consider how to take incremental compilation into account.
1085 var buf: Type.SlicePtrFieldTypeBuffer = undefined;1289 const di_ty = dib.createBasicType("anyerror", 16, DW.ATE.unsigned);
1086 const ptr_type = t.slicePtrFieldType(&buf);1290 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
10871291 return di_ty;
1088 const fields: [2]*const llvm.Type = .{
1089 try dg.llvmType(ptr_type),
1090 try dg.llvmType(Type.usize),
1091 };
1092 return dg.context.structType(&fields, fields.len, .False);
1093 }
1094 const ptr_info = t.ptrInfo().data;
1095 const llvm_addrspace = dg.llvmAddressSpace(ptr_info.@"addrspace");
1096 if (ptr_info.host_size != 0) {
1097 return dg.context.intType(ptr_info.host_size * 8).pointerType(llvm_addrspace);
1098 }
1099 const elem_ty = ptr_info.pointee_type;
1100 const lower_elem_ty = switch (elem_ty.zigTypeTag()) {
1101 .Opaque, .Fn => true,
1102 .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(),
1103 else => elem_ty.hasRuntimeBitsIgnoreComptime(),
1104 };
1105 const llvm_elem_ty = if (lower_elem_ty)
1106 try dg.llvmType(elem_ty)
1107 else
1108 dg.context.intType(8);
1109 return llvm_elem_ty.pointerType(llvm_addrspace);
1110 },1292 },
1111 .Opaque => switch (t.tag()) {1293 .Struct => {
1112 .@"opaque" => {1294 const compile_unit_scope = o.di_compile_unit.?.toScope();
1113 const gop = try dg.object.type_map.getOrPut(gpa, t);1295 const name = try ty.nameAlloc(gpa);
1114 if (gop.found_existing) return gop.value_ptr.*;1296 defer gpa.free(name);
1115
1116 // The Type memory is ephemeral; since we want to store a longer-lived
1117 // reference, we need to copy it here.
1118 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
1119
1120 const opaque_obj = t.castTag(.@"opaque").?.data;
1121 const name = try opaque_obj.getFullyQualifiedName(gpa);
1122 defer gpa.free(name);
11231297
1124 const llvm_struct_ty = dg.context.structCreateNamed(name);1298 if (ty.castTag(.@"struct")) |payload| {
1125 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls1299 const struct_obj = payload.data;
1126 return llvm_struct_ty;1300 if (struct_obj.layout == .Packed) {
1127 },1301 var buf: Type.Payload.Bits = undefined;
1128 .anyopaque => return dg.context.intType(8),1302 const info = struct_obj.packedIntegerType(target, &buf).intInfo(target);
1129 else => unreachable,1303 const dwarf_encoding: c_uint = switch (info.signedness) {
1130 },1304 .signed => DW.ATE.signed,
1131 .Array => {1305 .unsigned => DW.ATE.unsigned,
1132 const elem_ty = t.childType();1306 };
1133 assert(elem_ty.onePossibleValue() == null);1307 const di_ty = dib.createBasicType(name, info.bits, dwarf_encoding);
1134 const elem_llvm_ty = try dg.llvmType(elem_ty);1308 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
1135 const total_len = t.arrayLen() + @boolToInt(t.sentinel() != null);1309 return di_ty;
1136 return elem_llvm_ty.arrayType(@intCast(c_uint, total_len));1310 }
1137 },
1138 .Vector => {
1139 const elem_type = try dg.llvmType(t.childType());
1140 return elem_type.vectorType(t.vectorLen());
1141 },
1142 .Optional => {
1143 var buf: Type.Payload.ElemType = undefined;
1144 const child_ty = t.optionalChild(&buf);
1145 if (!child_ty.hasRuntimeBitsIgnoreComptime()) {
1146 return dg.context.intType(1);
1147 }
1148 const payload_llvm_ty = try dg.llvmType(child_ty);
1149 if (t.isPtrLikeOptional()) {
1150 return payload_llvm_ty;
1151 }1311 }
11521312
1153 const fields: [2]*const llvm.Type = .{1313 const fwd_decl = opt_fwd_decl orelse blk: {
1154 payload_llvm_ty, dg.context.intType(1),1314 const fwd_decl = dib.createReplaceableCompositeType(
1315 DW.TAG.structure_type,
1316 name.ptr,
1317 compile_unit_scope,
1318 null, // file
1319 0, // line
1320 );
1321 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
1322 if (resolve == .fwd) return fwd_decl;
1323 break :blk fwd_decl;
1155 };1324 };
1156 return dg.context.structType(&fields, fields.len, .False);
1157 },
1158 .ErrorUnion => {
1159 const error_type = t.errorUnionSet();
1160 const payload_type = t.errorUnionPayload();
1161 const llvm_error_type = try dg.llvmType(error_type);
1162 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
1163 return llvm_error_type;
1164 }
1165 const llvm_payload_type = try dg.llvmType(payload_type);
1166
1167 const fields: [2]*const llvm.Type = .{ llvm_error_type, llvm_payload_type };
1168 return dg.context.structType(&fields, fields.len, .False);
1169 },
1170 .ErrorSet => {
1171 return dg.context.intType(16);
1172 },
1173 .Struct => {
1174 const gop = try dg.object.type_map.getOrPut(gpa, t);
1175 if (gop.found_existing) return gop.value_ptr.*;
1176
1177 // The Type memory is ephemeral; since we want to store a longer-lived
1178 // reference, we need to copy it here.
1179 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
11801325
1181 if (t.isTupleOrAnonStruct()) {1326 if (ty.isTupleOrAnonStruct()) {
1182 const tuple = t.tupleFields();1327 const tuple = ty.tupleFields();
1183 const llvm_struct_ty = dg.context.structCreateNamed("");
1184 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
11851328
1186 var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{};1329 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
1187 defer llvm_field_types.deinit(gpa);1330 defer di_fields.deinit(gpa);
11881331
1189 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);1332 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
11901333
1191 comptime assert(struct_layout_version == 2);1334 comptime assert(struct_layout_version == 2);
1192 var offset: u64 = 0;1335 var offset: u64 = 0;
1193 var big_align: u32 = 0;
11941336
1195 for (tuple.types) |field_ty, i| {1337 for (tuple.types) |field_ty, i| {
1196 const field_val = tuple.values[i];1338 const field_val = tuple.values[i];
1197 if (field_val.tag() != .unreachable_value) continue;1339 if (field_val.tag() != .unreachable_value) continue;
11981340
1341 const field_size = field_ty.abiSize(target);
1199 const field_align = field_ty.abiAlignment(target);1342 const field_align = field_ty.abiAlignment(target);
1200 big_align = @maximum(big_align, field_align);1343 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1201 const prev_offset = offset;1344 offset = field_offset + field_size;
1202 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1203
1204 const padding_len = offset - prev_offset;
1205 if (padding_len > 0) {
1206 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
1207 try llvm_field_types.append(gpa, llvm_array_ty);
1208 }
1209 const field_llvm_ty = try dg.llvmType(field_ty);
1210 try llvm_field_types.append(gpa, field_llvm_ty);
12111345
1212 offset += field_ty.abiSize(target);1346 const field_name = if (ty.castTag(.anon_struct)) |payload|
1213 }1347 try gpa.dupeZ(u8, payload.data.names[i])
1214 {1348 else
1215 const prev_offset = offset;1349 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
1216 offset = std.mem.alignForwardGeneric(u64, offset, big_align);1350 defer gpa.free(field_name);
1217 const padding_len = offset - prev_offset;1351
1218 if (padding_len > 0) {1352 try di_fields.append(gpa, dib.createMemberType(
1219 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));1353 fwd_decl.toScope(),
1220 try llvm_field_types.append(gpa, llvm_array_ty);1354 field_name,
1221 }1355 null, // file
1356 0, // line
1357 field_size * 8, // size in bits
1358 field_align * 8, // align in bits
1359 field_offset * 8, // offset in bits
1360 0, // flags
1361 try o.lowerDebugType(field_ty, .full),
1362 ));
1222 }1363 }
12231364
1224 llvm_struct_ty.structSetBody(1365 const full_di_ty = dib.createStructType(
1225 llvm_field_types.items.ptr,1366 compile_unit_scope,
1226 @intCast(c_uint, llvm_field_types.items.len),1367 name.ptr,
1227 .False,1368 null, // file
1369 0, // line
1370 ty.abiSize(target) * 8, // size in bits
1371 ty.abiAlignment(target) * 8, // align in bits
1372 0, // flags
1373 null, // derived from
1374 di_fields.items.ptr,
1375 @intCast(c_int, di_fields.items.len),
1376 0, // run time lang
1377 null, // vtable holder
1378 "", // unique id
1228 );1379 );
12291380 dib.replaceTemporary(fwd_decl, full_di_ty);
1230 return llvm_struct_ty;1381 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1382 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty));
1383 return full_di_ty;
1231 }1384 }
12321385
1233 const struct_obj = t.castTag(.@"struct").?.data;1386 if (ty.castTag(.@"struct")) |payload| {
12341387 const struct_obj = payload.data;
1235 if (struct_obj.layout == .Packed) {1388 if (!struct_obj.haveFieldTypes()) {
1236 var buf: Type.Payload.Bits = undefined;1389 // TODO: improve the frontend to populate this struct.
1237 const int_ty = struct_obj.packedIntegerType(target, &buf);1390 // For now we treat it as a zero bit type.
1238 const int_llvm_ty = try dg.llvmType(int_ty);1391 const owner_decl = ty.getOwnerDecl();
1239 gop.value_ptr.* = int_llvm_ty;1392 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
1240 return int_llvm_ty;1393 dib.replaceTemporary(fwd_decl, struct_di_ty);
1394 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
1395 // means we can't use `gop` anymore.
1396 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty));
1397 return struct_di_ty;
1398 }
1241 }1399 }
12421400
1243 const name = try struct_obj.getFullyQualifiedName(gpa);1401 if (!ty.hasRuntimeBitsIgnoreComptime()) {
1244 defer gpa.free(name);1402 const owner_decl = ty.getOwnerDecl();
12451403 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
1246 const llvm_struct_ty = dg.context.structCreateNamed(name);1404 dib.replaceTemporary(fwd_decl, struct_di_ty);
1247 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls1405 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
1406 // means we can't use `gop` anymore.
1407 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty));
1408 return struct_di_ty;
1409 }
12481410
1249 assert(struct_obj.haveFieldTypes());1411 const fields = ty.structFields();
12501412
1251 var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{};1413 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
1252 defer llvm_field_types.deinit(gpa);1414 defer di_fields.deinit(gpa);
12531415
1254 try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count());1416 try di_fields.ensureUnusedCapacity(gpa, fields.count());
12551417
1256 comptime assert(struct_layout_version == 2);1418 comptime assert(struct_layout_version == 2);
1257 var offset: u64 = 0;1419 var offset: u64 = 0;
1258 var big_align: u32 = 0;
12591420
1260 for (struct_obj.fields.values()) |field| {1421 for (fields.values()) |field, i| {
1261 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;1422 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
12621423
1424 const field_size = field.ty.abiSize(target);
1263 const field_align = field.normalAlignment(target);1425 const field_align = field.normalAlignment(target);
1264 big_align = @maximum(big_align, field_align);1426 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1265 const prev_offset = offset;1427 offset = field_offset + field_size;
1266 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
12671428
1268 const padding_len = offset - prev_offset;1429 const field_name = try gpa.dupeZ(u8, fields.keys()[i]);
1269 if (padding_len > 0) {1430 defer gpa.free(field_name);
1270 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
1271 try llvm_field_types.append(gpa, llvm_array_ty);
1272 }
1273 const field_llvm_ty = try dg.llvmType(field.ty);
1274 try llvm_field_types.append(gpa, field_llvm_ty);
12751431
1276 offset += field.ty.abiSize(target);1432 try di_fields.append(gpa, dib.createMemberType(
1277 }1433 fwd_decl.toScope(),
1278 {1434 field_name,
1279 const prev_offset = offset;1435 null, // file
1280 offset = std.mem.alignForwardGeneric(u64, offset, big_align);1436 0, // line
1281 const padding_len = offset - prev_offset;1437 field_size * 8, // size in bits
1282 if (padding_len > 0) {1438 field_align * 8, // align in bits
1283 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));1439 field_offset * 8, // offset in bits
1284 try llvm_field_types.append(gpa, llvm_array_ty);1440 0, // flags
1285 }1441 try o.lowerDebugType(field.ty, .full),
1442 ));
1286 }1443 }
12871444
1288 llvm_struct_ty.structSetBody(1445 const full_di_ty = dib.createStructType(
1289 llvm_field_types.items.ptr,1446 compile_unit_scope,
1290 @intCast(c_uint, llvm_field_types.items.len),1447 name.ptr,
1291 .False,1448 null, // file
1449 0, // line
1450 ty.abiSize(target) * 8, // size in bits
1451 ty.abiAlignment(target) * 8, // align in bits
1452 0, // flags
1453 null, // derived from
1454 di_fields.items.ptr,
1455 @intCast(c_int, di_fields.items.len),
1456 0, // run time lang
1457 null, // vtable holder
1458 "", // unique id
1292 );1459 );
12931460 dib.replaceTemporary(fwd_decl, full_di_ty);
1294 return llvm_struct_ty;1461 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1462 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty));
1463 return full_di_ty;
1295 },1464 },
1296 .Union => {1465 .Union => {
1297 const gop = try dg.object.type_map.getOrPut(gpa, t);1466 const owner_decl = ty.getOwnerDecl();
1298 if (gop.found_existing) return gop.value_ptr.*;
12991467
1300 // The Type memory is ephemeral; since we want to store a longer-lived1468 const name = try ty.nameAlloc(gpa);
1301 // reference, we need to copy it here.1469 defer gpa.free(name);
1302 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
13031470
1304 const layout = t.unionGetLayout(target);1471 const fwd_decl = opt_fwd_decl orelse blk: {
1305 const union_obj = t.cast(Type.Payload.Union).?.data;1472 const fwd_decl = dib.createReplaceableCompositeType(
1473 DW.TAG.structure_type,
1474 name.ptr,
1475 o.di_compile_unit.?.toScope(),
1476 null, // file
1477 0, // line
1478 );
1479 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
1480 if (resolve == .fwd) return fwd_decl;
1481 break :blk fwd_decl;
1482 };
13061483
1307 if (layout.payload_size == 0) {1484 const TODO_implement_this = true; // TODO
1308 const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);1485 if (TODO_implement_this or !ty.hasRuntimeBitsIgnoreComptime()) {
1309 gop.value_ptr.* = enum_tag_llvm_ty;1486 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
1310 return enum_tag_llvm_ty;1487 dib.replaceTemporary(fwd_decl, union_di_ty);
1488 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
1489 // means we can't use `gop` anymore.
1490 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty));
1491 return union_di_ty;
1311 }1492 }
13121493
1313 const name = try union_obj.getFullyQualifiedName(gpa);1494 @panic("TODO debug info type for union");
1314 defer gpa.free(name);1495 //const gop = try o.type_map.getOrPut(gpa, ty);
1496 //if (gop.found_existing) return gop.value_ptr.*;
13151497
1316 const llvm_union_ty = dg.context.structCreateNamed(name);1498 //// The Type memory is ephemeral; since we want to store a longer-lived
1317 gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls1499 //// reference, we need to copy it here.
1500 //gop.key_ptr.* = try ty.copy(o.type_map_arena.allocator());
13181501
1319 const aligned_field = union_obj.fields.values()[layout.most_aligned_field];1502 //const layout = ty.unionGetLayout(target);
1320 const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty);1503 //const union_obj = ty.cast(Type.Payload.Union).?.data;
13211504
1322 const llvm_payload_ty = t: {1505 //if (layout.payload_size == 0) {
1323 if (layout.most_aligned_field_size == layout.payload_size) {1506 // const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
1324 break :t llvm_aligned_field_ty;1507 // gop.value_ptr.* = enum_tag_llvm_ty;
1325 }1508 // return enum_tag_llvm_ty;
1326 const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);1509 //}
1327 const fields: [2]*const llvm.Type = .{
1328 llvm_aligned_field_ty,
1329 dg.context.intType(8).arrayType(padding_len),
1330 };
1331 break :t dg.context.structType(&fields, fields.len, .True);
1332 };
13331510
1334 if (layout.tag_size == 0) {1511 //const name = try union_obj.getFullyQualifiedName(gpa);
1335 var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty};1512 //defer gpa.free(name);
1336 llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False);
1337 return llvm_union_ty;
1338 }
1339 const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
13401513
1341 // Put the tag before or after the payload depending on which one's1514 //const llvm_union_ty = dg.context.structCreateNamed(name);
1342 // alignment is greater.1515 //gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls
1343 var llvm_fields: [3]*const llvm.Type = undefined;
1344 var llvm_fields_len: c_uint = 2;
13451516
1346 if (layout.tag_align >= layout.payload_align) {1517 //const aligned_field = union_obj.fields.values()[layout.most_aligned_field];
1347 llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined };1518 //const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty);
1348 } else {
1349 llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined };
1350 }
13511519
1352 // Insert padding to make the LLVM struct ABI size match the Zig union ABI size.1520 //const llvm_payload_ty = ty: {
1353 if (layout.padding != 0) {1521 // if (layout.most_aligned_field_size == layout.payload_size) {
1354 llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding);1522 // break :ty llvm_aligned_field_ty;
1355 llvm_fields_len = 3;1523 // }
1356 }1524 // const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);
1525 // const fields: [2]*const llvm.Type = .{
1526 // llvm_aligned_field_ty,
1527 // dg.context.intType(8).arrayType(padding_len),
1528 // };
1529 // break :ty dg.context.structType(&fields, fields.len, .True);
1530 //};
13571531
1358 llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);1532 //if (layout.tag_size == 0) {
1359 return llvm_union_ty;1533 // var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty};
1534 // llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False);
1535 // return llvm_union_ty;
1536 //}
1537 //const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
1538
1539 //// Put the tag before or after the payload depending on which one's
1540 //// alignment is greater.
1541 //var llvm_fields: [3]*const llvm.Type = undefined;
1542 //var llvm_fields_len: c_uint = 2;
1543
1544 //if (layout.tag_align >= layout.payload_align) {
1545 // llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined };
1546 //} else {
1547 // llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined };
1548 //}
1549
1550 //// Insert padding to make the LLVM struct ABI size match the Zig union ABI size.
1551 //if (layout.padding != 0) {
1552 // llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding);
1553 // llvm_fields_len = 3;
1554 //}
1555
1556 //llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);
1557 //return llvm_union_ty;
1360 },1558 },
1361 .Fn => {1559 .Fn => {
1362 const fn_info = t.fnInfo();1560 const fn_info = ty.fnInfo();
1363 const sret = firstParamSRet(fn_info, target);1561 const sret = firstParamSRet(fn_info, target);
1364 const return_type = fn_info.return_type;
1365 const llvm_sret_ty = if (return_type.hasRuntimeBitsIgnoreComptime())
1366 try dg.llvmType(return_type)
1367 else
1368 dg.context.voidType();
1369 const llvm_ret_ty = if (sret) dg.context.voidType() else llvm_sret_ty;
13701562
1371 var llvm_params = std.ArrayList(*const llvm.Type).init(dg.gpa);1563 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);
1372 defer llvm_params.deinit();1564 defer param_di_types.deinit();
13731565
1374 if (sret) {1566 // Return type goes first.
1375 try llvm_params.append(llvm_sret_ty.pointerType(0));1567 const di_ret_ty = if (sret or !fn_info.return_type.hasRuntimeBitsIgnoreComptime())
1376 }1568 Type.void
1569 else
1570 fn_info.return_type;
1571 try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full));
13771572
1378 for (fn_info.param_types) |param_ty| {1573 if (sret) {
1379 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;1574 var ptr_ty_payload: Type.Payload.ElemType = .{
1575 .base = .{ .tag = .single_mut_pointer },
1576 .data = fn_info.return_type,
1577 };
1578 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
1579 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
1580 }
13801581
1381 const raw_llvm_ty = try dg.llvmType(param_ty);1582 for (fn_info.param_types) |param_ty| {
1382 const actual_llvm_ty = if (!isByRef(param_ty)) raw_llvm_ty else raw_llvm_ty.pointerType(0);1583 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
1383 try llvm_params.append(actual_llvm_ty);1584
1585 if (isByRef(param_ty)) {
1586 var ptr_ty_payload: Type.Payload.ElemType = .{
1587 .base = .{ .tag = .single_mut_pointer },
1588 .data = param_ty,
1589 };
1590 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
1591 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
1592 } else {
1593 try param_di_types.append(try o.lowerDebugType(param_ty, .full));
1594 }
1384 }1595 }
13851596
1386 return llvm.functionType(1597 const fn_di_ty = dib.createSubroutineType(
1387 llvm_ret_ty,1598 param_di_types.items.ptr,
1388 llvm_params.items.ptr,1599 @intCast(c_int, param_di_types.items.len),
1389 @intCast(c_uint, llvm_params.items.len),1600 0,
1390 llvm.Bool.fromBool(fn_info.is_var_args),
1391 );1601 );
1602 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1603 try o.di_type_map.put(gpa, ty, AnnotatedDITypePtr.initFull(fn_di_ty));
1604 return fn_di_ty;
1392 },1605 },
1393 .ComptimeInt => unreachable,1606 .ComptimeInt => unreachable,
1394 .ComptimeFloat => unreachable,1607 .ComptimeFloat => unreachable,
...@@ -1399,1387 +1612,1282 @@ pub const DeclGen = struct {...@@ -1399,1387 +1612,1282 @@ pub const DeclGen = struct {
13991612
1400 .BoundFn => @panic("TODO remove BoundFn from the language"),1613 .BoundFn => @panic("TODO remove BoundFn from the language"),
14011614
1402 .Frame => @panic("TODO implement llvmType for Frame types"),1615 .Frame => @panic("TODO implement lowerDebugType for Frame types"),
1403 .AnyFrame => @panic("TODO implement llvmType for AnyFrame types"),1616 .AnyFrame => @panic("TODO implement lowerDebugType for AnyFrame types"),
1404 }1617 }
1405 }1618 }
14061619
1407 fn genTypedValue(dg: *DeclGen, tv: TypedValue) Error!*const llvm.Value {1620 fn namespaceToDebugScope(o: *Object, namespace: *const Module.Namespace) !*llvm.DIScope {
1408 if (tv.val.isUndef()) {1621 if (namespace.parent == null) {
1409 const llvm_type = try dg.llvmType(tv.ty);1622 const di_file = try o.getDIFile(o.gpa, namespace.file_scope);
1410 return llvm_type.getUndef();1623 return di_file.toScope();
1411 }1624 }
1625 const di_type = try o.lowerDebugType(namespace.ty, .fwd);
1626 return di_type.toScope();
1627 }
14121628
1413 switch (tv.ty.zigTypeTag()) {1629 /// This is to be used instead of void for debug info types, to avoid tripping
1414 .Bool => {1630 /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
1415 const llvm_type = try dg.llvmType(tv.ty);1631 /// when targeting CodeView (Windows).
1416 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();1632 fn makeEmptyNamespaceDIType(o: *Object, decl: *const Module.Decl) !*llvm.DIType {
1417 },1633 const fields: [0]*llvm.DIType = .{};
1418 // TODO this duplicates code with Pointer but they should share the handling1634 return o.di_builder.?.createStructType(
1419 // of the tv.val.tag() and then Int should do extra constPtrToInt on top1635 try o.namespaceToDebugScope(decl.src_namespace),
1420 .Int => switch (tv.val.tag()) {1636 decl.name, // TODO use fully qualified name
1421 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl),1637 try o.getDIFile(o.gpa, decl.src_namespace.file_scope),
1422 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),1638 decl.src_line + 1,
1423 else => {1639 0, // size in bits
1424 var bigint_space: Value.BigIntSpace = undefined;1640 0, // align in bits
1425 const bigint = tv.val.toBigInt(&bigint_space);1641 0, // flags
1426 const target = dg.module.getTarget();1642 null, // derived from
1427 const int_info = tv.ty.intInfo(target);1643 undefined, // TODO should be able to pass &fields,
1428 assert(int_info.bits != 0);1644 fields.len,
1429 const llvm_type = dg.context.intType(int_info.bits);1645 0, // run time lang
1646 null, // vtable holder
1647 "", // unique id
1648 );
1649 }
1650};
14301651
1431 const unsigned_val = v: {1652pub const DeclGen = struct {
1432 if (bigint.limbs.len == 1) {1653 context: *const llvm.Context,
1433 break :v llvm_type.constInt(bigint.limbs[0], .False);1654 object: *Object,
1434 }1655 module: *Module,
1435 if (@sizeOf(usize) == @sizeOf(u64)) {1656 decl: *Module.Decl,
1436 break :v llvm_type.constIntOfArbitraryPrecision(1657 gpa: Allocator,
1437 @intCast(c_uint, bigint.limbs.len),1658 err_msg: ?*Module.ErrorMsg,
1438 bigint.limbs.ptr,
1439 );
1440 }
1441 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
1442 };
1443 if (!bigint.positive) {
1444 return llvm.constNeg(unsigned_val);
1445 }
1446 return unsigned_val;
1447 },
1448 },
1449 .Enum => {
1450 var int_buffer: Value.Payload.U64 = undefined;
1451 const int_val = tv.enumToInt(&int_buffer);
14521659
1453 var bigint_space: Value.BigIntSpace = undefined;1660 fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
1454 const bigint = int_val.toBigInt(&bigint_space);1661 @setCold(true);
1662 assert(self.err_msg == null);
1663 const src_loc = @as(LazySrcLoc, .{ .node_offset = 0 }).toSrcLoc(self.decl);
1664 self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args);
1665 return error.CodegenFail;
1666 }
14551667
1456 const target = dg.module.getTarget();1668 fn llvmModule(self: *DeclGen) *const llvm.Module {
1457 const int_info = tv.ty.intInfo(target);1669 return self.object.llvm_module;
1458 const llvm_type = dg.context.intType(int_info.bits);1670 }
14591671
1460 const unsigned_val = v: {1672 fn genDecl(dg: *DeclGen) !void {
1461 if (bigint.limbs.len == 1) {1673 const decl = dg.decl;
1462 break :v llvm_type.constInt(bigint.limbs[0], .False);1674 assert(decl.has_tv);
1463 }1675
1464 if (@sizeOf(usize) == @sizeOf(u64)) {1676 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val });
1465 break :v llvm_type.constIntOfArbitraryPrecision(1677
1466 @intCast(c_uint, bigint.limbs.len),1678 if (decl.val.castTag(.function)) |func_payload| {
1467 bigint.limbs.ptr,1679 _ = func_payload;
1468 );1680 @panic("TODO llvm backend genDecl function pointer");
1469 }1681 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {
1470 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");1682 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
1471 };1683 } else {
1472 if (!bigint.positive) {1684 const target = dg.module.getTarget();
1473 return llvm.constNeg(unsigned_val);1685 var global = try dg.resolveGlobalDecl(decl);
1474 }1686 global.setAlignment(decl.getAlignment(target));
1475 return unsigned_val;1687 assert(decl.has_tv);
1476 },1688 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
1477 .Float => {1689 const variable = payload.data;
1478 const llvm_ty = try dg.llvmType(tv.ty);1690 break :init_val variable.init;
1479 const target = dg.module.getTarget();1691 } else init_val: {
1480 switch (tv.ty.floatBits(target)) {1692 global.setGlobalConstant(.True);
1481 16, 32, 64 => return llvm_ty.constReal(tv.val.toFloat(f64)),1693 break :init_val decl.val;
1482 80 => {1694 };
1483 const float = tv.val.toFloat(f80);1695 if (init_val.tag() != .unreachable_value) {
1484 const repr = std.math.break_f80(float);1696 const llvm_init = try dg.genTypedValue(.{ .ty = decl.ty, .val = init_val });
1485 const llvm_i80 = dg.context.intType(80);1697 if (global.globalGetValueType() == llvm_init.typeOf()) {
1486 var x = llvm_i80.constInt(repr.exp, .False);1698 global.setInitializer(llvm_init);
1487 x = x.constShl(llvm_i80.constInt(64, .False));1699 } else {
1488 x = x.constOr(llvm_i80.constInt(repr.fraction, .False));1700 // LLVM does not allow us to change the type of globals. So we must
1489 if (backendSupportsF80(target)) {1701 // create a new global with the correct type, copy all its attributes,
1490 return x.constBitCast(llvm_ty);1702 // and then update all references to point to the new global,
1491 } else {1703 // delete the original, and rename the new one to the old one's name.
1492 return x;1704 // This is necessary because LLVM does not support const bitcasting
1493 }1705 // a struct with padding bytes, which is needed to lower a const union value
1494 },1706 // to LLVM, when a field other than the most-aligned is active. Instead,
1495 128 => {1707 // we must lower to an unnamed struct, and pointer cast at usage sites
1496 var buf: [2]u64 = @bitCast([2]u64, tv.val.toFloat(f128));1708 // of the global. Such an unnamed struct is the cause of the global type
1497 // LLVM seems to require that the lower half of the f128 be placed first1709 // mismatch, because we don't have the LLVM type until the *value* is created,
1498 // in the buffer.1710 // whereas the global needs to be created based on the type alone, because
1499 if (native_endian == .Big) {1711 // lowering the value may reference the global as a pointer.
1500 std.mem.swap(u64, &buf[0], &buf[1]);1712 const new_global = dg.object.llvm_module.addGlobalInAddressSpace(
1501 }1713 llvm_init.typeOf(),
1502 const int = dg.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf);1714 "",
1503 return int.constBitCast(llvm_ty);1715 dg.llvmAddressSpace(decl.@"addrspace"),
1504 },1716 );
1505 else => unreachable,1717 new_global.setLinkage(global.getLinkage());
1718 new_global.setUnnamedAddr(global.getUnnamedAddress());
1719 new_global.setAlignment(global.getAlignment());
1720 new_global.setInitializer(llvm_init);
1721 // replaceAllUsesWith requires the type to be unchanged. So we bitcast
1722 // the new global to the old type and use that as the thing to replace
1723 // old uses.
1724 const new_global_ptr = new_global.constBitCast(global.typeOf());
1725 global.replaceAllUsesWith(new_global_ptr);
1726 dg.object.decl_map.putAssumeCapacity(decl, new_global);
1727 new_global.takeName(global);
1728 global.deleteGlobal();
1729 global = new_global;
1506 }1730 }
1507 },1731 }
1508 .Pointer => switch (tv.val.tag()) {
1509 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl),
1510 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
1511 .variable => {
1512 const decl = tv.val.castTag(.variable).?.data.owner_decl;
1513 decl.markAlive();
1514 const val = try dg.resolveGlobalDecl(decl);
1515 const llvm_var_type = try dg.llvmType(tv.ty);
1516 const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");
1517 const llvm_type = llvm_var_type.pointerType(llvm_addrspace);
1518 return val.constBitCast(llvm_type);
1519 },
1520 .slice => {
1521 const slice = tv.val.castTag(.slice).?.data;
1522 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1523 const fields: [2]*const llvm.Value = .{
1524 try dg.genTypedValue(.{
1525 .ty = tv.ty.slicePtrFieldType(&buf),
1526 .val = slice.ptr,
1527 }),
1528 try dg.genTypedValue(.{
1529 .ty = Type.usize,
1530 .val = slice.len,
1531 }),
1532 };
1533 return dg.context.constStruct(&fields, fields.len, .False);
1534 },
1535 .int_u64, .one, .int_big_positive => {
1536 const llvm_usize = try dg.llvmType(Type.usize);
1537 const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(), .False);
1538 return llvm_int.constIntToPtr(try dg.llvmType(tv.ty));
1539 },
1540 .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => {
1541 return dg.lowerParentPtr(tv.val, tv.ty.childType());
1542 },
1543 .null_value, .zero => {
1544 const llvm_type = try dg.llvmType(tv.ty);
1545 return llvm_type.constNull();
1546 },
1547 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }),
1548 },
1549 .Array => switch (tv.val.tag()) {
1550 .bytes => {
1551 const bytes = tv.val.castTag(.bytes).?.data;
1552 return dg.context.constString(
1553 bytes.ptr,
1554 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel()),
1555 .True, // don't null terminate. bytes has the sentinel, if any.
1556 );
1557 },
1558 .aggregate => {
1559 const elem_vals = tv.val.castTag(.aggregate).?.data;
1560 const elem_ty = tv.ty.elemType();
1561 const gpa = dg.gpa;
1562 const len = @intCast(usize, tv.ty.arrayLenIncludingSentinel());
1563 const llvm_elems = try gpa.alloc(*const llvm.Value, len);
1564 defer gpa.free(llvm_elems);
1565 var need_unnamed = false;
1566 for (elem_vals[0..len]) |elem_val, i| {
1567 llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val });
1568 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
1569 }
1570 if (need_unnamed) {
1571 return dg.context.constStruct(
1572 llvm_elems.ptr,
1573 @intCast(c_uint, llvm_elems.len),
1574 .True,
1575 );
1576 } else {
1577 const llvm_elem_ty = try dg.llvmType(elem_ty);
1578 return llvm_elem_ty.constArray(
1579 llvm_elems.ptr,
1580 @intCast(c_uint, llvm_elems.len),
1581 );
1582 }
1583 },
1584 .repeated => {
1585 const val = tv.val.castTag(.repeated).?.data;
1586 const elem_ty = tv.ty.elemType();
1587 const sentinel = tv.ty.sentinel();
1588 const len = @intCast(usize, tv.ty.arrayLen());
1589 const len_including_sent = len + @boolToInt(sentinel != null);
1590 const gpa = dg.gpa;
1591 const llvm_elems = try gpa.alloc(*const llvm.Value, len_including_sent);
1592 defer gpa.free(llvm_elems);
1593
1594 var need_unnamed = false;
1595 if (len != 0) {
1596 for (llvm_elems[0..len]) |*elem| {
1597 elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val });
1598 }
1599 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
1600 }
16011732
1602 if (sentinel) |sent| {1733 if (dg.object.di_builder) |dib| {
1603 llvm_elems[len] = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent });1734 const di_file = try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope);
1604 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
1605 }
16061735
1607 if (need_unnamed) {1736 const line_number = decl.src_line + 1;
1608 return dg.context.constStruct(1737 const is_internal_linkage = !dg.module.decl_exports.contains(decl);
1609 llvm_elems.ptr,1738 const di_global = dib.createGlobalVariable(
1610 @intCast(c_uint, llvm_elems.len),1739 di_file.toScope(),
1611 .True,1740 decl.name,
1612 );1741 global.getValueName(),
1613 } else {1742 di_file,
1614 const llvm_elem_ty = try dg.llvmType(elem_ty);1743 line_number,
1615 return llvm_elem_ty.constArray(1744 try dg.object.lowerDebugType(decl.ty, .full),
1616 llvm_elems.ptr,1745 is_internal_linkage,
1617 @intCast(c_uint, llvm_elems.len),1746 );
1618 );
1619 }
1620 },
1621 .empty_array_sentinel => {
1622 const elem_ty = tv.ty.elemType();
1623 const sent_val = tv.ty.sentinel().?;
1624 const sentinel = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent_val });
1625 const llvm_elems: [1]*const llvm.Value = .{sentinel};
1626 const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]);
1627 if (need_unnamed) {
1628 return dg.context.constStruct(&llvm_elems, llvm_elems.len, .True);
1629 } else {
1630 const llvm_elem_ty = try dg.llvmType(elem_ty);
1631 return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
1632 }
1633 },
1634 else => unreachable,
1635 },
1636 .Optional => {
1637 var buf: Type.Payload.ElemType = undefined;
1638 const payload_ty = tv.ty.optionalChild(&buf);
1639 const llvm_i1 = dg.context.intType(1);
1640 const is_pl = !tv.val.isNull();
1641 const non_null_bit = if (is_pl) llvm_i1.constAllOnes() else llvm_i1.constNull();
1642 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1643 return non_null_bit;
1644 }
1645 if (tv.ty.isPtrLikeOptional()) {
1646 if (tv.val.castTag(.opt_payload)) |payload| {
1647 return dg.genTypedValue(.{ .ty = payload_ty, .val = payload.data });
1648 } else if (is_pl) {
1649 return dg.genTypedValue(.{ .ty = payload_ty, .val = tv.val });
1650 } else {
1651 const llvm_ty = try dg.llvmType(tv.ty);
1652 return llvm_ty.constNull();
1653 }
1654 }
1655 assert(payload_ty.zigTypeTag() != .Fn);
1656 const fields: [2]*const llvm.Value = .{
1657 try dg.genTypedValue(.{
1658 .ty = payload_ty,
1659 .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),
1660 }),
1661 non_null_bit,
1662 };
1663 return dg.context.constStruct(&fields, fields.len, .False);
1664 },
1665 .Fn => {
1666 const fn_decl = switch (tv.val.tag()) {
1667 .extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl,
1668 .function => tv.val.castTag(.function).?.data.owner_decl,
1669 else => unreachable,
1670 };
1671 fn_decl.markAlive();
1672 return dg.resolveLlvmFunction(fn_decl);
1673 },
1674 .ErrorSet => {
1675 const llvm_ty = try dg.llvmType(tv.ty);
1676 switch (tv.val.tag()) {
1677 .@"error" => {
1678 const err_name = tv.val.castTag(.@"error").?.data.name;
1679 const kv = try dg.module.getErrorValue(err_name);
1680 return llvm_ty.constInt(kv.value, .False);
1681 },
1682 else => {
1683 // In this case we are rendering an error union which has a 0 bits payload.
1684 return llvm_ty.constNull();
1685 },
1686 }
1687 },
1688 .ErrorUnion => {
1689 const error_type = tv.ty.errorUnionSet();
1690 const payload_type = tv.ty.errorUnionPayload();
1691 const is_pl = tv.val.errorUnionIsPayload();
16921747
1693 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {1748 try dg.object.di_map.put(dg.gpa, dg.decl, di_global.toNode());
1694 // We use the error type directly as the type.1749 }
1695 const err_val = if (!is_pl) tv.val else Value.initTag(.zero);1750 }
1696 return dg.genTypedValue(.{ .ty = error_type, .val = err_val });1751 }
1697 }
16981752
1699 const fields: [2]*const llvm.Value = .{1753 /// If the llvm function does not exist, create it.
1700 try dg.genTypedValue(.{1754 /// Note that this can be called before the function's semantic analysis has
1701 .ty = error_type,1755 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.
1702 .val = if (is_pl) Value.initTag(.zero) else tv.val,1756 fn resolveLlvmFunction(dg: *DeclGen, decl: *Module.Decl) !*const llvm.Value {
1703 }),1757 const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl);
1704 try dg.genTypedValue(.{1758 if (gop.found_existing) return gop.value_ptr.*;
1705 .ty = payload_type,
1706 .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef),
1707 }),
1708 };
1709 return dg.context.constStruct(&fields, fields.len, .False);
1710 },
1711 .Struct => {
1712 const llvm_struct_ty = try dg.llvmType(tv.ty);
1713 const field_vals = tv.val.castTag(.aggregate).?.data;
1714 const gpa = dg.gpa;
1715 const target = dg.module.getTarget();
17161759
1717 if (tv.ty.isTupleOrAnonStruct()) {1760 assert(decl.has_tv);
1718 const tuple = tv.ty.tupleFields();1761 const zig_fn_type = decl.ty;
1719 var llvm_fields: std.ArrayListUnmanaged(*const llvm.Value) = .{};1762 const fn_info = zig_fn_type.fnInfo();
1720 defer llvm_fields.deinit(gpa);1763 const target = dg.module.getTarget();
1764 const sret = firstParamSRet(fn_info, target);
17211765
1722 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);1766 const fn_type = try dg.llvmType(zig_fn_type);
17231767
1724 comptime assert(struct_layout_version == 2);1768 const fqn = try decl.getFullyQualifiedName(dg.gpa);
1725 var offset: u64 = 0;1769 defer dg.gpa.free(fqn);
1726 var big_align: u32 = 0;
1727 var need_unnamed = false;
17281770
1729 for (tuple.types) |field_ty, i| {1771 const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");
1730 if (tuple.values[i].tag() != .unreachable_value) continue;1772 const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(fqn, fn_type, llvm_addrspace);
1731 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;1773 gop.value_ptr.* = llvm_fn;
17321774
1733 const field_align = field_ty.abiAlignment(target);1775 const is_extern = decl.isExtern();
1734 big_align = @maximum(big_align, field_align);1776 if (!is_extern) {
1735 const prev_offset = offset;1777 llvm_fn.setLinkage(.Internal);
1736 offset = std.mem.alignForwardGeneric(u64, offset, field_align);1778 llvm_fn.setUnnamedAddr(.True);
1779 } else if (dg.module.getTarget().isWasm()) {
1780 dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0));
1781 if (decl.getExternFn().?.lib_name) |lib_name| {
1782 const module_name = std.mem.sliceTo(lib_name, 0);
1783 if (!std.mem.eql(u8, module_name, "c")) {
1784 dg.addFnAttrString(llvm_fn, "wasm-import-module", module_name);
1785 }
1786 }
1787 }
17371788
1738 const padding_len = offset - prev_offset;1789 if (sret) {
1739 if (padding_len > 0) {1790 dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0
1740 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));1791 dg.addArgAttr(llvm_fn, 0, "noalias");
1741 // TODO make this and all other padding elsewhere in debug
1742 // builds be 0xaa not undef.
1743 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
1744 }
17451792
1746 const field_llvm_val = try dg.genTypedValue(.{1793 const raw_llvm_ret_ty = try dg.llvmType(fn_info.return_type);
1747 .ty = field_ty,1794 llvm_fn.addSretAttr(0, raw_llvm_ret_ty);
1748 .val = field_vals[i],1795 }
1749 });
17501796
1751 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field_llvm_val);1797 // Set parameter attributes.
17521798 var llvm_param_i: c_uint = @boolToInt(sret);
1753 llvm_fields.appendAssumeCapacity(field_llvm_val);1799 for (fn_info.param_types) |param_ty| {
1800 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
17541801
1755 offset += field_ty.abiSize(target);1802 if (isByRef(param_ty)) {
1756 }1803 dg.addArgAttr(llvm_fn, llvm_param_i, "nonnull");
1757 {1804 // TODO readonly, noalias, align
1758 const prev_offset = offset;1805 }
1759 offset = std.mem.alignForwardGeneric(u64, offset, big_align);1806 llvm_param_i += 1;
1760 const padding_len = offset - prev_offset;1807 }
1761 if (padding_len > 0) {
1762 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
1763 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
1764 }
1765 }
17661808
1767 if (need_unnamed) {1809 // TODO: more attributes. see codegen.cpp `make_fn_llvm_value`.
1768 return dg.context.constStruct(1810 if (fn_info.cc == .Naked) {
1769 llvm_fields.items.ptr,1811 dg.addFnAttr(llvm_fn, "naked");
1770 @intCast(c_uint, llvm_fields.items.len),1812 } else {
1771 .False,1813 llvm_fn.setFunctionCallConv(toLlvmCallConv(fn_info.cc, target));
1772 );1814 }
1773 } else {
1774 return llvm_struct_ty.constNamedStruct(
1775 llvm_fields.items.ptr,
1776 @intCast(c_uint, llvm_fields.items.len),
1777 );
1778 }
1779 }
17801815
1781 const struct_obj = tv.ty.castTag(.@"struct").?.data;1816 if (fn_info.alignment != 0) {
1817 llvm_fn.setAlignment(fn_info.alignment);
1818 }
17821819
1783 if (struct_obj.layout == .Packed) {1820 // Function attributes that are independent of analysis results of the function body.
1784 const big_bits = struct_obj.packedIntegerBits(target);1821 dg.addCommonFnAttributes(llvm_fn);
1785 const int_llvm_ty = dg.context.intType(big_bits);
1786 const fields = struct_obj.fields.values();
1787 comptime assert(Type.packed_struct_layout_version == 2);
1788 var running_int: *const llvm.Value = int_llvm_ty.constNull();
1789 var running_bits: u16 = 0;
1790 for (field_vals) |field_val, i| {
1791 const field = fields[i];
1792 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
17931822
1794 const non_int_val = try dg.genTypedValue(.{1823 if (fn_info.return_type.isNoReturn()) {
1795 .ty = field.ty,1824 dg.addFnAttr(llvm_fn, "noreturn");
1796 .val = field_val,1825 }
1797 });
1798 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
1799 const small_int_ty = dg.context.intType(ty_bit_size);
1800 const small_int_val = non_int_val.constBitCast(small_int_ty);
1801 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
1802 // If the field is as large as the entire packed struct, this
1803 // zext would go from, e.g. i16 to i16. This is legal with
1804 // constZExtOrBitCast but not legal with constZExt.
1805 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);
1806 const shifted = extended_int_val.constShl(shift_rhs);
1807 running_int = running_int.constOr(shifted);
1808 running_bits += ty_bit_size;
1809 }
1810 return running_int;
1811 }
18121826
1813 const llvm_field_count = llvm_struct_ty.countStructElementTypes();1827 return llvm_fn;
1814 var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, llvm_field_count);1828 }
1815 defer llvm_fields.deinit(gpa);
18161829
1817 comptime assert(struct_layout_version == 2);1830 fn addCommonFnAttributes(dg: *DeclGen, llvm_fn: *const llvm.Value) void {
1818 var offset: u64 = 0;1831 if (!dg.module.comp.bin_file.options.red_zone) {
1819 var big_align: u32 = 0;1832 dg.addFnAttr(llvm_fn, "noredzone");
1820 var need_unnamed = false;1833 }
1834 if (dg.module.comp.bin_file.options.omit_frame_pointer) {
1835 dg.addFnAttrString(llvm_fn, "frame-pointer", "none");
1836 } else {
1837 dg.addFnAttrString(llvm_fn, "frame-pointer", "all");
1838 }
1839 dg.addFnAttr(llvm_fn, "nounwind");
1840 if (dg.module.comp.unwind_tables) {
1841 dg.addFnAttr(llvm_fn, "uwtable");
1842 }
1843 if (dg.module.comp.bin_file.options.skip_linker_dependencies) {
1844 // The intent here is for compiler-rt and libc functions to not generate
1845 // infinite recursion. For example, if we are compiling the memcpy function,
1846 // and llvm detects that the body is equivalent to memcpy, it may replace the
1847 // body of memcpy with a call to memcpy, which would then cause a stack
1848 // overflow instead of performing memcpy.
1849 dg.addFnAttr(llvm_fn, "nobuiltin");
1850 }
1851 if (dg.module.comp.bin_file.options.optimize_mode == .ReleaseSmall) {
1852 dg.addFnAttr(llvm_fn, "minsize");
1853 dg.addFnAttr(llvm_fn, "optsize");
1854 }
1855 if (dg.module.comp.bin_file.options.tsan) {
1856 dg.addFnAttr(llvm_fn, "sanitize_thread");
1857 }
1858 // TODO add target-cpu and target-features fn attributes
1859 }
18211860
1822 for (struct_obj.fields.values()) |field, i| {1861 fn resolveGlobalDecl(dg: *DeclGen, decl: *Module.Decl) Error!*const llvm.Value {
1823 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;1862 const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl);
1863 if (gop.found_existing) return gop.value_ptr.*;
1864 errdefer assert(dg.object.decl_map.remove(decl));
18241865
1825 const field_align = field.normalAlignment(target);1866 const fqn = try decl.getFullyQualifiedName(dg.gpa);
1826 big_align = @maximum(big_align, field_align);1867 defer dg.gpa.free(fqn);
1827 const prev_offset = offset;
1828 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
18291868
1830 const padding_len = offset - prev_offset;1869 const llvm_type = try dg.llvmType(decl.ty);
1831 if (padding_len > 0) {1870 const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");
1832 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));1871 const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace(llvm_type, fqn, llvm_addrspace);
1833 // TODO make this and all other padding elsewhere in debug1872 gop.value_ptr.* = llvm_global;
1834 // builds be 0xaa not undef.
1835 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
1836 }
18371873
1838 const field_llvm_val = try dg.genTypedValue(.{1874 // This is needed for declarations created by `@extern`.
1839 .ty = field.ty,1875 if (decl.isExtern()) {
1840 .val = field_vals[i],1876 llvm_global.setValueName(decl.name);
1841 });1877 llvm_global.setUnnamedAddr(.False);
1878 llvm_global.setLinkage(.External);
1879 if (decl.val.castTag(.variable)) |variable| {
1880 const single_threaded = dg.module.comp.bin_file.options.single_threaded;
1881 if (variable.data.is_threadlocal and !single_threaded) {
1882 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1883 } else {
1884 llvm_global.setThreadLocalMode(.NotThreadLocal);
1885 }
1886 if (variable.data.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);
1887 }
1888 } else {
1889 llvm_global.setLinkage(.Internal);
1890 llvm_global.setUnnamedAddr(.True);
1891 }
18421892
1843 need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val);1893 return llvm_global;
1894 }
18441895
1845 llvm_fields.appendAssumeCapacity(field_llvm_val);1896 fn llvmAddressSpace(self: DeclGen, address_space: std.builtin.AddressSpace) c_uint {
1897 const target = self.module.getTarget();
1898 return switch (target.cpu.arch) {
1899 .i386, .x86_64 => switch (address_space) {
1900 .generic => llvm.address_space.default,
1901 .gs => llvm.address_space.x86.gs,
1902 .fs => llvm.address_space.x86.fs,
1903 .ss => llvm.address_space.x86.ss,
1904 else => unreachable,
1905 },
1906 .nvptx, .nvptx64 => switch (address_space) {
1907 .generic => llvm.address_space.default,
1908 .global => llvm.address_space.nvptx.global,
1909 .constant => llvm.address_space.nvptx.constant,
1910 .param => llvm.address_space.nvptx.param,
1911 .shared => llvm.address_space.nvptx.shared,
1912 .local => llvm.address_space.nvptx.local,
1913 else => unreachable,
1914 },
1915 else => switch (address_space) {
1916 .generic => llvm.address_space.default,
1917 else => unreachable,
1918 },
1919 };
1920 }
18461921
1847 offset += field.ty.abiSize(target);1922 fn isUnnamedType(dg: *DeclGen, ty: Type, val: *const llvm.Value) bool {
1848 }1923 // Once `llvmType` succeeds, successive calls to it with the same Zig type
1849 {1924 // are guaranteed to succeed. So if a call to `llvmType` fails here it means
1850 const prev_offset = offset;1925 // it is the first time lowering the type, which means the value can't possible
1851 offset = std.mem.alignForwardGeneric(u64, offset, big_align);1926 // have that type.
1852 const padding_len = offset - prev_offset;1927 const llvm_ty = dg.llvmType(ty) catch return true;
1853 if (padding_len > 0) {1928 return val.typeOf() != llvm_ty;
1854 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));1929 }
1855 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
1856 }
1857 }
18581930
1859 if (need_unnamed) {1931 fn llvmType(dg: *DeclGen, t: Type) Allocator.Error!*const llvm.Type {
1860 return dg.context.constStruct(1932 const gpa = dg.gpa;
1861 llvm_fields.items.ptr,1933 const target = dg.module.getTarget();
1862 @intCast(c_uint, llvm_fields.items.len),1934 switch (t.zigTypeTag()) {
1863 .False,1935 .Void, .NoReturn => return dg.context.voidType(),
1864 );1936 .Int => {
1865 } else {1937 const info = t.intInfo(target);
1866 return llvm_struct_ty.constNamedStruct(1938 assert(info.bits != 0);
1867 llvm_fields.items.ptr,1939 return dg.context.intType(info.bits);
1868 @intCast(c_uint, llvm_fields.items.len),
1869 );
1870 }
1871 },1940 },
1872 .Union => {1941 .Enum => {
1873 const llvm_union_ty = try dg.llvmType(tv.ty);1942 var buffer: Type.Payload.Bits = undefined;
1874 const tag_and_val = tv.val.castTag(.@"union").?.data;1943 const int_ty = t.intTagType(&buffer);
1944 const bit_count = int_ty.intInfo(target).bits;
1945 assert(bit_count != 0);
1946 return dg.context.intType(bit_count);
1947 },
1948 .Float => switch (t.floatBits(target)) {
1949 16 => return dg.context.halfType(),
1950 32 => return dg.context.floatType(),
1951 64 => return dg.context.doubleType(),
1952 80 => return if (backendSupportsF80(target)) dg.context.x86FP80Type() else dg.context.intType(80),
1953 128 => return dg.context.fp128Type(),
1954 else => unreachable,
1955 },
1956 .Bool => return dg.context.intType(1),
1957 .Pointer => {
1958 if (t.isSlice()) {
1959 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1960 const ptr_type = t.slicePtrFieldType(&buf);
18751961
1876 const target = dg.module.getTarget();1962 const fields: [2]*const llvm.Type = .{
1877 const layout = tv.ty.unionGetLayout(target);1963 try dg.llvmType(ptr_type),
18781964 try dg.llvmType(Type.usize),
1879 if (layout.payload_size == 0) {
1880 return genTypedValue(dg, .{
1881 .ty = tv.ty.unionTagType().?,
1882 .val = tag_and_val.tag,
1883 });
1884 }
1885 const union_obj = tv.ty.cast(Type.Payload.Union).?.data;
1886 const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag).?;
1887 assert(union_obj.haveFieldTypes());
1888 const field_ty = union_obj.fields.values()[field_index].ty;
1889 const payload = p: {
1890 if (!field_ty.hasRuntimeBitsIgnoreComptime()) {
1891 const padding_len = @intCast(c_uint, layout.payload_size);
1892 break :p dg.context.intType(8).arrayType(padding_len).getUndef();
1893 }
1894 const field = try genTypedValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });
1895 const field_size = field_ty.abiSize(target);
1896 if (field_size == layout.payload_size) {
1897 break :p field;
1898 }
1899 const padding_len = @intCast(c_uint, layout.payload_size - field_size);
1900 const fields: [2]*const llvm.Value = .{
1901 field, dg.context.intType(8).arrayType(padding_len).getUndef(),
1902 };1965 };
1903 break :p dg.context.constStruct(&fields, fields.len, .True);1966 return dg.context.structType(&fields, fields.len, .False);
1904 };
1905
1906 // In this case we must make an unnamed struct because LLVM does
1907 // not support bitcasting our payload struct to the true union payload type.
1908 // Instead we use an unnamed struct and every reference to the global
1909 // must pointer cast to the expected type before accessing the union.
1910 const need_unnamed = layout.most_aligned_field != field_index;
1911
1912 if (layout.tag_size == 0) {
1913 const fields: [1]*const llvm.Value = .{payload};
1914 if (need_unnamed) {
1915 return dg.context.constStruct(&fields, fields.len, .False);
1916 } else {
1917 return llvm_union_ty.constNamedStruct(&fields, fields.len);
1918 }
1919 }
1920 const llvm_tag_value = try genTypedValue(dg, .{
1921 .ty = tv.ty.unionTagType().?,
1922 .val = tag_and_val.tag,
1923 });
1924 var fields: [3]*const llvm.Value = undefined;
1925 var fields_len: c_uint = 2;
1926 if (layout.tag_align >= layout.payload_align) {
1927 fields = .{ llvm_tag_value, payload, undefined };
1928 } else {
1929 fields = .{ payload, llvm_tag_value, undefined };
1930 }
1931 if (layout.padding != 0) {
1932 fields[2] = dg.context.intType(8).arrayType(layout.padding).getUndef();
1933 fields_len = 3;
1934 }1967 }
1935 if (need_unnamed) {1968 const ptr_info = t.ptrInfo().data;
1936 return dg.context.constStruct(&fields, fields_len, .False);1969 const llvm_addrspace = dg.llvmAddressSpace(ptr_info.@"addrspace");
1937 } else {1970 if (ptr_info.host_size != 0) {
1938 return llvm_union_ty.constNamedStruct(&fields, fields_len);1971 return dg.context.intType(ptr_info.host_size * 8).pointerType(llvm_addrspace);
1939 }1972 }
1973 const elem_ty = ptr_info.pointee_type;
1974 const lower_elem_ty = switch (elem_ty.zigTypeTag()) {
1975 .Opaque, .Fn => true,
1976 .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(),
1977 else => elem_ty.hasRuntimeBitsIgnoreComptime(),
1978 };
1979 const llvm_elem_ty = if (lower_elem_ty)
1980 try dg.llvmType(elem_ty)
1981 else
1982 dg.context.intType(8);
1983 return llvm_elem_ty.pointerType(llvm_addrspace);
1940 },1984 },
1941 .Vector => switch (tv.val.tag()) {1985 .Opaque => switch (t.tag()) {
1942 .bytes => {1986 .@"opaque" => {
1943 // Note, sentinel is not stored even if the type has a sentinel.1987 const gop = try dg.object.type_map.getOrPut(gpa, t);
1944 const bytes = tv.val.castTag(.bytes).?.data;1988 if (gop.found_existing) return gop.value_ptr.*;
1945 const vector_len = @intCast(usize, tv.ty.arrayLen());
1946 assert(vector_len == bytes.len or vector_len + 1 == bytes.len);
19471989
1948 const elem_ty = tv.ty.elemType();1990 // The Type memory is ephemeral; since we want to store a longer-lived
1949 const llvm_elems = try dg.gpa.alloc(*const llvm.Value, vector_len);1991 // reference, we need to copy it here.
1950 defer dg.gpa.free(llvm_elems);1992 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
1951 for (llvm_elems) |*elem, i| {
1952 var byte_payload: Value.Payload.U64 = .{
1953 .base = .{ .tag = .int_u64 },
1954 .data = bytes[i],
1955 };
19561993
1957 elem.* = try dg.genTypedValue(.{1994 const opaque_obj = t.castTag(.@"opaque").?.data;
1958 .ty = elem_ty,1995 const name = try opaque_obj.getFullyQualifiedName(gpa);
1959 .val = Value.initPayload(&byte_payload.base),1996 defer gpa.free(name);
1960 });1997
1961 }1998 const llvm_struct_ty = dg.context.structCreateNamed(name);
1962 return llvm.constVector(1999 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
1963 llvm_elems.ptr,2000 return llvm_struct_ty;
1964 @intCast(c_uint, llvm_elems.len),
1965 );
1966 },
1967 .aggregate => {
1968 // Note, sentinel is not stored even if the type has a sentinel.
1969 // The value includes the sentinel in those cases.
1970 const elem_vals = tv.val.castTag(.aggregate).?.data;
1971 const vector_len = @intCast(usize, tv.ty.arrayLen());
1972 assert(vector_len == elem_vals.len or vector_len + 1 == elem_vals.len);
1973 const elem_ty = tv.ty.elemType();
1974 const llvm_elems = try dg.gpa.alloc(*const llvm.Value, vector_len);
1975 defer dg.gpa.free(llvm_elems);
1976 for (llvm_elems) |*elem, i| {
1977 elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_vals[i] });
1978 }
1979 return llvm.constVector(
1980 llvm_elems.ptr,
1981 @intCast(c_uint, llvm_elems.len),
1982 );
1983 },
1984 .repeated => {
1985 // Note, sentinel is not stored even if the type has a sentinel.
1986 const val = tv.val.castTag(.repeated).?.data;
1987 const elem_ty = tv.ty.elemType();
1988 const len = @intCast(usize, tv.ty.arrayLen());
1989 const llvm_elems = try dg.gpa.alloc(*const llvm.Value, len);
1990 defer dg.gpa.free(llvm_elems);
1991 for (llvm_elems) |*elem| {
1992 elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val });
1993 }
1994 return llvm.constVector(
1995 llvm_elems.ptr,
1996 @intCast(c_uint, llvm_elems.len),
1997 );
1998 },2001 },
2002 .anyopaque => return dg.context.intType(8),
1999 else => unreachable,2003 else => unreachable,
2000 },2004 },
2005 .Array => {
2006 const elem_ty = t.childType();
2007 assert(elem_ty.onePossibleValue() == null);
2008 const elem_llvm_ty = try dg.llvmType(elem_ty);
2009 const total_len = t.arrayLen() + @boolToInt(t.sentinel() != null);
2010 return elem_llvm_ty.arrayType(@intCast(c_uint, total_len));
2011 },
2012 .Vector => {
2013 const elem_type = try dg.llvmType(t.childType());
2014 return elem_type.vectorType(t.vectorLen());
2015 },
2016 .Optional => {
2017 var buf: Type.Payload.ElemType = undefined;
2018 const child_ty = t.optionalChild(&buf);
2019 if (!child_ty.hasRuntimeBitsIgnoreComptime()) {
2020 return dg.context.intType(1);
2021 }
2022 const payload_llvm_ty = try dg.llvmType(child_ty);
2023 if (t.isPtrLikeOptional()) {
2024 return payload_llvm_ty;
2025 }
20012026
2002 .ComptimeInt => unreachable,2027 const fields: [2]*const llvm.Type = .{
2003 .ComptimeFloat => unreachable,2028 payload_llvm_ty, dg.context.intType(1),
2004 .Type => unreachable,2029 };
2005 .EnumLiteral => unreachable,2030 return dg.context.structType(&fields, fields.len, .False);
2006 .Void => unreachable,2031 },
2007 .NoReturn => unreachable,2032 .ErrorUnion => {
2008 .Undefined => unreachable,2033 const error_type = t.errorUnionSet();
2009 .Null => unreachable,2034 const payload_type = t.errorUnionPayload();
2010 .BoundFn => unreachable,2035 const llvm_error_type = try dg.llvmType(error_type);
2011 .Opaque => unreachable,2036 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
20122037 return llvm_error_type;
2013 .Frame,2038 }
2014 .AnyFrame,2039 const llvm_payload_type = try dg.llvmType(payload_type);
2015 => return dg.todo("implement const of type '{}'", .{tv.ty}),
2016 }
2017 }
20182040
2019 fn lowerDebugType(dg: *DeclGen, ty: Type) Allocator.Error!*llvm.DIType {2041 const fields: [2]*const llvm.Type = .{ llvm_error_type, llvm_payload_type };
2020 const gpa = dg.gpa;2042 return dg.context.structType(&fields, fields.len, .False);
2021 // Be careful not to reference this `gop` variable after any recursive calls
2022 // to `lowerDebugType`.
2023 const gop = try dg.object.di_type_map.getOrPut(gpa, ty);
2024 if (gop.found_existing) return gop.value_ptr.*;
2025 errdefer assert(dg.object.di_type_map.remove(ty));
2026 // The Type memory is ephemeral; since we want to store a longer-lived
2027 // reference, we need to copy it here.
2028 gop.key_ptr.* = try ty.copy(dg.object.type_map_arena.allocator());
2029 const target = dg.module.getTarget();
2030 const dib = dg.object.di_builder.?;
2031 switch (ty.zigTypeTag()) {
2032 .Void, .NoReturn => {
2033 gop.value_ptr.* = dib.createBasicType("void", 0, DW.ATE.signed);
2034 return gop.value_ptr.*;
2035 },2043 },
2036 .Int => {2044 .ErrorSet => {
2037 const info = ty.intInfo(target);2045 return dg.context.intType(16);
2038 assert(info.bits != 0);
2039 const name = try ty.nameAlloc(gpa);
2040 defer gpa.free(name);
2041 const dwarf_encoding: c_uint = switch (info.signedness) {
2042 .signed => DW.ATE.signed,
2043 .unsigned => DW.ATE.unsigned,
2044 };
2045 gop.value_ptr.* = dib.createBasicType(name, info.bits, dwarf_encoding);
2046 return gop.value_ptr.*;
2047 },2046 },
2048 .Enum => {2047 .Struct => {
2049 const owner_decl = ty.getOwnerDecl();2048 const gop = try dg.object.type_map.getOrPut(gpa, t);
2049 if (gop.found_existing) return gop.value_ptr.*;
20502050
2051 if (!ty.hasRuntimeBitsIgnoreComptime()) {2051 // The Type memory is ephemeral; since we want to store a longer-lived
2052 const enum_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl);2052 // reference, we need to copy it here.
2053 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2053 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
2054 // means we can't use `gop` anymore.
2055 try dg.object.di_type_map.put(gpa, ty, enum_di_ty);
2056 return enum_di_ty;
2057 }
20582054
2059 const field_names = ty.enumFields().keys();2055 if (t.isTupleOrAnonStruct()) {
2056 const tuple = t.tupleFields();
2057 const llvm_struct_ty = dg.context.structCreateNamed("");
2058 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
20602059
2061 const enumerators = try gpa.alloc(*llvm.DIEnumerator, field_names.len);2060 var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{};
2062 defer gpa.free(enumerators);2061 defer llvm_field_types.deinit(gpa);
20632062
2064 var buf_field_index: Value.Payload.U32 = .{2063 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);
2065 .base = .{ .tag = .enum_field_index },
2066 .data = undefined,
2067 };
2068 const field_index_val = Value.initPayload(&buf_field_index.base);
20692064
2070 for (field_names) |field_name, i| {2065 comptime assert(struct_layout_version == 2);
2071 const field_name_z = try gpa.dupeZ(u8, field_name);2066 var offset: u64 = 0;
2072 defer gpa.free(field_name_z);2067 var big_align: u32 = 0;
20732068
2074 buf_field_index.data = @intCast(u32, i);2069 for (tuple.types) |field_ty, i| {
2075 var buf_u64: Value.Payload.U64 = undefined;2070 const field_val = tuple.values[i];
2076 const field_int_val = field_index_val.enumToInt(ty, &buf_u64);2071 if (field_val.tag() != .unreachable_value) continue;
2077 // See https://github.com/ziglang/zig/issues/6452072
2078 const field_int = field_int_val.toSignedInt();2073 const field_align = field_ty.abiAlignment(target);
2079 enumerators[i] = dib.createEnumerator(field_name_z, field_int);2074 big_align = @maximum(big_align, field_align);
2075 const prev_offset = offset;
2076 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2077
2078 const padding_len = offset - prev_offset;
2079 if (padding_len > 0) {
2080 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2081 try llvm_field_types.append(gpa, llvm_array_ty);
2082 }
2083 const field_llvm_ty = try dg.llvmType(field_ty);
2084 try llvm_field_types.append(gpa, field_llvm_ty);
2085
2086 offset += field_ty.abiSize(target);
2087 }
2088 {
2089 const prev_offset = offset;
2090 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2091 const padding_len = offset - prev_offset;
2092 if (padding_len > 0) {
2093 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2094 try llvm_field_types.append(gpa, llvm_array_ty);
2095 }
2096 }
2097
2098 llvm_struct_ty.structSetBody(
2099 llvm_field_types.items.ptr,
2100 @intCast(c_uint, llvm_field_types.items.len),
2101 .False,
2102 );
2103
2104 return llvm_struct_ty;
2080 }2105 }
20812106
2082 const di_file = try dg.object.getDIFile(gpa, owner_decl.src_namespace.file_scope);2107 const struct_obj = t.castTag(.@"struct").?.data;
2083 const di_scope = try dg.namespaceToDebugScope(owner_decl.src_namespace);
20842108
2085 const name = try ty.nameAlloc(gpa);2109 if (struct_obj.layout == .Packed) {
2086 defer gpa.free(name);2110 var buf: Type.Payload.Bits = undefined;
2087 var buffer: Type.Payload.Bits = undefined;2111 const int_ty = struct_obj.packedIntegerType(target, &buf);
2088 const int_ty = ty.intTagType(&buffer);2112 const int_llvm_ty = try dg.llvmType(int_ty);
2113 gop.value_ptr.* = int_llvm_ty;
2114 return int_llvm_ty;
2115 }
20892116
2090 const enum_di_ty = dib.createEnumerationType(2117 const name = try struct_obj.getFullyQualifiedName(gpa);
2091 di_scope,
2092 name,
2093 di_file,
2094 owner_decl.src_node + 1,
2095 ty.abiSize(target) * 8,
2096 ty.abiAlignment(target) * 8,
2097 enumerators.ptr,
2098 @intCast(c_int, enumerators.len),
2099 try lowerDebugType(dg, int_ty),
2100 "",
2101 );
2102 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2103 try dg.object.di_type_map.put(gpa, ty, enum_di_ty);
2104 return enum_di_ty;
2105 },
2106 .Float => {
2107 const bits = ty.floatBits(target);
2108 const name = try ty.nameAlloc(gpa);
2109 defer gpa.free(name);2118 defer gpa.free(name);
2110 gop.value_ptr.* = dib.createBasicType(name, bits, DW.ATE.float);
2111 return gop.value_ptr.*;
2112 },
2113 .Bool => {
2114 gop.value_ptr.* = dib.createBasicType("bool", 1, DW.ATE.boolean);
2115 return gop.value_ptr.*;
2116 },
2117 .Pointer => {
2118 // Normalize everything that the debug info does not represent.
2119 const ptr_info = ty.ptrInfo().data;
21202119
2121 if (ptr_info.sentinel != null or2120 const llvm_struct_ty = dg.context.structCreateNamed(name);
2122 ptr_info.@"addrspace" != .generic or2121 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
2123 ptr_info.bit_offset != 0 or
2124 ptr_info.host_size != 0 or
2125 ptr_info.@"allowzero" or
2126 !ptr_info.mutable or
2127 ptr_info.@"volatile" or
2128 ptr_info.size == .Many or ptr_info.size == .C or
2129 !ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime())
2130 {
2131 var payload: Type.Payload.Pointer = .{
2132 .data = .{
2133 .pointee_type = ptr_info.pointee_type,
2134 .sentinel = null,
2135 .@"align" = ptr_info.@"align",
2136 .@"addrspace" = .generic,
2137 .bit_offset = 0,
2138 .host_size = 0,
2139 .@"allowzero" = false,
2140 .mutable = true,
2141 .@"volatile" = false,
2142 .size = switch (ptr_info.size) {
2143 .Many, .C, .One => .One,
2144 .Slice => .Slice,
2145 },
2146 },
2147 };
2148 if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) {
2149 payload.data.pointee_type = Type.anyopaque;
2150 }
2151 const bland_ptr_ty = Type.initPayload(&payload.base);
2152 const ptr_di_ty = try dg.lowerDebugType(bland_ptr_ty);
2153 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2154 try dg.object.di_type_map.put(gpa, ty, ptr_di_ty);
2155 return ptr_di_ty;
2156 }
21572122
2158 if (ty.isSlice()) {2123 assert(struct_obj.haveFieldTypes());
2159 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2160 const ptr_ty = ty.slicePtrFieldType(&buf);
2161 const len_ty = Type.usize;
21622124
2163 const name = try ty.nameAlloc(gpa);2125 var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{};
2164 defer gpa.free(name);2126 defer llvm_field_types.deinit(gpa);
2165 const di_file: ?*llvm.DIFile = null;
2166 const line = 0;
2167 const compile_unit_scope = dg.object.di_compile_unit.?.toScope();
2168 const fwd_decl = dib.createReplaceableCompositeType(
2169 DW.TAG.structure_type,
2170 name.ptr,
2171 compile_unit_scope,
2172 di_file,
2173 line,
2174 );
2175 gop.value_ptr.* = fwd_decl;
21762127
2177 const ptr_size = ptr_ty.abiSize(target);2128 try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count());
2178 const ptr_align = ptr_ty.abiAlignment(target);
2179 const len_size = len_ty.abiSize(target);
2180 const len_align = len_ty.abiAlignment(target);
21812129
2182 var offset: u64 = 0;2130 comptime assert(struct_layout_version == 2);
2183 offset += ptr_size;2131 var offset: u64 = 0;
2184 offset = std.mem.alignForwardGeneric(u64, offset, len_align);2132 var big_align: u32 = 0;
2185 const len_offset = offset;
21862133
2187 const fields: [2]*llvm.DIType = .{2134 for (struct_obj.fields.values()) |field| {
2188 dib.createMemberType(2135 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
2189 fwd_decl.toScope(),
2190 "ptr",
2191 di_file,
2192 line,
2193 ptr_size * 8, // size in bits
2194 ptr_align * 8, // align in bits
2195 0, // offset in bits
2196 0, // flags
2197 try dg.lowerDebugType(ptr_ty),
2198 ),
2199 dib.createMemberType(
2200 fwd_decl.toScope(),
2201 "len",
2202 di_file,
2203 line,
2204 len_size * 8, // size in bits
2205 len_align * 8, // align in bits
2206 len_offset * 8, // offset in bits
2207 0, // flags
2208 try dg.lowerDebugType(len_ty),
2209 ),
2210 };
22112136
2212 const replacement_di_ty = dib.createStructType(2137 const field_align = field.normalAlignment(target);
2213 compile_unit_scope,2138 big_align = @maximum(big_align, field_align);
2214 name.ptr,2139 const prev_offset = offset;
2215 di_file,2140 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2216 line,2141
2217 ty.abiSize(target) * 8, // size in bits2142 const padding_len = offset - prev_offset;
2218 ty.abiAlignment(target) * 8, // align in bits2143 if (padding_len > 0) {
2219 0, // flags2144 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2220 null, // derived from2145 try llvm_field_types.append(gpa, llvm_array_ty);
2221 &fields,2146 }
2222 fields.len,2147 const field_llvm_ty = try dg.llvmType(field.ty);
2223 0, // run time lang2148 try llvm_field_types.append(gpa, field_llvm_ty);
2224 null, // vtable holder2149
2225 "", // unique id2150 offset += field.ty.abiSize(target);
2226 );2151 }
2227 dib.replaceTemporary(fwd_decl, replacement_di_ty);2152 {
2228 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2153 const prev_offset = offset;
2229 try dg.object.di_type_map.put(gpa, ty, replacement_di_ty);2154 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2230 return replacement_di_ty;2155 const padding_len = offset - prev_offset;
2156 if (padding_len > 0) {
2157 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2158 try llvm_field_types.append(gpa, llvm_array_ty);
2159 }
2231 }2160 }
22322161
2233 const elem_di_ty = try lowerDebugType(dg, ptr_info.pointee_type);2162 llvm_struct_ty.structSetBody(
2234 const name = try ty.nameAlloc(gpa);2163 llvm_field_types.items.ptr,
2235 defer gpa.free(name);2164 @intCast(c_uint, llvm_field_types.items.len),
2236 const ptr_di_ty = dib.createPointerType(2165 .False,
2237 elem_di_ty,
2238 target.cpu.arch.ptrBitWidth(),
2239 ty.ptrAlignment(target) * 8,
2240 name,
2241 );2166 );
2242 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2167
2243 try dg.object.di_type_map.put(gpa, ty, ptr_di_ty);2168 return llvm_struct_ty;
2244 return ptr_di_ty;
2245 },2169 },
2246 .Opaque => {2170 .Union => {
2247 if (ty.tag() == .anyopaque) {2171 const gop = try dg.object.type_map.getOrPut(gpa, t);
2248 gop.value_ptr.* = dib.createBasicType("anyopaque", 0, DW.ATE.signed);2172 if (gop.found_existing) return gop.value_ptr.*;
2249 return gop.value_ptr.*;2173
2174 // The Type memory is ephemeral; since we want to store a longer-lived
2175 // reference, we need to copy it here.
2176 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
2177
2178 const layout = t.unionGetLayout(target);
2179 const union_obj = t.cast(Type.Payload.Union).?.data;
2180
2181 if (layout.payload_size == 0) {
2182 const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
2183 gop.value_ptr.* = enum_tag_llvm_ty;
2184 return enum_tag_llvm_ty;
2250 }2185 }
2251 const name = try ty.nameAlloc(gpa);2186
2187 const name = try union_obj.getFullyQualifiedName(gpa);
2252 defer gpa.free(name);2188 defer gpa.free(name);
2253 const owner_decl = ty.getOwnerDecl();2189
2254 const opaque_di_ty = dib.createForwardDeclType(2190 const llvm_union_ty = dg.context.structCreateNamed(name);
2255 DW.TAG.structure_type,2191 gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls
2256 name,2192
2257 try dg.namespaceToDebugScope(owner_decl.src_namespace),2193 const aligned_field = union_obj.fields.values()[layout.most_aligned_field];
2258 try dg.object.getDIFile(gpa, owner_decl.src_namespace.file_scope),2194 const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty);
2259 owner_decl.src_node + 1,2195
2260 );2196 const llvm_payload_ty = t: {
2261 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`2197 if (layout.most_aligned_field_size == layout.payload_size) {
2262 // means we can't use `gop` anymore.2198 break :t llvm_aligned_field_ty;
2263 try dg.object.di_type_map.put(gpa, ty, opaque_di_ty);2199 }
2264 return opaque_di_ty;2200 const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);
2265 },2201 const fields: [2]*const llvm.Type = .{
2266 .Array => {2202 llvm_aligned_field_ty,
2267 const array_di_ty = dib.createArrayType(2203 dg.context.intType(8).arrayType(padding_len),
2268 ty.abiSize(target) * 8,2204 };
2269 ty.abiAlignment(target) * 8,2205 break :t dg.context.structType(&fields, fields.len, .True);
2270 try lowerDebugType(dg, ty.childType()),2206 };
2271 @intCast(c_int, ty.arrayLen()),2207
2272 );2208 if (layout.tag_size == 0) {
2273 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2209 var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty};
2274 try dg.object.di_type_map.put(gpa, ty, array_di_ty);2210 llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False);
2275 return array_di_ty;2211 return llvm_union_ty;
2276 },2212 }
2277 .Vector => {2213 const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
2278 const vector_di_ty = dib.createVectorType(2214
2279 ty.abiSize(target) * 8,2215 // Put the tag before or after the payload depending on which one's
2280 ty.abiAlignment(target) * 8,2216 // alignment is greater.
2281 try lowerDebugType(dg, ty.childType()),2217 var llvm_fields: [3]*const llvm.Type = undefined;
2282 ty.vectorLen(),2218 var llvm_fields_len: c_uint = 2;
2283 );2219
2284 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2220 if (layout.tag_align >= layout.payload_align) {
2285 try dg.object.di_type_map.put(gpa, ty, vector_di_ty);2221 llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined };
2286 return vector_di_ty;2222 } else {
2223 llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined };
2224 }
2225
2226 // Insert padding to make the LLVM struct ABI size match the Zig union ABI size.
2227 if (layout.padding != 0) {
2228 llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding);
2229 llvm_fields_len = 3;
2230 }
2231
2232 llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);
2233 return llvm_union_ty;
2287 },2234 },
2288 .Optional => {2235 .Fn => {
2289 const name = try ty.nameAlloc(gpa);2236 const fn_info = t.fnInfo();
2290 defer gpa.free(name);2237 const sret = firstParamSRet(fn_info, target);
2291 var buf: Type.Payload.ElemType = undefined;2238 const return_type = fn_info.return_type;
2292 const child_ty = ty.optionalChild(&buf);2239 const llvm_sret_ty = if (return_type.hasRuntimeBitsIgnoreComptime())
2293 if (!child_ty.hasRuntimeBitsIgnoreComptime()) {2240 try dg.llvmType(return_type)
2294 gop.value_ptr.* = dib.createBasicType(name, 1, DW.ATE.boolean);2241 else
2295 return gop.value_ptr.*;2242 dg.context.voidType();
2243 const llvm_ret_ty = if (sret) dg.context.voidType() else llvm_sret_ty;
2244
2245 var llvm_params = std.ArrayList(*const llvm.Type).init(dg.gpa);
2246 defer llvm_params.deinit();
2247
2248 if (sret) {
2249 try llvm_params.append(llvm_sret_ty.pointerType(0));
2296 }2250 }
2297 if (ty.isPtrLikeOptional()) {2251
2298 const ptr_di_ty = try dg.lowerDebugType(child_ty);2252 for (fn_info.param_types) |param_ty| {
2299 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2253 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
2300 try dg.object.di_type_map.put(gpa, ty, ptr_di_ty);2254
2301 return ptr_di_ty;2255 const raw_llvm_ty = try dg.llvmType(param_ty);
2256 const actual_llvm_ty = if (!isByRef(param_ty)) raw_llvm_ty else raw_llvm_ty.pointerType(0);
2257 try llvm_params.append(actual_llvm_ty);
2302 }2258 }
23032259
2304 const di_file: ?*llvm.DIFile = null;2260 return llvm.functionType(
2305 const line = 0;2261 llvm_ret_ty,
2306 const compile_unit_scope = dg.object.di_compile_unit.?.toScope();2262 llvm_params.items.ptr,
2307 const fwd_decl = dib.createReplaceableCompositeType(2263 @intCast(c_uint, llvm_params.items.len),
2308 DW.TAG.structure_type,2264 llvm.Bool.fromBool(fn_info.is_var_args),
2309 name.ptr,
2310 compile_unit_scope,
2311 di_file,
2312 line,
2313 );2265 );
2314 gop.value_ptr.* = fwd_decl;2266 },
2267 .ComptimeInt => unreachable,
2268 .ComptimeFloat => unreachable,
2269 .Type => unreachable,
2270 .Undefined => unreachable,
2271 .Null => unreachable,
2272 .EnumLiteral => unreachable,
23152273
2316 const non_null_ty = Type.bool;2274 .BoundFn => @panic("TODO remove BoundFn from the language"),
2317 const payload_size = child_ty.abiSize(target);
2318 const payload_align = child_ty.abiAlignment(target);
2319 const non_null_size = non_null_ty.abiSize(target);
2320 const non_null_align = non_null_ty.abiAlignment(target);
23212275
2322 var offset: u64 = 0;2276 .Frame => @panic("TODO implement llvmType for Frame types"),
2323 offset += payload_size;2277 .AnyFrame => @panic("TODO implement llvmType for AnyFrame types"),
2324 offset = std.mem.alignForwardGeneric(u64, offset, non_null_align);2278 }
2325 const non_null_offset = offset;2279 }
23262280
2327 const fields: [2]*llvm.DIType = .{2281 fn genTypedValue(dg: *DeclGen, tv: TypedValue) Error!*const llvm.Value {
2328 dib.createMemberType(2282 if (tv.val.isUndef()) {
2329 fwd_decl.toScope(),2283 const llvm_type = try dg.llvmType(tv.ty);
2330 "data",2284 return llvm_type.getUndef();
2331 di_file,2285 }
2332 line,
2333 payload_size * 8, // size in bits
2334 payload_align * 8, // align in bits
2335 0, // offset in bits
2336 0, // flags
2337 try dg.lowerDebugType(child_ty),
2338 ),
2339 dib.createMemberType(
2340 fwd_decl.toScope(),
2341 "some",
2342 di_file,
2343 line,
2344 non_null_size * 8, // size in bits
2345 non_null_align * 8, // align in bits
2346 non_null_offset * 8, // offset in bits
2347 0, // flags
2348 try dg.lowerDebugType(non_null_ty),
2349 ),
2350 };
23512286
2352 const replacement_di_ty = dib.createStructType(2287 switch (tv.ty.zigTypeTag()) {
2353 compile_unit_scope,2288 .Bool => {
2354 name.ptr,2289 const llvm_type = try dg.llvmType(tv.ty);
2355 di_file,2290 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();
2356 line,
2357 ty.abiSize(target) * 8, // size in bits
2358 ty.abiAlignment(target) * 8, // align in bits
2359 0, // flags
2360 null, // derived from
2361 &fields,
2362 fields.len,
2363 0, // run time lang
2364 null, // vtable holder
2365 "", // unique id
2366 );
2367 dib.replaceTemporary(fwd_decl, replacement_di_ty);
2368 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2369 try dg.object.di_type_map.put(gpa, ty, replacement_di_ty);
2370 return replacement_di_ty;
2371 },2291 },
2372 .ErrorUnion => {2292 // TODO this duplicates code with Pointer but they should share the handling
2373 const err_set_ty = ty.errorUnionSet();2293 // of the tv.val.tag() and then Int should do extra constPtrToInt on top
2374 const payload_ty = ty.errorUnionPayload();2294 .Int => switch (tv.val.tag()) {
2375 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {2295 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl),
2376 const err_set_di_ty = try dg.lowerDebugType(err_set_ty);2296 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
2377 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2297 else => {
2378 try dg.object.di_type_map.put(gpa, ty, err_set_di_ty);2298 var bigint_space: Value.BigIntSpace = undefined;
2379 return err_set_di_ty;2299 const bigint = tv.val.toBigInt(&bigint_space);
2380 }2300 const target = dg.module.getTarget();
2381 const name = try ty.nameAlloc(gpa);2301 const int_info = tv.ty.intInfo(target);
2382 defer gpa.free(name);2302 assert(int_info.bits != 0);
2383 const di_file: ?*llvm.DIFile = null;2303 const llvm_type = dg.context.intType(int_info.bits);
2384 const line = 0;
2385 const compile_unit_scope = dg.object.di_compile_unit.?.toScope();
2386 const fwd_decl = dib.createReplaceableCompositeType(
2387 DW.TAG.structure_type,
2388 name.ptr,
2389 compile_unit_scope,
2390 di_file,
2391 line,
2392 );
2393 gop.value_ptr.* = fwd_decl;
23942304
2395 const err_set_size = err_set_ty.abiSize(target);2305 const unsigned_val = v: {
2396 const err_set_align = err_set_ty.abiAlignment(target);2306 if (bigint.limbs.len == 1) {
2397 const payload_size = payload_ty.abiSize(target);2307 break :v llvm_type.constInt(bigint.limbs[0], .False);
2398 const payload_align = payload_ty.abiAlignment(target);2308 }
2309 if (@sizeOf(usize) == @sizeOf(u64)) {
2310 break :v llvm_type.constIntOfArbitraryPrecision(
2311 @intCast(c_uint, bigint.limbs.len),
2312 bigint.limbs.ptr,
2313 );
2314 }
2315 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
2316 };
2317 if (!bigint.positive) {
2318 return llvm.constNeg(unsigned_val);
2319 }
2320 return unsigned_val;
2321 },
2322 },
2323 .Enum => {
2324 var int_buffer: Value.Payload.U64 = undefined;
2325 const int_val = tv.enumToInt(&int_buffer);
23992326
2400 var offset: u64 = 0;2327 var bigint_space: Value.BigIntSpace = undefined;
2401 offset += err_set_size;2328 const bigint = int_val.toBigInt(&bigint_space);
2402 offset = std.mem.alignForwardGeneric(u64, offset, payload_align);
2403 const payload_offset = offset;
24042329
2405 const fields: [2]*llvm.DIType = .{2330 const target = dg.module.getTarget();
2406 dib.createMemberType(2331 const int_info = tv.ty.intInfo(target);
2407 fwd_decl.toScope(),2332 const llvm_type = dg.context.intType(int_info.bits);
2408 "tag",2333
2409 di_file,2334 const unsigned_val = v: {
2410 line,2335 if (bigint.limbs.len == 1) {
2411 err_set_size * 8, // size in bits2336 break :v llvm_type.constInt(bigint.limbs[0], .False);
2412 err_set_align * 8, // align in bits2337 }
2413 0, // offset in bits2338 if (@sizeOf(usize) == @sizeOf(u64)) {
2414 0, // flags2339 break :v llvm_type.constIntOfArbitraryPrecision(
2415 try dg.lowerDebugType(err_set_ty),2340 @intCast(c_uint, bigint.limbs.len),
2416 ),2341 bigint.limbs.ptr,
2417 dib.createMemberType(2342 );
2418 fwd_decl.toScope(),2343 }
2419 "value",2344 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
2420 di_file,
2421 line,
2422 payload_size * 8, // size in bits
2423 payload_align * 8, // align in bits
2424 payload_offset * 8, // offset in bits
2425 0, // flags
2426 try dg.lowerDebugType(payload_ty),
2427 ),
2428 };2345 };
2346 if (!bigint.positive) {
2347 return llvm.constNeg(unsigned_val);
2348 }
2349 return unsigned_val;
2350 },
2351 .Float => {
2352 const llvm_ty = try dg.llvmType(tv.ty);
2353 const target = dg.module.getTarget();
2354 switch (tv.ty.floatBits(target)) {
2355 16, 32, 64 => return llvm_ty.constReal(tv.val.toFloat(f64)),
2356 80 => {
2357 const float = tv.val.toFloat(f80);
2358 const repr = std.math.break_f80(float);
2359 const llvm_i80 = dg.context.intType(80);
2360 var x = llvm_i80.constInt(repr.exp, .False);
2361 x = x.constShl(llvm_i80.constInt(64, .False));
2362 x = x.constOr(llvm_i80.constInt(repr.fraction, .False));
2363 if (backendSupportsF80(target)) {
2364 return x.constBitCast(llvm_ty);
2365 } else {
2366 return x;
2367 }
2368 },
2369 128 => {
2370 var buf: [2]u64 = @bitCast([2]u64, tv.val.toFloat(f128));
2371 // LLVM seems to require that the lower half of the f128 be placed first
2372 // in the buffer.
2373 if (native_endian == .Big) {
2374 std.mem.swap(u64, &buf[0], &buf[1]);
2375 }
2376 const int = dg.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf);
2377 return int.constBitCast(llvm_ty);
2378 },
2379 else => unreachable,
2380 }
2381 },
2382 .Pointer => switch (tv.val.tag()) {
2383 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl),
2384 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
2385 .variable => {
2386 const decl = tv.val.castTag(.variable).?.data.owner_decl;
2387 decl.markAlive();
2388 const val = try dg.resolveGlobalDecl(decl);
2389 const llvm_var_type = try dg.llvmType(tv.ty);
2390 const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");
2391 const llvm_type = llvm_var_type.pointerType(llvm_addrspace);
2392 return val.constBitCast(llvm_type);
2393 },
2394 .slice => {
2395 const slice = tv.val.castTag(.slice).?.data;
2396 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2397 const fields: [2]*const llvm.Value = .{
2398 try dg.genTypedValue(.{
2399 .ty = tv.ty.slicePtrFieldType(&buf),
2400 .val = slice.ptr,
2401 }),
2402 try dg.genTypedValue(.{
2403 .ty = Type.usize,
2404 .val = slice.len,
2405 }),
2406 };
2407 return dg.context.constStruct(&fields, fields.len, .False);
2408 },
2409 .int_u64, .one, .int_big_positive => {
2410 const llvm_usize = try dg.llvmType(Type.usize);
2411 const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(), .False);
2412 return llvm_int.constIntToPtr(try dg.llvmType(tv.ty));
2413 },
2414 .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => {
2415 return dg.lowerParentPtr(tv.val, tv.ty.childType());
2416 },
2417 .null_value, .zero => {
2418 const llvm_type = try dg.llvmType(tv.ty);
2419 return llvm_type.constNull();
2420 },
2421 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }),
2422 },
2423 .Array => switch (tv.val.tag()) {
2424 .bytes => {
2425 const bytes = tv.val.castTag(.bytes).?.data;
2426 return dg.context.constString(
2427 bytes.ptr,
2428 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel()),
2429 .True, // don't null terminate. bytes has the sentinel, if any.
2430 );
2431 },
2432 .aggregate => {
2433 const elem_vals = tv.val.castTag(.aggregate).?.data;
2434 const elem_ty = tv.ty.elemType();
2435 const gpa = dg.gpa;
2436 const len = @intCast(usize, tv.ty.arrayLenIncludingSentinel());
2437 const llvm_elems = try gpa.alloc(*const llvm.Value, len);
2438 defer gpa.free(llvm_elems);
2439 var need_unnamed = false;
2440 for (elem_vals[0..len]) |elem_val, i| {
2441 llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val });
2442 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
2443 }
2444 if (need_unnamed) {
2445 return dg.context.constStruct(
2446 llvm_elems.ptr,
2447 @intCast(c_uint, llvm_elems.len),
2448 .True,
2449 );
2450 } else {
2451 const llvm_elem_ty = try dg.llvmType(elem_ty);
2452 return llvm_elem_ty.constArray(
2453 llvm_elems.ptr,
2454 @intCast(c_uint, llvm_elems.len),
2455 );
2456 }
2457 },
2458 .repeated => {
2459 const val = tv.val.castTag(.repeated).?.data;
2460 const elem_ty = tv.ty.elemType();
2461 const sentinel = tv.ty.sentinel();
2462 const len = @intCast(usize, tv.ty.arrayLen());
2463 const len_including_sent = len + @boolToInt(sentinel != null);
2464 const gpa = dg.gpa;
2465 const llvm_elems = try gpa.alloc(*const llvm.Value, len_including_sent);
2466 defer gpa.free(llvm_elems);
24292467
2430 const replacement_di_ty = dib.createStructType(2468 var need_unnamed = false;
2431 compile_unit_scope,2469 if (len != 0) {
2432 name.ptr,2470 for (llvm_elems[0..len]) |*elem| {
2433 di_file,2471 elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val });
2434 line,2472 }
2435 ty.abiSize(target) * 8, // size in bits2473 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
2436 ty.abiAlignment(target) * 8, // align in bits2474 }
2437 0, // flags2475
2438 null, // derived from2476 if (sentinel) |sent| {
2439 &fields,2477 llvm_elems[len] = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent });
2440 fields.len,2478 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
2441 0, // run time lang2479 }
2442 null, // vtable holder2480
2443 "", // unique id2481 if (need_unnamed) {
2444 );2482 return dg.context.constStruct(
2445 dib.replaceTemporary(fwd_decl, replacement_di_ty);2483 llvm_elems.ptr,
2446 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2484 @intCast(c_uint, llvm_elems.len),
2447 try dg.object.di_type_map.put(gpa, ty, replacement_di_ty);2485 .True,
2448 return replacement_di_ty;2486 );
2487 } else {
2488 const llvm_elem_ty = try dg.llvmType(elem_ty);
2489 return llvm_elem_ty.constArray(
2490 llvm_elems.ptr,
2491 @intCast(c_uint, llvm_elems.len),
2492 );
2493 }
2494 },
2495 .empty_array_sentinel => {
2496 const elem_ty = tv.ty.elemType();
2497 const sent_val = tv.ty.sentinel().?;
2498 const sentinel = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent_val });
2499 const llvm_elems: [1]*const llvm.Value = .{sentinel};
2500 const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]);
2501 if (need_unnamed) {
2502 return dg.context.constStruct(&llvm_elems, llvm_elems.len, .True);
2503 } else {
2504 const llvm_elem_ty = try dg.llvmType(elem_ty);
2505 return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
2506 }
2507 },
2508 else => unreachable,
2509 },
2510 .Optional => {
2511 var buf: Type.Payload.ElemType = undefined;
2512 const payload_ty = tv.ty.optionalChild(&buf);
2513 const llvm_i1 = dg.context.intType(1);
2514 const is_pl = !tv.val.isNull();
2515 const non_null_bit = if (is_pl) llvm_i1.constAllOnes() else llvm_i1.constNull();
2516 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
2517 return non_null_bit;
2518 }
2519 if (tv.ty.isPtrLikeOptional()) {
2520 if (tv.val.castTag(.opt_payload)) |payload| {
2521 return dg.genTypedValue(.{ .ty = payload_ty, .val = payload.data });
2522 } else if (is_pl) {
2523 return dg.genTypedValue(.{ .ty = payload_ty, .val = tv.val });
2524 } else {
2525 const llvm_ty = try dg.llvmType(tv.ty);
2526 return llvm_ty.constNull();
2527 }
2528 }
2529 assert(payload_ty.zigTypeTag() != .Fn);
2530 const fields: [2]*const llvm.Value = .{
2531 try dg.genTypedValue(.{
2532 .ty = payload_ty,
2533 .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),
2534 }),
2535 non_null_bit,
2536 };
2537 return dg.context.constStruct(&fields, fields.len, .False);
2538 },
2539 .Fn => {
2540 const fn_decl = switch (tv.val.tag()) {
2541 .extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl,
2542 .function => tv.val.castTag(.function).?.data.owner_decl,
2543 else => unreachable,
2544 };
2545 fn_decl.markAlive();
2546 return dg.resolveLlvmFunction(fn_decl);
2449 },2547 },
2450 .ErrorSet => {2548 .ErrorSet => {
2451 // TODO make this a proper enum with all the error codes in it.2549 const llvm_ty = try dg.llvmType(tv.ty);
2452 // will need to consider how to take incremental compilation into account.2550 switch (tv.val.tag()) {
2453 gop.value_ptr.* = dib.createBasicType("anyerror", 16, DW.ATE.unsigned);2551 .@"error" => {
2454 return gop.value_ptr.*;2552 const err_name = tv.val.castTag(.@"error").?.data.name;
2553 const kv = try dg.module.getErrorValue(err_name);
2554 return llvm_ty.constInt(kv.value, .False);
2555 },
2556 else => {
2557 // In this case we are rendering an error union which has a 0 bits payload.
2558 return llvm_ty.constNull();
2559 },
2560 }
2455 },2561 },
2456 .Struct => {2562 .ErrorUnion => {
2457 const compile_unit_scope = dg.object.di_compile_unit.?.toScope();2563 const error_type = tv.ty.errorUnionSet();
2458 const name = try ty.nameAlloc(gpa);2564 const payload_type = tv.ty.errorUnionPayload();
2459 defer gpa.free(name);2565 const is_pl = tv.val.errorUnionIsPayload();
2460 const fwd_decl = dib.createReplaceableCompositeType(
2461 DW.TAG.structure_type,
2462 name.ptr,
2463 compile_unit_scope,
2464 null, // file
2465 0, // line
2466 );
2467 gop.value_ptr.* = fwd_decl;
24682566
2469 if (ty.isTupleOrAnonStruct()) {2567 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
2470 const tuple = ty.tupleFields();2568 // We use the error type directly as the type.
2569 const err_val = if (!is_pl) tv.val else Value.initTag(.zero);
2570 return dg.genTypedValue(.{ .ty = error_type, .val = err_val });
2571 }
24712572
2472 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2573 const fields: [2]*const llvm.Value = .{
2473 defer di_fields.deinit(gpa);2574 try dg.genTypedValue(.{
2575 .ty = error_type,
2576 .val = if (is_pl) Value.initTag(.zero) else tv.val,
2577 }),
2578 try dg.genTypedValue(.{
2579 .ty = payload_type,
2580 .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef),
2581 }),
2582 };
2583 return dg.context.constStruct(&fields, fields.len, .False);
2584 },
2585 .Struct => {
2586 const llvm_struct_ty = try dg.llvmType(tv.ty);
2587 const field_vals = tv.val.castTag(.aggregate).?.data;
2588 const gpa = dg.gpa;
2589 const target = dg.module.getTarget();
24742590
2475 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);2591 if (tv.ty.isTupleOrAnonStruct()) {
2592 const tuple = tv.ty.tupleFields();
2593 var llvm_fields: std.ArrayListUnmanaged(*const llvm.Value) = .{};
2594 defer llvm_fields.deinit(gpa);
2595
2596 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);
24762597
2477 comptime assert(struct_layout_version == 2);2598 comptime assert(struct_layout_version == 2);
2478 var offset: u64 = 0;2599 var offset: u64 = 0;
2600 var big_align: u32 = 0;
2601 var need_unnamed = false;
24792602
2480 for (tuple.types) |field_ty, i| {2603 for (tuple.types) |field_ty, i| {
2481 const field_val = tuple.values[i];2604 if (tuple.values[i].tag() != .unreachable_value) continue;
2482 if (field_val.tag() != .unreachable_value) continue;2605 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
24832606
2484 const field_size = field_ty.abiSize(target);
2485 const field_align = field_ty.abiAlignment(target);2607 const field_align = field_ty.abiAlignment(target);
2486 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);2608 big_align = @maximum(big_align, field_align);
2487 offset = field_offset + field_size;2609 const prev_offset = offset;
24882610 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2489 const field_name = if (ty.castTag(.anon_struct)) |payload|
2490 try gpa.dupeZ(u8, payload.data.names[i])
2491 else
2492 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2493 defer gpa.free(field_name);
2494
2495 try di_fields.append(gpa, dib.createMemberType(
2496 fwd_decl.toScope(),
2497 field_name,
2498 null, // file
2499 0, // line
2500 field_size * 8, // size in bits
2501 field_align * 8, // align in bits
2502 field_offset * 8, // offset in bits
2503 0, // flags
2504 try dg.lowerDebugType(field_ty),
2505 ));
2506 }
2507
2508 const replacement_di_ty = dib.createStructType(
2509 compile_unit_scope,
2510 name.ptr,
2511 null, // file
2512 0, // line
2513 ty.abiSize(target) * 8, // size in bits
2514 ty.abiAlignment(target) * 8, // align in bits
2515 0, // flags
2516 null, // derived from
2517 di_fields.items.ptr,
2518 @intCast(c_int, di_fields.items.len),
2519 0, // run time lang
2520 null, // vtable holder
2521 "", // unique id
2522 );
2523 dib.replaceTemporary(fwd_decl, replacement_di_ty);
2524 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2525 try dg.object.di_type_map.put(gpa, ty, replacement_di_ty);
2526 return replacement_di_ty;
2527 }
2528
2529 const TODO_implement_this = true; // TODO
2530 if (TODO_implement_this or !ty.hasRuntimeBitsIgnoreComptime()) {
2531 const owner_decl = ty.getOwnerDecl();
2532 const struct_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl);
2533 dib.replaceTemporary(fwd_decl, struct_di_ty);
2534 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2535 // means we can't use `gop` anymore.
2536 try dg.object.di_type_map.put(gpa, ty, struct_di_ty);
2537 return struct_di_ty;
2538 }
2539 @panic("TODO debug info type for struct");
2540
2541 //const struct_obj = ty.castTag(.@"struct").?.data;
2542
2543 //if (struct_obj.layout == .Packed) {
2544 // var buf: Type.Payload.Bits = undefined;
2545 // const int_ty = struct_obj.packedIntegerType(target, &buf);
2546 // const int_llvm_ty = try dg.llvmType(int_ty);
2547 // gop.value_ptr.* = int_llvm_ty;
2548 // return int_llvm_ty;
2549 //}
2550
2551 //const name = try struct_obj.getFullyQualifiedName(gpa);
2552 //defer gpa.free(name);
2553
2554 //const llvm_struct_ty = dg.context.structCreateNamed(name);
2555 //gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
2556
2557 //assert(struct_obj.haveFieldTypes());
2558
2559 //var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{};
2560 //defer llvm_field_types.deinit(gpa);
2561
2562 //try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count());
2563
2564 //comptime assert(struct_layout_version == 2);
2565 //var offset: u64 = 0;
2566 //var big_align: u32 = 0;
2567
2568 //for (struct_obj.fields.values()) |field| {
2569 // if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
2570
2571 // const field_align = field.normalAlignment(target);
2572 // big_align = @maximum(big_align, field_align);
2573 // const prev_offset = offset;
2574 // offset = std.mem.alignForwardGeneric(u64, offset, field_align);
25752611
2576 // const padding_len = offset - prev_offset;2612 const padding_len = offset - prev_offset;
2577 // if (padding_len > 0) {2613 if (padding_len > 0) {
2578 // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));2614 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2579 // try llvm_field_types.append(gpa, llvm_array_ty);2615 // TODO make this and all other padding elsewhere in debug
2580 // }2616 // builds be 0xaa not undef.
2581 // const field_llvm_ty = try dg.llvmType(field.ty);2617 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
2582 // try llvm_field_types.append(gpa, field_llvm_ty);2618 }
25832619
2584 // offset += field.ty.abiSize(target);2620 const field_llvm_val = try dg.genTypedValue(.{
2585 //}2621 .ty = field_ty,
2586 //{2622 .val = field_vals[i],
2587 // const prev_offset = offset;2623 });
2588 // offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2589 // const padding_len = offset - prev_offset;
2590 // if (padding_len > 0) {
2591 // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2592 // try llvm_field_types.append(gpa, llvm_array_ty);
2593 // }
2594 //}
25952624
2596 //llvm_struct_ty.structSetBody(2625 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field_llvm_val);
2597 // llvm_field_types.items.ptr,
2598 // @intCast(c_uint, llvm_field_types.items.len),
2599 // .False,
2600 //);
26012626
2602 //return llvm_struct_ty;2627 llvm_fields.appendAssumeCapacity(field_llvm_val);
2603 },
2604 .Union => {
2605 const owner_decl = ty.getOwnerDecl();
26062628
2607 const name = try ty.nameAlloc(gpa);2629 offset += field_ty.abiSize(target);
2608 defer gpa.free(name);2630 }
2609 const fwd_decl = dib.createReplaceableCompositeType(2631 {
2610 DW.TAG.structure_type,2632 const prev_offset = offset;
2611 name.ptr,2633 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2612 dg.object.di_compile_unit.?.toScope(),2634 const padding_len = offset - prev_offset;
2613 null, // file2635 if (padding_len > 0) {
2614 0, // line2636 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2615 );2637 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
2616 gop.value_ptr.* = fwd_decl;2638 }
2639 }
26172640
2618 const TODO_implement_this = true; // TODO2641 if (need_unnamed) {
2619 if (TODO_implement_this or !ty.hasRuntimeBitsIgnoreComptime()) {2642 return dg.context.constStruct(
2620 const union_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl);2643 llvm_fields.items.ptr,
2621 dib.replaceTemporary(fwd_decl, union_di_ty);2644 @intCast(c_uint, llvm_fields.items.len),
2622 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2645 .False,
2623 // means we can't use `gop` anymore.2646 );
2624 try dg.object.di_type_map.put(gpa, ty, union_di_ty);2647 } else {
2625 return union_di_ty;2648 return llvm_struct_ty.constNamedStruct(
2649 llvm_fields.items.ptr,
2650 @intCast(c_uint, llvm_fields.items.len),
2651 );
2652 }
2626 }2653 }
26272654
2628 @panic("TODO debug info type for union");2655 const struct_obj = tv.ty.castTag(.@"struct").?.data;
2629 //const gop = try dg.object.type_map.getOrPut(gpa, ty);
2630 //if (gop.found_existing) return gop.value_ptr.*;
26312656
2632 //// The Type memory is ephemeral; since we want to store a longer-lived2657 if (struct_obj.layout == .Packed) {
2633 //// reference, we need to copy it here.2658 const big_bits = struct_obj.packedIntegerBits(target);
2634 //gop.key_ptr.* = try ty.copy(dg.object.type_map_arena.allocator());2659 const int_llvm_ty = dg.context.intType(big_bits);
2660 const fields = struct_obj.fields.values();
2661 comptime assert(Type.packed_struct_layout_version == 2);
2662 var running_int: *const llvm.Value = int_llvm_ty.constNull();
2663 var running_bits: u16 = 0;
2664 for (field_vals) |field_val, i| {
2665 const field = fields[i];
2666 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
26352667
2636 //const layout = ty.unionGetLayout(target);2668 const non_int_val = try dg.genTypedValue(.{
2637 //const union_obj = ty.cast(Type.Payload.Union).?.data;2669 .ty = field.ty,
2670 .val = field_val,
2671 });
2672 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
2673 const small_int_ty = dg.context.intType(ty_bit_size);
2674 const small_int_val = non_int_val.constBitCast(small_int_ty);
2675 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
2676 // If the field is as large as the entire packed struct, this
2677 // zext would go from, e.g. i16 to i16. This is legal with
2678 // constZExtOrBitCast but not legal with constZExt.
2679 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);
2680 const shifted = extended_int_val.constShl(shift_rhs);
2681 running_int = running_int.constOr(shifted);
2682 running_bits += ty_bit_size;
2683 }
2684 return running_int;
2685 }
26382686
2639 //if (layout.payload_size == 0) {2687 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
2640 // const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);2688 var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, llvm_field_count);
2641 // gop.value_ptr.* = enum_tag_llvm_ty;2689 defer llvm_fields.deinit(gpa);
2642 // return enum_tag_llvm_ty;
2643 //}
26442690
2645 //const name = try union_obj.getFullyQualifiedName(gpa);2691 comptime assert(struct_layout_version == 2);
2646 //defer gpa.free(name);2692 var offset: u64 = 0;
2693 var big_align: u32 = 0;
2694 var need_unnamed = false;
26472695
2648 //const llvm_union_ty = dg.context.structCreateNamed(name);2696 for (struct_obj.fields.values()) |field, i| {
2649 //gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls2697 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
26502698
2651 //const aligned_field = union_obj.fields.values()[layout.most_aligned_field];2699 const field_align = field.normalAlignment(target);
2652 //const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty);2700 big_align = @maximum(big_align, field_align);
2701 const prev_offset = offset;
2702 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
26532703
2654 //const llvm_payload_ty = ty: {2704 const padding_len = offset - prev_offset;
2655 // if (layout.most_aligned_field_size == layout.payload_size) {2705 if (padding_len > 0) {
2656 // break :ty llvm_aligned_field_ty;2706 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2657 // }2707 // TODO make this and all other padding elsewhere in debug
2658 // const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);2708 // builds be 0xaa not undef.
2659 // const fields: [2]*const llvm.Type = .{2709 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
2660 // llvm_aligned_field_ty,2710 }
2661 // dg.context.intType(8).arrayType(padding_len),
2662 // };
2663 // break :ty dg.context.structType(&fields, fields.len, .True);
2664 //};
26652711
2666 //if (layout.tag_size == 0) {2712 const field_llvm_val = try dg.genTypedValue(.{
2667 // var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty};2713 .ty = field.ty,
2668 // llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False);2714 .val = field_vals[i],
2669 // return llvm_union_ty;2715 });
2670 //}
2671 //const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
26722716
2673 //// Put the tag before or after the payload depending on which one's2717 need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val);
2674 //// alignment is greater.
2675 //var llvm_fields: [3]*const llvm.Type = undefined;
2676 //var llvm_fields_len: c_uint = 2;
26772718
2678 //if (layout.tag_align >= layout.payload_align) {2719 llvm_fields.appendAssumeCapacity(field_llvm_val);
2679 // llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined };
2680 //} else {
2681 // llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined };
2682 //}
26832720
2684 //// Insert padding to make the LLVM struct ABI size match the Zig union ABI size.2721 offset += field.ty.abiSize(target);
2685 //if (layout.padding != 0) {2722 }
2686 // llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding);2723 {
2687 // llvm_fields_len = 3;2724 const prev_offset = offset;
2688 //}2725 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2726 const padding_len = offset - prev_offset;
2727 if (padding_len > 0) {
2728 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2729 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
2730 }
2731 }
26892732
2690 //llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);2733 if (need_unnamed) {
2691 //return llvm_union_ty;2734 return dg.context.constStruct(
2735 llvm_fields.items.ptr,
2736 @intCast(c_uint, llvm_fields.items.len),
2737 .False,
2738 );
2739 } else {
2740 return llvm_struct_ty.constNamedStruct(
2741 llvm_fields.items.ptr,
2742 @intCast(c_uint, llvm_fields.items.len),
2743 );
2744 }
2692 },2745 },
2693 .Fn => {2746 .Union => {
2694 const fn_info = ty.fnInfo();2747 const llvm_union_ty = try dg.llvmType(tv.ty);
2695 const sret = firstParamSRet(fn_info, target);2748 const tag_and_val = tv.val.castTag(.@"union").?.data;
2696
2697 var param_di_types = std.ArrayList(*llvm.DIType).init(dg.gpa);
2698 defer param_di_types.deinit();
26992749
2700 // Return type goes first.2750 const target = dg.module.getTarget();
2701 const di_ret_ty = if (sret or !fn_info.return_type.hasRuntimeBitsIgnoreComptime())2751 const layout = tv.ty.unionGetLayout(target);
2702 Type.void
2703 else
2704 fn_info.return_type;
2705 try param_di_types.append(try dg.lowerDebugType(di_ret_ty));
27062752
2707 if (sret) {2753 if (layout.payload_size == 0) {
2708 var ptr_ty_payload: Type.Payload.ElemType = .{2754 return genTypedValue(dg, .{
2709 .base = .{ .tag = .single_mut_pointer },2755 .ty = tv.ty.unionTagType().?,
2710 .data = fn_info.return_type,2756 .val = tag_and_val.tag,
2711 };2757 });
2712 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2713 try param_di_types.append(try dg.lowerDebugType(ptr_ty));
2714 }2758 }
2759 const union_obj = tv.ty.cast(Type.Payload.Union).?.data;
2760 const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag).?;
2761 assert(union_obj.haveFieldTypes());
2762 const field_ty = union_obj.fields.values()[field_index].ty;
2763 const payload = p: {
2764 if (!field_ty.hasRuntimeBitsIgnoreComptime()) {
2765 const padding_len = @intCast(c_uint, layout.payload_size);
2766 break :p dg.context.intType(8).arrayType(padding_len).getUndef();
2767 }
2768 const field = try genTypedValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });
2769 const field_size = field_ty.abiSize(target);
2770 if (field_size == layout.payload_size) {
2771 break :p field;
2772 }
2773 const padding_len = @intCast(c_uint, layout.payload_size - field_size);
2774 const fields: [2]*const llvm.Value = .{
2775 field, dg.context.intType(8).arrayType(padding_len).getUndef(),
2776 };
2777 break :p dg.context.constStruct(&fields, fields.len, .True);
2778 };
27152779
2716 for (fn_info.param_types) |param_ty| {2780 // In this case we must make an unnamed struct because LLVM does
2717 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;2781 // not support bitcasting our payload struct to the true union payload type.
2782 // Instead we use an unnamed struct and every reference to the global
2783 // must pointer cast to the expected type before accessing the union.
2784 const need_unnamed = layout.most_aligned_field != field_index;
27182785
2719 if (isByRef(param_ty)) {2786 if (layout.tag_size == 0) {
2720 var ptr_ty_payload: Type.Payload.ElemType = .{2787 const fields: [1]*const llvm.Value = .{payload};
2721 .base = .{ .tag = .single_mut_pointer },2788 if (need_unnamed) {
2722 .data = param_ty,2789 return dg.context.constStruct(&fields, fields.len, .False);
2723 };
2724 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2725 try param_di_types.append(try dg.lowerDebugType(ptr_ty));
2726 } else {2790 } else {
2727 try param_di_types.append(try dg.lowerDebugType(param_ty));2791 return llvm_union_ty.constNamedStruct(&fields, fields.len);
2728 }2792 }
2729 }2793 }
2794 const llvm_tag_value = try genTypedValue(dg, .{
2795 .ty = tv.ty.unionTagType().?,
2796 .val = tag_and_val.tag,
2797 });
2798 var fields: [3]*const llvm.Value = undefined;
2799 var fields_len: c_uint = 2;
2800 if (layout.tag_align >= layout.payload_align) {
2801 fields = .{ llvm_tag_value, payload, undefined };
2802 } else {
2803 fields = .{ payload, llvm_tag_value, undefined };
2804 }
2805 if (layout.padding != 0) {
2806 fields[2] = dg.context.intType(8).arrayType(layout.padding).getUndef();
2807 fields_len = 3;
2808 }
2809 if (need_unnamed) {
2810 return dg.context.constStruct(&fields, fields_len, .False);
2811 } else {
2812 return llvm_union_ty.constNamedStruct(&fields, fields_len);
2813 }
2814 },
2815 .Vector => switch (tv.val.tag()) {
2816 .bytes => {
2817 // Note, sentinel is not stored even if the type has a sentinel.
2818 const bytes = tv.val.castTag(.bytes).?.data;
2819 const vector_len = @intCast(usize, tv.ty.arrayLen());
2820 assert(vector_len == bytes.len or vector_len + 1 == bytes.len);
27302821
2731 const fn_di_ty = dib.createSubroutineType(2822 const elem_ty = tv.ty.elemType();
2732 param_di_types.items.ptr,2823 const llvm_elems = try dg.gpa.alloc(*const llvm.Value, vector_len);
2733 @intCast(c_int, param_di_types.items.len),2824 defer dg.gpa.free(llvm_elems);
2734 0,2825 for (llvm_elems) |*elem, i| {
2735 );2826 var byte_payload: Value.Payload.U64 = .{
2736 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2827 .base = .{ .tag = .int_u64 },
2737 try dg.object.di_type_map.put(gpa, ty, fn_di_ty);2828 .data = bytes[i],
2738 return fn_di_ty;2829 };
2830
2831 elem.* = try dg.genTypedValue(.{
2832 .ty = elem_ty,
2833 .val = Value.initPayload(&byte_payload.base),
2834 });
2835 }
2836 return llvm.constVector(
2837 llvm_elems.ptr,
2838 @intCast(c_uint, llvm_elems.len),
2839 );
2840 },
2841 .aggregate => {
2842 // Note, sentinel is not stored even if the type has a sentinel.
2843 // The value includes the sentinel in those cases.
2844 const elem_vals = tv.val.castTag(.aggregate).?.data;
2845 const vector_len = @intCast(usize, tv.ty.arrayLen());
2846 assert(vector_len == elem_vals.len or vector_len + 1 == elem_vals.len);
2847 const elem_ty = tv.ty.elemType();
2848 const llvm_elems = try dg.gpa.alloc(*const llvm.Value, vector_len);
2849 defer dg.gpa.free(llvm_elems);
2850 for (llvm_elems) |*elem, i| {
2851 elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_vals[i] });
2852 }
2853 return llvm.constVector(
2854 llvm_elems.ptr,
2855 @intCast(c_uint, llvm_elems.len),
2856 );
2857 },
2858 .repeated => {
2859 // Note, sentinel is not stored even if the type has a sentinel.
2860 const val = tv.val.castTag(.repeated).?.data;
2861 const elem_ty = tv.ty.elemType();
2862 const len = @intCast(usize, tv.ty.arrayLen());
2863 const llvm_elems = try dg.gpa.alloc(*const llvm.Value, len);
2864 defer dg.gpa.free(llvm_elems);
2865 for (llvm_elems) |*elem| {
2866 elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val });
2867 }
2868 return llvm.constVector(
2869 llvm_elems.ptr,
2870 @intCast(c_uint, llvm_elems.len),
2871 );
2872 },
2873 else => unreachable,
2739 },2874 },
2875
2740 .ComptimeInt => unreachable,2876 .ComptimeInt => unreachable,
2741 .ComptimeFloat => unreachable,2877 .ComptimeFloat => unreachable,
2742 .Type => unreachable,2878 .Type => unreachable,
2879 .EnumLiteral => unreachable,
2880 .Void => unreachable,
2881 .NoReturn => unreachable,
2743 .Undefined => unreachable,2882 .Undefined => unreachable,
2744 .Null => unreachable,2883 .Null => unreachable,
2745 .EnumLiteral => unreachable,2884 .BoundFn => unreachable,
27462885 .Opaque => unreachable,
2747 .BoundFn => @panic("TODO remove BoundFn from the language"),
2748
2749 .Frame => @panic("TODO implement lowerDebugType for Frame types"),
2750 .AnyFrame => @panic("TODO implement lowerDebugType for AnyFrame types"),
2751 }
2752 }
27532886
2754 fn namespaceToDebugScope(dg: *DeclGen, namespace: *const Module.Namespace) !*llvm.DIScope {2887 .Frame,
2755 if (namespace.parent == null) {2888 .AnyFrame,
2756 const di_file = try dg.object.getDIFile(dg.gpa, namespace.file_scope);2889 => return dg.todo("implement const of type '{}'", .{tv.ty}),
2757 return di_file.toScope();
2758 }2890 }
2759 const di_type = try dg.lowerDebugType(namespace.ty);
2760 return di_type.toScope();
2761 }
2762
2763 /// This is to be used instead of void for debug info types, to avoid tripping
2764 /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
2765 /// when targeting CodeView (Windows).
2766 fn makeEmptyNamespaceDIType(dg: *DeclGen, decl: *const Module.Decl) !*llvm.DIType {
2767 const fields: [0]*llvm.DIType = .{};
2768 return dg.object.di_builder.?.createStructType(
2769 try dg.namespaceToDebugScope(decl.src_namespace),
2770 decl.name, // TODO use fully qualified name
2771 try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope),
2772 decl.src_line + 1,
2773 0, // size in bits
2774 0, // align in bits
2775 0, // flags
2776 null, // derived from
2777 undefined, // TODO should be able to pass &fields,
2778 fields.len,
2779 0, // run time lang
2780 null, // vtable holder
2781 "", // unique id
2782 );
2783 }2891 }
27842892
2785 const ParentPtr = struct {2893 const ParentPtr = struct {
...@@ -4085,7 +4193,7 @@ pub const FuncGen = struct {...@@ -4085,7 +4193,7 @@ pub const FuncGen = struct {
4085 name.ptr,4193 name.ptr,
4086 self.di_file.?,4194 self.di_file.?,
4087 self.prev_dbg_line,4195 self.prev_dbg_line,
4088 try self.dg.lowerDebugType(ptr_ty.childType()),4196 try self.dg.object.lowerDebugType(ptr_ty.childType(), .full),
4089 true, // always preserve4197 true, // always preserve
4090 0, // flags4198 0, // flags
4091 );4199 );
...@@ -4107,7 +4215,7 @@ pub const FuncGen = struct {...@@ -4107,7 +4215,7 @@ pub const FuncGen = struct {
4107 name.ptr,4215 name.ptr,
4108 self.di_file.?,4216 self.di_file.?,
4109 self.prev_dbg_line,4217 self.prev_dbg_line,
4110 try self.dg.lowerDebugType(operand_ty),4218 try self.dg.object.lowerDebugType(operand_ty, .full),
4111 true, // always preserve4219 true, // always preserve
4112 0, // flags4220 0, // flags
4113 );4221 );
...@@ -5359,7 +5467,7 @@ pub const FuncGen = struct {...@@ -5359,7 +5467,7 @@ pub const FuncGen = struct {
5359 func.getParamName(src_index).ptr, // TODO test 0 bit args5467 func.getParamName(src_index).ptr, // TODO test 0 bit args
5360 self.di_file.?,5468 self.di_file.?,
5361 lbrace_line,5469 lbrace_line,
5362 try self.dg.lowerDebugType(inst_ty),5470 try self.dg.object.lowerDebugType(inst_ty, .full),
5363 true, // always preserve5471 true, // always preserve
5364 0, // flags5472 0, // flags
5365 self.arg_index, // includes +1 because 0 is return type5473 self.arg_index, // includes +1 because 0 is return type
...@@ -7107,3 +7215,30 @@ fn backendSupportsF80(target: std.Target) bool {...@@ -7107,3 +7215,30 @@ fn backendSupportsF80(target: std.Target) bool {
7107/// We can do this because for all types, Zig ABI alignment >= LLVM ABI7215/// We can do this because for all types, Zig ABI alignment >= LLVM ABI
7108/// alignment.7216/// alignment.
7109const struct_layout_version = 2;7217const struct_layout_version = 2;
7218
7219/// We use the least significant bit of the pointer address to tell us
7220/// whether the type is fully resolved. Types that are only fwd declared
7221/// have the LSB flipped to a 1.
7222const AnnotatedDITypePtr = enum(usize) {
7223 _,
7224
7225 fn initFwd(di_type: *llvm.DIType) AnnotatedDITypePtr {
7226 const addr = @ptrToInt(di_type);
7227 assert(@truncate(u1, addr) == 0);
7228 return @intToEnum(AnnotatedDITypePtr, addr | 1);
7229 }
7230
7231 fn initFull(di_type: *llvm.DIType) AnnotatedDITypePtr {
7232 const addr = @ptrToInt(di_type);
7233 return @intToEnum(AnnotatedDITypePtr, addr);
7234 }
7235
7236 fn toDIType(self: AnnotatedDITypePtr) *llvm.DIType {
7237 const fixed_addr = @enumToInt(self) & ~@as(usize, 1);
7238 return @intToPtr(*llvm.DIType, fixed_addr);
7239 }
7240
7241 fn isFwdOnly(self: AnnotatedDITypePtr) bool {
7242 return @truncate(u1, @enumToInt(self)) != 0;
7243 }
7244};