authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-24 22:18:30+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-24 22:18:30+01:00
logb344ff01d380d85256929b6be2428d3c022a8580
tree63d259f50f7f1571ade492df4a187da3c9e9903a
parent8d651f512bf5032e1255dd66750faff0152e2f84
parentedb6486b3bf7a1c333d7cc3348f88ab121b72830
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19031 from antlilja/llvm-bc

Emit LLVM bitcode without using LLVM

10 files changed, 8605 insertions(+), 5425 deletions(-)

lib/std/meta.zig+4-5
...@@ -460,13 +460,12 @@ test "std.meta.FieldType" {...@@ -460,13 +460,12 @@ test "std.meta.FieldType" {
460 try testing.expect(FieldType(U, .d) == *const u8);460 try testing.expect(FieldType(U, .d) == *const u8);
461}461}
462462
463pub fn fieldNames(comptime T: type) *const [fields(T).len][]const u8 {463pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 {
464 return comptime blk: {464 return comptime blk: {
465 const fieldInfos = fields(T);465 const fieldInfos = fields(T);
466 var names: [fieldInfos.len][]const u8 = undefined;466 var names: [fieldInfos.len][:0]const u8 = undefined;
467 for (fieldInfos, 0..) |field, i| {467 // This concat can be removed with the next zig1 update.
468 names[i] = field.name;468 for (&names, fieldInfos) |*name, field| name.* = field.name ++ "";
469 }
470 break :blk &names;469 break :blk &names;
471 };470 };
472}471}
src/arch/x86_64/CodeGen.zig+31-23
...@@ -16683,36 +16683,44 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -16683,36 +16683,44 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
16683 else => null,16683 else => null,
16684 };16684 };
16685 defer if (elem_lock) |lock| self.register_manager.unlockReg(lock);16685 defer if (elem_lock) |lock| self.register_manager.unlockReg(lock);
16686 const elem_reg = registerAlias(16686
16687 try self.copyToTmpRegister(elem_ty, mat_elem_mcv),
16688 elem_abi_size,
16689 );
16690 const elem_extra_bits = self.regExtraBits(elem_ty);16687 const elem_extra_bits = self.regExtraBits(elem_ty);
16691 if (elem_bit_off < elem_extra_bits) {16688 {
16692 try self.truncateRegister(elem_ty, elem_reg);16689 const temp_reg = try self.copyToTmpRegister(elem_ty, mat_elem_mcv);
16690 const temp_alias = registerAlias(temp_reg, elem_abi_size);
16691 const temp_lock = self.register_manager.lockRegAssumeUnused(temp_reg);
16692 defer self.register_manager.unlockReg(temp_lock);
16693
16694 if (elem_bit_off < elem_extra_bits) {
16695 try self.truncateRegister(elem_ty, temp_alias);
16696 }
16697 if (elem_bit_off > 0) try self.genShiftBinOpMir(
16698 .{ ._l, .sh },
16699 elem_ty,
16700 .{ .register = temp_alias },
16701 Type.u8,
16702 .{ .immediate = elem_bit_off },
16703 );
16704 try self.genBinOpMir(
16705 .{ ._, .@"or" },
16706 elem_ty,
16707 .{ .load_frame = .{ .index = frame_index, .off = elem_byte_off } },
16708 .{ .register = temp_alias },
16709 );
16693 }16710 }
16694 if (elem_bit_off > 0) try self.genShiftBinOpMir(
16695 .{ ._l, .sh },
16696 elem_ty,
16697 .{ .register = elem_reg },
16698 Type.u8,
16699 .{ .immediate = elem_bit_off },
16700 );
16701 try self.genBinOpMir(
16702 .{ ._, .@"or" },
16703 elem_ty,
16704 .{ .load_frame = .{ .index = frame_index, .off = elem_byte_off } },
16705 .{ .register = elem_reg },
16706 );
16707 if (elem_bit_off > elem_extra_bits) {16711 if (elem_bit_off > elem_extra_bits) {
16708 const reg = try self.copyToTmpRegister(elem_ty, mat_elem_mcv);16712 const temp_reg = try self.copyToTmpRegister(elem_ty, mat_elem_mcv);
16713 const temp_alias = registerAlias(temp_reg, elem_abi_size);
16714 const temp_lock = self.register_manager.lockRegAssumeUnused(temp_reg);
16715 defer self.register_manager.unlockReg(temp_lock);
16716
16709 if (elem_extra_bits > 0) {16717 if (elem_extra_bits > 0) {
16710 try self.truncateRegister(elem_ty, registerAlias(reg, elem_abi_size));16718 try self.truncateRegister(elem_ty, temp_alias);
16711 }16719 }
16712 try self.genShiftBinOpMir(16720 try self.genShiftBinOpMir(
16713 .{ ._r, .sh },16721 .{ ._r, .sh },
16714 elem_ty,16722 elem_ty,
16715 .{ .register = reg },16723 .{ .register = temp_reg },
16716 Type.u8,16724 Type.u8,
16717 .{ .immediate = elem_abi_bits - elem_bit_off },16725 .{ .immediate = elem_abi_bits - elem_bit_off },
16718 );16726 );
...@@ -16723,7 +16731,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -16723,7 +16731,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
16723 .index = frame_index,16731 .index = frame_index,
16724 .off = elem_byte_off + @as(i32, @intCast(elem_abi_size)),16732 .off = elem_byte_off + @as(i32, @intCast(elem_abi_size)),
16725 } },16733 } },
16726 .{ .register = reg },16734 .{ .register = temp_alias },
16727 );16735 );
16728 }16736 }
16729 }16737 }
src/codegen/llvm.zig+1280-1125
...@@ -770,37 +770,20 @@ pub const Object = struct {...@@ -770,37 +770,20 @@ pub const Object = struct {
770 builder: Builder,770 builder: Builder,
771771
772 module: *Module,772 module: *Module,
773 di_builder: ?if (build_options.have_llvm) *llvm.DIBuilder else noreturn,
774 /// One of these mappings:
775 /// - *Module.File => *DIFile
776 /// - *Module.Decl (Fn) => *DISubprogram
777 /// - *Module.Decl (Non-Fn) => *DIGlobalVariable
778 di_map: if (build_options.have_llvm) std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DINode) else struct {
779 const K = *const anyopaque;
780 const V = noreturn;
781773
782 const Self = @This();774 debug_compile_unit: Builder.Metadata,
783775
784 metadata: ?noreturn = null,776 debug_enums_fwd_ref: Builder.Metadata,
785 size: Size = 0,777 debug_globals_fwd_ref: Builder.Metadata,
786 available: Size = 0,
787778
788 pub const Size = u0;779 debug_enums: std.ArrayListUnmanaged(Builder.Metadata),
780 debug_globals: std.ArrayListUnmanaged(Builder.Metadata),
789781
790 pub fn deinit(self: *Self, allocator: Allocator) void {782 debug_file_map: std.AutoHashMapUnmanaged(*const Module.File, Builder.Metadata),
791 _ = allocator;783 debug_type_map: std.AutoHashMapUnmanaged(Type, Builder.Metadata),
792 self.* = undefined;784
793 }785 debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata),
794786
795 pub fn get(self: Self, key: K) ?V {
796 _ = self;
797 _ = key;
798 return null;
799 }
800 },
801 di_compile_unit: ?if (build_options.have_llvm) *llvm.DICompileUnit else noreturn,
802 target_machine: if (build_options.have_llvm) *llvm.TargetMachine else void,
803 target_data: if (build_options.have_llvm) *llvm.TargetData else void,
804 target: std.Target,787 target: std.Target,
805 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,788 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,
806 /// but that has some downsides:789 /// but that has some downsides:
...@@ -820,7 +803,6 @@ pub const Object = struct {...@@ -820,7 +803,6 @@ pub const Object = struct {
820 /// TODO when InternPool garbage collection is implemented, this map needs803 /// TODO when InternPool garbage collection is implemented, this map needs
821 /// to be garbage collected as well.804 /// to be garbage collected as well.
822 type_map: TypeMap,805 type_map: TypeMap,
823 di_type_map: DITypeMap,
824 /// The LLVM global table which holds the names corresponding to Zig errors.806 /// The LLVM global table which holds the names corresponding to Zig errors.
825 /// Note that the values are not added until `emit`, when all errors in807 /// Note that the values are not added until `emit`, when all errors in
826 /// the compilation are known.808 /// the compilation are known.
...@@ -850,164 +832,144 @@ pub const Object = struct {...@@ -850,164 +832,144 @@ pub const Object = struct {
850832
851 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);833 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);
852834
853 /// This is an ArrayHashMap as opposed to a HashMap because in `emit` we
854 /// want to iterate over it while adding entries to it.
855 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
856
857 pub fn create(arena: Allocator, comp: *Compilation) !*Object {835 pub fn create(arena: Allocator, comp: *Compilation) !*Object {
858 if (build_options.only_c) unreachable;836 if (build_options.only_c) unreachable;
859 const gpa = comp.gpa;837 const gpa = comp.gpa;
860 const target = comp.root_mod.resolved_target.result;838 const target = comp.root_mod.resolved_target.result;
861 const llvm_target_triple = try targetTriple(arena, target);839 const llvm_target_triple = try targetTriple(arena, target);
862 const strip = comp.root_mod.strip;840 const strip = comp.root_mod.strip;
863 const optimize_mode = comp.root_mod.optimize_mode;
864 const pic = comp.root_mod.pic;
865841
866 var builder = try Builder.init(.{842 var builder = try Builder.init(.{
867 .allocator = gpa,843 .allocator = gpa,
868 .use_lib_llvm = comp.config.use_lib_llvm,844 .strip = strip,
869 .strip = strip or !comp.config.use_lib_llvm, // TODO
870 .name = comp.root_name,845 .name = comp.root_name,
871 .target = target,846 .target = target,
872 .triple = llvm_target_triple,847 .triple = llvm_target_triple,
873 });848 });
874 errdefer builder.deinit();849 errdefer builder.deinit();
875850
876 var target_machine: if (build_options.have_llvm) *llvm.TargetMachine else void = undefined;851 builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});
877 var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined;852
878 if (builder.useLibLlvm()) {853 const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =
879 debug_info: {854 if (!builder.strip)
880 switch (comp.config.debug_format) {855 debug_info: {
881 .strip => break :debug_info,856 // We fully resolve all paths at this point to avoid lack of
882 .code_view => builder.llvm.module.?.addModuleCodeViewFlag(),857 // source line info in stack traces or lack of debugging
883 .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"),858 // information which, if relative paths were used, would be
859 // very location dependent.
860 // TODO: the only concern I have with this is WASI as either host or target, should
861 // we leave the paths as relative then?
862 // TODO: This is totally wrong. In dwarf, paths are encoded as relative to
863 // a particular directory, and then the directory path is specified elsewhere.
864 // In the compiler frontend we have it stored correctly in this
865 // way already, but here we throw all that sweet information
866 // into the garbage can by converting into absolute paths. What
867 // a terrible tragedy.
868 const compile_unit_dir = blk: {
869 if (comp.module) |zcu| m: {
870 const d = try zcu.root_mod.root.joinString(arena, "");
871 if (d.len == 0) break :m;
872 if (std.fs.path.isAbsolute(d)) break :blk d;
873 break :blk std.fs.realpathAlloc(arena, d) catch break :blk d;
884 }874 }
885 builder.llvm.di_builder = builder.llvm.module.?.createDIBuilder(true);875 break :blk try std.process.getCwdAlloc(arena);
876 };
877
878 const debug_file = try builder.debugFile(
879 try builder.metadataString(comp.root_name),
880 try builder.metadataString(compile_unit_dir),
881 );
886882
883 const debug_enums_fwd_ref = try builder.debugForwardReference();
884 const debug_globals_fwd_ref = try builder.debugForwardReference();
885
886 const debug_compile_unit = try builder.debugCompileUnit(
887 debug_file,
887 // Don't use the version string here; LLVM misparses it when it888 // Don't use the version string here; LLVM misparses it when it
888 // includes the git revision.889 // includes the git revision.
889 const producer = try builder.fmt("zig {d}.{d}.{d}", .{890 try builder.metadataStringFmt("zig {d}.{d}.{d}", .{
890 build_options.semver.major,891 build_options.semver.major,
891 build_options.semver.minor,892 build_options.semver.minor,
892 build_options.semver.patch,893 build_options.semver.patch,
893 });894 }),
894895 debug_enums_fwd_ref,
895 // We fully resolve all paths at this point to avoid lack of896 debug_globals_fwd_ref,
896 // source line info in stack traces or lack of debugging897 .{ .optimized = comp.root_mod.optimize_mode != .Debug },
897 // information which, if relative paths were used, would be
898 // very location dependent.
899 // TODO: the only concern I have with this is WASI as either host or target, should
900 // we leave the paths as relative then?
901 // TODO: This is totally wrong. In dwarf, paths are encoded as relative to
902 // a particular directory, and then the directory path is specified elsewhere.
903 // In the compiler frontend we have it stored correctly in this
904 // way already, but here we throw all that sweet information
905 // into the garbage can by converting into absolute paths. What
906 // a terrible tragedy.
907 const compile_unit_dir_z = blk: {
908 if (comp.module) |zcu| m: {
909 const d = try zcu.root_mod.root.joinStringZ(arena, "");
910 if (d.len == 0) break :m;
911 if (std.fs.path.isAbsolute(d)) break :blk d;
912 const realpath = std.fs.realpathAlloc(arena, d) catch break :blk d;
913 break :blk try arena.dupeZ(u8, realpath);
914 }
915 const cwd = try std.process.getCwdAlloc(arena);
916 break :blk try arena.dupeZ(u8, cwd);
917 };
918
919 builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit(
920 DW.LANG.C99,
921 builder.llvm.di_builder.?.createFile(comp.root_name, compile_unit_dir_z),
922 producer.slice(&builder).?,
923 optimize_mode != .Debug,
924 "", // flags
925 0, // runtime version
926 "", // split name
927 0, // dwo id
928 true, // emit debug info
929 );
930 }
931
932 const opt_level: llvm.CodeGenOptLevel = if (optimize_mode == .Debug)
933 .None
934 else
935 .Aggressive;
936
937 const reloc_mode: llvm.RelocMode = if (pic)
938 .PIC
939 else if (comp.config.link_mode == .Dynamic)
940 llvm.RelocMode.DynamicNoPIC
941 else
942 .Static;
943
944 const code_model: llvm.CodeModel = switch (comp.root_mod.code_model) {
945 .default => .Default,
946 .tiny => .Tiny,
947 .small => .Small,
948 .kernel => .Kernel,
949 .medium => .Medium,
950 .large => .Large,
951 };
952
953 // TODO handle float ABI better- it should depend on the ABI portion of std.Target
954 const float_abi: llvm.ABIType = .Default;
955
956 target_machine = llvm.TargetMachine.create(
957 builder.llvm.target.?,
958 builder.target_triple.slice(&builder).?,
959 if (target.cpu.model.llvm_name) |s| s.ptr else null,
960 comp.root_mod.resolved_target.llvm_cpu_features.?,
961 opt_level,
962 reloc_mode,
963 code_model,
964 comp.function_sections,
965 comp.data_sections,
966 float_abi,
967 if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
968 );898 );
969 errdefer target_machine.dispose();
970899
971 target_data = target_machine.createTargetDataLayout();900 const i32_2 = try builder.intConst(.i32, 2);
972 errdefer target_data.dispose();901 const i32_3 = try builder.intConst(.i32, 3);
973902 const debug_info_version = try builder.debugModuleFlag(
974 builder.llvm.module.?.setModuleDataLayout(target_data);903 try builder.debugConstant(i32_2),
975904 try builder.metadataString("Debug Info Version"),
976 if (pic) builder.llvm.module.?.setModulePICLevel();905 try builder.debugConstant(i32_3),
977 if (comp.config.pie) builder.llvm.module.?.setModulePIELevel();906 );
978 if (code_model != .Default) builder.llvm.module.?.setModuleCodeModel(code_model);
979907
980 if (comp.llvm_opt_bisect_limit >= 0) {908 switch (comp.config.debug_format) {
981 builder.llvm.context.setOptBisectLimit(comp.llvm_opt_bisect_limit);909 .strip => unreachable,
910 .dwarf => |f| {
911 const i32_4 = try builder.intConst(.i32, 4);
912 const dwarf_version = try builder.debugModuleFlag(
913 try builder.debugConstant(i32_2),
914 try builder.metadataString("Dwarf Version"),
915 try builder.debugConstant(i32_4),
916 );
917 switch (f) {
918 .@"32" => {
919 try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{
920 debug_info_version,
921 dwarf_version,
922 });
923 },
924 .@"64" => {
925 const dwarf64 = try builder.debugModuleFlag(
926 try builder.debugConstant(i32_2),
927 try builder.metadataString("DWARF64"),
928 try builder.debugConstant(.@"1"),
929 );
930 try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{
931 debug_info_version,
932 dwarf_version,
933 dwarf64,
934 });
935 },
936 }
937 },
938 .code_view => {
939 const code_view = try builder.debugModuleFlag(
940 try builder.debugConstant(i32_2),
941 try builder.metadataString("CodeView"),
942 try builder.debugConstant(.@"1"),
943 );
944 try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{
945 debug_info_version,
946 code_view,
947 });
948 },
982 }949 }
983950
984 builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});951 try builder.debugNamed(try builder.metadataString("llvm.dbg.cu"), &.{debug_compile_unit});
985 if (std.debug.runtime_safety) {952 break :debug_info .{ debug_compile_unit, debug_enums_fwd_ref, debug_globals_fwd_ref };
986 const rep = target_data.stringRep();953 } else .{.none} ** 3;
987 defer llvm.disposeMessage(rep);
988 std.testing.expectEqualStrings(
989 std.mem.span(rep),
990 builder.data_layout.slice(&builder).?,
991 ) catch unreachable;
992 }
993 }
994954
995 const obj = try arena.create(Object);955 const obj = try arena.create(Object);
996 obj.* = .{956 obj.* = .{
997 .gpa = gpa,957 .gpa = gpa,
998 .builder = builder,958 .builder = builder,
999 .module = comp.module.?,959 .module = comp.module.?,
1000 .di_map = .{},960 .debug_compile_unit = debug_compile_unit,
1001 .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO961 .debug_enums_fwd_ref = debug_enums_fwd_ref,
1002 .di_compile_unit = if (builder.useLibLlvm()) builder.llvm.di_compile_unit else null,962 .debug_globals_fwd_ref = debug_globals_fwd_ref,
1003 .target_machine = target_machine,963 .debug_enums = .{},
1004 .target_data = target_data,964 .debug_globals = .{},
965 .debug_file_map = .{},
966 .debug_type_map = .{},
967 .debug_unresolved_namespace_scopes = .{},
1005 .target = target,968 .target = target,
1006 .decl_map = .{},969 .decl_map = .{},
1007 .anon_decl_map = .{},970 .anon_decl_map = .{},
1008 .named_enum_map = .{},971 .named_enum_map = .{},
1009 .type_map = .{},972 .type_map = .{},
1010 .di_type_map = .{},
1011 .error_name_table = .none,973 .error_name_table = .none,
1012 .extern_collisions = .{},974 .extern_collisions = .{},
1013 .null_opt_usize = .no_init,975 .null_opt_usize = .no_init,
...@@ -1018,12 +980,11 @@ pub const Object = struct {...@@ -1018,12 +980,11 @@ pub const Object = struct {
1018980
1019 pub fn deinit(self: *Object) void {981 pub fn deinit(self: *Object) void {
1020 const gpa = self.gpa;982 const gpa = self.gpa;
1021 self.di_map.deinit(gpa);983 self.debug_enums.deinit(gpa);
1022 self.di_type_map.deinit(gpa);984 self.debug_globals.deinit(gpa);
1023 if (self.builder.useLibLlvm()) {985 self.debug_file_map.deinit(gpa);
1024 self.target_data.dispose();986 self.debug_type_map.deinit(gpa);
1025 self.target_machine.dispose();987 self.debug_unresolved_namespace_scopes.deinit(gpa);
1026 }
1027 self.decl_map.deinit(gpa);988 self.decl_map.deinit(gpa);
1028 self.anon_decl_map.deinit(gpa);989 self.anon_decl_map.deinit(gpa);
1029 self.named_enum_map.deinit(gpa);990 self.named_enum_map.deinit(gpa);
...@@ -1052,8 +1013,8 @@ pub const Object = struct {...@@ -1052,8 +1013,8 @@ pub const Object = struct {
10521013
1053 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);1014 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
1054 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {1015 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {
1055 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));1016 const name_string = try o.builder.stringNull(mod.intern_pool.stringToSlice(name));
1056 const name_init = try o.builder.stringNullConst(name_string);1017 const name_init = try o.builder.stringConst(name_string);
1057 const name_variable_index =1018 const name_variable_index =
1058 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);1019 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
1059 try name_variable_index.setInitializer(name_init, &o.builder);1020 try name_variable_index.setInitializer(name_init, &o.builder);
...@@ -1064,7 +1025,7 @@ pub const Object = struct {...@@ -1064,7 +1025,7 @@ pub const Object = struct {
10641025
1065 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{1026 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
1066 name_variable_index.toConst(&o.builder),1027 name_variable_index.toConst(&o.builder),
1067 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len),1028 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len - 1),
1068 });1029 });
1069 }1030 }
10701031
...@@ -1193,24 +1154,29 @@ pub const Object = struct {...@@ -1193,24 +1154,29 @@ pub const Object = struct {
1193 try self.genCmpLtErrorsLenFunction();1154 try self.genCmpLtErrorsLenFunction();
1194 try self.genModuleLevelAssembly();1155 try self.genModuleLevelAssembly();
11951156
1196 if (self.di_builder) |dib| {1157 if (!self.builder.strip) {
1197 // When lowering debug info for pointers, we emitted the element types as1158 {
1198 // forward decls. Now we must go flesh those out.1159 var i: usize = 0;
1199 // Here we iterate over a hash map while modifying it but it is OK because1160 while (i < self.debug_unresolved_namespace_scopes.count()) : (i += 1) {
1200 // we never add or remove entries during this loop.1161 const namespace_index = self.debug_unresolved_namespace_scopes.keys()[i];
1201 var i: usize = 0;1162 const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i];
1202 while (i < self.di_type_map.count()) : (i += 1) {1163
1203 const value_ptr = &self.di_type_map.values()[i];1164 const namespace = self.module.namespacePtr(namespace_index);
1204 const annotated = value_ptr.*;1165 const debug_type = try self.lowerDebugType(namespace.ty);
1205 if (!annotated.isFwdOnly()) continue;1166
1206 const entry: Object.DITypeMap.Entry = .{1167 self.builder.debugForwardReferenceSetType(fwd_ref, debug_type);
1207 .key_ptr = &self.di_type_map.keys()[i],1168 }
1208 .value_ptr = value_ptr,
1209 };
1210 _ = try self.lowerDebugTypeImpl(entry, .full, annotated.toDIType());
1211 }1169 }
12121170
1213 dib.finalize();1171 self.builder.debugForwardReferenceSetType(
1172 self.debug_enums_fwd_ref,
1173 try self.builder.debugTuple(self.debug_enums.items),
1174 );
1175
1176 self.builder.debugForwardReferenceSetType(
1177 self.debug_globals_fwd_ref,
1178 try self.builder.debugTuple(self.debug_globals.items),
1179 );
1214 }1180 }
12151181
1216 if (options.pre_ir_path) |path| {1182 if (options.pre_ir_path) |path| {
...@@ -1221,10 +1187,21 @@ pub const Object = struct {...@@ -1221,10 +1187,21 @@ pub const Object = struct {
1221 }1187 }
1222 }1188 }
12231189
1224 if (options.pre_bc_path) |path| _ = try self.builder.writeBitcodeToFile(path);1190 var bitcode_arena_allocator = std.heap.ArenaAllocator.init(
1191 std.heap.page_allocator,
1192 );
1193 errdefer bitcode_arena_allocator.deinit();
1194
1195 const bitcode = try self.builder.toBitcode(
1196 bitcode_arena_allocator.allocator(),
1197 );
1198
1199 if (options.pre_bc_path) |path| {
1200 var file = try std.fs.cwd().createFile(path, .{});
1201 defer file.close();
12251202
1226 if (std.debug.runtime_safety and !try self.builder.verify()) {1203 const ptr: [*]const u8 = @ptrCast(bitcode.ptr);
1227 @panic("LLVM module verification failed");1204 try file.writeAll(ptr[0..(bitcode.len * 4)]);
1228 }1205 }
12291206
1230 const emit_asm_msg = options.asm_path orelse "(none)";1207 const emit_asm_msg = options.asm_path orelse "(none)";
...@@ -1238,16 +1215,116 @@ pub const Object = struct {...@@ -1238,16 +1215,116 @@ pub const Object = struct {
1238 if (options.asm_path == null and options.bin_path == null and1215 if (options.asm_path == null and options.bin_path == null and
1239 options.post_ir_path == null and options.post_bc_path == null) return;1216 options.post_ir_path == null and options.post_bc_path == null) return;
12401217
1241 if (!self.builder.useLibLlvm()) unreachable; // caught in Compilation.Config.resolve1218 if (options.post_bc_path) |path| {
1219 var file = try std.fs.cwd().createFileZ(path, .{});
1220 defer file.close();
1221
1222 const ptr: [*]const u8 = @ptrCast(bitcode.ptr);
1223 try file.writeAll(ptr[0..(bitcode.len * 4)]);
1224 }
1225
1226 if (!build_options.have_llvm or !self.module.comp.config.use_lib_llvm) {
1227 log.err("emitting without libllvm not implemented", .{});
1228 return error.FailedToEmit;
1229 }
1230
1231 initializeLLVMTarget(self.module.comp.root_mod.resolved_target.result.cpu.arch);
1232
1233 const context: *llvm.Context = llvm.Context.create();
1234 defer context.dispose();
1235
1236 const module = blk: {
1237 const bitcode_memory_buffer = llvm.MemoryBuffer.createMemoryBufferWithMemoryRange(
1238 @ptrCast(bitcode.ptr),
1239 bitcode.len * 4,
1240 "BitcodeBuffer",
1241 llvm.Bool.False,
1242 );
1243 defer bitcode_memory_buffer.dispose();
1244
1245 var module: *llvm.Module = undefined;
1246 if (context.parseBitcodeInContext2(bitcode_memory_buffer, &module).toBool()) {
1247 std.debug.print("Failed to parse bitcode\n", .{});
1248 return error.FailedToEmit;
1249 }
1250
1251 break :blk module;
1252 };
1253 bitcode_arena_allocator.deinit();
1254
1255 const target_triple_sentinel =
1256 try self.gpa.dupeZ(u8, self.builder.target_triple.slice(&self.builder).?);
1257 defer self.gpa.free(target_triple_sentinel);
1258 var target: *llvm.Target = undefined;
1259 var error_message: [*:0]const u8 = undefined;
1260 if (llvm.Target.getFromTriple(target_triple_sentinel, &target, &error_message).toBool()) {
1261 defer llvm.disposeMessage(error_message);
1262
1263 log.err("LLVM failed to parse '{s}': {s}", .{
1264 self.builder.target_triple.slice(&self.builder).?,
1265 error_message,
1266 });
1267 @panic("Invalid LLVM triple");
1268 }
1269
1270 const optimize_mode = self.module.comp.root_mod.optimize_mode;
1271 const pic = self.module.comp.root_mod.pic;
1272
1273 const opt_level: llvm.CodeGenOptLevel = if (optimize_mode == .Debug)
1274 .None
1275 else
1276 .Aggressive;
1277
1278 const reloc_mode: llvm.RelocMode = if (pic)
1279 .PIC
1280 else if (self.module.comp.config.link_mode == .Dynamic)
1281 llvm.RelocMode.DynamicNoPIC
1282 else
1283 .Static;
1284
1285 const code_model: llvm.CodeModel = switch (self.module.comp.root_mod.code_model) {
1286 .default => .Default,
1287 .tiny => .Tiny,
1288 .small => .Small,
1289 .kernel => .Kernel,
1290 .medium => .Medium,
1291 .large => .Large,
1292 };
1293
1294 // TODO handle float ABI better- it should depend on the ABI portion of std.Target
1295 const float_abi: llvm.ABIType = .Default;
1296
1297 var target_machine = llvm.TargetMachine.create(
1298 target,
1299 target_triple_sentinel,
1300 if (self.module.comp.root_mod.resolved_target.result.cpu.model.llvm_name) |s| s.ptr else null,
1301 self.module.comp.root_mod.resolved_target.llvm_cpu_features.?,
1302 opt_level,
1303 reloc_mode,
1304 code_model,
1305 self.module.comp.function_sections,
1306 self.module.comp.data_sections,
1307 float_abi,
1308 if (target_util.llvmMachineAbi(self.module.comp.root_mod.resolved_target.result)) |s| s.ptr else null,
1309 );
1310 errdefer target_machine.dispose();
1311
1312 if (pic) module.setModulePICLevel();
1313 if (self.module.comp.config.pie) module.setModulePIELevel();
1314 if (code_model != .Default) module.setModuleCodeModel(code_model);
1315
1316 if (self.module.comp.llvm_opt_bisect_limit >= 0) {
1317 context.setOptBisectLimit(self.module.comp.llvm_opt_bisect_limit);
1318 }
12421319
1243 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.1320 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
1244 // So we call the entire pipeline multiple times if this is requested.1321 // So we call the entire pipeline multiple times if this is requested.
1245 var error_message: [*:0]const u8 = undefined;1322 // var error_message: [*:0]const u8 = undefined;
1246 var emit_bin_path = options.bin_path;1323 var emit_bin_path = options.bin_path;
1247 var post_ir_path = options.post_ir_path;1324 var post_ir_path = options.post_ir_path;
1248 if (options.asm_path != null and options.bin_path != null) {1325 if (options.asm_path != null and options.bin_path != null) {
1249 if (self.target_machine.emitToFile(1326 if (target_machine.emitToFile(
1250 self.builder.llvm.module.?,1327 module,
1251 &error_message,1328 &error_message,
1252 options.is_debug,1329 options.is_debug,
1253 options.is_small,1330 options.is_small,
...@@ -1270,8 +1347,8 @@ pub const Object = struct {...@@ -1270,8 +1347,8 @@ pub const Object = struct {
1270 post_ir_path = null;1347 post_ir_path = null;
1271 }1348 }
12721349
1273 if (self.target_machine.emitToFile(1350 if (target_machine.emitToFile(
1274 self.builder.llvm.module.?,1351 module,
1275 &error_message,1352 &error_message,
1276 options.is_debug,1353 options.is_debug,
1277 options.is_small,1354 options.is_small,
...@@ -1281,7 +1358,7 @@ pub const Object = struct {...@@ -1281,7 +1358,7 @@ pub const Object = struct {
1281 options.asm_path,1358 options.asm_path,
1282 emit_bin_path,1359 emit_bin_path,
1283 post_ir_path,1360 post_ir_path,
1284 options.post_bc_path,1361 null,
1285 )) {1362 )) {
1286 defer llvm.disposeMessage(error_message);1363 defer llvm.disposeMessage(error_message);
12871364
...@@ -1421,7 +1498,7 @@ pub const Object = struct {...@@ -1421,7 +1498,7 @@ pub const Object = struct {
1421 if (isByRef(param_ty, zcu)) {1498 if (isByRef(param_ty, zcu)) {
1422 const alignment = param_ty.abiAlignment(zcu).toLlvm();1499 const alignment = param_ty.abiAlignment(zcu).toLlvm();
1423 const param_llvm_ty = param.typeOfWip(&wip);1500 const param_llvm_ty = param.typeOfWip(&wip);
1424 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);1501 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
1425 _ = try wip.store(.normal, param, arg_ptr, alignment);1502 _ = try wip.store(.normal, param, arg_ptr, alignment);
1426 args.appendAssumeCapacity(arg_ptr);1503 args.appendAssumeCapacity(arg_ptr);
1427 } else {1504 } else {
...@@ -1469,7 +1546,7 @@ pub const Object = struct {...@@ -1469,7 +1546,7 @@ pub const Object = struct {
14691546
1470 const param_llvm_ty = try o.lowerType(param_ty);1547 const param_llvm_ty = try o.lowerType(param_ty);
1471 const alignment = param_ty.abiAlignment(zcu).toLlvm();1548 const alignment = param_ty.abiAlignment(zcu).toLlvm();
1472 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);1549 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
1473 _ = try wip.store(.normal, param, arg_ptr, alignment);1550 _ = try wip.store(.normal, param, arg_ptr, alignment);
14741551
1475 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))1552 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
...@@ -1514,7 +1591,7 @@ pub const Object = struct {...@@ -1514,7 +1591,7 @@ pub const Object = struct {
1514 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);1591 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
1515 const param_llvm_ty = try o.lowerType(param_ty);1592 const param_llvm_ty = try o.lowerType(param_ty);
1516 const param_alignment = param_ty.abiAlignment(zcu).toLlvm();1593 const param_alignment = param_ty.abiAlignment(zcu).toLlvm();
1517 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, param_alignment, target);1594 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, param_alignment, target);
1518 const llvm_ty = try o.builder.structType(.normal, field_types);1595 const llvm_ty = try o.builder.structType(.normal, field_types);
1519 for (0..field_types.len) |field_i| {1596 for (0..field_types.len) |field_i| {
1520 const param = wip.arg(llvm_arg_i);1597 const param = wip.arg(llvm_arg_i);
...@@ -1544,7 +1621,7 @@ pub const Object = struct {...@@ -1544,7 +1621,7 @@ pub const Object = struct {
1544 llvm_arg_i += 1;1621 llvm_arg_i += 1;
15451622
1546 const alignment = param_ty.abiAlignment(zcu).toLlvm();1623 const alignment = param_ty.abiAlignment(zcu).toLlvm();
1547 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);1624 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
1548 _ = try wip.store(.normal, param, arg_ptr, alignment);1625 _ = try wip.store(.normal, param, arg_ptr, alignment);
15491626
1550 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))1627 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
...@@ -1559,7 +1636,7 @@ pub const Object = struct {...@@ -1559,7 +1636,7 @@ pub const Object = struct {
1559 llvm_arg_i += 1;1636 llvm_arg_i += 1;
15601637
1561 const alignment = param_ty.abiAlignment(zcu).toLlvm();1638 const alignment = param_ty.abiAlignment(zcu).toLlvm();
1562 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);1639 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
1563 _ = try wip.store(.normal, param, arg_ptr, alignment);1640 _ = try wip.store(.normal, param, arg_ptr, alignment);
15641641
1565 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))1642 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
...@@ -1573,40 +1650,37 @@ pub const Object = struct {...@@ -1573,40 +1650,37 @@ pub const Object = struct {
15731650
1574 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);1651 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
15751652
1576 var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null;1653 const file, const subprogram = if (!o.builder.strip) debug_info: {
1577 var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null;1654 const file = try o.getDebugFile(namespace.file_scope);
1578
1579 if (o.di_builder) |dib| {
1580 di_file = try o.getDIFile(gpa, namespace.file_scope);
15811655
1582 const line_number = decl.src_line + 1;1656 const line_number = decl.src_line + 1;
1583 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and1657 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and
1584 !zcu.decl_exports.contains(decl_index);1658 !zcu.decl_exports.contains(decl_index);
1585 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)1659 const debug_decl_type = try o.lowerDebugType(decl.ty);
1586 llvm.DIFlags.NoReturn1660
1587 else1661 const subprogram = try o.builder.debugSubprogram(
1588 0;1662 file,
1589 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);1663 try o.builder.metadataString(ip.stringToSlice(decl.name)),
1590 const subprogram = dib.createFunction(1664 try o.builder.metadataStringFromString(function_index.name(&o.builder)),
1591 di_file.?.toScope(),
1592 ip.stringToSlice(decl.name),
1593 function_index.name(&o.builder).slice(&o.builder).?,
1594 di_file.?,
1595 line_number,1665 line_number,
1596 decl_di_ty,1666 line_number + func.lbrace_line,
1597 is_internal_linkage,1667 debug_decl_type,
1598 true, // is definition1668 .{
1599 line_number + func.lbrace_line, // scope line1669 .di_flags = .{
1600 llvm.DIFlags.StaticMember | noret_bit,1670 .StaticMember = true,
1601 owner_mod.optimize_mode != .Debug,1671 .NoReturn = fn_info.return_type == .noreturn_type,
1602 null, // decl_subprogram1672 },
1673 .sp_flags = .{
1674 .Optimized = owner_mod.optimize_mode != .Debug,
1675 .Definition = true,
1676 .LocalToUnit = is_internal_linkage,
1677 },
1678 },
1679 o.debug_compile_unit,
1603 );1680 );
1604 try o.di_map.put(gpa, decl, subprogram.toNode());1681 function_index.setSubprogram(subprogram, &o.builder);
16051682 break :debug_info .{ file, subprogram };
1606 function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram);1683 } else .{.none} ** 2;
1607
1608 di_scope = subprogram.toScope();
1609 }
16101684
1611 var fg: FuncGen = .{1685 var fg: FuncGen = .{
1612 .gpa = gpa,1686 .gpa = gpa,
...@@ -1620,8 +1694,8 @@ pub const Object = struct {...@@ -1620,8 +1694,8 @@ pub const Object = struct {
1620 .func_inst_table = .{},1694 .func_inst_table = .{},
1621 .blocks = .{},1695 .blocks = .{},
1622 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,1696 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
1623 .di_scope = di_scope,1697 .file = file,
1624 .di_file = di_file,1698 .scope = subprogram,
1625 .base_line = dg.decl.src_line,1699 .base_line = dg.decl.src_line,
1626 .prev_dbg_line = 0,1700 .prev_dbg_line = 0,
1627 .prev_dbg_column = 0,1701 .prev_dbg_column = 0,
...@@ -1707,26 +1781,7 @@ pub const Object = struct {...@@ -1707,26 +1781,7 @@ pub const Object = struct {
1707 global_index.setUnnamedAddr(.default, &self.builder);1781 global_index.setUnnamedAddr(.default, &self.builder);
1708 if (comp.config.dll_export_fns)1782 if (comp.config.dll_export_fns)
1709 global_index.setDllStorageClass(.default, &self.builder);1783 global_index.setDllStorageClass(.default, &self.builder);
1710 if (self.di_map.get(decl)) |di_node| {1784
1711 const decl_name_slice = decl_name.slice(&self.builder).?;
1712 if (try decl.isFunction(mod)) {
1713 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
1714 const linkage_name = llvm.MDString.get(
1715 self.builder.llvm.context,
1716 decl_name_slice.ptr,
1717 decl_name_slice.len,
1718 );
1719 di_func.replaceLinkageName(linkage_name);
1720 } else {
1721 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
1722 const linkage_name = llvm.MDString.get(
1723 self.builder.llvm.context,
1724 decl_name_slice.ptr,
1725 decl_name_slice.len,
1726 );
1727 di_global.replaceLinkageName(linkage_name);
1728 }
1729 }
1730 if (decl.val.getVariable(mod)) |decl_var| {1785 if (decl.val.getVariable(mod)) |decl_var| {
1731 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(1786 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1732 if (decl_var.is_threadlocal) .generaldynamic else .default,1787 if (decl_var.is_threadlocal) .generaldynamic else .default,
...@@ -1740,27 +1795,6 @@ pub const Object = struct {...@@ -1740,27 +1795,6 @@ pub const Object = struct {
1740 );1795 );
1741 try global_index.rename(main_exp_name, &self.builder);1796 try global_index.rename(main_exp_name, &self.builder);
17421797
1743 if (self.di_map.get(decl)) |di_node| {
1744 const main_exp_name_slice = main_exp_name.slice(&self.builder).?;
1745 if (try decl.isFunction(mod)) {
1746 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
1747 const linkage_name = llvm.MDString.get(
1748 self.builder.llvm.context,
1749 main_exp_name_slice.ptr,
1750 main_exp_name_slice.len,
1751 );
1752 di_func.replaceLinkageName(linkage_name);
1753 } else {
1754 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
1755 const linkage_name = llvm.MDString.get(
1756 self.builder.llvm.context,
1757 main_exp_name_slice.ptr,
1758 main_exp_name_slice.len,
1759 );
1760 di_global.replaceLinkageName(linkage_name);
1761 }
1762 }
1763
1764 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)1798 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
1765 global_index.ptrConst(&self.builder).kind1799 global_index.ptrConst(&self.builder).kind
1766 .variable.setThreadLocal(.generaldynamic, &self.builder);1800 .variable.setThreadLocal(.generaldynamic, &self.builder);
...@@ -1890,119 +1924,79 @@ pub const Object = struct {...@@ -1890,119 +1924,79 @@ pub const Object = struct {
1890 global.delete(&self.builder);1924 global.delete(&self.builder);
1891 }1925 }
18921926
1893 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {1927 fn getDebugFile(o: *Object, file: *const Module.File) Allocator.Error!Builder.Metadata {
1894 const gop = try o.di_map.getOrPut(gpa, file);1928 const gpa = o.gpa;
1895 errdefer assert(o.di_map.remove(file));1929 const gop = try o.debug_file_map.getOrPut(gpa, file);
1896 if (gop.found_existing) {1930 errdefer assert(o.debug_file_map.remove(file));
1897 return @ptrCast(gop.value_ptr.*);1931 if (gop.found_existing) return gop.value_ptr.*;
1898 }1932 gop.value_ptr.* = try o.builder.debugFile(
1899 const dir_path_z = d: {1933 try o.builder.metadataString(std.fs.path.basename(file.sub_file_path)),
1900 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;1934 dir_path: {
1901 const sub_path = std.fs.path.dirname(file.sub_file_path) orelse "";1935 const sub_path = std.fs.path.dirname(file.sub_file_path) orelse "";
1902 const dir_path = try file.mod.root.joinStringZ(gpa, sub_path);1936 const dir_path = try file.mod.root.joinString(gpa, sub_path);
1903 if (std.fs.path.isAbsolute(dir_path)) break :d dir_path;1937 defer gpa.free(dir_path);
1904 const abs = std.fs.realpath(dir_path, &buffer) catch break :d dir_path;1938 if (std.fs.path.isAbsolute(dir_path))
1905 gpa.free(dir_path);1939 break :dir_path try o.builder.metadataString(dir_path);
1906 break :d try gpa.dupeZ(u8, abs);1940 var abs_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
1907 };1941 const abs_path = std.fs.realpath(dir_path, &abs_buffer) catch
1908 defer gpa.free(dir_path_z);1942 break :dir_path try o.builder.metadataString(dir_path);
1909 const sub_file_path_z = try gpa.dupeZ(u8, std.fs.path.basename(file.sub_file_path));1943 break :dir_path try o.builder.metadataString(abs_path);
1910 defer gpa.free(sub_file_path_z);1944 },
1911 const di_file = o.di_builder.?.createFile(sub_file_path_z, dir_path_z);1945 );
1912 gop.value_ptr.* = di_file.toNode();1946 return gop.value_ptr.*;
1913 return di_file;
1914 }1947 }
19151948
1916 const DebugResolveStatus = enum { fwd, full };1949 pub fn lowerDebugType(
1917
1918 /// In the implementation of this function, it is required to store a forward decl
1919 /// into `gop` before making any recursive calls (even directly).
1920 fn lowerDebugType(
1921 o: *Object,1950 o: *Object,
1922 ty: Type,1951 ty: Type,
1923 resolve: DebugResolveStatus,1952 ) Allocator.Error!Builder.Metadata {
1924 ) Allocator.Error!*llvm.DIType {1953 assert(!o.builder.strip);
1925 const gpa = o.gpa;
1926 // Be careful not to reference this `gop` variable after any recursive calls
1927 // to `lowerDebugType`.
1928 const gop = try o.di_type_map.getOrPut(gpa, ty.toIntern());
1929 if (gop.found_existing) {
1930 const annotated = gop.value_ptr.*;
1931 switch (annotated) {
1932 // This type is currently attempting to be resolved fully, so make
1933 // sure a second recursion through the types uses forward resolution.
1934 .null => assert(resolve == .fwd),
1935 // This type already has at least forward resolution, only resolve
1936 // fully during full resolution.
1937 _ => {
1938 const di_type = annotated.toDIType();
1939 if (!annotated.isFwdOnly() or resolve == .fwd) {
1940 return di_type;
1941 }
1942 const entry: Object.DITypeMap.Entry = .{
1943 .key_ptr = gop.key_ptr,
1944 .value_ptr = gop.value_ptr,
1945 };
1946 return o.lowerDebugTypeImpl(entry, resolve, di_type);
1947 },
1948 }
1949 } else gop.value_ptr.* = .null;
1950 errdefer if (!gop.found_existing) assert(o.di_type_map.orderedRemove(ty.toIntern()));
1951 const entry: Object.DITypeMap.Entry = .{
1952 .key_ptr = gop.key_ptr,
1953 .value_ptr = gop.value_ptr,
1954 };
1955 return o.lowerDebugTypeImpl(entry, resolve, null);
1956 }
19571954
1958 /// This is a helper function used by `lowerDebugType`.
1959 fn lowerDebugTypeImpl(
1960 o: *Object,
1961 gop: Object.DITypeMap.Entry,
1962 resolve: DebugResolveStatus,
1963 opt_fwd_decl: ?*llvm.DIType,
1964 ) Allocator.Error!*llvm.DIType {
1965 const ty = Type.fromInterned(gop.key_ptr.*);
1966 const gpa = o.gpa;1955 const gpa = o.gpa;
1967 const target = o.target;1956 const target = o.target;
1968 const dib = o.di_builder.?;
1969 const mod = o.module;1957 const mod = o.module;
1970 const ip = &mod.intern_pool;1958 const ip = &mod.intern_pool;
1959
1960 if (o.debug_type_map.get(ty)) |debug_type| return debug_type;
1961
1971 switch (ty.zigTypeTag(mod)) {1962 switch (ty.zigTypeTag(mod)) {
1972 .Void, .NoReturn => {1963 .Void,
1973 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);1964 .NoReturn,
1974 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);1965 => {
1975 return di_type;1966 const debug_void_type = try o.builder.debugSignedType(
1967 try o.builder.metadataString("void"),
1968 0,
1969 );
1970 try o.debug_type_map.put(gpa, ty, debug_void_type);
1971 return debug_void_type;
1976 },1972 },
1977 .Int => {1973 .Int => {
1978 const info = ty.intInfo(mod);1974 const info = ty.intInfo(mod);
1979 assert(info.bits != 0);1975 assert(info.bits != 0);
1980 const name = try o.allocTypeName(ty);1976 const name = try o.allocTypeName(ty);
1981 defer gpa.free(name);1977 defer gpa.free(name);
1982 const dwarf_encoding: c_uint = switch (info.signedness) {1978 const builder_name = try o.builder.metadataString(name);
1983 .signed => DW.ATE.signed,1979 const debug_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
1984 .unsigned => DW.ATE.unsigned,1980 const debug_int_type = switch (info.signedness) {
1981 .signed => try o.builder.debugSignedType(builder_name, debug_bits),
1982 .unsigned => try o.builder.debugUnsignedType(builder_name, debug_bits),
1985 };1983 };
1986 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types1984 try o.debug_type_map.put(gpa, ty, debug_int_type);
1987 const di_type = dib.createBasicType(name, di_bits, dwarf_encoding);1985 return debug_int_type;
1988 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
1989 return di_type;
1990 },1986 },
1991 .Enum => {1987 .Enum => {
1992 const owner_decl_index = ty.getOwnerDecl(mod);1988 const owner_decl_index = ty.getOwnerDecl(mod);
1993 const owner_decl = o.module.declPtr(owner_decl_index);1989 const owner_decl = o.module.declPtr(owner_decl_index);
19941990
1995 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {1991 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
1996 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);1992 const debug_enum_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
1997 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`1993 try o.debug_type_map.put(gpa, ty, debug_enum_type);
1998 // means we can't use `gop` anymore.1994 return debug_enum_type;
1999 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));
2000 return enum_di_ty;
2001 }1995 }
20021996
2003 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;1997 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
20041998
2005 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);1999 const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len);
2006 defer gpa.free(enumerators);2000 defer gpa.free(enumerators);
20072001
2008 const int_ty = Type.fromInterned(enum_type.tag_ty);2002 const int_ty = Type.fromInterned(enum_type.tag_ty);
...@@ -2010,66 +2004,59 @@ pub const Object = struct {...@@ -2010,66 +2004,59 @@ pub const Object = struct {
2010 assert(int_info.bits != 0);2004 assert(int_info.bits != 0);
20112005
2012 for (enum_type.names.get(ip), 0..) |field_name_ip, i| {2006 for (enum_type.names.get(ip), 0..) |field_name_ip, i| {
2013 const field_name_z = ip.stringToSlice(field_name_ip);
2014
2015 var bigint_space: Value.BigIntSpace = undefined;2007 var bigint_space: Value.BigIntSpace = undefined;
2016 const bigint = if (enum_type.values.len != 0)2008 const bigint = if (enum_type.values.len != 0)
2017 Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, mod)2009 Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, mod)
2018 else2010 else
2019 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();2011 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
20202012
2021 if (bigint.limbs.len == 1) {2013 enumerators[i] = try o.builder.debugEnumerator(
2022 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);2014 try o.builder.metadataString(ip.stringToSlice(field_name_ip)),
2023 continue;2015 int_ty.isUnsignedInt(mod),
2024 }2016 int_info.bits,
2025 if (@sizeOf(usize) == @sizeOf(u64)) {2017 bigint,
2026 enumerators[i] = dib.createEnumerator2(2018 );
2027 field_name_z,
2028 @intCast(bigint.limbs.len),
2029 bigint.limbs.ptr,
2030 int_info.bits,
2031 int_info.signedness == .unsigned,
2032 );
2033 continue;
2034 }
2035 @panic("TODO implement bigint debug enumerators to llvm int for 32-bit compiler builds");
2036 }2019 }
20372020
2038 const di_file = try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope);2021 const file = try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope);
2039 const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace);2022 const scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
20402023
2041 const name = try o.allocTypeName(ty);2024 const name = try o.allocTypeName(ty);
2042 defer gpa.free(name);2025 defer gpa.free(name);
20432026
2044 const enum_di_ty = dib.createEnumerationType(2027 const debug_enum_type = try o.builder.debugEnumerationType(
2045 di_scope,2028 try o.builder.metadataString(name),
2046 name,2029 file,
2047 di_file,2030 scope,
2048 owner_decl.src_node + 1,2031 owner_decl.src_node + 1, // Line
2032 try o.lowerDebugType(int_ty),
2049 ty.abiSize(mod) * 8,2033 ty.abiSize(mod) * 8,
2050 ty.abiAlignment(mod).toByteUnits(0) * 8,2034 ty.abiAlignment(mod).toByteUnits(0) * 8,
2051 enumerators.ptr,2035 try o.builder.debugTuple(enumerators),
2052 @intCast(enumerators.len),
2053 try o.lowerDebugType(int_ty, resolve),
2054 "",
2055 );2036 );
2056 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2037
2057 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));2038 try o.debug_type_map.put(gpa, ty, debug_enum_type);
2058 return enum_di_ty;2039 try o.debug_enums.append(gpa, debug_enum_type);
2040 return debug_enum_type;
2059 },2041 },
2060 .Float => {2042 .Float => {
2061 const bits = ty.floatBits(target);2043 const bits = ty.floatBits(target);
2062 const name = try o.allocTypeName(ty);2044 const name = try o.allocTypeName(ty);
2063 defer gpa.free(name);2045 defer gpa.free(name);
2064 const di_type = dib.createBasicType(name, bits, DW.ATE.float);2046 const debug_float_type = try o.builder.debugFloatType(
2065 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);2047 try o.builder.metadataString(name),
2066 return di_type;2048 bits,
2049 );
2050 try o.debug_type_map.put(gpa, ty, debug_float_type);
2051 return debug_float_type;
2067 },2052 },
2068 .Bool => {2053 .Bool => {
2069 const di_bits = 8; // lldb cannot handle non-byte sized types2054 const debug_bool_type = try o.builder.debugBoolType(
2070 const di_type = dib.createBasicType("bool", di_bits, DW.ATE.boolean);2055 try o.builder.metadataString("bool"),
2071 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);2056 8, // lldb cannot handle non-byte sized types
2072 return di_type;2057 );
2058 try o.debug_type_map.put(gpa, ty, debug_bool_type);
2059 return debug_bool_type;
2073 },2060 },
2074 .Pointer => {2061 .Pointer => {
2075 // Normalize everything that the debug info does not represent.2062 // Normalize everything that the debug info does not represent.
...@@ -2099,136 +2086,145 @@ pub const Object = struct {...@@ -2099,136 +2086,145 @@ pub const Object = struct {
2099 },2086 },
2100 },2087 },
2101 });2088 });
2102 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);2089 const debug_ptr_type = try o.lowerDebugType(bland_ptr_ty);
2103 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2090 try o.debug_type_map.put(gpa, ty, debug_ptr_type);
2104 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));2091 return debug_ptr_type;
2105 return ptr_di_ty;
2106 }2092 }
21072093
2094 const debug_fwd_ref = try o.builder.debugForwardReference();
2095
2096 // Set as forward reference while the type is lowered in case it references itself
2097 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
2098
2108 if (ty.isSlice(mod)) {2099 if (ty.isSlice(mod)) {
2109 const ptr_ty = ty.slicePtrFieldType(mod);2100 const ptr_ty = ty.slicePtrFieldType(mod);
2110 const len_ty = Type.usize;2101 const len_ty = Type.usize;
21112102
2112 const name = try o.allocTypeName(ty);2103 const name = try o.allocTypeName(ty);
2113 defer gpa.free(name);2104 defer gpa.free(name);
2114 const di_file: ?*llvm.DIFile = null;
2115 const line = 0;2105 const line = 0;
2116 const compile_unit_scope = o.di_compile_unit.?.toScope();
2117
2118 const fwd_decl = opt_fwd_decl orelse blk: {
2119 const fwd_decl = dib.createReplaceableCompositeType(
2120 DW.TAG.structure_type,
2121 name.ptr,
2122 compile_unit_scope,
2123 di_file,
2124 line,
2125 );
2126 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2127 if (resolve == .fwd) return fwd_decl;
2128 break :blk fwd_decl;
2129 };
21302106
2131 const ptr_size = ptr_ty.abiSize(mod);2107 const ptr_size = ptr_ty.abiSize(mod);
2132 const ptr_align = ptr_ty.abiAlignment(mod);2108 const ptr_align = ptr_ty.abiAlignment(mod);
2133 const len_size = len_ty.abiSize(mod);2109 const len_size = len_ty.abiSize(mod);
2134 const len_align = len_ty.abiAlignment(mod);2110 const len_align = len_ty.abiAlignment(mod);
21352111
2136 var offset: u64 = 0;2112 const len_offset = len_align.forward(ptr_size);
2137 offset += ptr_size;2113
2138 offset = len_align.forward(offset);2114 const debug_ptr_type = try o.builder.debugMemberType(
2139 const len_offset = offset;2115 try o.builder.metadataString("ptr"),
21402116 .none, // File
2141 const fields: [2]*llvm.DIType = .{2117 debug_fwd_ref,
2142 dib.createMemberType(2118 0, // Line
2143 fwd_decl.toScope(),2119 try o.lowerDebugType(ptr_ty),
2144 "ptr",2120 ptr_size * 8,
2145 di_file,2121 ptr_align.toByteUnits(0) * 8,
2146 line,2122 0, // Offset
2147 ptr_size * 8, // size in bits2123 );
2148 ptr_align.toByteUnits(0) * 8, // align in bits2124
2149 0, // offset in bits2125 const debug_len_type = try o.builder.debugMemberType(
2150 0, // flags2126 try o.builder.metadataString("len"),
2151 try o.lowerDebugType(ptr_ty, resolve),2127 .none, // File
2152 ),2128 debug_fwd_ref,
2153 dib.createMemberType(2129 0, // Line
2154 fwd_decl.toScope(),2130 try o.lowerDebugType(len_ty),
2155 "len",2131 len_size * 8,
2156 di_file,2132 len_align.toByteUnits(0) * 8,
2157 line,2133 len_offset * 8,
2158 len_size * 8, // size in bits2134 );
2159 len_align.toByteUnits(0) * 8, // align in bits
2160 len_offset * 8, // offset in bits
2161 0, // flags
2162 try o.lowerDebugType(len_ty, resolve),
2163 ),
2164 };
21652135
2166 const full_di_ty = dib.createStructType(2136 const debug_slice_type = try o.builder.debugStructType(
2167 compile_unit_scope,2137 try o.builder.metadataString(name),
2168 name.ptr,2138 .none, // File
2169 di_file,2139 o.debug_compile_unit, // Scope
2170 line,2140 line,
2171 ty.abiSize(mod) * 8, // size in bits2141 .none, // Underlying type
2172 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2142 ty.abiSize(mod) * 8,
2173 0, // flags2143 ty.abiAlignment(mod).toByteUnits(0) * 8,
2174 null, // derived from2144 try o.builder.debugTuple(&.{
2175 &fields,2145 debug_ptr_type,
2176 fields.len,2146 debug_len_type,
2177 0, // run time lang2147 }),
2178 null, // vtable holder
2179 "", // unique id
2180 );2148 );
2181 dib.replaceTemporary(fwd_decl, full_di_ty);2149
2182 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2150 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_slice_type);
2183 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2151
2184 return full_di_ty;2152 // Set to real type now that it has been lowered fully
2153 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2154 map_ptr.* = debug_slice_type;
2155
2156 return debug_slice_type;
2185 }2157 }
21862158
2187 const elem_di_ty = try o.lowerDebugType(Type.fromInterned(ptr_info.child), .fwd);2159 const debug_elem_ty = try o.lowerDebugType(Type.fromInterned(ptr_info.child));
2160
2188 const name = try o.allocTypeName(ty);2161 const name = try o.allocTypeName(ty);
2189 defer gpa.free(name);2162 defer gpa.free(name);
2190 const ptr_di_ty = dib.createPointerType(2163
2191 elem_di_ty,2164 const debug_ptr_type = try o.builder.debugPointerType(
2165 try o.builder.metadataString(name),
2166 .none, // File
2167 .none, // Scope
2168 0, // Line
2169 debug_elem_ty,
2192 target.ptrBitWidth(),2170 target.ptrBitWidth(),
2193 ty.ptrAlignment(mod).toByteUnits(0) * 8,2171 ty.ptrAlignment(mod).toByteUnits(0) * 8,
2194 name,2172 0, // Offset
2195 );2173 );
2196 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2174
2197 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(ptr_di_ty));2175 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_ptr_type);
2198 return ptr_di_ty;2176
2177 // Set to real type now that it has been lowered fully
2178 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2179 map_ptr.* = debug_ptr_type;
2180
2181 return debug_ptr_type;
2199 },2182 },
2200 .Opaque => {2183 .Opaque => {
2201 if (ty.toIntern() == .anyopaque_type) {2184 if (ty.toIntern() == .anyopaque_type) {
2202 const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed);2185 const debug_opaque_type = try o.builder.debugSignedType(
2203 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);2186 try o.builder.metadataString("anyopaque"),
2204 return di_ty;2187 0,
2188 );
2189 try o.debug_type_map.put(gpa, ty, debug_opaque_type);
2190 return debug_opaque_type;
2205 }2191 }
2192
2206 const name = try o.allocTypeName(ty);2193 const name = try o.allocTypeName(ty);
2207 defer gpa.free(name);2194 defer gpa.free(name);
2208 const owner_decl_index = ty.getOwnerDecl(mod);2195 const owner_decl_index = ty.getOwnerDecl(mod);
2209 const owner_decl = o.module.declPtr(owner_decl_index);2196 const owner_decl = o.module.declPtr(owner_decl_index);
2210 const opaque_di_ty = dib.createForwardDeclType(2197 const debug_opaque_type = try o.builder.debugStructType(
2211 DW.TAG.structure_type,2198 try o.builder.metadataString(name),
2212 name,2199 try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope),
2213 try o.namespaceToDebugScope(owner_decl.src_namespace),2200 try o.namespaceToDebugScope(owner_decl.src_namespace),
2214 try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope),2201 owner_decl.src_node + 1, // Line
2215 owner_decl.src_node + 1,2202 .none, // Underlying type
2203 0, // Size
2204 0, // Align
2205 .none, // Fields
2216 );2206 );
2217 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`2207 try o.debug_type_map.put(gpa, ty, debug_opaque_type);
2218 // means we can't use `gop` anymore.2208 return debug_opaque_type;
2219 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(opaque_di_ty));
2220 return opaque_di_ty;
2221 },2209 },
2222 .Array => {2210 .Array => {
2223 const array_di_ty = dib.createArrayType(2211 const debug_array_type = try o.builder.debugArrayType(
2212 .none, // Name
2213 .none, // File
2214 .none, // Scope
2215 0, // Line
2216 try o.lowerDebugType(ty.childType(mod)),
2224 ty.abiSize(mod) * 8,2217 ty.abiSize(mod) * 8,
2225 ty.abiAlignment(mod).toByteUnits(0) * 8,2218 ty.abiAlignment(mod).toByteUnits(0) * 8,
2226 try o.lowerDebugType(ty.childType(mod), resolve),2219 try o.builder.debugTuple(&.{
2227 @intCast(ty.arrayLen(mod)),2220 try o.builder.debugSubrange(
2221 try o.builder.debugConstant(try o.builder.intConst(.i64, 0)),
2222 try o.builder.debugConstant(try o.builder.intConst(.i64, ty.arrayLen(mod))),
2223 ),
2224 }),
2228 );2225 );
2229 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2226 try o.debug_type_map.put(gpa, ty, debug_array_type);
2230 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(array_di_ty));2227 return debug_array_type;
2231 return array_di_ty;
2232 },2228 },
2233 .Vector => {2229 .Vector => {
2234 const elem_ty = ty.elemType2(mod);2230 const elem_ty = ty.elemType2(mod);
...@@ -2236,146 +2232,136 @@ pub const Object = struct {...@@ -2236,146 +2232,136 @@ pub const Object = struct {
2236 // @bitSizOf(elem) * len > @bitSizOf(vec).2232 // @bitSizOf(elem) * len > @bitSizOf(vec).
2237 // Neither gdb nor lldb seem to be able to display non-byte sized2233 // Neither gdb nor lldb seem to be able to display non-byte sized
2238 // vectors properly.2234 // vectors properly.
2239 const elem_di_type = switch (elem_ty.zigTypeTag(mod)) {2235 const debug_elem_type = switch (elem_ty.zigTypeTag(mod)) {
2240 .Int => blk: {2236 .Int => blk: {
2241 const info = elem_ty.intInfo(mod);2237 const info = elem_ty.intInfo(mod);
2242 assert(info.bits != 0);2238 assert(info.bits != 0);
2243 const name = try o.allocTypeName(ty);2239 const name = try o.allocTypeName(ty);
2244 defer gpa.free(name);2240 defer gpa.free(name);
2245 const dwarf_encoding: c_uint = switch (info.signedness) {2241 const builder_name = try o.builder.metadataString(name);
2246 .signed => DW.ATE.signed,2242 break :blk switch (info.signedness) {
2247 .unsigned => DW.ATE.unsigned,2243 .signed => try o.builder.debugSignedType(builder_name, info.bits),
2244 .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits),
2248 };2245 };
2249 break :blk dib.createBasicType(name, info.bits, dwarf_encoding);
2250 },2246 },
2251 .Bool => dib.createBasicType("bool", 1, DW.ATE.boolean),2247 .Bool => try o.builder.debugBoolType(
2252 else => try o.lowerDebugType(ty.childType(mod), resolve),2248 try o.builder.metadataString("bool"),
2249 1,
2250 ),
2251 else => try o.lowerDebugType(ty.childType(mod)),
2253 };2252 };
22542253
2255 const vector_di_ty = dib.createVectorType(2254 const debug_vector_type = try o.builder.debugVectorType(
2255 .none, // Name
2256 .none, // File
2257 .none, // Scope
2258 0, // Line
2259 debug_elem_type,
2256 ty.abiSize(mod) * 8,2260 ty.abiSize(mod) * 8,
2257 @intCast(ty.abiAlignment(mod).toByteUnits(0) * 8),2261 ty.abiAlignment(mod).toByteUnits(0) * 8,
2258 elem_di_type,2262 try o.builder.debugTuple(&.{
2259 ty.vectorLen(mod),2263 try o.builder.debugSubrange(
2264 try o.builder.debugConstant(try o.builder.intConst(.i64, 0)),
2265 try o.builder.debugConstant(try o.builder.intConst(.i64, ty.vectorLen(mod))),
2266 ),
2267 }),
2260 );2268 );
2261 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2269
2262 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(vector_di_ty));2270 try o.debug_type_map.put(gpa, ty, debug_vector_type);
2263 return vector_di_ty;2271 return debug_vector_type;
2264 },2272 },
2265 .Optional => {2273 .Optional => {
2266 const name = try o.allocTypeName(ty);2274 const name = try o.allocTypeName(ty);
2267 defer gpa.free(name);2275 defer gpa.free(name);
2268 const child_ty = ty.optionalChild(mod);2276 const child_ty = ty.optionalChild(mod);
2269 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {2277 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2270 const di_bits = 8; // lldb cannot handle non-byte sized types2278 const debug_bool_type = try o.builder.debugBoolType(
2271 const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean);2279 try o.builder.metadataString(name),
2272 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);2280 8,
2273 return di_ty;2281 );
2282 try o.debug_type_map.put(gpa, ty, debug_bool_type);
2283 return debug_bool_type;
2274 }2284 }
2285
2286 const debug_fwd_ref = try o.builder.debugForwardReference();
2287
2288 // Set as forward reference while the type is lowered in case it references itself
2289 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
2290
2275 if (ty.optionalReprIsPayload(mod)) {2291 if (ty.optionalReprIsPayload(mod)) {
2276 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);2292 const debug_optional_type = try o.lowerDebugType(child_ty);
2277 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2278 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));
2279 return ptr_di_ty;
2280 }
22812293
2282 const di_file: ?*llvm.DIFile = null;2294 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
2283 const line = 0;2295
2284 const compile_unit_scope = o.di_compile_unit.?.toScope();2296 // Set to real type now that it has been lowered fully
2285 const fwd_decl = opt_fwd_decl orelse blk: {2297 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2286 const fwd_decl = dib.createReplaceableCompositeType(2298 map_ptr.* = debug_optional_type;
2287 DW.TAG.structure_type,2299
2288 name.ptr,2300 return debug_optional_type;
2289 compile_unit_scope,2301 }
2290 di_file,
2291 line,
2292 );
2293 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2294 if (resolve == .fwd) return fwd_decl;
2295 break :blk fwd_decl;
2296 };
22972302
2298 const non_null_ty = Type.u8;2303 const non_null_ty = Type.u8;
2299 const payload_size = child_ty.abiSize(mod);2304 const payload_size = child_ty.abiSize(mod);
2300 const payload_align = child_ty.abiAlignment(mod);2305 const payload_align = child_ty.abiAlignment(mod);
2301 const non_null_size = non_null_ty.abiSize(mod);2306 const non_null_size = non_null_ty.abiSize(mod);
2302 const non_null_align = non_null_ty.abiAlignment(mod);2307 const non_null_align = non_null_ty.abiAlignment(mod);
2308 const non_null_offset = non_null_align.forward(payload_size);
2309
2310 const debug_data_type = try o.builder.debugMemberType(
2311 try o.builder.metadataString("data"),
2312 .none, // File
2313 debug_fwd_ref,
2314 0, // Line
2315 try o.lowerDebugType(child_ty),
2316 payload_size * 8,
2317 payload_align.toByteUnits(0) * 8,
2318 0, // Offset
2319 );
23032320
2304 var offset: u64 = 0;2321 const debug_some_type = try o.builder.debugMemberType(
2305 offset += payload_size;2322 try o.builder.metadataString("some"),
2306 offset = non_null_align.forward(offset);2323 .none,
2307 const non_null_offset = offset;2324 debug_fwd_ref,
23082325 0,
2309 const fields: [2]*llvm.DIType = .{2326 try o.lowerDebugType(non_null_ty),
2310 dib.createMemberType(2327 non_null_size * 8,
2311 fwd_decl.toScope(),2328 non_null_align.toByteUnits(0) * 8,
2312 "data",2329 non_null_offset * 8,
2313 di_file,2330 );
2314 line,
2315 payload_size * 8, // size in bits
2316 payload_align.toByteUnits(0) * 8, // align in bits
2317 0, // offset in bits
2318 0, // flags
2319 try o.lowerDebugType(child_ty, resolve),
2320 ),
2321 dib.createMemberType(
2322 fwd_decl.toScope(),
2323 "some",
2324 di_file,
2325 line,
2326 non_null_size * 8, // size in bits
2327 non_null_align.toByteUnits(0) * 8, // align in bits
2328 non_null_offset * 8, // offset in bits
2329 0, // flags
2330 try o.lowerDebugType(non_null_ty, resolve),
2331 ),
2332 };
23332331
2334 const full_di_ty = dib.createStructType(2332 const debug_optional_type = try o.builder.debugStructType(
2335 compile_unit_scope,2333 try o.builder.metadataString(name),
2336 name.ptr,2334 .none, // File
2337 di_file,2335 o.debug_compile_unit, // Scope
2338 line,2336 0, // Line
2339 ty.abiSize(mod) * 8, // size in bits2337 .none, // Underlying type
2340 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2338 ty.abiSize(mod) * 8,
2341 0, // flags2339 ty.abiAlignment(mod).toByteUnits(0) * 8,
2342 null, // derived from2340 try o.builder.debugTuple(&.{
2343 &fields,2341 debug_data_type,
2344 fields.len,2342 debug_some_type,
2345 0, // run time lang2343 }),
2346 null, // vtable holder
2347 "", // unique id
2348 );2344 );
2349 dib.replaceTemporary(fwd_decl, full_di_ty);2345
2350 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2346 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
2351 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2347
2352 return full_di_ty;2348 // Set to real type now that it has been lowered fully
2349 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2350 map_ptr.* = debug_optional_type;
2351
2352 return debug_optional_type;
2353 },2353 },
2354 .ErrorUnion => {2354 .ErrorUnion => {
2355 const payload_ty = ty.errorUnionPayload(mod);2355 const payload_ty = ty.errorUnionPayload(mod);
2356 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {2356 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2357 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, resolve);2357 // TODO: Maybe remove?
2358 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2358 const debug_error_union_type = try o.lowerDebugType(Type.anyerror);
2359 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(err_set_di_ty));2359 try o.debug_type_map.put(gpa, ty, debug_error_union_type);
2360 return err_set_di_ty;2360 return debug_error_union_type;
2361 }2361 }
2362
2362 const name = try o.allocTypeName(ty);2363 const name = try o.allocTypeName(ty);
2363 defer gpa.free(name);2364 defer gpa.free(name);
2364 const di_file: ?*llvm.DIFile = null;
2365 const line = 0;
2366 const compile_unit_scope = o.di_compile_unit.?.toScope();
2367 const fwd_decl = opt_fwd_decl orelse blk: {
2368 const fwd_decl = dib.createReplaceableCompositeType(
2369 DW.TAG.structure_type,
2370 name.ptr,
2371 compile_unit_scope,
2372 di_file,
2373 line,
2374 );
2375 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2376 if (resolve == .fwd) return fwd_decl;
2377 break :blk fwd_decl;
2378 };
23792365
2380 const error_size = Type.anyerror.abiSize(mod);2366 const error_size = Type.anyerror.abiSize(mod);
2381 const error_align = Type.anyerror.abiAlignment(mod);2367 const error_align = Type.anyerror.abiAlignment(mod);
...@@ -2398,59 +2384,55 @@ pub const Object = struct {...@@ -2398,59 +2384,55 @@ pub const Object = struct {
2398 error_offset = error_align.forward(payload_size);2384 error_offset = error_align.forward(payload_size);
2399 }2385 }
24002386
2401 var fields: [2]*llvm.DIType = undefined;2387 const debug_fwd_ref = try o.builder.debugForwardReference();
2402 fields[error_index] = dib.createMemberType(2388
2403 fwd_decl.toScope(),2389 var fields: [2]Builder.Metadata = undefined;
2404 "tag",2390 fields[error_index] = try o.builder.debugMemberType(
2405 di_file,2391 try o.builder.metadataString("tag"),
2406 line,2392 .none, // File
2407 error_size * 8, // size in bits2393 debug_fwd_ref,
2408 error_align.toByteUnits(0) * 8, // align in bits2394 0, // Line
2409 error_offset * 8, // offset in bits2395 try o.lowerDebugType(Type.anyerror),
2410 0, // flags2396 error_size * 8,
2411 try o.lowerDebugType(Type.anyerror, resolve),2397 error_align.toByteUnits(0) * 8,
2398 error_offset * 8,
2412 );2399 );
2413 fields[payload_index] = dib.createMemberType(2400 fields[payload_index] = try o.builder.debugMemberType(
2414 fwd_decl.toScope(),2401 try o.builder.metadataString("value"),
2415 "value",2402 .none, // File
2416 di_file,2403 debug_fwd_ref,
2417 line,2404 0, // Line
2418 payload_size * 8, // size in bits2405 try o.lowerDebugType(payload_ty),
2419 payload_align.toByteUnits(0) * 8, // align in bits2406 payload_size * 8,
2420 payload_offset * 8, // offset in bits2407 payload_align.toByteUnits(0) * 8,
2421 0, // flags2408 payload_offset * 8,
2422 try o.lowerDebugType(payload_ty, resolve),
2423 );2409 );
24242410
2425 const full_di_ty = dib.createStructType(2411 const debug_error_union_type = try o.builder.debugStructType(
2426 compile_unit_scope,2412 try o.builder.metadataString(name),
2427 name.ptr,2413 .none, // File
2428 di_file,2414 o.debug_compile_unit, // Sope
2429 line,2415 0, // Line
2430 ty.abiSize(mod) * 8, // size in bits2416 .none, // Underlying type
2431 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2417 ty.abiSize(mod) * 8,
2432 0, // flags2418 ty.abiAlignment(mod).toByteUnits(0) * 8,
2433 null, // derived from2419 try o.builder.debugTuple(&fields),
2434 &fields,
2435 fields.len,
2436 0, // run time lang
2437 null, // vtable holder
2438 "", // unique id
2439 );2420 );
2440 dib.replaceTemporary(fwd_decl, full_di_ty);2421
2441 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2422 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_error_union_type);
2442 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2423
2443 return full_di_ty;2424 try o.debug_type_map.put(gpa, ty, debug_error_union_type);
2425 return debug_error_union_type;
2444 },2426 },
2445 .ErrorSet => {2427 .ErrorSet => {
2446 // TODO make this a proper enum with all the error codes in it.2428 const debug_error_set = try o.builder.debugUnsignedType(
2447 // will need to consider how to take incremental compilation into account.2429 try o.builder.metadataString("anyerror"),
2448 const di_ty = dib.createBasicType("anyerror", 16, DW.ATE.unsigned);2430 16,
2449 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);2431 );
2450 return di_ty;2432 try o.debug_type_map.put(gpa, ty, debug_error_set);
2433 return debug_error_set;
2451 },2434 },
2452 .Struct => {2435 .Struct => {
2453 const compile_unit_scope = o.di_compile_unit.?.toScope();
2454 const name = try o.allocTypeName(ty);2436 const name = try o.allocTypeName(ty);
2455 defer gpa.free(name);2437 defer gpa.free(name);
24562438
...@@ -2458,40 +2440,28 @@ pub const Object = struct {...@@ -2458,40 +2440,28 @@ pub const Object = struct {
2458 const backing_int_ty = struct_type.backingIntType(ip).*;2440 const backing_int_ty = struct_type.backingIntType(ip).*;
2459 if (backing_int_ty != .none) {2441 if (backing_int_ty != .none) {
2460 const info = Type.fromInterned(backing_int_ty).intInfo(mod);2442 const info = Type.fromInterned(backing_int_ty).intInfo(mod);
2461 const dwarf_encoding: c_uint = switch (info.signedness) {2443 const builder_name = try o.builder.metadataString(name);
2462 .signed => DW.ATE.signed,2444 const debug_int_type = switch (info.signedness) {
2463 .unsigned => DW.ATE.unsigned,2445 .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(mod) * 8),
2446 .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(mod) * 8),
2464 };2447 };
2465 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types2448 try o.debug_type_map.put(gpa, ty, debug_int_type);
2466 const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding);2449 return debug_int_type;
2467 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
2468 return di_ty;
2469 }2450 }
2470 }2451 }
24712452
2472 const fwd_decl = opt_fwd_decl orelse blk: {
2473 const fwd_decl = dib.createReplaceableCompositeType(
2474 DW.TAG.structure_type,
2475 name.ptr,
2476 compile_unit_scope,
2477 null, // file
2478 0, // line
2479 );
2480 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2481 if (resolve == .fwd) return fwd_decl;
2482 break :blk fwd_decl;
2483 };
2484
2485 switch (ip.indexToKey(ty.toIntern())) {2453 switch (ip.indexToKey(ty.toIntern())) {
2486 .anon_struct_type => |tuple| {2454 .anon_struct_type => |tuple| {
2487 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2455 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2488 defer di_fields.deinit(gpa);2456 defer fields.deinit(gpa);
24892457
2490 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);2458 try fields.ensureUnusedCapacity(gpa, tuple.types.len);
24912459
2492 comptime assert(struct_layout_version == 2);2460 comptime assert(struct_layout_version == 2);
2493 var offset: u64 = 0;2461 var offset: u64 = 0;
24942462
2463 const debug_fwd_ref = try o.builder.debugForwardReference();
2464
2495 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {2465 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
2496 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;2466 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
24972467
...@@ -2506,38 +2476,33 @@ pub const Object = struct {...@@ -2506,38 +2476,33 @@ pub const Object = struct {
2506 try std.fmt.allocPrintZ(gpa, "{d}", .{i});2476 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2507 defer if (tuple.names.len == 0) gpa.free(field_name);2477 defer if (tuple.names.len == 0) gpa.free(field_name);
25082478
2509 try di_fields.append(gpa, dib.createMemberType(2479 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2510 fwd_decl.toScope(),2480 try o.builder.metadataString(field_name),
2511 field_name,2481 .none, // File
2512 null, // file2482 debug_fwd_ref,
2513 0, // line2483 0,
2514 field_size * 8, // size in bits2484 try o.lowerDebugType(Type.fromInterned(field_ty)),
2515 field_align.toByteUnits(0) * 8, // align in bits2485 field_size * 8,
2516 field_offset * 8, // offset in bits2486 field_align.toByteUnits(0) * 8,
2517 0, // flags2487 field_offset * 8,
2518 try o.lowerDebugType(Type.fromInterned(field_ty), resolve),
2519 ));2488 ));
2520 }2489 }
25212490
2522 const full_di_ty = dib.createStructType(2491 const debug_struct_type = try o.builder.debugStructType(
2523 compile_unit_scope,2492 try o.builder.metadataString(name),
2524 name.ptr,2493 .none, // File
2525 null, // file2494 o.debug_compile_unit, // Scope
2526 0, // line2495 0, // Line
2527 ty.abiSize(mod) * 8, // size in bits2496 .none, // Underlying type
2528 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2497 ty.abiSize(mod) * 8,
2529 0, // flags2498 ty.abiAlignment(mod).toByteUnits(0) * 8,
2530 null, // derived from2499 try o.builder.debugTuple(fields.items),
2531 di_fields.items.ptr,
2532 @intCast(di_fields.items.len),
2533 0, // run time lang
2534 null, // vtable holder
2535 "", // unique id
2536 );2500 );
2537 dib.replaceTemporary(fwd_decl, full_di_ty);2501
2538 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2502 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type);
2539 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2503
2540 return full_di_ty;2504 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2505 return debug_struct_type;
2541 },2506 },
2542 .struct_type => |struct_type| {2507 .struct_type => |struct_type| {
2543 if (!struct_type.haveFieldTypes(ip)) {2508 if (!struct_type.haveFieldTypes(ip)) {
...@@ -2549,12 +2514,9 @@ pub const Object = struct {...@@ -2549,12 +2514,9 @@ pub const Object = struct {
2549 // rather than changing the frontend to unnecessarily resolve the2514 // rather than changing the frontend to unnecessarily resolve the
2550 // struct field types.2515 // struct field types.
2551 const owner_decl_index = ty.getOwnerDecl(mod);2516 const owner_decl_index = ty.getOwnerDecl(mod);
2552 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2517 const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2553 dib.replaceTemporary(fwd_decl, struct_di_ty);2518 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2554 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2519 return debug_struct_type;
2555 // means we can't use `gop` anymore.
2556 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
2557 return struct_di_ty;
2558 }2520 }
2559 },2521 },
2560 else => {},2522 else => {},
...@@ -2562,20 +2524,22 @@ pub const Object = struct {...@@ -2562,20 +2524,22 @@ pub const Object = struct {
25622524
2563 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {2525 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
2564 const owner_decl_index = ty.getOwnerDecl(mod);2526 const owner_decl_index = ty.getOwnerDecl(mod);
2565 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2527 const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2566 dib.replaceTemporary(fwd_decl, struct_di_ty);2528 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2567 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2529 return debug_struct_type;
2568 // means we can't use `gop` anymore.
2569 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
2570 return struct_di_ty;
2571 }2530 }
25722531
2573 const struct_type = mod.typeToStruct(ty).?;2532 const struct_type = mod.typeToStruct(ty).?;
25742533
2575 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2534 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2576 defer di_fields.deinit(gpa);2535 defer fields.deinit(gpa);
2536
2537 try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len);
2538
2539 const debug_fwd_ref = try o.builder.debugForwardReference();
25772540
2578 try di_fields.ensureUnusedCapacity(gpa, struct_type.field_types.len);2541 // Set as forward reference while the type is lowered in case it references itself
2542 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
25792543
2580 comptime assert(struct_layout_version == 2);2544 comptime assert(struct_layout_version == 2);
2581 var it = struct_type.iterateRuntimeOrder(ip);2545 var it = struct_type.iterateRuntimeOrder(ip);
...@@ -2593,103 +2557,88 @@ pub const Object = struct {...@@ -2593,103 +2557,88 @@ pub const Object = struct {
2593 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse2557 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
2594 try ip.getOrPutStringFmt(gpa, "{d}", .{field_index});2558 try ip.getOrPutStringFmt(gpa, "{d}", .{field_index});
25952559
2596 const field_di_ty = try o.lowerDebugType(field_ty, resolve);2560 fields.appendAssumeCapacity(try o.builder.debugMemberType(
25972561 try o.builder.metadataString(ip.stringToSlice(field_name)),
2598 try di_fields.append(gpa, dib.createMemberType(2562 .none, // File
2599 fwd_decl.toScope(),2563 debug_fwd_ref,
2600 ip.stringToSlice(field_name),2564 0, // Line
2601 null, // file2565 try o.lowerDebugType(field_ty),
2602 0, // line2566 field_size * 8,
2603 field_size * 8, // size in bits2567 field_align.toByteUnits(0) * 8,
2604 field_align.toByteUnits(0) * 8, // align in bits2568 field_offset * 8,
2605 field_offset * 8, // offset in bits
2606 0, // flags
2607 field_di_ty,
2608 ));2569 ));
2609 }2570 }
26102571
2611 const full_di_ty = dib.createStructType(2572 const debug_struct_type = try o.builder.debugStructType(
2612 compile_unit_scope,2573 try o.builder.metadataString(name),
2613 name.ptr,2574 .none, // File
2614 null, // file2575 o.debug_compile_unit, // Scope
2615 0, // line2576 0, // Line
2616 ty.abiSize(mod) * 8, // size in bits2577 .none, // Underlying type
2617 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2578 ty.abiSize(mod) * 8,
2618 0, // flags2579 ty.abiAlignment(mod).toByteUnits(0) * 8,
2619 null, // derived from2580 try o.builder.debugTuple(fields.items),
2620 di_fields.items.ptr,
2621 @intCast(di_fields.items.len),
2622 0, // run time lang
2623 null, // vtable holder
2624 "", // unique id
2625 );2581 );
2626 dib.replaceTemporary(fwd_decl, full_di_ty);2582
2627 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2583 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type);
2628 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2584
2629 return full_di_ty;2585 // Set to real type now that it has been lowered fully
2586 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2587 map_ptr.* = debug_struct_type;
2588
2589 return debug_struct_type;
2630 },2590 },
2631 .Union => {2591 .Union => {
2632 const compile_unit_scope = o.di_compile_unit.?.toScope();
2633 const owner_decl_index = ty.getOwnerDecl(mod);2592 const owner_decl_index = ty.getOwnerDecl(mod);
26342593
2635 const name = try o.allocTypeName(ty);2594 const name = try o.allocTypeName(ty);
2636 defer gpa.free(name);2595 defer gpa.free(name);
26372596
2638 const fwd_decl = opt_fwd_decl orelse blk: {
2639 const fwd_decl = dib.createReplaceableCompositeType(
2640 DW.TAG.structure_type,
2641 name.ptr,
2642 o.di_compile_unit.?.toScope(),
2643 null, // file
2644 0, // line
2645 );
2646 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2647 if (resolve == .fwd) return fwd_decl;
2648 break :blk fwd_decl;
2649 };
2650
2651 const union_type = ip.indexToKey(ty.toIntern()).union_type;2597 const union_type = ip.indexToKey(ty.toIntern()).union_type;
2652 if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) {2598 if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) {
2653 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2599 const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2654 dib.replaceTemporary(fwd_decl, union_di_ty);2600 try o.debug_type_map.put(gpa, ty, debug_union_type);
2655 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2601 return debug_union_type;
2656 // means we can't use `gop` anymore.
2657 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));
2658 return union_di_ty;
2659 }2602 }
26602603
2661 const union_obj = ip.loadUnionType(union_type);2604 const union_obj = ip.loadUnionType(union_type);
2662 const layout = mod.getUnionLayout(union_obj);2605 const layout = mod.getUnionLayout(union_obj);
26632606
2607 const debug_fwd_ref = try o.builder.debugForwardReference();
2608
2609 // Set as forward reference while the type is lowered in case it references itself
2610 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
2611
2664 if (layout.payload_size == 0) {2612 if (layout.payload_size == 0) {
2665 const tag_di_ty = try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve);2613 const debug_union_type = try o.builder.debugStructType(
2666 const di_fields = [_]*llvm.DIType{tag_di_ty};2614 try o.builder.metadataString(name),
2667 const full_di_ty = dib.createStructType(2615 .none, // File
2668 compile_unit_scope,2616 o.debug_compile_unit, // Scope
2669 name.ptr,2617 0, // Line
2670 null, // file2618 .none, // Underlying type
2671 0, // line2619 ty.abiSize(mod) * 8,
2672 ty.abiSize(mod) * 8, // size in bits2620 ty.abiAlignment(mod).toByteUnits(0) * 8,
2673 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2621 try o.builder.debugTuple(
2674 0, // flags2622 &.{try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty))},
2675 null, // derived from2623 ),
2676 &di_fields,
2677 di_fields.len,
2678 0, // run time lang
2679 null, // vtable holder
2680 "", // unique id
2681 );2624 );
2682 dib.replaceTemporary(fwd_decl, full_di_ty);2625
2683 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2626 // Set to real type now that it has been lowered fully
2684 // means we can't use `gop` anymore.2627 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2685 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2628 map_ptr.* = debug_union_type;
2686 return full_di_ty;2629
2630 return debug_union_type;
2687 }2631 }
26882632
2689 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2633 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2690 defer di_fields.deinit(gpa);2634 defer fields.deinit(gpa);
2635
2636 try fields.ensureUnusedCapacity(gpa, union_obj.field_names.len);
26912637
2692 try di_fields.ensureUnusedCapacity(gpa, union_obj.field_names.len);2638 const debug_union_fwd_ref = if (layout.tag_size == 0)
2639 debug_fwd_ref
2640 else
2641 try o.builder.debugForwardReference();
26932642
2694 for (0..union_obj.field_names.len) |field_index| {2643 for (0..union_obj.field_names.len) |field_index| {
2695 const field_ty = union_obj.field_types.get(ip)[field_index];2644 const field_ty = union_obj.field_types.get(ip)[field_index];
...@@ -2698,18 +2647,16 @@ pub const Object = struct {...@@ -2698,18 +2647,16 @@ pub const Object = struct {
2698 const field_size = Type.fromInterned(field_ty).abiSize(mod);2647 const field_size = Type.fromInterned(field_ty).abiSize(mod);
2699 const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index));2648 const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index));
27002649
2701 const field_di_ty = try o.lowerDebugType(Type.fromInterned(field_ty), resolve);
2702 const field_name = union_obj.field_names.get(ip)[field_index];2650 const field_name = union_obj.field_names.get(ip)[field_index];
2703 di_fields.appendAssumeCapacity(dib.createMemberType(2651 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2704 fwd_decl.toScope(),2652 try o.builder.metadataString(ip.stringToSlice(field_name)),
2705 ip.stringToSlice(field_name),2653 .none, // File
2706 null, // file2654 debug_union_fwd_ref,
2707 0, // line2655 0, // Line
2708 field_size * 8, // size in bits2656 try o.lowerDebugType(Type.fromInterned(field_ty)),
2709 field_align.toByteUnits(0) * 8, // align in bits2657 field_size * 8,
2710 0, // offset in bits2658 field_align.toByteUnits(0) * 8,
2711 0, // flags2659 0, // Offset
2712 field_di_ty,
2713 ));2660 ));
2714 }2661 }
27152662
...@@ -2720,25 +2667,25 @@ pub const Object = struct {...@@ -2720,25 +2667,25 @@ pub const Object = struct {
2720 break :name union_name_buf.?;2667 break :name union_name_buf.?;
2721 };2668 };
27222669
2723 const union_di_ty = dib.createUnionType(2670 const debug_union_type = try o.builder.debugUnionType(
2724 compile_unit_scope,2671 try o.builder.metadataString(union_name),
2725 union_name.ptr,2672 .none, // File
2726 null, // file2673 o.debug_compile_unit, // Scope
2727 0, // line2674 0, // Line
2728 ty.abiSize(mod) * 8, // size in bits2675 .none, // Underlying type
2729 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2676 ty.abiSize(mod) * 8,
2730 0, // flags2677 ty.abiAlignment(mod).toByteUnits(0) * 8,
2731 di_fields.items.ptr,2678 try o.builder.debugTuple(fields.items),
2732 @intCast(di_fields.items.len),
2733 0, // run time lang
2734 "", // unique id
2735 );2679 );
27362680
2681 o.builder.debugForwardReferenceSetType(debug_union_fwd_ref, debug_union_type);
2682
2737 if (layout.tag_size == 0) {2683 if (layout.tag_size == 0) {
2738 dib.replaceTemporary(fwd_decl, union_di_ty);2684 // Set to real type now that it has been lowered fully
2739 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2685 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2740 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));2686 map_ptr.* = debug_union_type;
2741 return union_di_ty;2687
2688 return debug_union_type;
2742 }2689 }
27432690
2744 var tag_offset: u64 = undefined;2691 var tag_offset: u64 = undefined;
...@@ -2751,81 +2698,80 @@ pub const Object = struct {...@@ -2751,81 +2698,80 @@ pub const Object = struct {
2751 tag_offset = layout.tag_align.forward(layout.payload_size);2698 tag_offset = layout.tag_align.forward(layout.payload_size);
2752 }2699 }
27532700
2754 const tag_di = dib.createMemberType(2701 const debug_tag_type = try o.builder.debugMemberType(
2755 fwd_decl.toScope(),2702 try o.builder.metadataString("tag"),
2756 "tag",2703 .none, // File
2757 null, // file2704 debug_fwd_ref,
2758 0, // line2705 0, // Line
2706 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty)),
2759 layout.tag_size * 8,2707 layout.tag_size * 8,
2760 layout.tag_align.toByteUnits(0) * 8,2708 layout.tag_align.toByteUnits(0) * 8,
2761 tag_offset * 8, // offset in bits2709 tag_offset * 8,
2762 0, // flags
2763 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve),
2764 );2710 );
27652711
2766 const payload_di = dib.createMemberType(2712 const debug_payload_type = try o.builder.debugMemberType(
2767 fwd_decl.toScope(),2713 try o.builder.metadataString("payload"),
2768 "payload",2714 .none, // File
2769 null, // file2715 debug_fwd_ref,
2770 0, // line2716 0, // Line
2771 layout.payload_size * 8, // size in bits2717 debug_union_type,
2718 layout.payload_size * 8,
2772 layout.payload_align.toByteUnits(0) * 8,2719 layout.payload_align.toByteUnits(0) * 8,
2773 payload_offset * 8, // offset in bits2720 payload_offset * 8,
2774 0, // flags
2775 union_di_ty,
2776 );2721 );
27772722
2778 const full_di_fields: [2]*llvm.DIType =2723 const full_fields: [2]Builder.Metadata =
2779 if (layout.tag_align.compare(.gte, layout.payload_align))2724 if (layout.tag_align.compare(.gte, layout.payload_align))
2780 .{ tag_di, payload_di }2725 .{ debug_tag_type, debug_payload_type }
2781 else2726 else
2782 .{ payload_di, tag_di };2727 .{ debug_payload_type, debug_tag_type };
27832728
2784 const full_di_ty = dib.createStructType(2729 const debug_tagged_union_type = try o.builder.debugStructType(
2785 compile_unit_scope,2730 try o.builder.metadataString(name),
2786 name.ptr,2731 .none, // File
2787 null, // file2732 o.debug_compile_unit, // Scope
2788 0, // line2733 0, // Line
2789 ty.abiSize(mod) * 8, // size in bits2734 .none, // Underlying type
2790 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2735 ty.abiSize(mod) * 8,
2791 0, // flags2736 ty.abiAlignment(mod).toByteUnits(0) * 8,
2792 null, // derived from2737 try o.builder.debugTuple(&full_fields),
2793 &full_di_fields,
2794 full_di_fields.len,
2795 0, // run time lang
2796 null, // vtable holder
2797 "", // unique id
2798 );2738 );
2799 dib.replaceTemporary(fwd_decl, full_di_ty);2739
2800 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2740 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_tagged_union_type);
2801 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2741
2802 return full_di_ty;2742 // Set to real type now that it has been lowered fully
2743 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2744 map_ptr.* = debug_tagged_union_type;
2745
2746 return debug_tagged_union_type;
2803 },2747 },
2804 .Fn => {2748 .Fn => {
2805 const fn_info = mod.typeToFunc(ty).?;2749 const fn_info = mod.typeToFunc(ty).?;
28062750
2807 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);2751 var debug_param_types = std.ArrayList(Builder.Metadata).init(gpa);
2808 defer param_di_types.deinit();2752 defer debug_param_types.deinit();
2753
2754 try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len);
28092755
2810 // Return type goes first.2756 // Return type goes first.
2811 if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(mod)) {2757 if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(mod)) {
2812 const sret = firstParamSRet(fn_info, mod);2758 const sret = firstParamSRet(fn_info, mod);
2813 const di_ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);2759 const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);
2814 try param_di_types.append(try o.lowerDebugType(di_ret_ty, resolve));2760 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ret_ty));
28152761
2816 if (sret) {2762 if (sret) {
2817 const ptr_ty = try mod.singleMutPtrType(Type.fromInterned(fn_info.return_type));2763 const ptr_ty = try mod.singleMutPtrType(Type.fromInterned(fn_info.return_type));
2818 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));2764 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
2819 }2765 }
2820 } else {2766 } else {
2821 try param_di_types.append(try o.lowerDebugType(Type.void, resolve));2767 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void));
2822 }2768 }
28232769
2824 if (Type.fromInterned(fn_info.return_type).isError(mod) and2770 if (Type.fromInterned(fn_info.return_type).isError(mod) and
2825 o.module.comp.config.any_error_tracing)2771 o.module.comp.config.any_error_tracing)
2826 {2772 {
2827 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());2773 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());
2828 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));2774 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
2829 }2775 }
28302776
2831 for (0..fn_info.param_types.len) |i| {2777 for (0..fn_info.param_types.len) |i| {
...@@ -2834,20 +2780,18 @@ pub const Object = struct {...@@ -2834,20 +2780,18 @@ pub const Object = struct {
28342780
2835 if (isByRef(param_ty, mod)) {2781 if (isByRef(param_ty, mod)) {
2836 const ptr_ty = try mod.singleMutPtrType(param_ty);2782 const ptr_ty = try mod.singleMutPtrType(param_ty);
2837 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));2783 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
2838 } else {2784 } else {
2839 try param_di_types.append(try o.lowerDebugType(param_ty, resolve));2785 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(param_ty));
2840 }2786 }
2841 }2787 }
28422788
2843 const fn_di_ty = dib.createSubroutineType(2789 const debug_function_type = try o.builder.debugSubroutineType(
2844 param_di_types.items.ptr,2790 try o.builder.debugTuple(debug_param_types.items),
2845 @intCast(param_di_types.items.len),
2846 0,
2847 );2791 );
2848 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2792
2849 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(fn_di_ty));2793 try o.debug_type_map.put(gpa, ty, debug_function_type);
2850 return fn_di_ty;2794 return debug_function_type;
2851 },2795 },
2852 .ComptimeInt => unreachable,2796 .ComptimeInt => unreachable,
2853 .ComptimeFloat => unreachable,2797 .ComptimeFloat => unreachable,
...@@ -2861,39 +2805,30 @@ pub const Object = struct {...@@ -2861,39 +2805,30 @@ pub const Object = struct {
2861 }2805 }
2862 }2806 }
28632807
2864 fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !*llvm.DIScope {2808 fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {
2865 const mod = o.module;2809 const mod = o.module;
2866 const namespace = mod.namespacePtr(namespace_index);2810 const namespace = mod.namespacePtr(namespace_index);
2867 if (namespace.parent == .none) {2811 if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope);
2868 const di_file = try o.getDIFile(o.gpa, namespace.file_scope);2812
2869 return di_file.toScope();2813 const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index);
2870 }2814
2871 const di_type = try o.lowerDebugType(namespace.ty, .fwd);2815 if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference();
2872 return di_type.toScope();2816
2817 return gop.value_ptr.*;
2873 }2818 }
28742819
2875 /// This is to be used instead of void for debug info types, to avoid tripping2820 fn makeEmptyNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex) !Builder.Metadata {
2876 /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
2877 /// when targeting CodeView (Windows).
2878 fn makeEmptyNamespaceDIType(o: *Object, decl_index: InternPool.DeclIndex) !*llvm.DIType {
2879 const mod = o.module;2821 const mod = o.module;
2880 const decl = mod.declPtr(decl_index);2822 const decl = mod.declPtr(decl_index);
2881 const fields: [0]*llvm.DIType = .{};2823 return o.builder.debugStructType(
2882 const di_scope = try o.namespaceToDebugScope(decl.src_namespace);2824 try o.builder.metadataString(mod.intern_pool.stringToSlice(decl.name)), // TODO use fully qualified name
2883 return o.di_builder.?.createStructType(2825 try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope),
2884 di_scope,2826 try o.namespaceToDebugScope(decl.src_namespace),
2885 mod.intern_pool.stringToSlice(decl.name), // TODO use fully qualified name
2886 try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope),
2887 decl.src_line + 1,2827 decl.src_line + 1,
2888 0, // size in bits2828 .none,
2889 0, // align in bits2829 0,
2890 0, // flags2830 0,
2891 null, // derived from2831 .none,
2892 undefined, // TODO should be able to pass &fields,
2893 fields.len,
2894 0, // run time lang
2895 null, // vtable holder
2896 "", // unique id
2897 );2832 );
2898 }2833 }
28992834
...@@ -3202,26 +3137,6 @@ pub const Object = struct {...@@ -3202,26 +3137,6 @@ pub const Object = struct {
3202 }3137 }
32033138
3204 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {3139 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
3205 const ty = try o.lowerTypeInner(t);
3206 const mod = o.module;
3207 if (std.debug.runtime_safety and o.builder.useLibLlvm() and false) check: {
3208 const llvm_ty = ty.toLlvm(&o.builder);
3209 if (t.zigTypeTag(mod) == .Opaque) break :check;
3210 if (!t.hasRuntimeBits(mod)) break :check;
3211 if (!try ty.isSized(&o.builder)) break :check;
3212
3213 const zig_size = t.abiSize(mod);
3214 const llvm_size = o.target_data.abiSizeOfType(llvm_ty);
3215 if (llvm_size != zig_size) {
3216 log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{
3217 t.fmt(o.module), zig_size, llvm_size,
3218 });
3219 }
3220 }
3221 return ty;
3222 }
3223
3224 fn lowerTypeInner(o: *Object, t: Type) Allocator.Error!Builder.Type {
3225 const mod = o.module;3140 const mod = o.module;
3226 const target = mod.getTarget();3141 const target = mod.getTarget();
3227 const ip = &mod.intern_pool;3142 const ip = &mod.intern_pool;
...@@ -3406,20 +3321,17 @@ pub const Object = struct {...@@ -3406,20 +3321,17 @@ pub const Object = struct {
3406 },3321 },
3407 .simple_type => unreachable,3322 .simple_type => unreachable,
3408 .struct_type => |struct_type| {3323 .struct_type => |struct_type| {
3409 const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());3324 if (o.type_map.get(t.toIntern())) |value| return value;
3410 if (gop.found_existing) return gop.value_ptr.*;
34113325
3412 if (struct_type.layout == .Packed) {3326 if (struct_type.layout == .Packed) {
3413 const int_ty = try o.lowerType(Type.fromInterned(struct_type.backingIntType(ip).*));3327 const int_ty = try o.lowerType(Type.fromInterned(struct_type.backingIntType(ip).*));
3414 gop.value_ptr.* = int_ty;3328 try o.type_map.put(o.gpa, t.toIntern(), int_ty);
3415 return int_ty;3329 return int_ty;
3416 }3330 }
34173331
3418 const name = try o.builder.string(ip.stringToSlice(3332 const name = try o.builder.string(ip.stringToSlice(
3419 try mod.declPtr(struct_type.decl.unwrap().?).getFullyQualifiedName(mod),3333 try mod.declPtr(struct_type.decl.unwrap().?).getFullyQualifiedName(mod),
3420 ));3334 ));
3421 const ty = try o.builder.opaqueType(name);
3422 gop.value_ptr.* = ty; // must be done before any recursive calls
34233335
3424 var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};3336 var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};
3425 defer llvm_field_types.deinit(o.gpa);3337 defer llvm_field_types.deinit(o.gpa);
...@@ -3484,7 +3396,10 @@ pub const Object = struct {...@@ -3484,7 +3396,10 @@ pub const Object = struct {
3484 );3396 );
3485 }3397 }
34863398
3487 try o.builder.namedTypeSetBody(3399 const ty = try o.builder.opaqueType(name);
3400 try o.type_map.put(o.gpa, t.toIntern(), ty);
3401
3402 o.builder.namedTypeSetBody(
3488 ty,3403 ty,
3489 try o.builder.structType(struct_kind, llvm_field_types.items),3404 try o.builder.structType(struct_kind, llvm_field_types.items),
3490 );3405 );
...@@ -3553,29 +3468,26 @@ pub const Object = struct {...@@ -3553,29 +3468,26 @@ pub const Object = struct {
3553 return o.builder.structType(.normal, llvm_field_types.items);3468 return o.builder.structType(.normal, llvm_field_types.items);
3554 },3469 },
3555 .union_type => |union_type| {3470 .union_type => |union_type| {
3556 const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());3471 if (o.type_map.get(t.toIntern())) |value| return value;
3557 if (gop.found_existing) return gop.value_ptr.*;
35583472
3559 const union_obj = ip.loadUnionType(union_type);3473 const union_obj = ip.loadUnionType(union_type);
3560 const layout = mod.getUnionLayout(union_obj);3474 const layout = mod.getUnionLayout(union_obj);
35613475
3562 if (union_obj.flagsPtr(ip).layout == .Packed) {3476 if (union_obj.flagsPtr(ip).layout == .Packed) {
3563 const int_ty = try o.builder.intType(@intCast(t.bitSize(mod)));3477 const int_ty = try o.builder.intType(@intCast(t.bitSize(mod)));
3564 gop.value_ptr.* = int_ty;3478 try o.type_map.put(o.gpa, t.toIntern(), int_ty);
3565 return int_ty;3479 return int_ty;
3566 }3480 }
35673481
3568 if (layout.payload_size == 0) {3482 if (layout.payload_size == 0) {
3569 const enum_tag_ty = try o.lowerType(Type.fromInterned(union_obj.enum_tag_ty));3483 const enum_tag_ty = try o.lowerType(Type.fromInterned(union_obj.enum_tag_ty));
3570 gop.value_ptr.* = enum_tag_ty;3484 try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty);
3571 return enum_tag_ty;3485 return enum_tag_ty;
3572 }3486 }
35733487
3574 const name = try o.builder.string(ip.stringToSlice(3488 const name = try o.builder.string(ip.stringToSlice(
3575 try mod.declPtr(union_obj.decl).getFullyQualifiedName(mod),3489 try mod.declPtr(union_obj.decl).getFullyQualifiedName(mod),
3576 ));3490 ));
3577 const ty = try o.builder.opaqueType(name);
3578 gop.value_ptr.* = ty; // must be done before any recursive calls
35793491
3580 const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]);3492 const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]);
3581 const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty);3493 const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty);
...@@ -3595,7 +3507,10 @@ pub const Object = struct {...@@ -3595,7 +3507,10 @@ pub const Object = struct {
3595 };3507 };
35963508
3597 if (layout.tag_size == 0) {3509 if (layout.tag_size == 0) {
3598 try o.builder.namedTypeSetBody(3510 const ty = try o.builder.opaqueType(name);
3511 try o.type_map.put(o.gpa, t.toIntern(), ty);
3512
3513 o.builder.namedTypeSetBody(
3599 ty,3514 ty,
3600 try o.builder.structType(.normal, &.{payload_ty}),3515 try o.builder.structType(.normal, &.{payload_ty}),
3601 );3516 );
...@@ -3620,7 +3535,10 @@ pub const Object = struct {...@@ -3620,7 +3535,10 @@ pub const Object = struct {
3620 llvm_fields_len += 1;3535 llvm_fields_len += 1;
3621 }3536 }
36223537
3623 try o.builder.namedTypeSetBody(3538 const ty = try o.builder.opaqueType(name);
3539 try o.type_map.put(o.gpa, t.toIntern(), ty);
3540
3541 o.builder.namedTypeSetBody(
3624 ty,3542 ty,
3625 try o.builder.structType(.normal, llvm_fields[0..llvm_fields_len]),3543 try o.builder.structType(.normal, llvm_fields[0..llvm_fields_len]),
3626 );3544 );
...@@ -4368,7 +4286,7 @@ pub const Object = struct {...@@ -4368,7 +4286,7 @@ pub const Object = struct {
4368 const err_align = err_int_ty.abiAlignment(mod);4286 const err_align = err_int_ty.abiAlignment(mod);
4369 const index: u32 = if (payload_align.compare(.gt, err_align)) 2 else 1;4287 const index: u32 = if (payload_align.compare(.gt, err_align)) 2 else 1;
4370 return o.builder.gepConst(.inbounds, try o.lowerType(eu_ty), parent_ptr, null, &.{4288 return o.builder.gepConst(.inbounds, try o.lowerType(eu_ty), parent_ptr, null, &.{
4371 try o.builder.intConst(.i32, 0), try o.builder.intConst(.i32, index),4289 .@"0", try o.builder.intConst(.i32, index),
4372 });4290 });
4373 },4291 },
4374 .opt_payload => |opt_ptr| {4292 .opt_payload => |opt_ptr| {
...@@ -4384,9 +4302,7 @@ pub const Object = struct {...@@ -4384,9 +4302,7 @@ pub const Object = struct {
4384 return parent_ptr;4302 return parent_ptr;
4385 }4303 }
43864304
4387 return o.builder.gepConst(.inbounds, try o.lowerType(opt_ty), parent_ptr, null, &.{4305 return o.builder.gepConst(.inbounds, try o.lowerType(opt_ty), parent_ptr, null, &.{ .@"0", .@"0" });
4388 try o.builder.intConst(.i32, 0), try o.builder.intConst(.i32, 0),
4389 });
4390 },4306 },
4391 .comptime_field => unreachable,4307 .comptime_field => unreachable,
4392 .elem => |elem_ptr| {4308 .elem => |elem_ptr| {
...@@ -4417,7 +4333,7 @@ pub const Object = struct {...@@ -4417,7 +4333,7 @@ pub const Object = struct {
44174333
4418 const parent_llvm_ty = try o.lowerType(parent_ty);4334 const parent_llvm_ty = try o.lowerType(parent_ty);
4419 return o.builder.gepConst(.inbounds, parent_llvm_ty, parent_ptr, null, &.{4335 return o.builder.gepConst(.inbounds, parent_llvm_ty, parent_ptr, null, &.{
4420 try o.builder.intConst(.i32, 0),4336 .@"0",
4421 try o.builder.intConst(.i32, @intFromBool(4337 try o.builder.intConst(.i32, @intFromBool(
4422 layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align),4338 layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align),
4423 )),4339 )),
...@@ -4443,7 +4359,7 @@ pub const Object = struct {...@@ -4443,7 +4359,7 @@ pub const Object = struct {
4443 parent_ptr,4359 parent_ptr,
4444 null,4360 null,
4445 if (o.llvmFieldIndex(parent_ty, field_index)) |llvm_field_index| &.{4361 if (o.llvmFieldIndex(parent_ty, field_index)) |llvm_field_index| &.{
4446 try o.builder.intConst(.i32, 0),4362 .@"0",
4447 try o.builder.intConst(.i32, llvm_field_index),4363 try o.builder.intConst(.i32, llvm_field_index),
4448 } else &.{4364 } else &.{
4449 try o.builder.intConst(.i32, @intFromBool(4365 try o.builder.intConst(.i32, @intFromBool(
...@@ -4456,7 +4372,7 @@ pub const Object = struct {...@@ -4456,7 +4372,7 @@ pub const Object = struct {
4456 assert(parent_ty.isSlice(mod));4372 assert(parent_ty.isSlice(mod));
4457 const parent_llvm_ty = try o.lowerType(parent_ty);4373 const parent_llvm_ty = try o.lowerType(parent_ty);
4458 return o.builder.gepConst(.inbounds, parent_llvm_ty, parent_ptr, null, &.{4374 return o.builder.gepConst(.inbounds, parent_llvm_ty, parent_ptr, null, &.{
4459 try o.builder.intConst(.i32, 0), try o.builder.intConst(.i32, field_index),4375 .@"0", try o.builder.intConst(.i32, field_index),
4460 });4376 });
4461 },4377 },
4462 else => unreachable,4378 else => unreachable,
...@@ -4716,8 +4632,8 @@ pub const Object = struct {...@@ -4716,8 +4632,8 @@ pub const Object = struct {
4716 defer wip_switch.finish(&wip);4632 defer wip_switch.finish(&wip);
47174633
4718 for (0..enum_type.names.len) |field_index| {4634 for (0..enum_type.names.len) |field_index| {
4719 const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index]));4635 const name = try o.builder.stringNull(ip.stringToSlice(enum_type.names.get(ip)[field_index]));
4720 const name_init = try o.builder.stringNullConst(name);4636 const name_init = try o.builder.stringConst(name);
4721 const name_variable_index =4637 const name_variable_index =
4722 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);4638 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
4723 try name_variable_index.setInitializer(name_init, &o.builder);4639 try name_variable_index.setInitializer(name_init, &o.builder);
...@@ -4728,7 +4644,7 @@ pub const Object = struct {...@@ -4728,7 +4644,7 @@ pub const Object = struct {
47284644
4729 const name_val = try o.builder.structValue(ret_ty, &.{4645 const name_val = try o.builder.structValue(ret_ty, &.{
4730 name_variable_index.toConst(&o.builder),4646 name_variable_index.toConst(&o.builder),
4731 try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len),4647 try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len - 1),
4732 });4648 });
47334649
4734 const return_block = try wip.block(1, "Name");4650 const return_block = try wip.block(1, "Name");
...@@ -4800,26 +4716,33 @@ pub const DeclGen = struct {...@@ -4800,26 +4716,33 @@ pub const DeclGen = struct {
4800 else => try o.lowerValue(init_val),4716 else => try o.lowerValue(init_val),
4801 }, &o.builder);4717 }, &o.builder);
48024718
4803 if (o.di_builder) |dib| {4719 const line_number = decl.src_line + 1;
4804 const di_file =4720 const is_internal_linkage = !o.module.decl_exports.contains(decl_index);
4805 try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
4806
4807 const line_number = decl.src_line + 1;
4808 const is_internal_linkage = !o.module.decl_exports.contains(decl_index);
4809 const di_global = dib.createGlobalVariableExpression(
4810 di_file.toScope(),
4811 mod.intern_pool.stringToSlice(decl.name),
4812 variable_index.name(&o.builder).slice(&o.builder).?,
4813 di_file,
4814 line_number,
4815 try o.lowerDebugType(decl.ty, .full),
4816 is_internal_linkage,
4817 );
48184721
4819 try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode());4722 if (dg.object.builder.strip) return;
4820 if (!is_internal_linkage or decl.isExtern(mod))4723
4821 variable_index.toLlvm(&o.builder).attachMetaData(di_global);4724 const debug_file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope);
4822 }4725
4726 const debug_global_var = try o.builder.debugGlobalVar(
4727 try o.builder.metadataString(mod.intern_pool.stringToSlice(decl.name)), // Name
4728 try o.builder.metadataStringFromString(variable_index.name(&o.builder)), // Linkage name
4729 debug_file, // File
4730 debug_file, // Scope
4731 line_number,
4732 try o.lowerDebugType(decl.ty),
4733 variable_index,
4734 .{ .local = is_internal_linkage },
4735 );
4736
4737 const debug_expression = try o.builder.debugExpression(&.{});
4738
4739 const debug_global_var_expression = try o.builder.debugGlobalVarExpression(
4740 debug_global_var,
4741 debug_expression,
4742 );
4743 if (!is_internal_linkage or decl.isExtern(mod))
4744 variable_index.setGlobalVariableExpression(debug_global_var_expression, &o.builder);
4745 try o.debug_globals.append(o.gpa, debug_global_var_expression);
4823 }4746 }
4824 }4747 }
4825};4748};
...@@ -4830,19 +4753,22 @@ pub const FuncGen = struct {...@@ -4830,19 +4753,22 @@ pub const FuncGen = struct {
4830 air: Air,4753 air: Air,
4831 liveness: Liveness,4754 liveness: Liveness,
4832 wip: Builder.WipFunction,4755 wip: Builder.WipFunction,
4833 di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn,4756
4834 di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn,4757 file: Builder.Metadata,
4758 scope: Builder.Metadata,
4759
4760 inlined: std.ArrayListUnmanaged(struct {
4761 base_line: u32,
4762 location: Builder.Metadata,
4763 scope: Builder.Metadata,
4764 }) = .{},
4765
4766 scope_stack: std.ArrayListUnmanaged(Builder.Metadata) = .{},
4767
4835 base_line: u32,4768 base_line: u32,
4836 prev_dbg_line: c_uint,4769 prev_dbg_line: c_uint,
4837 prev_dbg_column: c_uint,4770 prev_dbg_column: c_uint,
48384771
4839 /// Stack of locations where a call was inlined.
4840 dbg_inlined: std.ArrayListUnmanaged(if (build_options.have_llvm) DbgState else void) = .{},
4841
4842 /// Stack of `DILexicalBlock`s. dbg_block instructions cannot happend accross
4843 /// dbg_inline instructions so no special handling there is required.
4844 dbg_block_stack: std.ArrayListUnmanaged(if (build_options.have_llvm) *llvm.DIScope else void) = .{},
4845
4846 /// This stores the LLVM values used in a function, such that they can be referred to4772 /// This stores the LLVM values used in a function, such that they can be referred to
4847 /// in other instructions. This table is cleared before every function is generated.4773 /// in other instructions. This table is cleared before every function is generated.
4848 func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, Builder.Value),4774 func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, Builder.Value),
...@@ -4872,7 +4798,6 @@ pub const FuncGen = struct {...@@ -4872,7 +4798,6 @@ pub const FuncGen = struct {
48724798
4873 sync_scope: Builder.SyncScope,4799 sync_scope: Builder.SyncScope,
48744800
4875 const DbgState = if (build_options.have_llvm) struct { loc: *llvm.DILocation, scope: *llvm.DIScope, base_line: u32 } else struct {};
4876 const BreakList = union {4801 const BreakList = union {
4877 list: std.MultiArrayList(struct {4802 list: std.MultiArrayList(struct {
4878 bb: Builder.Function.Block.Index,4803 bb: Builder.Function.Block.Index,
...@@ -4883,8 +4808,8 @@ pub const FuncGen = struct {...@@ -4883,8 +4808,8 @@ pub const FuncGen = struct {
48834808
4884 fn deinit(self: *FuncGen) void {4809 fn deinit(self: *FuncGen) void {
4885 self.wip.deinit();4810 self.wip.deinit();
4886 self.dbg_inlined.deinit(self.gpa);4811 self.scope_stack.deinit(self.gpa);
4887 self.dbg_block_stack.deinit(self.gpa);4812 self.inlined.deinit(self.gpa);
4888 self.func_inst_table.deinit(self.gpa);4813 self.func_inst_table.deinit(self.gpa);
4889 self.blocks.deinit(self.gpa);4814 self.blocks.deinit(self.gpa);
4890 }4815 }
...@@ -5493,9 +5418,6 @@ pub const FuncGen = struct {...@@ -5493,9 +5418,6 @@ pub const FuncGen = struct {
5493 // a different LLVM type than the usual one. We solve this here at the callsite5418 // a different LLVM type than the usual one. We solve this here at the callsite
5494 // by using our canonical type, then loading it if necessary.5419 // by using our canonical type, then loading it if necessary.
5495 const alignment = return_type.abiAlignment(mod).toLlvm();5420 const alignment = return_type.abiAlignment(mod).toLlvm();
5496 if (o.builder.useLibLlvm())
5497 assert(o.target_data.abiSizeOfType(abi_ret_ty.toLlvm(&o.builder)) >=
5498 o.target_data.abiSizeOfType(llvm_ret_ty.toLlvm(&o.builder)));
5499 const rp = try self.buildAlloca(abi_ret_ty, alignment);5421 const rp = try self.buildAlloca(abi_ret_ty, alignment);
5500 _ = try self.wip.store(.normal, call, rp, alignment);5422 _ = try self.wip.store(.normal, call, rp, alignment);
5501 return if (isByRef(return_type, mod))5423 return if (isByRef(return_type, mod))
...@@ -5862,7 +5784,7 @@ pub const FuncGen = struct {...@@ -5862,7 +5784,7 @@ pub const FuncGen = struct {
5862 };5784 };
58635785
5864 const phi = try self.wip.phi(.i1, "");5786 const phi = try self.wip.phi(.i1, "");
5865 try phi.finish(5787 phi.finish(
5866 &incoming_values,5788 &incoming_values,
5867 &.{ both_null_block, mixed_block, both_pl_block_end },5789 &.{ both_null_block, mixed_block, both_pl_block_end },
5868 &self.wip,5790 &self.wip,
...@@ -5929,7 +5851,7 @@ pub const FuncGen = struct {...@@ -5929,7 +5851,7 @@ pub const FuncGen = struct {
59295851
5930 parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len);5852 parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len);
5931 const phi = try self.wip.phi(llvm_ty, "");5853 const phi = try self.wip.phi(llvm_ty, "");
5932 try phi.finish(breaks.list.items(.val), breaks.list.items(.bb), &self.wip);5854 phi.finish(breaks.list.items(.val), breaks.list.items(.bb), &self.wip);
5933 return phi.toValue();5855 return phi.toValue();
5934 } else {5856 } else {
5935 parent_bb.ptr(&self.wip).incoming = @intCast(breaks.len);5857 parent_bb.ptr(&self.wip).incoming = @intCast(breaks.len);
...@@ -6653,42 +6575,43 @@ pub const FuncGen = struct {...@@ -6653,42 +6575,43 @@ pub const FuncGen = struct {
6653 }6575 }
66546576
6655 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6577 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6656 const di_scope = self.di_scope orelse return .none;6578 if (self.wip.builder.strip) return .none;
6657 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;6579 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
6658 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);6580 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
6659 self.prev_dbg_column = @intCast(dbg_stmt.column + 1);6581 self.prev_dbg_column = @intCast(dbg_stmt.column + 1);
6660 const inlined_at = if (self.dbg_inlined.items.len > 0)6582 const inlined_at = if (self.inlined.items.len > 0)
6661 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc6583 self.inlined.items[self.inlined.items.len - 1].location
6662 else6584 else
6663 null;6585 .none;
6664 self.wip.llvm.builder.setCurrentDebugLocation(6586
6587 self.wip.current_debug_location = try self.wip.builder.debugLocation(
6665 self.prev_dbg_line,6588 self.prev_dbg_line,
6666 self.prev_dbg_column,6589 self.prev_dbg_column,
6667 di_scope,6590 self.scope,
6668 inlined_at,6591 inlined_at,
6669 );6592 );
6593
6670 return .none;6594 return .none;
6671 }6595 }
66726596
6673 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6597 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6598 if (self.wip.builder.strip) return .none;
6674 const o = self.dg.object;6599 const o = self.dg.object;
6675 const dib = o.di_builder orelse return .none;
6676 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
6677
6678 const zcu = o.module;6600 const zcu = o.module;
6601
6602 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
6679 const func = zcu.funcInfo(ty_fn.func);6603 const func = zcu.funcInfo(ty_fn.func);
6680 const decl_index = func.owner_decl;6604 const decl_index = func.owner_decl;
6681 const decl = zcu.declPtr(decl_index);6605 const decl = zcu.declPtr(decl_index);
6682 const namespace = zcu.namespacePtr(decl.src_namespace);6606 const namespace = zcu.namespacePtr(decl.src_namespace);
6683 const owner_mod = namespace.file_scope.mod;6607 const owner_mod = namespace.file_scope.mod;
6684 const di_file = try o.getDIFile(self.gpa, zcu.namespacePtr(decl.src_namespace).file_scope);
6685 self.di_file = di_file;
6686 const line_number = decl.src_line + 1;
6687 const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2();
66886608
6689 try self.dbg_inlined.append(self.gpa, .{6609 self.file = try o.getDebugFile(namespace.file_scope);
6690 .loc = @ptrCast(cur_debug_location),6610
6691 .scope = self.di_scope.?,6611 const line_number = decl.src_line + 1;
6612 try self.inlined.append(self.gpa, .{
6613 .location = self.wip.current_debug_location,
6614 .scope = self.scope,
6692 .base_line = self.base_line,6615 .base_line = self.base_line,
6693 });6616 });
66946617
...@@ -6699,91 +6622,118 @@ pub const FuncGen = struct {...@@ -6699,91 +6622,118 @@ pub const FuncGen = struct {
6699 .param_types = &.{},6622 .param_types = &.{},
6700 .return_type = .void_type,6623 .return_type = .void_type,
6701 });6624 });
6702 const fn_di_ty = try o.lowerDebugType(fn_ty, .full);6625
6703 const subprogram = dib.createFunction(6626 const subprogram = try o.builder.debugSubprogram(
6704 di_file.toScope(),6627 self.file,
6705 zcu.intern_pool.stringToSlice(decl.name),6628 try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)),
6706 zcu.intern_pool.stringToSlice(fqn),6629 try o.builder.metadataString(zcu.intern_pool.stringToSlice(fqn)),
6707 di_file,
6708 line_number,6630 line_number,
6709 fn_di_ty,6631 line_number + func.lbrace_line,
6710 is_internal_linkage,6632 try o.lowerDebugType(fn_ty),
6711 true, // is definition6633 .{
6712 line_number + func.lbrace_line, // scope line6634 .di_flags = .{ .StaticMember = true },
6713 llvm.DIFlags.StaticMember,6635 .sp_flags = .{
6714 owner_mod.optimize_mode != .Debug,6636 .Optimized = owner_mod.optimize_mode != .Debug,
6715 null, // decl_subprogram6637 .Definition = true,
6638 .LocalToUnit = is_internal_linkage,
6639 },
6640 },
6641 o.debug_compile_unit,
6716 );6642 );
67176643
6718 const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file, line_number, 1);6644 const lexical_block = try o.builder.debugLexicalBlock(
6719 self.di_scope = lexical_block.toScope();6645 subprogram,
6646 self.file,
6647 line_number,
6648 1,
6649 );
6650 self.scope = lexical_block;
6720 self.base_line = decl.src_line;6651 self.base_line = decl.src_line;
6652 const inlined_at = self.wip.current_debug_location;
6653 self.wip.current_debug_location = try o.builder.debugLocation(
6654 line_number,
6655 0,
6656 self.scope,
6657 inlined_at,
6658 );
6721 return .none;6659 return .none;
6722 }6660 }
67236661
6724 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6662 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
6663 if (self.wip.builder.strip) return .none;
6725 const o = self.dg.object;6664 const o = self.dg.object;
6726 if (o.di_builder == null) return .none;6665
6727 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;6666 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
67286667
6729 const mod = o.module;6668 const mod = o.module;
6730 const decl = mod.funcOwnerDeclPtr(ty_fn.func);6669 const decl = mod.funcOwnerDeclPtr(ty_fn.func);
6731 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6670 self.file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope);
6732 self.di_file = di_file;6671
6733 const old = self.dbg_inlined.pop();6672 const old = self.inlined.pop();
6734 self.di_scope = old.scope;6673 self.scope = old.scope;
6735 self.base_line = old.base_line;6674 self.base_line = old.base_line;
6675 self.wip.current_debug_location = old.location;
6736 return .none;6676 return .none;
6737 }6677 }
67386678
6739 fn airDbgBlockBegin(self: *FuncGen) !Builder.Value {6679 fn airDbgBlockBegin(self: *FuncGen) Allocator.Error!Builder.Value {
6680 if (self.wip.builder.strip) return .none;
6740 const o = self.dg.object;6681 const o = self.dg.object;
6741 const dib = o.di_builder orelse return .none;6682
6742 const old_scope = self.di_scope.?;6683 try self.scope_stack.append(self.gpa, self.scope);
6743 try self.dbg_block_stack.append(self.gpa, old_scope);6684
6744 const lexical_block = dib.createLexicalBlock(old_scope, self.di_file.?, self.prev_dbg_line, self.prev_dbg_column);6685 const old = self.scope;
6745 self.di_scope = lexical_block.toScope();6686 self.scope = try o.builder.debugLexicalBlock(
6687 old,
6688 self.file,
6689 self.prev_dbg_line,
6690 self.prev_dbg_column,
6691 );
6746 return .none;6692 return .none;
6747 }6693 }
67486694
6749 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {6695 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
6750 const o = self.dg.object;6696 if (self.wip.builder.strip) return .none;
6751 if (o.di_builder == null) return .none;6697 self.scope = self.scope_stack.pop();
6752 self.di_scope = self.dbg_block_stack.pop();
6753 return .none;6698 return .none;
6754 }6699 }
67556700
6756 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6701 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6702 if (self.wip.builder.strip) return .none;
6757 const o = self.dg.object;6703 const o = self.dg.object;
6758 const mod = o.module;6704 const mod = o.module;
6759 const dib = o.di_builder orelse return .none;
6760 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6705 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6761 const operand = try self.resolveInst(pl_op.operand);6706 const operand = try self.resolveInst(pl_op.operand);
6762 const name = self.air.nullTerminatedString(pl_op.payload);6707 const name = self.air.nullTerminatedString(pl_op.payload);
6763 const ptr_ty = self.typeOf(pl_op.operand);6708 const ptr_ty = self.typeOf(pl_op.operand);
67646709
6765 const di_local_var = dib.createAutoVariable(6710 const debug_local_var = try o.builder.debugLocalVar(
6766 self.di_scope.?,6711 try o.builder.metadataString(name),
6767 name.ptr,6712 self.file,
6768 self.di_file.?,6713 self.scope,
6769 self.prev_dbg_line,6714 self.prev_dbg_line,
6770 try o.lowerDebugType(ptr_ty.childType(mod), .full),6715 try o.lowerDebugType(ptr_ty.childType(mod)),
6771 true, // always preserve
6772 0, // flags
6773 );6716 );
6774 const inlined_at = if (self.dbg_inlined.items.len > 0)6717
6775 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc6718 _ = try self.wip.callIntrinsic(
6776 else6719 .normal,
6777 null;6720 .none,
6778 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);6721 .@"dbg.declare",
6779 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);6722 &.{},
6780 _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);6723 &.{
6724 (try self.wip.debugValue(operand)).toValue(),
6725 debug_local_var.toValue(),
6726 (try o.builder.debugExpression(&.{})).toValue(),
6727 },
6728 "",
6729 );
6730
6781 return .none;6731 return .none;
6782 }6732 }
67836733
6784 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6734 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6735 if (self.wip.builder.strip) return .none;
6785 const o = self.dg.object;6736 const o = self.dg.object;
6786 const dib = o.di_builder orelse return .none;
6787 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6737 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6788 const operand = try self.resolveInst(pl_op.operand);6738 const operand = try self.resolveInst(pl_op.operand);
6789 const operand_ty = self.typeOf(pl_op.operand);6739 const operand_ty = self.typeOf(pl_op.operand);
...@@ -6791,32 +6741,58 @@ pub const FuncGen = struct {...@@ -6791,32 +6741,58 @@ pub const FuncGen = struct {
67916741
6792 if (needDbgVarWorkaround(o)) return .none;6742 if (needDbgVarWorkaround(o)) return .none;
67936743
6794 const di_local_var = dib.createAutoVariable(6744 const debug_local_var = try o.builder.debugLocalVar(
6795 self.di_scope.?,6745 try o.builder.metadataString(name),
6796 name.ptr,6746 self.file,
6797 self.di_file.?,6747 self.scope,
6798 self.prev_dbg_line,6748 self.prev_dbg_line,
6799 try o.lowerDebugType(operand_ty, .full),6749 try o.lowerDebugType(operand_ty),
6800 true, // always preserve
6801 0, // flags
6802 );6750 );
6803 const inlined_at = if (self.dbg_inlined.items.len > 0)6751
6804 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
6805 else
6806 null;
6807 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);
6808 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);
6809 const zcu = o.module;6752 const zcu = o.module;
6810 const owner_mod = self.dg.ownerModule();6753 const owner_mod = self.dg.ownerModule();
6811 if (isByRef(operand_ty, zcu)) {6754 if (isByRef(operand_ty, zcu)) {
6812 _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);6755 _ = try self.wip.callIntrinsic(
6756 .normal,
6757 .none,
6758 .@"dbg.declare",
6759 &.{},
6760 &.{
6761 (try self.wip.debugValue(operand)).toValue(),
6762 debug_local_var.toValue(),
6763 (try o.builder.debugExpression(&.{})).toValue(),
6764 },
6765 "",
6766 );
6813 } else if (owner_mod.optimize_mode == .Debug) {6767 } else if (owner_mod.optimize_mode == .Debug) {
6814 const alignment = operand_ty.abiAlignment(zcu).toLlvm();6768 const alignment = operand_ty.abiAlignment(zcu).toLlvm();
6815 const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);6769 const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);
6816 _ = try self.wip.store(.normal, operand, alloca, alignment);6770 _ = try self.wip.store(.normal, operand, alloca, alignment);
6817 _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);6771 _ = try self.wip.callIntrinsic(
6772 .normal,
6773 .none,
6774 .@"dbg.declare",
6775 &.{},
6776 &.{
6777 (try self.wip.debugValue(alloca)).toValue(),
6778 debug_local_var.toValue(),
6779 (try o.builder.debugExpression(&.{})).toValue(),
6780 },
6781 "",
6782 );
6818 } else {6783 } else {
6819 _ = dib.insertDbgValueIntrinsicAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);6784 _ = try self.wip.callIntrinsic(
6785 .normal,
6786 .none,
6787 .@"dbg.value",
6788 &.{},
6789 &.{
6790 (try self.wip.debugValue(operand)).toValue(),
6791 debug_local_var.toValue(),
6792 (try o.builder.debugExpression(&.{})).toValue(),
6793 },
6794 "",
6795 );
6820 }6796 }
6821 return .none;6797 return .none;
6822 }6798 }
...@@ -7885,7 +7861,7 @@ pub const FuncGen = struct {...@@ -7885,7 +7861,7 @@ pub const FuncGen = struct {
7885 .none,7861 .none,
7886 if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat",7862 if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat",
7887 &.{try o.lowerType(inst_ty)},7863 &.{try o.lowerType(inst_ty)},
7888 &.{ lhs, rhs, try o.builder.intValue(.i32, 0) },7864 &.{ lhs, rhs, .@"0" },
7889 "",7865 "",
7890 );7866 );
7891 }7867 }
...@@ -8208,7 +8184,6 @@ pub const FuncGen = struct {...@@ -8208,7 +8184,6 @@ pub const FuncGen = struct {
82088184
8209 const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);8185 const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);
82108186
8211 const zero = try o.builder.intConst(.i32, 0);
8212 const int_cond: Builder.IntegerCondition = switch (pred) {8187 const int_cond: Builder.IntegerCondition = switch (pred) {
8213 .eq => .eq,8188 .eq => .eq,
8214 .neq => .ne,8189 .neq => .ne,
...@@ -8225,7 +8200,7 @@ pub const FuncGen = struct {...@@ -8225,7 +8200,7 @@ pub const FuncGen = struct {
8225 const init = try o.builder.poisonValue(vector_result_ty);8200 const init = try o.builder.poisonValue(vector_result_ty);
8226 const result = try self.buildElementwiseCall(libc_fn, &params, init, vec_len);8201 const result = try self.buildElementwiseCall(libc_fn, &params, init, vec_len);
82278202
8228 const zero_vector = try o.builder.splatValue(vector_result_ty, zero);8203 const zero_vector = try o.builder.splatValue(vector_result_ty, .@"0");
8229 return self.wip.icmp(int_cond, result, zero_vector, "");8204 return self.wip.icmp(int_cond, result, zero_vector, "");
8230 }8205 }
82318206
...@@ -8238,7 +8213,7 @@ pub const FuncGen = struct {...@@ -8238,7 +8213,7 @@ pub const FuncGen = struct {
8238 &params,8213 &params,
8239 "",8214 "",
8240 );8215 );
8241 return self.wip.icmp(int_cond, result, zero.toValue(), "");8216 return self.wip.icmp(int_cond, result, .@"0", "");
8242 }8217 }
82438218
8244 const FloatOp = enum {8219 const FloatOp = enum {
...@@ -8838,41 +8813,80 @@ pub const FuncGen = struct {...@@ -8838,41 +8813,80 @@ pub const FuncGen = struct {
8838 const arg_val = self.args[self.arg_index];8813 const arg_val = self.args[self.arg_index];
8839 self.arg_index += 1;8814 self.arg_index += 1;
88408815
8816 if (self.wip.builder.strip) return arg_val;
8817
8841 const inst_ty = self.typeOfIndex(inst);8818 const inst_ty = self.typeOfIndex(inst);
8842 if (o.di_builder) |dib| {8819 if (needDbgVarWorkaround(o)) return arg_val;
8843 if (needDbgVarWorkaround(o)) return arg_val;8820
88448821 const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
8845 const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;8822 const func_index = self.dg.decl.getOwnedFunctionIndex();
8846 const func_index = self.dg.decl.getOwnedFunctionIndex();8823 const func = mod.funcInfo(func_index);
8847 const func = mod.funcInfo(func_index);8824 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
8848 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;8825 const lbrace_col = func.lbrace_column + 1;
8849 const lbrace_col = func.lbrace_column + 1;8826
8850 const di_local_var = dib.createParameterVariable(8827 const debug_parameter = try o.builder.debugParameter(
8851 self.di_scope.?,8828 try o.builder.metadataString(mod.getParamName(func_index, src_index)),
8852 mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args8829 self.file,
8853 self.di_file.?,8830 self.scope,
8854 lbrace_line,8831 lbrace_line,
8855 try o.lowerDebugType(inst_ty, .full),8832 try o.lowerDebugType(inst_ty),
8856 true, // always preserve8833 @intCast(self.arg_index),
8857 0, // flags8834 );
8858 @intCast(self.arg_index), // includes +1 because 0 is return type
8859 );
88608835
8861 const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null);8836 const old_location = self.wip.current_debug_location;
8862 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);8837 self.wip.current_debug_location = try o.builder.debugLocation(
8863 const owner_mod = self.dg.ownerModule();8838 lbrace_line,
8864 if (isByRef(inst_ty, mod)) {8839 lbrace_col,
8865 _ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);8840 self.scope,
8866 } else if (owner_mod.optimize_mode == .Debug) {8841 .none,
8867 const alignment = inst_ty.abiAlignment(mod).toLlvm();8842 );
8868 const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment);8843
8869 _ = try self.wip.store(.normal, arg_val, alloca, alignment);8844 const owner_mod = self.dg.ownerModule();
8870 _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);8845 if (isByRef(inst_ty, mod)) {
8871 } else {8846 _ = try self.wip.callIntrinsic(
8872 _ = dib.insertDbgValueIntrinsicAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);8847 .normal,
8873 }8848 .none,
8849 .@"dbg.declare",
8850 &.{},
8851 &.{
8852 (try self.wip.debugValue(arg_val)).toValue(),
8853 debug_parameter.toValue(),
8854 (try o.builder.debugExpression(&.{})).toValue(),
8855 },
8856 "",
8857 );
8858 } else if (owner_mod.optimize_mode == .Debug) {
8859 const alignment = inst_ty.abiAlignment(mod).toLlvm();
8860 const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment);
8861 _ = try self.wip.store(.normal, arg_val, alloca, alignment);
8862 _ = try self.wip.callIntrinsic(
8863 .normal,
8864 .none,
8865 .@"dbg.declare",
8866 &.{},
8867 &.{
8868 (try self.wip.debugValue(alloca)).toValue(),
8869 debug_parameter.toValue(),
8870 (try o.builder.debugExpression(&.{})).toValue(),
8871 },
8872 "",
8873 );
8874 } else {
8875 _ = try self.wip.callIntrinsic(
8876 .normal,
8877 .none,
8878 .@"dbg.value",
8879 &.{},
8880 &.{
8881 (try self.wip.debugValue(arg_val)).toValue(),
8882 debug_parameter.toValue(),
8883 (try o.builder.debugExpression(&.{})).toValue(),
8884 },
8885 "",
8886 );
8874 }8887 }
88758888
8889 self.wip.current_debug_location = old_location;
8876 return arg_val;8890 return arg_val;
8877 }8891 }
88788892
...@@ -8910,7 +8924,7 @@ pub const FuncGen = struct {...@@ -8910,7 +8924,7 @@ pub const FuncGen = struct {
8910 alignment: Builder.Alignment,8924 alignment: Builder.Alignment,
8911 ) Allocator.Error!Builder.Value {8925 ) Allocator.Error!Builder.Value {
8912 const target = self.dg.object.module.getTarget();8926 const target = self.dg.object.module.getTarget();
8913 return buildAllocaInner(&self.wip, self.di_scope != null, llvm_ty, alignment, target);8927 return buildAllocaInner(&self.wip, llvm_ty, alignment, target);
8914 }8928 }
89158929
8916 // Workaround for https://github.com/ziglang/zig/issues/163928930 // Workaround for https://github.com/ziglang/zig/issues/16392
...@@ -9025,18 +9039,14 @@ pub const FuncGen = struct {...@@ -9025,18 +9039,14 @@ pub const FuncGen = struct {
9025 // https://github.com/ziglang/zig/issues/119469039 // https://github.com/ziglang/zig/issues/11946
9026 return o.builder.intValue(llvm_usize, 0);9040 return o.builder.intValue(llvm_usize, 0);
9027 }9041 }
9028 const result = try self.wip.callIntrinsic(.normal, .none, .returnaddress, &.{}, &.{9042 const result = try self.wip.callIntrinsic(.normal, .none, .returnaddress, &.{}, &.{.@"0"}, "");
9029 try o.builder.intValue(.i32, 0),
9030 }, "");
9031 return self.wip.cast(.ptrtoint, result, llvm_usize, "");9043 return self.wip.cast(.ptrtoint, result, llvm_usize, "");
9032 }9044 }
90339045
9034 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9046 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
9035 _ = inst;9047 _ = inst;
9036 const o = self.dg.object;9048 const o = self.dg.object;
9037 const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{9049 const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, "");
9038 try o.builder.intValue(.i32, 0),
9039 }, "");
9040 return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), "");9050 return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), "");
9041 }9051 }
90429052
...@@ -9364,7 +9374,7 @@ pub const FuncGen = struct {...@@ -9364,7 +9374,7 @@ pub const FuncGen = struct {
9364 _ = try self.wip.br(loop_block);9374 _ = try self.wip.br(loop_block);
93659375
9366 self.wip.cursor = .{ .block = end_block };9376 self.wip.cursor = .{ .block = end_block };
9367 try it_ptr.finish(&.{ next_ptr, dest_ptr }, &.{ body_block, entry_block }, &self.wip);9377 it_ptr.finish(&.{ next_ptr, dest_ptr }, &.{ body_block, entry_block }, &self.wip);
9368 return .none;9378 return .none;
9369 }9379 }
93709380
...@@ -9599,7 +9609,7 @@ pub const FuncGen = struct {...@@ -9599,7 +9609,7 @@ pub const FuncGen = struct {
95999609
9600 self.wip.cursor = .{ .block = end_block };9610 self.wip.cursor = .{ .block = end_block };
9601 const phi = try self.wip.phi(.i1, "");9611 const phi = try self.wip.phi(.i1, "");
9602 try phi.finish(&.{ .true, .false }, &.{ valid_block, invalid_block }, &self.wip);9612 phi.finish(&.{ .true, .false }, &.{ valid_block, invalid_block }, &self.wip);
9603 return phi.toValue();9613 return phi.toValue();
9604 }9614 }
96059615
...@@ -10120,7 +10130,6 @@ pub const FuncGen = struct {...@@ -10120,7 +10130,6 @@ pub const FuncGen = struct {
10120 const field_align = mod.unionFieldNormalAlignment(union_obj, extra.field_index);10130 const field_align = mod.unionFieldNormalAlignment(union_obj, extra.field_index);
10121 const llvm_usize = try o.lowerType(Type.usize);10131 const llvm_usize = try o.lowerType(Type.usize);
10122 const usize_zero = try o.builder.intValue(llvm_usize, 0);10132 const usize_zero = try o.builder.intValue(llvm_usize, 0);
10123 const i32_zero = try o.builder.intValue(.i32, 0);
1012410133
10125 const llvm_union_ty = t: {10134 const llvm_union_ty = t: {
10126 const payload_ty = p: {10135 const payload_ty = p: {
...@@ -10159,7 +10168,7 @@ pub const FuncGen = struct {...@@ -10159,7 +10168,7 @@ pub const FuncGen = struct {
10159 .flags = .{ .alignment = field_align },10168 .flags = .{ .alignment = field_align },
10160 });10169 });
10161 if (layout.tag_size == 0) {10170 if (layout.tag_size == 0) {
10162 const indices = [3]Builder.Value{ usize_zero, i32_zero, i32_zero };10171 const indices = [3]Builder.Value{ usize_zero, .@"0", .@"0" };
10163 const len: usize = if (field_size == layout.payload_size) 2 else 3;10172 const len: usize = if (field_size == layout.payload_size) 2 else 3;
10164 const field_ptr =10173 const field_ptr =
10165 try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, indices[0..len], "");10174 try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, indices[0..len], "");
...@@ -10169,11 +10178,9 @@ pub const FuncGen = struct {...@@ -10169,11 +10178,9 @@ pub const FuncGen = struct {
1016910178
10170 {10179 {
10171 const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align));10180 const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align));
10172 const indices: [3]Builder.Value =10181 const indices: [3]Builder.Value = .{ usize_zero, try o.builder.intValue(.i32, payload_index), .@"0" };
10173 .{ usize_zero, try o.builder.intValue(.i32, payload_index), i32_zero };
10174 const len: usize = if (field_size == layout.payload_size) 2 else 3;10182 const len: usize = if (field_size == layout.payload_size) 2 else 3;
10175 const field_ptr =10183 const field_ptr = try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, indices[0..len], "");
10176 try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, indices[0..len], "");
10177 try self.store(field_ptr, field_ptr_ty, llvm_payload, .none);10184 try self.store(field_ptr, field_ptr_ty, llvm_payload, .none);
10178 }10185 }
10179 {10186 {
...@@ -10279,7 +10286,7 @@ pub const FuncGen = struct {...@@ -10279,7 +10286,7 @@ pub const FuncGen = struct {
1027910286
10280 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;10287 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
10281 const dimension = pl_op.payload;10288 const dimension = pl_op.payload;
10282 if (dimension >= 3) return o.builder.intValue(.i32, 1);10289 if (dimension >= 3) return .@"1";
1028310290
10284 // Fetch the dispatch pointer, which points to this structure:10291 // Fetch the dispatch pointer, which points to this structure:
10285 // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L291310292 // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913
...@@ -11694,45 +11701,6 @@ const struct_layout_version = 2;...@@ -11694,45 +11701,6 @@ const struct_layout_version = 2;
11694// https://github.com/llvm/llvm-project/issues/56585/ is fixed11701// https://github.com/llvm/llvm-project/issues/56585/ is fixed
11695const optional_layout_version = 3;11702const optional_layout_version = 3;
1169611703
11697/// We use the least significant bit of the pointer address to tell us
11698/// whether the type is fully resolved. Types that are only fwd declared
11699/// have the LSB flipped to a 1.
11700const AnnotatedDITypePtr = enum(usize) {
11701 null,
11702 _,
11703
11704 fn initFwd(di_type: *llvm.DIType) AnnotatedDITypePtr {
11705 const addr = @intFromPtr(di_type);
11706 assert(@as(u1, @truncate(addr)) == 0);
11707 return @enumFromInt(addr | 1);
11708 }
11709
11710 fn initFull(di_type: *llvm.DIType) AnnotatedDITypePtr {
11711 const addr = @intFromPtr(di_type);
11712 return @enumFromInt(addr);
11713 }
11714
11715 fn init(di_type: *llvm.DIType, resolve: Object.DebugResolveStatus) AnnotatedDITypePtr {
11716 const addr = @intFromPtr(di_type);
11717 const bit = @intFromBool(resolve == .fwd);
11718 return @enumFromInt(addr | bit);
11719 }
11720
11721 fn toDIType(self: AnnotatedDITypePtr) *llvm.DIType {
11722 switch (self) {
11723 .null => unreachable,
11724 _ => return @ptrFromInt(@intFromEnum(self) & ~@as(usize, 1)),
11725 }
11726 }
11727
11728 fn isFwdOnly(self: AnnotatedDITypePtr) bool {
11729 switch (self) {
11730 .null => unreachable,
11731 _ => return @as(u1, @truncate(@intFromEnum(self))) != 0,
11732 }
11733 }
11734};
11735
11736const lt_errors_fn_name = "__zig_lt_errors_len";11704const lt_errors_fn_name = "__zig_lt_errors_len";
1173711705
11738/// Without this workaround, LLVM crashes with "unknown codeview register H1"11706/// Without this workaround, LLVM crashes with "unknown codeview register H1"
...@@ -11756,7 +11724,6 @@ fn compilerRtIntBits(bits: u16) u16 {...@@ -11756,7 +11724,6 @@ fn compilerRtIntBits(bits: u16) u16 {
1175611724
11757fn buildAllocaInner(11725fn buildAllocaInner(
11758 wip: *Builder.WipFunction,11726 wip: *Builder.WipFunction,
11759 di_scope_non_null: bool,
11760 llvm_ty: Builder.Type,11727 llvm_ty: Builder.Type,
11761 alignment: Builder.Alignment,11728 alignment: Builder.Alignment,
11762 target: std.Target,11729 target: std.Target,
...@@ -11765,19 +11732,15 @@ fn buildAllocaInner(...@@ -11765,19 +11732,15 @@ fn buildAllocaInner(
1176511732
11766 const alloca = blk: {11733 const alloca = blk: {
11767 const prev_cursor = wip.cursor;11734 const prev_cursor = wip.cursor;
11768 const prev_debug_location = if (wip.builder.useLibLlvm())11735 const prev_debug_location = wip.current_debug_location;
11769 wip.llvm.builder.getCurrentDebugLocation2()
11770 else
11771 undefined;
11772 defer {11736 defer {
11773 wip.cursor = prev_cursor;11737 wip.cursor = prev_cursor;
11774 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;11738 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;
11775 if (wip.builder.useLibLlvm() and di_scope_non_null)11739 wip.current_debug_location = prev_debug_location;
11776 wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location);
11777 }11740 }
1177811741
11779 wip.cursor = .{ .block = .entry };11742 wip.cursor = .{ .block = .entry };
11780 if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation();11743 wip.current_debug_location = .none;
11781 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");11744 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
11782 };11745 };
1178311746
...@@ -11823,3 +11786,195 @@ fn constraintAllowsRegister(constraint: []const u8) bool {...@@ -11823,3 +11786,195 @@ fn constraintAllowsRegister(constraint: []const u8) bool {
11823 }11786 }
11824 } else return false;11787 } else return false;
11825}11788}
11789
11790pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void {
11791 switch (arch) {
11792 .aarch64, .aarch64_be, .aarch64_32 => {
11793 llvm.LLVMInitializeAArch64Target();
11794 llvm.LLVMInitializeAArch64TargetInfo();
11795 llvm.LLVMInitializeAArch64TargetMC();
11796 llvm.LLVMInitializeAArch64AsmPrinter();
11797 llvm.LLVMInitializeAArch64AsmParser();
11798 },
11799 .amdgcn => {
11800 llvm.LLVMInitializeAMDGPUTarget();
11801 llvm.LLVMInitializeAMDGPUTargetInfo();
11802 llvm.LLVMInitializeAMDGPUTargetMC();
11803 llvm.LLVMInitializeAMDGPUAsmPrinter();
11804 llvm.LLVMInitializeAMDGPUAsmParser();
11805 },
11806 .thumb, .thumbeb, .arm, .armeb => {
11807 llvm.LLVMInitializeARMTarget();
11808 llvm.LLVMInitializeARMTargetInfo();
11809 llvm.LLVMInitializeARMTargetMC();
11810 llvm.LLVMInitializeARMAsmPrinter();
11811 llvm.LLVMInitializeARMAsmParser();
11812 },
11813 .avr => {
11814 llvm.LLVMInitializeAVRTarget();
11815 llvm.LLVMInitializeAVRTargetInfo();
11816 llvm.LLVMInitializeAVRTargetMC();
11817 llvm.LLVMInitializeAVRAsmPrinter();
11818 llvm.LLVMInitializeAVRAsmParser();
11819 },
11820 .bpfel, .bpfeb => {
11821 llvm.LLVMInitializeBPFTarget();
11822 llvm.LLVMInitializeBPFTargetInfo();
11823 llvm.LLVMInitializeBPFTargetMC();
11824 llvm.LLVMInitializeBPFAsmPrinter();
11825 llvm.LLVMInitializeBPFAsmParser();
11826 },
11827 .hexagon => {
11828 llvm.LLVMInitializeHexagonTarget();
11829 llvm.LLVMInitializeHexagonTargetInfo();
11830 llvm.LLVMInitializeHexagonTargetMC();
11831 llvm.LLVMInitializeHexagonAsmPrinter();
11832 llvm.LLVMInitializeHexagonAsmParser();
11833 },
11834 .lanai => {
11835 llvm.LLVMInitializeLanaiTarget();
11836 llvm.LLVMInitializeLanaiTargetInfo();
11837 llvm.LLVMInitializeLanaiTargetMC();
11838 llvm.LLVMInitializeLanaiAsmPrinter();
11839 llvm.LLVMInitializeLanaiAsmParser();
11840 },
11841 .mips, .mipsel, .mips64, .mips64el => {
11842 llvm.LLVMInitializeMipsTarget();
11843 llvm.LLVMInitializeMipsTargetInfo();
11844 llvm.LLVMInitializeMipsTargetMC();
11845 llvm.LLVMInitializeMipsAsmPrinter();
11846 llvm.LLVMInitializeMipsAsmParser();
11847 },
11848 .msp430 => {
11849 llvm.LLVMInitializeMSP430Target();
11850 llvm.LLVMInitializeMSP430TargetInfo();
11851 llvm.LLVMInitializeMSP430TargetMC();
11852 llvm.LLVMInitializeMSP430AsmPrinter();
11853 llvm.LLVMInitializeMSP430AsmParser();
11854 },
11855 .nvptx, .nvptx64 => {
11856 llvm.LLVMInitializeNVPTXTarget();
11857 llvm.LLVMInitializeNVPTXTargetInfo();
11858 llvm.LLVMInitializeNVPTXTargetMC();
11859 llvm.LLVMInitializeNVPTXAsmPrinter();
11860 // There is no LLVMInitializeNVPTXAsmParser function available.
11861 },
11862 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {
11863 llvm.LLVMInitializePowerPCTarget();
11864 llvm.LLVMInitializePowerPCTargetInfo();
11865 llvm.LLVMInitializePowerPCTargetMC();
11866 llvm.LLVMInitializePowerPCAsmPrinter();
11867 llvm.LLVMInitializePowerPCAsmParser();
11868 },
11869 .riscv32, .riscv64 => {
11870 llvm.LLVMInitializeRISCVTarget();
11871 llvm.LLVMInitializeRISCVTargetInfo();
11872 llvm.LLVMInitializeRISCVTargetMC();
11873 llvm.LLVMInitializeRISCVAsmPrinter();
11874 llvm.LLVMInitializeRISCVAsmParser();
11875 },
11876 .sparc, .sparc64, .sparcel => {
11877 llvm.LLVMInitializeSparcTarget();
11878 llvm.LLVMInitializeSparcTargetInfo();
11879 llvm.LLVMInitializeSparcTargetMC();
11880 llvm.LLVMInitializeSparcAsmPrinter();
11881 llvm.LLVMInitializeSparcAsmParser();
11882 },
11883 .s390x => {
11884 llvm.LLVMInitializeSystemZTarget();
11885 llvm.LLVMInitializeSystemZTargetInfo();
11886 llvm.LLVMInitializeSystemZTargetMC();
11887 llvm.LLVMInitializeSystemZAsmPrinter();
11888 llvm.LLVMInitializeSystemZAsmParser();
11889 },
11890 .wasm32, .wasm64 => {
11891 llvm.LLVMInitializeWebAssemblyTarget();
11892 llvm.LLVMInitializeWebAssemblyTargetInfo();
11893 llvm.LLVMInitializeWebAssemblyTargetMC();
11894 llvm.LLVMInitializeWebAssemblyAsmPrinter();
11895 llvm.LLVMInitializeWebAssemblyAsmParser();
11896 },
11897 .x86, .x86_64 => {
11898 llvm.LLVMInitializeX86Target();
11899 llvm.LLVMInitializeX86TargetInfo();
11900 llvm.LLVMInitializeX86TargetMC();
11901 llvm.LLVMInitializeX86AsmPrinter();
11902 llvm.LLVMInitializeX86AsmParser();
11903 },
11904 .xtensa => {
11905 if (build_options.llvm_has_xtensa) {
11906 llvm.LLVMInitializeXtensaTarget();
11907 llvm.LLVMInitializeXtensaTargetInfo();
11908 llvm.LLVMInitializeXtensaTargetMC();
11909 // There is no LLVMInitializeXtensaAsmPrinter function.
11910 llvm.LLVMInitializeXtensaAsmParser();
11911 }
11912 },
11913 .xcore => {
11914 llvm.LLVMInitializeXCoreTarget();
11915 llvm.LLVMInitializeXCoreTargetInfo();
11916 llvm.LLVMInitializeXCoreTargetMC();
11917 llvm.LLVMInitializeXCoreAsmPrinter();
11918 // There is no LLVMInitializeXCoreAsmParser function.
11919 },
11920 .m68k => {
11921 if (build_options.llvm_has_m68k) {
11922 llvm.LLVMInitializeM68kTarget();
11923 llvm.LLVMInitializeM68kTargetInfo();
11924 llvm.LLVMInitializeM68kTargetMC();
11925 llvm.LLVMInitializeM68kAsmPrinter();
11926 llvm.LLVMInitializeM68kAsmParser();
11927 }
11928 },
11929 .csky => {
11930 if (build_options.llvm_has_csky) {
11931 llvm.LLVMInitializeCSKYTarget();
11932 llvm.LLVMInitializeCSKYTargetInfo();
11933 llvm.LLVMInitializeCSKYTargetMC();
11934 // There is no LLVMInitializeCSKYAsmPrinter function.
11935 llvm.LLVMInitializeCSKYAsmParser();
11936 }
11937 },
11938 .ve => {
11939 llvm.LLVMInitializeVETarget();
11940 llvm.LLVMInitializeVETargetInfo();
11941 llvm.LLVMInitializeVETargetMC();
11942 llvm.LLVMInitializeVEAsmPrinter();
11943 llvm.LLVMInitializeVEAsmParser();
11944 },
11945 .arc => {
11946 if (build_options.llvm_has_arc) {
11947 llvm.LLVMInitializeARCTarget();
11948 llvm.LLVMInitializeARCTargetInfo();
11949 llvm.LLVMInitializeARCTargetMC();
11950 llvm.LLVMInitializeARCAsmPrinter();
11951 // There is no LLVMInitializeARCAsmParser function.
11952 }
11953 },
11954
11955 // LLVM backends that have no initialization functions.
11956 .tce,
11957 .tcele,
11958 .r600,
11959 .le32,
11960 .le64,
11961 .amdil,
11962 .amdil64,
11963 .hsail,
11964 .hsail64,
11965 .shave,
11966 .spir,
11967 .spir64,
11968 .kalimba,
11969 .renderscript32,
11970 .renderscript64,
11971 .dxil,
11972 .loongarch32,
11973 .loongarch64,
11974 => {},
11975
11976 .spu_2 => unreachable, // LLVM does not support this backend
11977 .spirv32 => unreachable, // LLVM does not support this backend
11978 .spirv64 => unreachable, // LLVM does not support this backend
11979 }
11980}
src/codegen/llvm/Builder.zig+5222-1998
...@@ -1,21 +1,6 @@...@@ -1,21 +1,6 @@
1gpa: Allocator,1gpa: Allocator,
2use_lib_llvm: bool,
3strip: bool,2strip: bool,
43
5llvm: if (build_options.have_llvm) struct {
6 context: *llvm.Context,
7 module: ?*llvm.Module,
8 target: ?*llvm.Target,
9 di_builder: ?*llvm.DIBuilder,
10 di_compile_unit: ?*llvm.DICompileUnit,
11 attribute_kind_ids: ?*[Attribute.Kind.len]c_uint,
12 attributes: std.ArrayListUnmanaged(*llvm.Attribute),
13 types: std.ArrayListUnmanaged(*llvm.Type),
14 globals: std.ArrayListUnmanaged(*llvm.Value),
15 constants: std.ArrayListUnmanaged(*llvm.Value),
16 replacements: std.AutoHashMapUnmanaged(*llvm.Value, Global.Index),
17} else void,
18
19source_filename: String,4source_filename: String,
20data_layout: String,5data_layout: String,
21target_triple: String,6target_triple: String,
...@@ -37,6 +22,8 @@ attributes_map: std.AutoArrayHashMapUnmanaged(void, void),...@@ -37,6 +22,8 @@ attributes_map: std.AutoArrayHashMapUnmanaged(void, void),
37attributes_indices: std.ArrayListUnmanaged(u32),22attributes_indices: std.ArrayListUnmanaged(u32),
38attributes_extra: std.ArrayListUnmanaged(u32),23attributes_extra: std.ArrayListUnmanaged(u32),
3924
25function_attributes_set: std.AutoArrayHashMapUnmanaged(FunctionAttributes, void),
26
40globals: std.AutoArrayHashMapUnmanaged(String, Global),27globals: std.AutoArrayHashMapUnmanaged(String, Global),
41next_unnamed_global: String,28next_unnamed_global: String,
42next_replaced_global: String,29next_replaced_global: String,
...@@ -50,17 +37,29 @@ constant_items: std.MultiArrayList(Constant.Item),...@@ -50,17 +37,29 @@ constant_items: std.MultiArrayList(Constant.Item),
50constant_extra: std.ArrayListUnmanaged(u32),37constant_extra: std.ArrayListUnmanaged(u32),
51constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),38constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),
5239
40metadata_map: std.AutoArrayHashMapUnmanaged(void, void),
41metadata_items: std.MultiArrayList(Metadata.Item),
42metadata_extra: std.ArrayListUnmanaged(u32),
43metadata_limbs: std.ArrayListUnmanaged(std.math.big.Limb),
44metadata_forward_references: std.ArrayListUnmanaged(Metadata),
45metadata_named: std.AutoArrayHashMapUnmanaged(MetadataString, struct {
46 len: u32,
47 index: Metadata.Item.ExtraIndex,
48}),
49
50metadata_string_map: std.AutoArrayHashMapUnmanaged(void, void),
51metadata_string_indices: std.ArrayListUnmanaged(u32),
52metadata_string_bytes: std.ArrayListUnmanaged(u8),
53
53pub const expected_args_len = 16;54pub const expected_args_len = 16;
54pub const expected_attrs_len = 16;55pub const expected_attrs_len = 16;
55pub const expected_fields_len = 32;56pub const expected_fields_len = 32;
56pub const expected_gep_indices_len = 8;57pub const expected_gep_indices_len = 8;
57pub const expected_cases_len = 8;58pub const expected_cases_len = 8;
58pub const expected_incoming_len = 8;59pub const expected_incoming_len = 8;
59pub const expected_intrinsic_name_len = 64;
6060
61pub const Options = struct {61pub const Options = struct {
62 allocator: Allocator,62 allocator: Allocator,
63 use_lib_llvm: bool = false,
64 strip: bool = true,63 strip: bool = true,
65 name: []const u8 = &.{},64 name: []const u8 = &.{},
66 target: std.Target = builtin.target,65 target: std.Target = builtin.target,
...@@ -77,11 +76,11 @@ pub const String = enum(u32) {...@@ -77,11 +76,11 @@ pub const String = enum(u32) {
77 return self.toIndex() == null;76 return self.toIndex() == null;
78 }77 }
7978
80 pub fn slice(self: String, b: *const Builder) ?[:0]const u8 {79 pub fn slice(self: String, builder: *const Builder) ?[]const u8 {
81 const index = self.toIndex() orelse return null;80 const index = self.toIndex() orelse return null;
82 const start = b.string_indices.items[index];81 const start = builder.string_indices.items[index];
83 const end = b.string_indices.items[index + 1];82 const end = builder.string_indices.items[index + 1];
84 return b.string_bytes.items[start .. end - 1 :0];83 return builder.string_bytes.items[start..end];
85 }84 }
8685
87 const FormatData = struct {86 const FormatData = struct {
...@@ -94,17 +93,21 @@ pub const String = enum(u32) {...@@ -94,17 +93,21 @@ pub const String = enum(u32) {
94 _: std.fmt.FormatOptions,93 _: std.fmt.FormatOptions,
95 writer: anytype,94 writer: anytype,
96 ) @TypeOf(writer).Error!void {95 ) @TypeOf(writer).Error!void {
97 if (comptime std.mem.indexOfNone(u8, fmt_str, "@\"")) |_|96 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
98 @compileError("invalid format string: '" ++ fmt_str ++ "'");97 @compileError("invalid format string: '" ++ fmt_str ++ "'");
99 assert(data.string != .none);98 assert(data.string != .none);
100 const sentinel_slice = data.string.slice(data.builder) orelse99 const string_slice = data.string.slice(data.builder) orelse
101 return writer.print("{d}", .{@intFromEnum(data.string)});100 return writer.print("{d}", .{@intFromEnum(data.string)});
102 try printEscapedString(sentinel_slice[0 .. sentinel_slice.len + comptime @intFromBool(101 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|
103 std.mem.indexOfScalar(u8, fmt_str, '@') != null,102 return writer.writeAll(string_slice);
104 )], if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|103 try printEscapedString(
105 .always_quote104 string_slice,
106 else105 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
107 .quote_unless_valid_identifier, writer);106 .always_quote
107 else
108 .quote_unless_valid_identifier,
109 writer,
110 );
108 }111 }
109 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {112 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {
110 return .{ .data = .{ .string = self, .builder = builder } };113 return .{ .data = .{ .string = self, .builder = builder } };
...@@ -130,6 +133,72 @@ pub const String = enum(u32) {...@@ -130,6 +133,72 @@ pub const String = enum(u32) {
130 };133 };
131};134};
132135
136pub const BinaryOpcode = enum(u4) {
137 add = 0,
138 sub = 1,
139 mul = 2,
140 udiv = 3,
141 sdiv = 4,
142 urem = 5,
143 srem = 6,
144 shl = 7,
145 lshr = 8,
146 ashr = 9,
147 @"and" = 10,
148 @"or" = 11,
149 xor = 12,
150};
151
152pub const CastOpcode = enum(u4) {
153 trunc = 0,
154 zext = 1,
155 sext = 2,
156 fptoui = 3,
157 fptosi = 4,
158 uitofp = 5,
159 sitofp = 6,
160 fptrunc = 7,
161 fpext = 8,
162 ptrtoint = 9,
163 inttoptr = 10,
164 bitcast = 11,
165 addrspacecast = 12,
166};
167
168pub const CmpPredicate = enum(u6) {
169 fcmp_false = 0,
170 fcmp_oeq = 1,
171 fcmp_ogt = 2,
172 fcmp_oge = 3,
173 fcmp_olt = 4,
174 fcmp_ole = 5,
175 fcmp_one = 6,
176 fcmp_ord = 7,
177 fcmp_uno = 8,
178 fcmp_ueq = 9,
179 fcmp_ugt = 10,
180 fcmp_uge = 11,
181 fcmp_ult = 12,
182 fcmp_ule = 13,
183 fcmp_une = 14,
184 fcmp_true = 15,
185 icmp_eq = 32,
186 icmp_ne = 33,
187 icmp_ugt = 34,
188 icmp_uge = 35,
189 icmp_ult = 36,
190 icmp_ule = 37,
191 icmp_sgt = 38,
192 icmp_sge = 39,
193 icmp_slt = 40,
194 icmp_sle = 41,
195};
196
197pub const StrtabString = struct {
198 offset: usize,
199 size: usize,
200};
201
133pub const Type = enum(u32) {202pub const Type = enum(u32) {
134 void,203 void,
135 half,204 half,
...@@ -178,20 +247,20 @@ pub const Type = enum(u32) {...@@ -178,20 +247,20 @@ pub const Type = enum(u32) {
178 named_structure,247 named_structure,
179 };248 };
180249
181 pub const Simple = enum {250 pub const Simple = enum(u5) {
182 void,251 void = 2,
183 half,252 half = 10,
184 bfloat,253 bfloat = 23,
185 float,254 float = 3,
186 double,255 double = 4,
187 fp128,256 fp128 = 14,
188 x86_fp80,257 x86_fp80 = 13,
189 ppc_fp128,258 ppc_fp128 = 15,
190 x86_amx,259 x86_amx = 24,
191 x86_mmx,260 x86_mmx = 17,
192 label,261 label = 5,
193 token,262 token = 22,
194 metadata,263 metadata = 16,
195 };264 };
196265
197 pub const Function = struct {266 pub const Function = struct {
...@@ -579,7 +648,6 @@ pub const Type = enum(u32) {...@@ -579,7 +648,6 @@ pub const Type = enum(u32) {
579 var visited: IsSizedVisited = .{};648 var visited: IsSizedVisited = .{};
580 defer visited.deinit(builder.gpa);649 defer visited.deinit(builder.gpa);
581 const result = try self.isSizedVisited(&visited, builder);650 const result = try self.isSizedVisited(&visited, builder);
582 if (builder.useLibLlvm()) assert(result == self.toLlvm(builder).isSized().toBool());
583 return result;651 return result;
584 }652 }
585653
...@@ -766,11 +834,6 @@ pub const Type = enum(u32) {...@@ -766,11 +834,6 @@ pub const Type = enum(u32) {
766 return .{ .data = .{ .type = self, .builder = builder } };834 return .{ .data = .{ .type = self, .builder = builder } };
767 }835 }
768836
769 pub fn toLlvm(self: Type, builder: *const Builder) *llvm.Type {
770 assert(builder.useLibLlvm());
771 return builder.llvm.types.items[@intFromEnum(self)];
772 }
773
774 const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void);837 const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void);
775 fn isSizedVisited(838 fn isSizedVisited(
776 self: Type,839 self: Type,
...@@ -1051,14 +1114,21 @@ pub const Attribute = union(Kind) {...@@ -1051,14 +1114,21 @@ pub const Attribute = union(Kind) {
1051 .no_sanitize_hwaddress,1114 .no_sanitize_hwaddress,
1052 .sanitize_address_dyninit,1115 .sanitize_address_dyninit,
1053 => |kind| {1116 => |kind| {
1054 const field = @typeInfo(Attribute).Union.fields[@intFromEnum(kind)];1117 const field = comptime blk: {
1118 @setEvalBranchQuota(10_000);
1119 for (@typeInfo(Attribute).Union.fields) |field| {
1120 if (std.mem.eql(u8, field.name, @tagName(kind))) break :blk field;
1121 }
1122 unreachable;
1123 };
1055 comptime assert(std.mem.eql(u8, @tagName(kind), field.name));1124 comptime assert(std.mem.eql(u8, @tagName(kind), field.name));
1056 return @unionInit(Attribute, field.name, switch (field.type) {1125 return @unionInit(Attribute, field.name, switch (field.type) {
1057 void => {},1126 void => {},
1058 u32 => storage.value,1127 u32 => storage.value,
1059 Alignment, String, Type, UwTable => @enumFromInt(storage.value),1128 Alignment, String, Type, UwTable => @enumFromInt(storage.value),
1060 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value),1129 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value),
1061 else => @compileError("bad payload type: " ++ @typeName(field.type)),1130 else => @compileError("bad payload type: " ++ field.name ++ ": " ++
1131 @typeName(field.type)),
1062 });1132 });
1063 },1133 },
1064 .string, .none => unreachable,1134 .string, .none => unreachable,
...@@ -1246,109 +1316,104 @@ pub const Attribute = union(Kind) {...@@ -1246,109 +1316,104 @@ pub const Attribute = union(Kind) {
1246 fn toStorage(self: Index, builder: *const Builder) Storage {1316 fn toStorage(self: Index, builder: *const Builder) Storage {
1247 return builder.attributes.keys()[@intFromEnum(self)];1317 return builder.attributes.keys()[@intFromEnum(self)];
1248 }1318 }
1249
1250 fn toLlvm(self: Index, builder: *const Builder) *llvm.Attribute {
1251 assert(builder.useLibLlvm());
1252 return builder.llvm.attributes.items[@intFromEnum(self)];
1253 }
1254 };1319 };
12551320
1256 pub const Kind = enum(u32) {1321 pub const Kind = enum(u32) {
1257 // Parameter Attributes1322 // Parameter Attributes
1258 zeroext,1323 zeroext = 34,
1259 signext,1324 signext = 24,
1260 inreg,1325 inreg = 5,
1261 byval,1326 byval = 3,
1262 byref,1327 byref = 69,
1263 preallocated,1328 preallocated = 65,
1264 inalloca,1329 inalloca = 38,
1265 sret,1330 sret = 29, // TODO: ?
1266 elementtype,1331 elementtype = 77,
1267 @"align",1332 @"align" = 1,
1268 @"noalias",1333 @"noalias" = 9,
1269 nocapture,1334 nocapture = 11,
1270 nofree,1335 nofree = 62,
1271 nest,1336 nest = 8,
1272 returned,1337 returned = 22,
1273 nonnull,1338 nonnull = 39,
1274 dereferenceable,1339 dereferenceable = 41,
1275 dereferenceable_or_null,1340 dereferenceable_or_null = 42,
1276 swiftself,1341 swiftself = 46,
1277 swiftasync,1342 swiftasync = 75,
1278 swifterror,1343 swifterror = 47,
1279 immarg,1344 immarg = 60,
1280 noundef,1345 noundef = 68,
1281 nofpclass,1346 nofpclass = 87,
1282 alignstack,1347 alignstack = 25,
1283 allocalign,1348 allocalign = 80,
1284 allocptr,1349 allocptr = 81,
1285 readnone,1350 readnone = 20,
1286 readonly,1351 readonly = 21,
1287 writeonly,1352 writeonly = 52,
12881353
1289 // Function Attributes1354 // Function Attributes
1290 //alignstack,1355 //alignstack,
1291 allockind,1356 allockind = 82,
1292 allocsize,1357 allocsize = 51,
1293 alwaysinline,1358 alwaysinline = 2,
1294 builtin,1359 builtin = 35,
1295 cold,1360 cold = 36,
1296 convergent,1361 convergent = 43,
1297 disable_sanitizer_information,1362 disable_sanitizer_information = 78,
1298 fn_ret_thunk_extern,1363 fn_ret_thunk_extern = 84,
1299 hot,1364 hot = 72,
1300 inlinehint,1365 inlinehint = 4,
1301 jumptable,1366 jumptable = 40,
1302 memory,1367 memory = 86,
1303 minsize,1368 minsize = 6,
1304 naked,1369 naked = 7,
1305 nobuiltin,1370 nobuiltin = 10,
1306 nocallback,1371 nocallback = 71,
1307 noduplicate,1372 noduplicate = 12,
1308 //nofree,1373 //nofree,
1309 noimplicitfloat,1374 noimplicitfloat = 13,
1310 @"noinline",1375 @"noinline" = 14,
1311 nomerge,1376 nomerge = 66,
1312 nonlazybind,1377 nonlazybind = 15,
1313 noprofile,1378 noprofile = 73,
1314 skipprofile,1379 skipprofile = 85,
1315 noredzone,1380 noredzone = 16,
1316 noreturn,1381 noreturn = 17,
1317 norecurse,1382 norecurse = 48,
1318 willreturn,1383 willreturn = 61,
1319 nosync,1384 nosync = 63,
1320 nounwind,1385 nounwind = 18,
1321 nosanitize_bounds,1386 nosanitize_bounds = 79,
1322 nosanitize_coverage,1387 nosanitize_coverage = 76,
1323 null_pointer_is_valid,1388 null_pointer_is_valid = 67,
1324 optforfuzzing,1389 optforfuzzing = 57,
1325 optnone,1390 optnone = 37,
1326 optsize,1391 optsize = 19,
1327 //preallocated,1392 //preallocated,
1328 returns_twice,1393 returns_twice = 23,
1329 safestack,1394 safestack = 44,
1330 sanitize_address,1395 sanitize_address = 30,
1331 sanitize_memory,1396 sanitize_memory = 32,
1332 sanitize_thread,1397 sanitize_thread = 31,
1333 sanitize_hwaddress,1398 sanitize_hwaddress = 55,
1334 sanitize_memtag,1399 sanitize_memtag = 64,
1335 speculative_load_hardening,1400 speculative_load_hardening = 59,
1336 speculatable,1401 speculatable = 53,
1337 ssp,1402 ssp = 26,
1338 sspstrong,1403 sspstrong = 28,
1339 sspreq,1404 sspreq = 27,
1340 strictfp,1405 strictfp = 54,
1341 uwtable,1406 uwtable = 33,
1342 nocf_check,1407 nocf_check = 56,
1343 shadowcallstack,1408 shadowcallstack = 58,
1344 mustprogress,1409 mustprogress = 70,
1345 vscale_range,1410 vscale_range = 74,
13461411
1347 // Global Attributes1412 // Global Attributes
1348 no_sanitize_address,1413 no_sanitize_address = 100,
1349 no_sanitize_hwaddress,1414 no_sanitize_hwaddress = 101,
1350 //sanitize_memtag,1415 //sanitize_memtag,
1351 sanitize_address_dyninit,1416 sanitize_address_dyninit = 102,
13521417
1353 string = std.math.maxInt(u31),1418 string = std.math.maxInt(u31),
1354 none = std.math.maxInt(u32),1419 none = std.math.maxInt(u32),
...@@ -1368,11 +1433,6 @@ pub const Attribute = union(Kind) {...@@ -1368,11 +1433,6 @@ pub const Attribute = union(Kind) {
1368 const str: String = @enumFromInt(@intFromEnum(self));1433 const str: String = @enumFromInt(@intFromEnum(self));
1369 return if (str.isAnon()) null else str;1434 return if (str.isAnon()) null else str;
1370 }1435 }
1371
1372 fn toLlvm(self: Kind, builder: *const Builder) *c_uint {
1373 assert(builder.useLibLlvm());
1374 return &builder.llvm.attribute_kind_ids.?[@intFromEnum(self)];
1375 }
1376 };1436 };
13771437
1378 pub const FpClass = packed struct(u32) {1438 pub const FpClass = packed struct(u32) {
...@@ -1494,12 +1554,12 @@ pub const Attribute = union(Kind) {...@@ -1494,12 +1554,12 @@ pub const Attribute = union(Kind) {
14941554
1495 fn toStorage(self: Attribute) Storage {1555 fn toStorage(self: Attribute) Storage {
1496 return switch (self) {1556 return switch (self) {
1497 inline else => |value| .{ .kind = @as(Kind, self), .value = switch (@TypeOf(value)) {1557 inline else => |value, tag| .{ .kind = @as(Kind, self), .value = switch (@TypeOf(value)) {
1498 void => 0,1558 void => 0,
1499 u32 => value,1559 u32 => value,
1500 Alignment, String, Type, UwTable => @intFromEnum(value),1560 Alignment, String, Type, UwTable => @intFromEnum(value),
1501 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value),1561 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value),
1502 else => @compileError("bad payload type: " ++ @typeName(@TypeOf(value))),1562 else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))),
1503 } },1563 } },
1504 .string => |string_attr| .{1564 .string => |string_attr| .{
1505 .kind = Kind.fromString(string_attr.kind),1565 .kind = Kind.fromString(string_attr.kind),
...@@ -1709,18 +1769,18 @@ pub const FunctionAttributes = enum(u32) {...@@ -1709,18 +1769,18 @@ pub const FunctionAttributes = enum(u32) {
1709 }1769 }
1710};1770};
17111771
1712pub const Linkage = enum {1772pub const Linkage = enum(u4) {
1713 private,1773 private = 9,
1714 internal,1774 internal = 3,
1715 weak,1775 weak = 1,
1716 weak_odr,1776 weak_odr = 10,
1717 linkonce,1777 linkonce = 4,
1718 linkonce_odr,1778 linkonce_odr = 11,
1719 available_externally,1779 available_externally = 12,
1720 appending,1780 appending = 2,
1721 common,1781 common = 8,
1722 extern_weak,1782 extern_weak = 7,
1723 external,1783 external = 0,
17241784
1725 pub fn format(1785 pub fn format(
1726 self: Linkage,1786 self: Linkage,
...@@ -1731,20 +1791,16 @@ pub const Linkage = enum {...@@ -1731,20 +1791,16 @@ pub const Linkage = enum {
1731 if (self != .external) try writer.print(" {s}", .{@tagName(self)});1791 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
1732 }1792 }
17331793
1734 fn toLlvm(self: Linkage) llvm.Linkage {1794 fn formatOptional(
1735 return switch (self) {1795 data: ?Linkage,
1736 .private => .Private,1796 comptime _: []const u8,
1737 .internal => .Internal,1797 _: std.fmt.FormatOptions,
1738 .weak => .WeakAny,1798 writer: anytype,
1739 .weak_odr => .WeakODR,1799 ) @TypeOf(writer).Error!void {
1740 .linkonce => .LinkOnceAny,1800 if (data) |linkage| try writer.print(" {s}", .{@tagName(linkage)});
1741 .linkonce_odr => .LinkOnceODR,1801 }
1742 .available_externally => .AvailableExternally,1802 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) {
1743 .appending => .Appending,1803 return .{ .data = self };
1744 .common => .Common,
1745 .extern_weak => .ExternalWeak,
1746 .external => .External,
1747 };
1748 }1804 }
1749};1805};
17501806
...@@ -1763,10 +1819,10 @@ pub const Preemption = enum {...@@ -1763,10 +1819,10 @@ pub const Preemption = enum {
1763 }1819 }
1764};1820};
17651821
1766pub const Visibility = enum {1822pub const Visibility = enum(u2) {
1767 default,1823 default = 0,
1768 hidden,1824 hidden = 1,
1769 protected,1825 protected = 2,
17701826
1771 pub fn format(1827 pub fn format(
1772 self: Visibility,1828 self: Visibility,
...@@ -1776,20 +1832,12 @@ pub const Visibility = enum {...@@ -1776,20 +1832,12 @@ pub const Visibility = enum {
1776 ) @TypeOf(writer).Error!void {1832 ) @TypeOf(writer).Error!void {
1777 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1833 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1778 }1834 }
1779
1780 fn toLlvm(self: Visibility) llvm.Visibility {
1781 return switch (self) {
1782 .default => .Default,
1783 .hidden => .Hidden,
1784 .protected => .Protected,
1785 };
1786 }
1787};1835};
17881836
1789pub const DllStorageClass = enum {1837pub const DllStorageClass = enum(u2) {
1790 default,1838 default = 0,
1791 dllimport,1839 dllimport = 1,
1792 dllexport,1840 dllexport = 2,
17931841
1794 pub fn format(1842 pub fn format(
1795 self: DllStorageClass,1843 self: DllStorageClass,
...@@ -1799,22 +1847,14 @@ pub const DllStorageClass = enum {...@@ -1799,22 +1847,14 @@ pub const DllStorageClass = enum {
1799 ) @TypeOf(writer).Error!void {1847 ) @TypeOf(writer).Error!void {
1800 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1848 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1801 }1849 }
1802
1803 fn toLlvm(self: DllStorageClass) llvm.DLLStorageClass {
1804 return switch (self) {
1805 .default => .Default,
1806 .dllimport => .DLLImport,
1807 .dllexport => .DLLExport,
1808 };
1809 }
1810};1850};
18111851
1812pub const ThreadLocal = enum {1852pub const ThreadLocal = enum(u3) {
1813 default,1853 default = 0,
1814 generaldynamic,1854 generaldynamic = 1,
1815 localdynamic,1855 localdynamic = 2,
1816 initialexec,1856 initialexec = 3,
1817 localexec,1857 localexec = 4,
18181858
1819 pub fn format(1859 pub fn format(
1820 self: ThreadLocal,1860 self: ThreadLocal,
...@@ -1826,24 +1866,14 @@ pub const ThreadLocal = enum {...@@ -1826,24 +1866,14 @@ pub const ThreadLocal = enum {
1826 try writer.print("{s}thread_local", .{prefix});1866 try writer.print("{s}thread_local", .{prefix});
1827 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});1867 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});
1828 }1868 }
1829
1830 fn toLlvm(self: ThreadLocal) llvm.ThreadLocalMode {
1831 return switch (self) {
1832 .default => .NotThreadLocal,
1833 .generaldynamic => .GeneralDynamicTLSModel,
1834 .localdynamic => .LocalDynamicTLSModel,
1835 .initialexec => .InitialExecTLSModel,
1836 .localexec => .LocalExecTLSModel,
1837 };
1838 }
1839};1869};
18401870
1841pub const Mutability = enum { global, constant };1871pub const Mutability = enum { global, constant };
18421872
1843pub const UnnamedAddr = enum {1873pub const UnnamedAddr = enum(u2) {
1844 default,1874 default = 0,
1845 unnamed_addr,1875 unnamed_addr = 1,
1846 local_unnamed_addr,1876 local_unnamed_addr = 2,
18471877
1848 pub fn format(1878 pub fn format(
1849 self: UnnamedAddr,1879 self: UnnamedAddr,
...@@ -1971,6 +2001,10 @@ pub const Alignment = enum(u6) {...@@ -1971,6 +2001,10 @@ pub const Alignment = enum(u6) {
1971 return if (self == .default) null else @as(u64, 1) << @intFromEnum(self);2001 return if (self == .default) null else @as(u64, 1) << @intFromEnum(self);
1972 }2002 }
19732003
2004 pub fn toLlvm(self: Alignment) u6 {
2005 return if (self == .default) 0 else (@intFromEnum(self) + 1);
2006 }
2007
1974 pub fn format(2008 pub fn format(
1975 self: Alignment,2009 self: Alignment,
1976 comptime prefix: []const u8,2010 comptime prefix: []const u8,
...@@ -2100,11 +2134,6 @@ pub const CallConv = enum(u10) {...@@ -2100,11 +2134,6 @@ pub const CallConv = enum(u10) {
2100 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),2134 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),
2101 }2135 }
2102 }2136 }
2103
2104 fn toLlvm(self: CallConv) llvm.CallConv {
2105 // These enum values appear in LLVM IR, and so are guaranteed to be stable.
2106 return @enumFromInt(@intFromEnum(self));
2107 }
2108};2137};
21092138
2110pub const Global = struct {2139pub const Global = struct {
...@@ -2117,6 +2146,7 @@ pub const Global = struct {...@@ -2117,6 +2146,7 @@ pub const Global = struct {
2117 externally_initialized: ExternallyInitialized = .default,2146 externally_initialized: ExternallyInitialized = .default,
2118 type: Type,2147 type: Type,
2119 partition: String = .none,2148 partition: String = .none,
2149 dbg: Metadata = .none,
2120 kind: union(enum) {2150 kind: union(enum) {
2121 alias: Alias.Index,2151 alias: Alias.Index,
2122 variable: Variable.Index,2152 variable: Variable.Index,
...@@ -2153,6 +2183,18 @@ pub const Global = struct {...@@ -2153,6 +2183,18 @@ pub const Global = struct {
2153 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];2183 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2154 }2184 }
21552185
2186 pub fn strtab(self: Index, builder: *const Builder) StrtabString {
2187 const name_index = self.name(builder).toIndex() orelse return .{
2188 .offset = 0,
2189 .size = 0,
2190 };
2191
2192 return .{
2193 .offset = builder.string_indices.items[name_index],
2194 .size = builder.string_indices.items[name_index + 1] - builder.string_indices.items[name_index],
2195 };
2196 }
2197
2156 pub fn typeOf(self: Index, builder: *const Builder) Type {2198 pub fn typeOf(self: Index, builder: *const Builder) Type {
2157 return self.ptrConst(builder).type;2199 return self.ptrConst(builder).type;
2158 }2200 }
...@@ -2162,32 +2204,25 @@ pub const Global = struct {...@@ -2162,32 +2204,25 @@ pub const Global = struct {
2162 }2204 }
21632205
2164 pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void {2206 pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void {
2165 if (builder.useLibLlvm()) self.toLlvm(builder).setLinkage(linkage.toLlvm());
2166 self.ptr(builder).linkage = linkage;2207 self.ptr(builder).linkage = linkage;
2167 self.updateDsoLocal(builder);2208 self.updateDsoLocal(builder);
2168 }2209 }
21692210
2170 pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void {2211 pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void {
2171 if (builder.useLibLlvm()) self.toLlvm(builder).setVisibility(visibility.toLlvm());
2172 self.ptr(builder).visibility = visibility;2212 self.ptr(builder).visibility = visibility;
2173 self.updateDsoLocal(builder);2213 self.updateDsoLocal(builder);
2174 }2214 }
21752215
2176 pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void {2216 pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void {
2177 if (builder.useLibLlvm()) self.toLlvm(builder).setDLLStorageClass(class.toLlvm());
2178 self.ptr(builder).dll_storage_class = class;2217 self.ptr(builder).dll_storage_class = class;
2179 }2218 }
21802219
2181 pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void {2220 pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void {
2182 if (builder.useLibLlvm()) self.toLlvm(builder).setUnnamedAddr(
2183 llvm.Bool.fromBool(unnamed_addr != .default),
2184 );
2185 self.ptr(builder).unnamed_addr = unnamed_addr;2221 self.ptr(builder).unnamed_addr = unnamed_addr;
2186 }2222 }
21872223
2188 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {2224 pub fn setDebugMetadata(self: Index, dbg: Metadata, builder: *Builder) void {
2189 assert(builder.useLibLlvm());2225 self.ptr(builder).dbg = dbg;
2190 return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))];
2191 }2226 }
21922227
2193 const FormatData = struct {2228 const FormatData = struct {
...@@ -2220,13 +2255,10 @@ pub const Global = struct {...@@ -2220,13 +2255,10 @@ pub const Global = struct {
22202255
2221 pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {2256 pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
2222 try builder.ensureUnusedGlobalCapacity(.empty);2257 try builder.ensureUnusedGlobalCapacity(.empty);
2223 if (builder.useLibLlvm())
2224 try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1);
2225 self.replaceAssumeCapacity(other, builder);2258 self.replaceAssumeCapacity(other, builder);
2226 }2259 }
22272260
2228 pub fn delete(self: Index, builder: *Builder) void {2261 pub fn delete(self: Index, builder: *Builder) void {
2229 if (builder.useLibLlvm()) self.toLlvm(builder).eraseGlobalValue();
2230 self.ptr(builder).kind = .{ .replaced = .none };2262 self.ptr(builder).kind = .{ .replaced = .none };
2231 }2263 }
22322264
...@@ -2254,12 +2286,8 @@ pub const Global = struct {...@@ -2254,12 +2286,8 @@ pub const Global = struct {
2254 const old_name = self.name(builder);2286 const old_name = self.name(builder);
2255 if (new_name == old_name) return;2287 if (new_name == old_name) return;
2256 const index = @intFromEnum(self.unwrap(builder));2288 const index = @intFromEnum(self.unwrap(builder));
2257 if (builder.useLibLlvm())
2258 builder.llvm.globals.appendAssumeCapacity(builder.llvm.globals.items[index]);
2259 _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);2289 _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);
2260 if (builder.useLibLlvm()) _ = builder.llvm.globals.pop();
2261 builder.globals.swapRemoveAt(index);2290 builder.globals.swapRemoveAt(index);
2262 self.updateName(builder);
2263 if (!old_name.isAnon()) return;2291 if (!old_name.isAnon()) return;
2264 builder.next_unnamed_global = @enumFromInt(@intFromEnum(builder.next_unnamed_global) - 1);2292 builder.next_unnamed_global = @enumFromInt(@intFromEnum(builder.next_unnamed_global) - 1);
2265 if (builder.next_unnamed_global == old_name) return;2293 if (builder.next_unnamed_global == old_name) return;
...@@ -2272,23 +2300,10 @@ pub const Global = struct {...@@ -2272,23 +2300,10 @@ pub const Global = struct {
2272 self.renameAssumeCapacity(other_name, builder);2300 self.renameAssumeCapacity(other_name, builder);
2273 }2301 }
22742302
2275 fn updateName(self: Index, builder: *const Builder) void {
2276 if (!builder.useLibLlvm()) return;
2277 const index = @intFromEnum(self.unwrap(builder));
2278 const name_slice = self.name(builder).slice(builder) orelse "";
2279 builder.llvm.globals.items[index].setValueName(name_slice.ptr, name_slice.len);
2280 }
2281
2282 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {2303 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
2283 if (self.eql(other, builder)) return;2304 if (self.eql(other, builder)) return;
2284 builder.next_replaced_global = @enumFromInt(@intFromEnum(builder.next_replaced_global) - 1);2305 builder.next_replaced_global = @enumFromInt(@intFromEnum(builder.next_replaced_global) - 1);
2285 self.renameAssumeCapacity(builder.next_replaced_global, builder);2306 self.renameAssumeCapacity(builder.next_replaced_global, builder);
2286 if (builder.useLibLlvm()) {
2287 const self_llvm = self.toLlvm(builder);
2288 self_llvm.replaceAllUsesWith(other.toLlvm(builder));
2289 self_llvm.removeGlobalValue();
2290 builder.llvm.replacements.putAssumeCapacityNoClobber(self_llvm, other);
2291 }
2292 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };2307 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
2293 }2308 }
22942309
...@@ -2345,13 +2360,8 @@ pub const Alias = struct {...@@ -2345,13 +2360,8 @@ pub const Alias = struct {
2345 }2360 }
23462361
2347 pub fn setAliasee(self: Index, aliasee: Constant, builder: *Builder) void {2362 pub fn setAliasee(self: Index, aliasee: Constant, builder: *Builder) void {
2348 if (builder.useLibLlvm()) self.toLlvm(builder).setAliasee(aliasee.toLlvm(builder));
2349 self.ptr(builder).aliasee = aliasee;2363 self.ptr(builder).aliasee = aliasee;
2350 }2364 }
2351
2352 fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2353 return self.ptrConst(builder).global.toLlvm(builder);
2354 }
2355 };2365 };
2356};2366};
23572367
...@@ -2404,14 +2414,10 @@ pub const Variable = struct {...@@ -2404,14 +2414,10 @@ pub const Variable = struct {
2404 }2414 }
24052415
2406 pub fn setThreadLocal(self: Index, thread_local: ThreadLocal, builder: *Builder) void {2416 pub fn setThreadLocal(self: Index, thread_local: ThreadLocal, builder: *Builder) void {
2407 if (builder.useLibLlvm()) self.toLlvm(builder).setThreadLocalMode(thread_local.toLlvm());
2408 self.ptr(builder).thread_local = thread_local;2417 self.ptr(builder).thread_local = thread_local;
2409 }2418 }
24102419
2411 pub fn setMutability(self: Index, mutability: Mutability, builder: *Builder) void {2420 pub fn setMutability(self: Index, mutability: Mutability, builder: *Builder) void {
2412 if (builder.useLibLlvm()) self.toLlvm(builder).setGlobalConstant(
2413 llvm.Bool.fromBool(mutability == .constant),
2414 );
2415 self.ptr(builder).mutability = mutability;2421 self.ptr(builder).mutability = mutability;
2416 }2422 }
24172423
...@@ -2424,67 +2430,25 @@ pub const Variable = struct {...@@ -2424,67 +2430,25 @@ pub const Variable = struct {
2424 const variable = self.ptrConst(builder);2430 const variable = self.ptrConst(builder);
2425 const global = variable.global.ptr(builder);2431 const global = variable.global.ptr(builder);
2426 const initializer_type = initializer.typeOf(builder);2432 const initializer_type = initializer.typeOf(builder);
2427 if (builder.useLibLlvm() and global.type != initializer_type) {
2428 try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1);
2429 // LLVM does not allow us to change the type of globals. So we must
2430 // create a new global with the correct type, copy all its attributes,
2431 // and then update all references to point to the new global,
2432 // delete the original, and rename the new one to the old one's name.
2433 // This is necessary because LLVM does not support const bitcasting
2434 // a struct with padding bytes, which is needed to lower a const union value
2435 // to LLVM, when a field other than the most-aligned is active. Instead,
2436 // we must lower to an unnamed struct, and pointer cast at usage sites
2437 // of the global. Such an unnamed struct is the cause of the global type
2438 // mismatch, because we don't have the LLVM type until the *value* is created,
2439 // whereas the global needs to be created based on the type alone, because
2440 // lowering the value may reference the global as a pointer.
2441 // Related: https://github.com/ziglang/zig/issues/13265
2442 const old_global = &builder.llvm.globals.items[@intFromEnum(variable.global)];
2443 const new_global = builder.llvm.module.?.addGlobalInAddressSpace(
2444 initializer_type.toLlvm(builder),
2445 "",
2446 @intFromEnum(global.addr_space),
2447 );
2448 new_global.setLinkage(global.linkage.toLlvm());
2449 new_global.setUnnamedAddr(llvm.Bool.fromBool(global.unnamed_addr != .default));
2450 new_global.setAlignment(@intCast(variable.alignment.toByteUnits() orelse 0));
2451 if (variable.section != .none)
2452 new_global.setSection(variable.section.slice(builder).?);
2453 old_global.*.replaceAllUsesWith(new_global);
2454 builder.llvm.replacements.putAssumeCapacityNoClobber(old_global.*, variable.global);
2455 new_global.takeName(old_global.*);
2456 old_global.*.removeGlobalValue();
2457 old_global.* = new_global;
2458 self.ptr(builder).mutability = .global;
2459 }
2460 global.type = initializer_type;2433 global.type = initializer_type;
2461 }2434 }
2462 if (builder.useLibLlvm()) self.toLlvm(builder).setInitializer(switch (initializer) {
2463 .no_init => null,
2464 else => initializer.toLlvm(builder),
2465 });
2466 self.ptr(builder).init = initializer;2435 self.ptr(builder).init = initializer;
2467 }2436 }
24682437
2469 pub fn setSection(self: Index, section: String, builder: *Builder) void {2438 pub fn setSection(self: Index, section: String, builder: *Builder) void {
2470 if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?);
2471 self.ptr(builder).section = section;2439 self.ptr(builder).section = section;
2472 }2440 }
24732441
2474 pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void {2442 pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void {
2475 if (builder.useLibLlvm())
2476 self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0));
2477 self.ptr(builder).alignment = alignment;2443 self.ptr(builder).alignment = alignment;
2478 }2444 }
24792445
2480 pub fn getAlignment(self: Index, builder: *Builder) Alignment {2446 pub fn getAlignment(self: Index, builder: *Builder) Alignment {
2481 if (builder.useLibLlvm())
2482 return Alignment.fromByteUnits(self.toLlvm(builder).getAlignment());
2483 return self.ptr(builder).alignment;2447 return self.ptr(builder).alignment;
2484 }2448 }
24852449
2486 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {2450 pub fn setGlobalVariableExpression(self: Index, expression: Metadata, builder: *Builder) void {
2487 return self.ptrConst(builder).global.toLlvm(builder);2451 self.ptrConst(builder).global.setDebugMetadata(expression, builder);
2488 }2452 }
2489 };2453 };
2490};2454};
...@@ -2633,6 +2597,10 @@ pub const Intrinsic = enum {...@@ -2633,6 +2597,10 @@ pub const Intrinsic = enum {
2633 @"threadlocal.address",2597 @"threadlocal.address",
2634 vscale,2598 vscale,
26352599
2600 // Debug
2601 @"dbg.declare",
2602 @"dbg.value",
2603
2636 // AMDGPU2604 // AMDGPU
2637 @"amdgcn.workitem.id.x",2605 @"amdgcn.workitem.id.x",
2638 @"amdgcn.workitem.id.y",2606 @"amdgcn.workitem.id.y",
...@@ -3727,6 +3695,25 @@ pub const Intrinsic = enum {...@@ -3727,6 +3695,25 @@ pub const Intrinsic = enum {
3727 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3695 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3728 },3696 },
37293697
3698 .@"dbg.declare" = .{
3699 .ret_len = 0,
3700 .params = &.{
3701 .{ .kind = .{ .type = .metadata } },
3702 .{ .kind = .{ .type = .metadata } },
3703 .{ .kind = .{ .type = .metadata } },
3704 },
3705 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3706 },
3707 .@"dbg.value" = .{
3708 .ret_len = 0,
3709 .params = &.{
3710 .{ .kind = .{ .type = .metadata } },
3711 .{ .kind = .{ .type = .metadata } },
3712 .{ .kind = .{ .type = .metadata } },
3713 },
3714 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3715 },
3716
3730 .@"amdgcn.workitem.id.x" = .{3717 .@"amdgcn.workitem.id.x" = .{
3731 .ret_len = 1,3718 .ret_len = 1,
3732 .params = &.{3719 .params = &.{
...@@ -3809,7 +3796,9 @@ pub const Function = struct {...@@ -3809,7 +3796,9 @@ pub const Function = struct {
3809 blocks: []const Block = &.{},3796 blocks: []const Block = &.{},
3810 instructions: std.MultiArrayList(Instruction) = .{},3797 instructions: std.MultiArrayList(Instruction) = .{},
3811 names: [*]const String = &[0]String{},3798 names: [*]const String = &[0]String{},
3812 metadata: ?[*]const Metadata = null,3799 value_indices: [*]const u32 = &[0]u32{},
3800 debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, Metadata) = .{},
3801 debug_values: []const Instruction.Index = &.{},
3813 extra: []const u32 = &.{},3802 extra: []const u32 = &.{},
38143803
3815 pub const Index = enum(u32) {3804 pub const Index = enum(u32) {
...@@ -3853,7 +3842,6 @@ pub const Function = struct {...@@ -3853,7 +3842,6 @@ pub const Function = struct {
3853 }3842 }
38543843
3855 pub fn setCallConv(self: Index, call_conv: CallConv, builder: *Builder) void {3844 pub fn setCallConv(self: Index, call_conv: CallConv, builder: *Builder) void {
3856 if (builder.useLibLlvm()) self.toLlvm(builder).setFunctionCallConv(call_conv.toLlvm());
3857 self.ptr(builder).call_conv = call_conv;3845 self.ptr(builder).call_conv = call_conv;
3858 }3846 }
38593847
...@@ -3862,94 +3850,19 @@ pub const Function = struct {...@@ -3862,94 +3850,19 @@ pub const Function = struct {
3862 new_function_attributes: FunctionAttributes,3850 new_function_attributes: FunctionAttributes,
3863 builder: *Builder,3851 builder: *Builder,
3864 ) void {3852 ) void {
3865 if (builder.useLibLlvm()) {
3866 const llvm_function = self.toLlvm(builder);
3867 const old_function_attributes = self.ptrConst(builder).attributes;
3868 for (0..@max(
3869 old_function_attributes.slice(builder).len,
3870 new_function_attributes.slice(builder).len,
3871 )) |function_attribute_index| {
3872 const llvm_attribute_index =
3873 @as(llvm.AttributeIndex, @intCast(function_attribute_index)) -% 1;
3874 const old_attributes_slice =
3875 old_function_attributes.get(function_attribute_index, builder).slice(builder);
3876 const new_attributes_slice =
3877 new_function_attributes.get(function_attribute_index, builder).slice(builder);
3878 var old_attribute_index: usize = 0;
3879 var new_attribute_index: usize = 0;
3880 while (true) {
3881 const old_attribute_kind = if (old_attribute_index < old_attributes_slice.len)
3882 old_attributes_slice[old_attribute_index].getKind(builder)
3883 else
3884 .none;
3885 const new_attribute_kind = if (new_attribute_index < new_attributes_slice.len)
3886 new_attributes_slice[new_attribute_index].getKind(builder)
3887 else
3888 .none;
3889 switch (std.math.order(
3890 @intFromEnum(old_attribute_kind),
3891 @intFromEnum(new_attribute_kind),
3892 )) {
3893 .lt => {
3894 // Removed
3895 if (old_attribute_kind.toString()) |attribute_name| {
3896 const attribute_name_slice = attribute_name.slice(builder).?;
3897 llvm_function.removeStringAttributeAtIndex(
3898 llvm_attribute_index,
3899 attribute_name_slice.ptr,
3900 @intCast(attribute_name_slice.len),
3901 );
3902 } else {
3903 const llvm_kind_id = old_attribute_kind.toLlvm(builder).*;
3904 assert(llvm_kind_id != 0);
3905 llvm_function.removeEnumAttributeAtIndex(
3906 llvm_attribute_index,
3907 llvm_kind_id,
3908 );
3909 }
3910 old_attribute_index += 1;
3911 continue;
3912 },
3913 .eq => {
3914 // Iteration finished
3915 if (old_attribute_kind == .none) break;
3916 // No change
3917 if (old_attributes_slice[old_attribute_index] ==
3918 new_attributes_slice[new_attribute_index])
3919 {
3920 old_attribute_index += 1;
3921 new_attribute_index += 1;
3922 continue;
3923 }
3924 old_attribute_index += 1;
3925 },
3926 .gt => {},
3927 }
3928 // New or changed
3929 llvm_function.addAttributeAtIndex(
3930 llvm_attribute_index,
3931 new_attributes_slice[new_attribute_index].toLlvm(builder),
3932 );
3933 new_attribute_index += 1;
3934 }
3935 }
3936 }
3937 self.ptr(builder).attributes = new_function_attributes;3853 self.ptr(builder).attributes = new_function_attributes;
3938 }3854 }
39393855
3940 pub fn setSection(self: Index, section: String, builder: *Builder) void {3856 pub fn setSection(self: Index, section: String, builder: *Builder) void {
3941 if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?);
3942 self.ptr(builder).section = section;3857 self.ptr(builder).section = section;
3943 }3858 }
39443859
3945 pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void {3860 pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void {
3946 if (builder.useLibLlvm())
3947 self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0));
3948 self.ptr(builder).alignment = alignment;3861 self.ptr(builder).alignment = alignment;
3949 }3862 }
39503863
3951 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {3864 pub fn setSubprogram(self: Index, subprogram: Metadata, builder: *Builder) void {
3952 return self.ptrConst(builder).global.toLlvm(builder);3865 self.ptrConst(builder).global.setDebugMetadata(subprogram, builder);
3953 }3866 }
3954 };3867 };
39553868
...@@ -4098,6 +4011,143 @@ pub const Function = struct {...@@ -4098,6 +4011,143 @@ pub const Function = struct {
4098 va_arg,4011 va_arg,
4099 xor,4012 xor,
4100 zext,4013 zext,
4014
4015 pub fn toBinaryOpcode(self: Tag) BinaryOpcode {
4016 return switch (self) {
4017 .add,
4018 .@"add nsw",
4019 .@"add nuw",
4020 .@"add nuw nsw",
4021 .fadd,
4022 .@"fadd fast",
4023 => .add,
4024 .sub,
4025 .@"sub nsw",
4026 .@"sub nuw",
4027 .@"sub nuw nsw",
4028 .fsub,
4029 .@"fsub fast",
4030 => .sub,
4031 .sdiv,
4032 .@"sdiv exact",
4033 .fdiv,
4034 .@"fdiv fast",
4035 => .sdiv,
4036 .fmul,
4037 .@"fmul fast",
4038 .mul,
4039 .@"mul nsw",
4040 .@"mul nuw",
4041 .@"mul nuw nsw",
4042 => .mul,
4043 .srem,
4044 .frem,
4045 .@"frem fast",
4046 => .srem,
4047 .udiv,
4048 .@"udiv exact",
4049 => .udiv,
4050 .shl,
4051 .@"shl nsw",
4052 .@"shl nuw",
4053 .@"shl nuw nsw",
4054 => .shl,
4055 .lshr,
4056 .@"lshr exact",
4057 => .lshr,
4058 .ashr,
4059 .@"ashr exact",
4060 => .ashr,
4061 .@"and" => .@"and",
4062 .@"or" => .@"or",
4063 .xor => .xor,
4064 .urem => .urem,
4065 else => unreachable,
4066 };
4067 }
4068
4069 pub fn toCastOpcode(self: Tag) CastOpcode {
4070 return switch (self) {
4071 .trunc => .trunc,
4072 .zext => .zext,
4073 .sext => .sext,
4074 .fptoui => .fptoui,
4075 .fptosi => .fptosi,
4076 .uitofp => .uitofp,
4077 .sitofp => .sitofp,
4078 .fptrunc => .fptrunc,
4079 .fpext => .fpext,
4080 .ptrtoint => .ptrtoint,
4081 .inttoptr => .inttoptr,
4082 .bitcast => .bitcast,
4083 .addrspacecast => .addrspacecast,
4084 else => unreachable,
4085 };
4086 }
4087
4088 pub fn toCmpPredicate(self: Tag) CmpPredicate {
4089 return switch (self) {
4090 .@"fcmp false",
4091 .@"fcmp fast false",
4092 => .fcmp_false,
4093 .@"fcmp oeq",
4094 .@"fcmp fast oeq",
4095 => .fcmp_oeq,
4096 .@"fcmp oge",
4097 .@"fcmp fast oge",
4098 => .fcmp_oge,
4099 .@"fcmp ogt",
4100 .@"fcmp fast ogt",
4101 => .fcmp_ogt,
4102 .@"fcmp ole",
4103 .@"fcmp fast ole",
4104 => .fcmp_ole,
4105 .@"fcmp olt",
4106 .@"fcmp fast olt",
4107 => .fcmp_olt,
4108 .@"fcmp one",
4109 .@"fcmp fast one",
4110 => .fcmp_one,
4111 .@"fcmp ord",
4112 .@"fcmp fast ord",
4113 => .fcmp_ord,
4114 .@"fcmp true",
4115 .@"fcmp fast true",
4116 => .fcmp_true,
4117 .@"fcmp ueq",
4118 .@"fcmp fast ueq",
4119 => .fcmp_ueq,
4120 .@"fcmp uge",
4121 .@"fcmp fast uge",
4122 => .fcmp_uge,
4123 .@"fcmp ugt",
4124 .@"fcmp fast ugt",
4125 => .fcmp_ugt,
4126 .@"fcmp ule",
4127 .@"fcmp fast ule",
4128 => .fcmp_ule,
4129 .@"fcmp ult",
4130 .@"fcmp fast ult",
4131 => .fcmp_ult,
4132 .@"fcmp une",
4133 .@"fcmp fast une",
4134 => .fcmp_une,
4135 .@"fcmp uno",
4136 .@"fcmp fast uno",
4137 => .fcmp_uno,
4138 .@"icmp eq" => .icmp_eq,
4139 .@"icmp ne" => .icmp_ne,
4140 .@"icmp sge" => .icmp_sge,
4141 .@"icmp sgt" => .icmp_sgt,
4142 .@"icmp sle" => .icmp_sle,
4143 .@"icmp slt" => .icmp_slt,
4144 .@"icmp uge" => .icmp_uge,
4145 .@"icmp ugt" => .icmp_ugt,
4146 .@"icmp ule" => .icmp_ule,
4147 .@"icmp ult" => .icmp_ult,
4148 else => unreachable,
4149 };
4150 }
4101 };4151 };
41024152
4103 pub const Index = enum(u32) {4153 pub const Index = enum(u32) {
...@@ -4108,6 +4158,10 @@ pub const Function = struct {...@@ -4108,6 +4158,10 @@ pub const Function = struct {
4108 return function.names[@intFromEnum(self)];4158 return function.names[@intFromEnum(self)];
4109 }4159 }
41104160
4161 pub fn valueIndex(self: Instruction.Index, function: *const Function) u32 {
4162 return function.value_indices[@intFromEnum(self)];
4163 }
4164
4111 pub fn toValue(self: Instruction.Index) Value {4165 pub fn toValue(self: Instruction.Index) Value {
4112 return @enumFromInt(@intFromEnum(self));4166 return @enumFromInt(@intFromEnum(self));
4113 }4167 }
...@@ -4136,6 +4190,7 @@ pub const Function = struct {...@@ -4136,6 +4190,7 @@ pub const Function = struct {
4136 .@"store atomic",4190 .@"store atomic",
4137 .@"switch",4191 .@"switch",
4138 .@"unreachable",4192 .@"unreachable",
4193 .block,
4139 => false,4194 => false,
4140 .call,4195 .call,
4141 .@"call fast",4196 .@"call fast",
...@@ -4240,7 +4295,7 @@ pub const Function = struct {...@@ -4240,7 +4295,7 @@ pub const Function = struct {
4240 => wip.builder.structTypeAssumeCapacity(.normal, &.{4295 => wip.builder.structTypeAssumeCapacity(.normal, &.{
4241 wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip),4296 wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip),
4242 .i1,4297 .i1,
4243 }) catch unreachable,4298 }),
4244 .extractelement => wip.extraData(ExtractElement, instruction.data)4299 .extractelement => wip.extraData(ExtractElement, instruction.data)
4245 .val.typeOfWip(wip).childType(wip.builder),4300 .val.typeOfWip(wip).childType(wip.builder),
4246 .extractvalue => {4301 .extractvalue => {
...@@ -4427,7 +4482,7 @@ pub const Function = struct {...@@ -4427,7 +4482,7 @@ pub const Function = struct {
4427 function.extraData(CmpXchg, instruction.data)4482 function.extraData(CmpXchg, instruction.data)
4428 .cmp.typeOf(function_index, builder),4483 .cmp.typeOf(function_index, builder),
4429 .i1,4484 .i1,
4430 }) catch unreachable,4485 }),
4431 .extractelement => function.extraData(ExtractElement, instruction.data)4486 .extractelement => function.extraData(ExtractElement, instruction.data)
4432 .val.typeOf(function_index, builder).childType(builder),4487 .val.typeOf(function_index, builder).childType(builder),
4433 .extractvalue => {4488 .extractvalue => {
...@@ -4557,20 +4612,6 @@ pub const Function = struct {...@@ -4557,20 +4612,6 @@ pub const Function = struct {
4557 ) std.fmt.Formatter(format) {4612 ) std.fmt.Formatter(format) {
4558 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };4613 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };
4559 }4614 }
4560
4561 fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {
4562 assert(wip.builder.useLibLlvm());
4563 const llvm_value = wip.llvm.instructions.items[@intFromEnum(self)];
4564 const global = wip.builder.llvm.replacements.get(llvm_value) orelse return llvm_value;
4565 return global.toLlvm(wip.builder);
4566 }
4567
4568 fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 {
4569 return if (wip.builder.strip)
4570 ""
4571 else
4572 wip.names.items[@intFromEnum(self)].slice(wip.builder).?;
4573 }
4574 };4615 };
45754616
4576 pub const ExtraIndex = u32;4617 pub const ExtraIndex = u32;
...@@ -4664,43 +4705,22 @@ pub const Function = struct {...@@ -4664,43 +4705,22 @@ pub const Function = struct {
4664 val: Value,4705 val: Value,
46654706
4666 pub const Operation = enum(u5) {4707 pub const Operation = enum(u5) {
4667 xchg,4708 xchg = 0,
4668 add,4709 add = 1,
4669 sub,4710 sub = 2,
4670 @"and",4711 @"and" = 3,
4671 nand,4712 nand = 4,
4672 @"or",4713 @"or" = 5,
4673 xor,4714 xor = 6,
4674 max,4715 max = 7,
4675 min,4716 min = 8,
4676 umax,4717 umax = 9,
4677 umin,4718 umin = 10,
4678 fadd,4719 fadd = 11,
4679 fsub,4720 fsub = 12,
4680 fmax,4721 fmax = 13,
4681 fmin,4722 fmin = 14,
4682 none = std.math.maxInt(u5),4723 none = std.math.maxInt(u5),
4683
4684 fn toLlvm(self: Operation) llvm.AtomicRMWBinOp {
4685 return switch (self) {
4686 .xchg => .Xchg,
4687 .add => .Add,
4688 .sub => .Sub,
4689 .@"and" => .And,
4690 .nand => .Nand,
4691 .@"or" => .Or,
4692 .xor => .Xor,
4693 .max => .Max,
4694 .min => .Min,
4695 .umax => .UMax,
4696 .umin => .UMin,
4697 .fadd => .FAdd,
4698 .fsub => .FSub,
4699 .fmax => .FMax,
4700 .fmin => .FMin,
4701 .none => unreachable,
4702 };
4703 }
4704 };4724 };
4705 };4725 };
47064726
...@@ -4764,7 +4784,9 @@ pub const Function = struct {...@@ -4764,7 +4784,9 @@ pub const Function = struct {
47644784
4765 pub fn deinit(self: *Function, gpa: Allocator) void {4785 pub fn deinit(self: *Function, gpa: Allocator) void {
4766 gpa.free(self.extra);4786 gpa.free(self.extra);
4767 if (self.metadata) |metadata| gpa.free(metadata[0..self.instructions.len]);4787 gpa.free(self.debug_values);
4788 self.debug_locations.deinit(gpa);
4789 gpa.free(self.value_indices[0..self.instructions.len]);
4768 gpa.free(self.names[0..self.instructions.len]);4790 gpa.free(self.names[0..self.instructions.len]);
4769 self.instructions.deinit(gpa);4791 self.instructions.deinit(gpa);
4770 gpa.free(self.blocks);4792 gpa.free(self.blocks);
...@@ -4822,7 +4844,7 @@ pub const Function = struct {...@@ -4822,7 +4844,7 @@ pub const Function = struct {
4822 Instruction.Alloca.Info,4844 Instruction.Alloca.Info,
4823 Instruction.Call.Info,4845 Instruction.Call.Info,
4824 => @bitCast(value),4846 => @bitCast(value),
4825 else => @compileError("bad field type: " ++ @typeName(field.type)),4847 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
4826 };4848 };
4827 return .{4849 return .{
4828 .data = result,4850 .data = result,
...@@ -4838,16 +4860,14 @@ pub const Function = struct {...@@ -4838,16 +4860,14 @@ pub const Function = struct {
4838pub const WipFunction = struct {4860pub const WipFunction = struct {
4839 builder: *Builder,4861 builder: *Builder,
4840 function: Function.Index,4862 function: Function.Index,
4841 llvm: if (build_options.have_llvm) struct {4863 last_debug_location: Metadata,
4842 builder: *llvm.Builder,4864 current_debug_location: Metadata,
4843 blocks: std.ArrayListUnmanaged(*llvm.BasicBlock),
4844 instructions: std.ArrayListUnmanaged(*llvm.Value),
4845 } else void,
4846 cursor: Cursor,4865 cursor: Cursor,
4847 blocks: std.ArrayListUnmanaged(Block),4866 blocks: std.ArrayListUnmanaged(Block),
4848 instructions: std.MultiArrayList(Instruction),4867 instructions: std.MultiArrayList(Instruction),
4849 names: std.ArrayListUnmanaged(String),4868 names: std.ArrayListUnmanaged(String),
4850 metadata: std.ArrayListUnmanaged(Metadata),4869 debug_locations: std.AutoArrayHashMapUnmanaged(Instruction.Index, Metadata),
4870 debug_values: std.AutoArrayHashMapUnmanaged(Instruction.Index, void),
4851 extra: std.ArrayListUnmanaged(u32),4871 extra: std.ArrayListUnmanaged(u32),
48524872
4853 pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 };4873 pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 };
...@@ -4873,35 +4893,23 @@ pub const WipFunction = struct {...@@ -4873,35 +4893,23 @@ pub const WipFunction = struct {
4873 pub fn toInst(self: Index, function: *const Function) Instruction.Index {4893 pub fn toInst(self: Index, function: *const Function) Instruction.Index {
4874 return function.blocks[@intFromEnum(self)].instruction;4894 return function.blocks[@intFromEnum(self)].instruction;
4875 }4895 }
4876
4877 pub fn toLlvm(self: Index, wip: *const WipFunction) *llvm.BasicBlock {
4878 assert(wip.builder.useLibLlvm());
4879 return wip.llvm.blocks.items[@intFromEnum(self)];
4880 }
4881 };4896 };
4882 };4897 };
48834898
4884 pub const Instruction = Function.Instruction;4899 pub const Instruction = Function.Instruction;
48854900
4886 pub fn init(builder: *Builder, function: Function.Index) Allocator.Error!WipFunction {4901 pub fn init(builder: *Builder, function: Function.Index) Allocator.Error!WipFunction {
4887 if (builder.useLibLlvm()) {4902 var self: WipFunction = .{
4888 const llvm_function = function.toLlvm(builder);
4889 while (llvm_function.getFirstBasicBlock()) |bb| bb.deleteBasicBlock();
4890 }
4891
4892 var self = WipFunction{
4893 .builder = builder,4903 .builder = builder,
4894 .function = function,4904 .function = function,
4895 .llvm = if (builder.useLibLlvm()) .{4905 .last_debug_location = .none,
4896 .builder = builder.llvm.context.createBuilder(),4906 .current_debug_location = .none,
4897 .blocks = .{},
4898 .instructions = .{},
4899 } else undefined,
4900 .cursor = undefined,4907 .cursor = undefined,
4901 .blocks = .{},4908 .blocks = .{},
4902 .instructions = .{},4909 .instructions = .{},
4903 .names = .{},4910 .names = .{},
4904 .metadata = .{},4911 .debug_locations = .{},
4912 .debug_values = .{},
4905 .extra = .{},4913 .extra = .{},
4906 };4914 };
4907 errdefer self.deinit();4915 errdefer self.deinit();
...@@ -4909,15 +4917,14 @@ pub const WipFunction = struct {...@@ -4909,15 +4917,14 @@ pub const WipFunction = struct {
4909 const params_len = function.typeOf(self.builder).functionParameters(self.builder).len;4917 const params_len = function.typeOf(self.builder).functionParameters(self.builder).len;
4910 try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0);4918 try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0);
4911 try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);4919 try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);
4912 if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, params_len);4920 if (!self.builder.strip) {
4913 if (self.builder.useLibLlvm())4921 try self.names.ensureUnusedCapacity(self.builder.gpa, params_len);
4914 try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);4922 }
4915 for (0..params_len) |param_index| {4923 for (0..params_len) |param_index| {
4916 self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) });4924 self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) });
4917 if (!self.builder.strip) self.names.appendAssumeCapacity(.empty); // TODO: param names4925 if (!self.builder.strip) {
4918 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(4926 self.names.appendAssumeCapacity(.empty); // TODO: param names
4919 function.toLlvm(self.builder).getParam(@intCast(param_index)),4927 }
4920 );
4921 }4928 }
49224929
4923 return self;4930 return self;
...@@ -4934,7 +4941,6 @@ pub const WipFunction = struct {...@@ -4934,7 +4941,6 @@ pub const WipFunction = struct {
49344941
4935 pub fn block(self: *WipFunction, incoming: u32, name: []const u8) Allocator.Error!Block.Index {4942 pub fn block(self: *WipFunction, incoming: u32, name: []const u8) Allocator.Error!Block.Index {
4936 try self.blocks.ensureUnusedCapacity(self.builder.gpa, 1);4943 try self.blocks.ensureUnusedCapacity(self.builder.gpa, 1);
4937 if (self.builder.useLibLlvm()) try self.llvm.blocks.ensureUnusedCapacity(self.builder.gpa, 1);
49384944
4939 const index: Block.Index = @enumFromInt(self.blocks.items.len);4945 const index: Block.Index = @enumFromInt(self.blocks.items.len);
4940 const final_name = if (self.builder.strip) .empty else try self.builder.string(name);4946 const final_name = if (self.builder.strip) .empty else try self.builder.string(name);
...@@ -4943,41 +4949,24 @@ pub const WipFunction = struct {...@@ -4943,41 +4949,24 @@ pub const WipFunction = struct {
4943 .incoming = incoming,4949 .incoming = incoming,
4944 .instructions = .{},4950 .instructions = .{},
4945 });4951 });
4946 if (self.builder.useLibLlvm()) self.llvm.blocks.appendAssumeCapacity(
4947 self.builder.llvm.context.appendBasicBlock(
4948 self.function.toLlvm(self.builder),
4949 final_name.slice(self.builder).?,
4950 ),
4951 );
4952 return index;4952 return index;
4953 }4953 }
49544954
4955 pub fn ret(self: *WipFunction, val: Value) Allocator.Error!Instruction.Index {4955 pub fn ret(self: *WipFunction, val: Value) Allocator.Error!Instruction.Index {
4956 assert(val.typeOfWip(self) == self.function.typeOf(self.builder).functionReturn(self.builder));4956 assert(val.typeOfWip(self) == self.function.typeOf(self.builder).functionReturn(self.builder));
4957 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);4957 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
4958 const instruction = try self.addInst(null, .{ .tag = .ret, .data = @intFromEnum(val) });4958 return try self.addInst(null, .{ .tag = .ret, .data = @intFromEnum(val) });
4959 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
4960 self.llvm.builder.buildRet(val.toLlvm(self)),
4961 );
4962 return instruction;
4963 }4959 }
49644960
4965 pub fn retVoid(self: *WipFunction) Allocator.Error!Instruction.Index {4961 pub fn retVoid(self: *WipFunction) Allocator.Error!Instruction.Index {
4966 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);4962 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
4967 const instruction = try self.addInst(null, .{ .tag = .@"ret void", .data = undefined });4963 return try self.addInst(null, .{ .tag = .@"ret void", .data = undefined });
4968 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
4969 self.llvm.builder.buildRetVoid(),
4970 );
4971 return instruction;
4972 }4964 }
49734965
4974 pub fn br(self: *WipFunction, dest: Block.Index) Allocator.Error!Instruction.Index {4966 pub fn br(self: *WipFunction, dest: Block.Index) Allocator.Error!Instruction.Index {
4975 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);4967 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
4976 const instruction = try self.addInst(null, .{ .tag = .br, .data = @intFromEnum(dest) });4968 const instruction = try self.addInst(null, .{ .tag = .br, .data = @intFromEnum(dest) });
4977 dest.ptr(self).branches += 1;4969 dest.ptr(self).branches += 1;
4978 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
4979 self.llvm.builder.buildBr(dest.toLlvm(self)),
4980 );
4981 return instruction;4970 return instruction;
4982 }4971 }
49834972
...@@ -4999,9 +4988,6 @@ pub const WipFunction = struct {...@@ -4999,9 +4988,6 @@ pub const WipFunction = struct {
4999 });4988 });
5000 then.ptr(self).branches += 1;4989 then.ptr(self).branches += 1;
5001 @"else".ptr(self).branches += 1;4990 @"else".ptr(self).branches += 1;
5002 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5003 self.llvm.builder.buildCondBr(cond.toLlvm(self), then.toLlvm(self), @"else".toLlvm(self)),
5004 );
5005 return instruction;4991 return instruction;
5006 }4992 }
50074993
...@@ -5022,8 +5008,6 @@ pub const WipFunction = struct {...@@ -5022,8 +5008,6 @@ pub const WipFunction = struct {
5022 extra.trail.nextMut(extra.data.cases_len, Block.Index, wip)[self.index] = dest;5008 extra.trail.nextMut(extra.data.cases_len, Block.Index, wip)[self.index] = dest;
5023 self.index += 1;5009 self.index += 1;
5024 dest.ptr(wip).branches += 1;5010 dest.ptr(wip).branches += 1;
5025 if (wip.builder.useLibLlvm())
5026 self.instruction.toLlvm(wip).addCase(val.toLlvm(wip.builder), dest.toLlvm(wip));
5027 }5011 }
50285012
5029 pub fn finish(self: WipSwitch, wip: *WipFunction) void {5013 pub fn finish(self: WipSwitch, wip: *WipFunction) void {
...@@ -5050,18 +5034,12 @@ pub const WipFunction = struct {...@@ -5050,18 +5034,12 @@ pub const WipFunction = struct {
5050 });5034 });
5051 _ = self.extra.addManyAsSliceAssumeCapacity(cases_len * 2);5035 _ = self.extra.addManyAsSliceAssumeCapacity(cases_len * 2);
5052 default.ptr(self).branches += 1;5036 default.ptr(self).branches += 1;
5053 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5054 self.llvm.builder.buildSwitch(val.toLlvm(self), default.toLlvm(self), @intCast(cases_len)),
5055 );
5056 return .{ .index = 0, .instruction = instruction };5037 return .{ .index = 0, .instruction = instruction };
5057 }5038 }
50585039
5059 pub fn @"unreachable"(self: *WipFunction) Allocator.Error!Instruction.Index {5040 pub fn @"unreachable"(self: *WipFunction) Allocator.Error!Instruction.Index {
5060 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);5041 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
5061 const instruction = try self.addInst(null, .{ .tag = .@"unreachable", .data = undefined });5042 const instruction = try self.addInst(null, .{ .tag = .@"unreachable", .data = undefined });
5062 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5063 self.llvm.builder.buildUnreachable(),
5064 );
5065 return instruction;5043 return instruction;
5066 }5044 }
50675045
...@@ -5079,17 +5057,6 @@ pub const WipFunction = struct {...@@ -5079,17 +5057,6 @@ pub const WipFunction = struct {
5079 }5057 }
5080 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);5058 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
5081 const instruction = try self.addInst(name, .{ .tag = tag, .data = @intFromEnum(val) });5059 const instruction = try self.addInst(name, .{ .tag = tag, .data = @intFromEnum(val) });
5082 if (self.builder.useLibLlvm()) {
5083 switch (tag) {
5084 .fneg => self.llvm.builder.setFastMath(false),
5085 .@"fneg fast" => self.llvm.builder.setFastMath(true),
5086 else => unreachable,
5087 }
5088 self.llvm.instructions.appendAssumeCapacity(switch (tag) {
5089 .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg,
5090 else => unreachable,
5091 }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));
5092 }
5093 return instruction.toValue();5060 return instruction.toValue();
5094 }5061 }
50955062
...@@ -5157,56 +5124,6 @@ pub const WipFunction = struct {...@@ -5157,56 +5124,6 @@ pub const WipFunction = struct {
5157 .tag = tag,5124 .tag = tag,
5158 .data = self.addExtraAssumeCapacity(Instruction.Binary{ .lhs = lhs, .rhs = rhs }),5125 .data = self.addExtraAssumeCapacity(Instruction.Binary{ .lhs = lhs, .rhs = rhs }),
5159 });5126 });
5160 if (self.builder.useLibLlvm()) {
5161 switch (tag) {
5162 .fadd,
5163 .fdiv,
5164 .fmul,
5165 .frem,
5166 .fsub,
5167 => self.llvm.builder.setFastMath(false),
5168 .@"fadd fast",
5169 .@"fdiv fast",
5170 .@"fmul fast",
5171 .@"frem fast",
5172 .@"fsub fast",
5173 => self.llvm.builder.setFastMath(true),
5174 else => {},
5175 }
5176 self.llvm.instructions.appendAssumeCapacity(switch (tag) {
5177 .add => &llvm.Builder.buildAdd,
5178 .@"add nsw" => &llvm.Builder.buildNSWAdd,
5179 .@"add nuw" => &llvm.Builder.buildNUWAdd,
5180 .@"and" => &llvm.Builder.buildAnd,
5181 .ashr => &llvm.Builder.buildAShr,
5182 .@"ashr exact" => &llvm.Builder.buildAShrExact,
5183 .fadd, .@"fadd fast" => &llvm.Builder.buildFAdd,
5184 .fdiv, .@"fdiv fast" => &llvm.Builder.buildFDiv,
5185 .fmul, .@"fmul fast" => &llvm.Builder.buildFMul,
5186 .frem, .@"frem fast" => &llvm.Builder.buildFRem,
5187 .fsub, .@"fsub fast" => &llvm.Builder.buildFSub,
5188 .lshr => &llvm.Builder.buildLShr,
5189 .@"lshr exact" => &llvm.Builder.buildLShrExact,
5190 .mul => &llvm.Builder.buildMul,
5191 .@"mul nsw" => &llvm.Builder.buildNSWMul,
5192 .@"mul nuw" => &llvm.Builder.buildNUWMul,
5193 .@"or" => &llvm.Builder.buildOr,
5194 .sdiv => &llvm.Builder.buildSDiv,
5195 .@"sdiv exact" => &llvm.Builder.buildExactSDiv,
5196 .shl => &llvm.Builder.buildShl,
5197 .@"shl nsw" => &llvm.Builder.buildNSWShl,
5198 .@"shl nuw" => &llvm.Builder.buildNUWShl,
5199 .srem => &llvm.Builder.buildSRem,
5200 .sub => &llvm.Builder.buildSub,
5201 .@"sub nsw" => &llvm.Builder.buildNSWSub,
5202 .@"sub nuw" => &llvm.Builder.buildNUWSub,
5203 .udiv => &llvm.Builder.buildUDiv,
5204 .@"udiv exact" => &llvm.Builder.buildExactUDiv,
5205 .urem => &llvm.Builder.buildURem,
5206 .xor => &llvm.Builder.buildXor,
5207 else => unreachable,
5208 }(self.llvm.builder, lhs.toLlvm(self), rhs.toLlvm(self), instruction.llvmName(self)));
5209 }
5210 return instruction.toValue();5127 return instruction.toValue();
5211 }5128 }
52125129
...@@ -5226,13 +5143,6 @@ pub const WipFunction = struct {...@@ -5226,13 +5143,6 @@ pub const WipFunction = struct {
5226 .index = index,5143 .index = index,
5227 }),5144 }),
5228 });5145 });
5229 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5230 self.llvm.builder.buildExtractElement(
5231 val.toLlvm(self),
5232 index.toLlvm(self),
5233 instruction.llvmName(self),
5234 ),
5235 );
5236 return instruction.toValue();5146 return instruction.toValue();
5237 }5147 }
52385148
...@@ -5254,14 +5164,6 @@ pub const WipFunction = struct {...@@ -5254,14 +5164,6 @@ pub const WipFunction = struct {
5254 .index = index,5164 .index = index,
5255 }),5165 }),
5256 });5166 });
5257 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5258 self.llvm.builder.buildInsertElement(
5259 val.toLlvm(self),
5260 elem.toLlvm(self),
5261 index.toLlvm(self),
5262 instruction.llvmName(self),
5263 ),
5264 );
5265 return instruction.toValue();5167 return instruction.toValue();
5266 }5168 }
52675169
...@@ -5284,14 +5186,6 @@ pub const WipFunction = struct {...@@ -5284,14 +5186,6 @@ pub const WipFunction = struct {
5284 .mask = mask,5186 .mask = mask,
5285 }),5187 }),
5286 });5188 });
5287 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5288 self.llvm.builder.buildShuffleVector(
5289 lhs.toLlvm(self),
5290 rhs.toLlvm(self),
5291 mask.toLlvm(self),
5292 instruction.llvmName(self),
5293 ),
5294 );
5295 return instruction.toValue();5189 return instruction.toValue();
5296 }5190 }
52975191
...@@ -5303,10 +5197,9 @@ pub const WipFunction = struct {...@@ -5303,10 +5197,9 @@ pub const WipFunction = struct {
5303 ) Allocator.Error!Value {5197 ) Allocator.Error!Value {
5304 const scalar_ty = try ty.changeLength(1, self.builder);5198 const scalar_ty = try ty.changeLength(1, self.builder);
5305 const mask_ty = try ty.changeScalar(.i32, self.builder);5199 const mask_ty = try ty.changeScalar(.i32, self.builder);
5306 const zero = try self.builder.intConst(.i32, 0);
5307 const poison = try self.builder.poisonValue(scalar_ty);5200 const poison = try self.builder.poisonValue(scalar_ty);
5308 const mask = try self.builder.splatValue(mask_ty, zero);5201 const mask = try self.builder.splatValue(mask_ty, .@"0");
5309 const scalar = try self.insertElement(poison, elem, zero.toValue(), name);5202 const scalar = try self.insertElement(poison, elem, .@"0", name);
5310 return self.shuffleVector(scalar, poison, mask, name);5203 return self.shuffleVector(scalar, poison, mask, name);
5311 }5204 }
53125205
...@@ -5327,13 +5220,6 @@ pub const WipFunction = struct {...@@ -5327,13 +5220,6 @@ pub const WipFunction = struct {
5327 }),5220 }),
5328 });5221 });
5329 self.extra.appendSliceAssumeCapacity(indices);5222 self.extra.appendSliceAssumeCapacity(indices);
5330 if (self.builder.useLibLlvm()) {
5331 const llvm_name = instruction.llvmName(self);
5332 var cur = val.toLlvm(self);
5333 for (indices) |index|
5334 cur = self.llvm.builder.buildExtractValue(cur, @intCast(index), llvm_name);
5335 self.llvm.instructions.appendAssumeCapacity(cur);
5336 }
5337 return instruction.toValue();5223 return instruction.toValue();
5338 }5224 }
53395225
...@@ -5356,35 +5242,6 @@ pub const WipFunction = struct {...@@ -5356,35 +5242,6 @@ pub const WipFunction = struct {
5356 }),5242 }),
5357 });5243 });
5358 self.extra.appendSliceAssumeCapacity(indices);5244 self.extra.appendSliceAssumeCapacity(indices);
5359 if (self.builder.useLibLlvm()) {
5360 const ExpectedContents = [expected_gep_indices_len]*llvm.Value;
5361 var stack align(@alignOf(ExpectedContents)) =
5362 std.heap.stackFallback(@sizeOf(ExpectedContents), self.builder.gpa);
5363 const allocator = stack.get();
5364
5365 const llvm_name = instruction.llvmName(self);
5366 const llvm_vals = try allocator.alloc(*llvm.Value, indices.len);
5367 defer allocator.free(llvm_vals);
5368 llvm_vals[0] = val.toLlvm(self);
5369 for (llvm_vals[1..], llvm_vals[0 .. llvm_vals.len - 1], indices[0 .. indices.len - 1]) |
5370 *cur_val,
5371 prev_val,
5372 index,
5373 | cur_val.* = self.llvm.builder.buildExtractValue(prev_val, @intCast(index), llvm_name);
5374
5375 var depth: usize = llvm_vals.len;
5376 var cur = elem.toLlvm(self);
5377 while (depth > 0) {
5378 depth -= 1;
5379 cur = self.llvm.builder.buildInsertValue(
5380 llvm_vals[depth],
5381 cur,
5382 @intCast(indices[depth]),
5383 llvm_name,
5384 );
5385 }
5386 self.llvm.instructions.appendAssumeCapacity(cur);
5387 }
5388 return instruction.toValue();5245 return instruction.toValue();
5389 }5246 }
53905247
...@@ -5420,19 +5277,13 @@ pub const WipFunction = struct {...@@ -5420,19 +5277,13 @@ pub const WipFunction = struct {
5420 },5277 },
5421 .data = self.addExtraAssumeCapacity(Instruction.Alloca{5278 .data = self.addExtraAssumeCapacity(Instruction.Alloca{
5422 .type = ty,5279 .type = ty,
5423 .len = len,5280 .len = switch (len) {
5281 .none => .@"1",
5282 else => len,
5283 },
5424 .info = .{ .alignment = alignment, .addr_space = addr_space },5284 .info = .{ .alignment = alignment, .addr_space = addr_space },
5425 }),5285 }),
5426 });5286 });
5427 if (self.builder.useLibLlvm()) {
5428 const llvm_instruction = self.llvm.builder.buildAllocaInAddressSpace(
5429 ty.toLlvm(self.builder),
5430 @intFromEnum(addr_space),
5431 instruction.llvmName(self),
5432 );
5433 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5434 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5435 }
5436 return instruction.toValue();5287 return instruction.toValue();
5437 }5288 }
54385289
...@@ -5478,17 +5329,6 @@ pub const WipFunction = struct {...@@ -5478,17 +5329,6 @@ pub const WipFunction = struct {
5478 .ptr = ptr,5329 .ptr = ptr,
5479 }),5330 }),
5480 });5331 });
5481 if (self.builder.useLibLlvm()) {
5482 const llvm_instruction = self.llvm.builder.buildLoad(
5483 ty.toLlvm(self.builder),
5484 ptr.toLlvm(self),
5485 instruction.llvmName(self),
5486 );
5487 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5488 if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm());
5489 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5490 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5491 }
5492 return instruction.toValue();5332 return instruction.toValue();
5493 }5333 }
54945334
...@@ -5532,13 +5372,6 @@ pub const WipFunction = struct {...@@ -5532,13 +5372,6 @@ pub const WipFunction = struct {
5532 .ptr = ptr,5372 .ptr = ptr,
5533 }),5373 }),
5534 });5374 });
5535 if (self.builder.useLibLlvm()) {
5536 const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));
5537 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5538 if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm());
5539 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5540 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5541 }
5542 return instruction;5375 return instruction;
5543 }5376 }
55445377
...@@ -5556,13 +5389,6 @@ pub const WipFunction = struct {...@@ -5556,13 +5389,6 @@ pub const WipFunction = struct {
5556 .success_ordering = ordering,5389 .success_ordering = ordering,
5557 }),5390 }),
5558 });5391 });
5559 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5560 self.llvm.builder.buildFence(
5561 ordering.toLlvm(),
5562 llvm.Bool.fromBool(sync_scope == .singlethread),
5563 "",
5564 ),
5565 );
5566 return instruction;5392 return instruction;
5567 }5393 }
55685394
...@@ -5605,25 +5431,6 @@ pub const WipFunction = struct {...@@ -5605,25 +5431,6 @@ pub const WipFunction = struct {
5605 .new = new,5431 .new = new,
5606 }),5432 }),
5607 });5433 });
5608 if (self.builder.useLibLlvm()) {
5609 const llvm_instruction = self.llvm.builder.buildAtomicCmpXchg(
5610 ptr.toLlvm(self),
5611 cmp.toLlvm(self),
5612 new.toLlvm(self),
5613 success_ordering.toLlvm(),
5614 failure_ordering.toLlvm(),
5615 llvm.Bool.fromBool(sync_scope == .singlethread),
5616 );
5617 if (kind == .weak) llvm_instruction.setWeak(.True);
5618 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5619 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5620 const llvm_name = instruction.llvmName(self);
5621 if (llvm_name.len > 0) llvm_instruction.setValueName(
5622 llvm_name.ptr,
5623 @intCast(llvm_name.len),
5624 );
5625 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5626 }
5627 return instruction.toValue();5434 return instruction.toValue();
5628 }5435 }
56295436
...@@ -5656,23 +5463,6 @@ pub const WipFunction = struct {...@@ -5656,23 +5463,6 @@ pub const WipFunction = struct {
5656 .val = val,5463 .val = val,
5657 }),5464 }),
5658 });5465 });
5659 if (self.builder.useLibLlvm()) {
5660 const llvm_instruction = self.llvm.builder.buildAtomicRmw(
5661 operation.toLlvm(),
5662 ptr.toLlvm(self),
5663 val.toLlvm(self),
5664 ordering.toLlvm(),
5665 llvm.Bool.fromBool(sync_scope == .singlethread),
5666 );
5667 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5668 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5669 const llvm_name = instruction.llvmName(self);
5670 if (llvm_name.len > 0) llvm_instruction.setValueName(
5671 llvm_name.ptr,
5672 @intCast(llvm_name.len),
5673 );
5674 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5675 }
5676 return instruction.toValue();5466 return instruction.toValue();
5677 }5467 }
56785468
...@@ -5732,28 +5522,6 @@ pub const WipFunction = struct {...@@ -5732,28 +5522,6 @@ pub const WipFunction = struct {
5732 }),5522 }),
5733 });5523 });
5734 self.extra.appendSliceAssumeCapacity(@ptrCast(indices));5524 self.extra.appendSliceAssumeCapacity(@ptrCast(indices));
5735 if (self.builder.useLibLlvm()) {
5736 const ExpectedContents = [expected_gep_indices_len]*llvm.Value;
5737 var stack align(@alignOf(ExpectedContents)) =
5738 std.heap.stackFallback(@sizeOf(ExpectedContents), self.builder.gpa);
5739 const allocator = stack.get();
5740
5741 const llvm_indices = try allocator.alloc(*llvm.Value, indices.len);
5742 defer allocator.free(llvm_indices);
5743 for (llvm_indices, indices) |*llvm_index, index| llvm_index.* = index.toLlvm(self);
5744
5745 self.llvm.instructions.appendAssumeCapacity(switch (kind) {
5746 .normal => &llvm.Builder.buildGEP,
5747 .inbounds => &llvm.Builder.buildInBoundsGEP,
5748 }(
5749 self.llvm.builder,
5750 ty.toLlvm(self.builder),
5751 base.toLlvm(self),
5752 llvm_indices.ptr,
5753 @intCast(llvm_indices.len),
5754 instruction.llvmName(self),
5755 ));
5756 }
5757 return instruction.toValue();5525 return instruction.toValue();
5758 }5526 }
57595527
...@@ -5765,9 +5533,7 @@ pub const WipFunction = struct {...@@ -5765,9 +5533,7 @@ pub const WipFunction = struct {
5765 name: []const u8,5533 name: []const u8,
5766 ) Allocator.Error!Value {5534 ) Allocator.Error!Value {
5767 assert(ty.isStruct(self.builder));5535 assert(ty.isStruct(self.builder));
5768 return self.gep(.inbounds, ty, base, &.{5536 return self.gep(.inbounds, ty, base, &.{ .@"0", try self.builder.intValue(.i32, index) }, name);
5769 try self.builder.intValue(.i32, 0), try self.builder.intValue(.i32, index),
5770 }, name);
5771 }5537 }
57725538
5773 pub fn conv(5539 pub fn conv(
...@@ -5815,22 +5581,6 @@ pub const WipFunction = struct {...@@ -5815,22 +5581,6 @@ pub const WipFunction = struct {
5815 .type = ty,5581 .type = ty,
5816 }),5582 }),
5817 });5583 });
5818 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(switch (tag) {
5819 .addrspacecast => &llvm.Builder.buildAddrSpaceCast,
5820 .bitcast => &llvm.Builder.buildBitCast,
5821 .fpext => &llvm.Builder.buildFPExt,
5822 .fptosi => &llvm.Builder.buildFPToSI,
5823 .fptoui => &llvm.Builder.buildFPToUI,
5824 .fptrunc => &llvm.Builder.buildFPTrunc,
5825 .inttoptr => &llvm.Builder.buildIntToPtr,
5826 .ptrtoint => &llvm.Builder.buildPtrToInt,
5827 .sext => &llvm.Builder.buildSExt,
5828 .sitofp => &llvm.Builder.buildSIToFP,
5829 .trunc => &llvm.Builder.buildTrunc,
5830 .uitofp => &llvm.Builder.buildUIToFP,
5831 .zext => &llvm.Builder.buildZExt,
5832 else => unreachable,
5833 }(self.llvm.builder, val.toLlvm(self), ty.toLlvm(self.builder), instruction.llvmName(self)));
5834 return instruction.toValue();5584 return instruction.toValue();
5835 }5585 }
58365586
...@@ -5843,7 +5593,7 @@ pub const WipFunction = struct {...@@ -5843,7 +5593,7 @@ pub const WipFunction = struct {
5843 ) Allocator.Error!Value {5593 ) Allocator.Error!Value {
5844 return self.cmpTag(switch (cond) {5594 return self.cmpTag(switch (cond) {
5845 inline else => |tag| @field(Instruction.Tag, "icmp " ++ @tagName(tag)),5595 inline else => |tag| @field(Instruction.Tag, "icmp " ++ @tagName(tag)),
5846 }, @intFromEnum(cond), lhs, rhs, name);5596 }, lhs, rhs, name);
5847 }5597 }
58485598
5849 pub fn fcmp(5599 pub fn fcmp(
...@@ -5861,7 +5611,7 @@ pub const WipFunction = struct {...@@ -5861,7 +5611,7 @@ pub const WipFunction = struct {
5861 .fast => "fast ",5611 .fast => "fast ",
5862 } ++ @tagName(cond_tag)),5612 } ++ @tagName(cond_tag)),
5863 },5613 },
5864 }, @intFromEnum(cond), lhs, rhs, name);5614 }, lhs, rhs, name);
5865 }5615 }
58665616
5867 pub const WipPhi = struct {5617 pub const WipPhi = struct {
...@@ -5877,7 +5627,7 @@ pub const WipFunction = struct {...@@ -5877,7 +5627,7 @@ pub const WipFunction = struct {
5877 vals: []const Value,5627 vals: []const Value,
5878 blocks: []const Block.Index,5628 blocks: []const Block.Index,
5879 wip: *WipFunction,5629 wip: *WipFunction,
5880 ) (if (build_options.have_llvm) Allocator.Error else error{})!void {5630 ) void {
5881 const incoming_len = self.block.ptrConst(wip).incoming;5631 const incoming_len = self.block.ptrConst(wip).incoming;
5882 assert(vals.len == incoming_len and blocks.len == incoming_len);5632 assert(vals.len == incoming_len and blocks.len == incoming_len);
5883 const instruction = wip.instructions.get(@intFromEnum(self.instruction));5633 const instruction = wip.instructions.get(@intFromEnum(self.instruction));
...@@ -5885,26 +5635,6 @@ pub const WipFunction = struct {...@@ -5885,26 +5635,6 @@ pub const WipFunction = struct {
5885 for (vals) |val| assert(val.typeOfWip(wip) == extra.data.type);5635 for (vals) |val| assert(val.typeOfWip(wip) == extra.data.type);
5886 @memcpy(extra.trail.nextMut(incoming_len, Value, wip), vals);5636 @memcpy(extra.trail.nextMut(incoming_len, Value, wip), vals);
5887 @memcpy(extra.trail.nextMut(incoming_len, Block.Index, wip), blocks);5637 @memcpy(extra.trail.nextMut(incoming_len, Block.Index, wip), blocks);
5888 if (wip.builder.useLibLlvm()) {
5889 const ExpectedContents = extern struct {
5890 values: [expected_incoming_len]*llvm.Value,
5891 blocks: [expected_incoming_len]*llvm.BasicBlock,
5892 };
5893 var stack align(@alignOf(ExpectedContents)) =
5894 std.heap.stackFallback(@sizeOf(ExpectedContents), wip.builder.gpa);
5895 const allocator = stack.get();
5896
5897 const llvm_vals = try allocator.alloc(*llvm.Value, incoming_len);
5898 defer allocator.free(llvm_vals);
5899 const llvm_blocks = try allocator.alloc(*llvm.BasicBlock, incoming_len);
5900 defer allocator.free(llvm_blocks);
5901
5902 for (llvm_vals, vals) |*llvm_val, incoming_val| llvm_val.* = incoming_val.toLlvm(wip);
5903 for (llvm_blocks, blocks) |*llvm_block, incoming_block|
5904 llvm_block.* = incoming_block.toLlvm(wip);
5905 self.instruction.toLlvm(wip)
5906 .addIncoming(llvm_vals.ptr, llvm_blocks.ptr, @intCast(incoming_len));
5907 }
5908 }5638 }
5909 };5639 };
59105640
...@@ -5970,53 +5700,6 @@ pub const WipFunction = struct {...@@ -5970,53 +5700,6 @@ pub const WipFunction = struct {
5970 }),5700 }),
5971 });5701 });
5972 self.extra.appendSliceAssumeCapacity(@ptrCast(args));5702 self.extra.appendSliceAssumeCapacity(@ptrCast(args));
5973 if (self.builder.useLibLlvm()) {
5974 const ExpectedContents = [expected_args_len]*llvm.Value;
5975 var stack align(@alignOf(ExpectedContents)) =
5976 std.heap.stackFallback(@sizeOf(ExpectedContents), self.builder.gpa);
5977 const allocator = stack.get();
5978
5979 const llvm_args = try allocator.alloc(*llvm.Value, args.len);
5980 defer allocator.free(llvm_args);
5981 for (llvm_args, args) |*llvm_arg, arg_val| llvm_arg.* = arg_val.toLlvm(self);
5982
5983 switch (kind) {
5984 .normal,
5985 .musttail,
5986 .notail,
5987 .tail,
5988 => self.llvm.builder.setFastMath(false),
5989 .fast,
5990 .musttail_fast,
5991 .notail_fast,
5992 .tail_fast,
5993 => self.llvm.builder.setFastMath(true),
5994 }
5995 const llvm_instruction = self.llvm.builder.buildCall(
5996 ty.toLlvm(self.builder),
5997 callee.toLlvm(self),
5998 llvm_args.ptr,
5999 @intCast(llvm_args.len),
6000 switch (ret_ty) {
6001 .void => "",
6002 else => instruction.llvmName(self),
6003 },
6004 );
6005 llvm_instruction.setInstructionCallConv(call_conv.toLlvm());
6006 llvm_instruction.setTailCallKind(switch (kind) {
6007 .normal, .fast => .None,
6008 .musttail, .musttail_fast => .MustTail,
6009 .notail, .notail_fast => .NoTail,
6010 .tail, .tail_fast => .Tail,
6011 });
6012 for (0.., function_attributes.slice(self.builder)) |index, attributes| {
6013 for (attributes.slice(self.builder)) |attribute| llvm_instruction.addCallSiteAttribute(
6014 @as(llvm.AttributeIndex, @intCast(index)) -% 1,
6015 attribute.toLlvm(self.builder),
6016 );
6017 }
6018 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
6019 }
6020 return instruction.toValue();5703 return instruction.toValue();
6021 }5704 }
60225705
...@@ -6117,16 +5800,25 @@ pub const WipFunction = struct {...@@ -6117,16 +5800,25 @@ pub const WipFunction = struct {
6117 .type = ty,5800 .type = ty,
6118 }),5801 }),
6119 });5802 });
6120 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
6121 self.llvm.builder.buildVAArg(
6122 list.toLlvm(self),
6123 ty.toLlvm(self.builder),
6124 instruction.llvmName(self),
6125 ),
6126 );
6127 return instruction.toValue();5803 return instruction.toValue();
6128 }5804 }
61295805
5806 pub fn debugValue(self: *WipFunction, value: Value) Allocator.Error!Metadata {
5807 if (self.builder.strip) return .none;
5808 return switch (value.unwrap()) {
5809 .instruction => |instr_index| blk: {
5810 const gop = try self.debug_values.getOrPut(self.builder.gpa, instr_index);
5811
5812 const metadata: Metadata = @enumFromInt(Metadata.first_local_metadata + gop.index);
5813 if (!gop.found_existing) gop.key_ptr.* = instr_index;
5814
5815 break :blk metadata;
5816 },
5817 .constant => |constant| try self.builder.debugConstant(constant),
5818 .metadata => |metadata| metadata,
5819 };
5820 }
5821
6130 pub fn finish(self: *WipFunction) Allocator.Error!void {5822 pub fn finish(self: *WipFunction) Allocator.Error!void {
6131 const gpa = self.builder.gpa;5823 const gpa = self.builder.gpa;
6132 const function = self.function.ptr(self.builder);5824 const function = self.function.ptr(self.builder);
...@@ -6146,6 +5838,7 @@ pub const WipFunction = struct {...@@ -6146,6 +5838,7 @@ pub const WipFunction = struct {
6146 @intFromEnum(instruction)5838 @intFromEnum(instruction)
6147 ].toValue(),5839 ].toValue(),
6148 .constant => |constant| constant.toValue(),5840 .constant => |constant| constant.toValue(),
5841 .metadata => |metadata| metadata.toValue(),
6149 };5842 };
6150 }5843 }
6151 } = .{ .items = try gpa.alloc(Instruction.Index, self.instructions.len) };5844 } = .{ .items = try gpa.alloc(Instruction.Index, self.instructions.len) };
...@@ -6154,9 +5847,15 @@ pub const WipFunction = struct {...@@ -6154,9 +5847,15 @@ pub const WipFunction = struct {
6154 const names = try gpa.alloc(String, final_instructions_len);5847 const names = try gpa.alloc(String, final_instructions_len);
6155 errdefer gpa.free(names);5848 errdefer gpa.free(names);
61565849
6157 const metadata =5850 const value_indices = try gpa.alloc(u32, final_instructions_len);
6158 if (self.builder.strip) null else try gpa.alloc(Metadata, final_instructions_len);5851 errdefer gpa.free(value_indices);
6159 errdefer if (metadata) |new_metadata| gpa.free(new_metadata);5852
5853 var debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, Metadata) = .{};
5854 errdefer debug_locations.deinit(gpa);
5855 try debug_locations.ensureUnusedCapacity(gpa, @intCast(self.debug_locations.count()));
5856
5857 const debug_values = try gpa.alloc(Instruction.Index, self.debug_values.count());
5858 errdefer gpa.free(debug_values);
61605859
6161 var wip_extra: struct {5860 var wip_extra: struct {
6162 index: Instruction.ExtraIndex = 0,5861 index: Instruction.ExtraIndex = 0,
...@@ -6179,7 +5878,7 @@ pub const WipFunction = struct {...@@ -6179,7 +5878,7 @@ pub const WipFunction = struct {
6179 Instruction.Alloca.Info,5878 Instruction.Alloca.Info,
6180 Instruction.Call.Info,5879 Instruction.Call.Info,
6181 => @bitCast(value),5880 => @bitCast(value),
6182 else => @compileError("bad field type: " ++ @typeName(field.type)),5881 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
6183 };5882 };
6184 wip_extra.index += 1;5883 wip_extra.index += 1;
6185 }5884 }
...@@ -6210,8 +5909,10 @@ pub const WipFunction = struct {...@@ -6210,8 +5909,10 @@ pub const WipFunction = struct {
6210 gpa.free(function.blocks);5909 gpa.free(function.blocks);
6211 function.blocks = &.{};5910 function.blocks = &.{};
6212 gpa.free(function.names[0..function.instructions.len]);5911 gpa.free(function.names[0..function.instructions.len]);
6213 if (function.metadata) |old_metadata| gpa.free(old_metadata[0..function.instructions.len]);5912 function.debug_locations.deinit(gpa);
6214 function.metadata = null;5913 function.debug_locations = .{};
5914 gpa.free(function.debug_values);
5915 function.debug_values = &.{};
6215 gpa.free(function.extra);5916 gpa.free(function.extra);
6216 function.extra = &.{};5917 function.extra = &.{};
62175918
...@@ -6238,33 +5939,76 @@ pub const WipFunction = struct {...@@ -6238,33 +5939,76 @@ pub const WipFunction = struct {
62385939
6239 var wip_name: struct {5940 var wip_name: struct {
6240 next_name: String = @enumFromInt(0),5941 next_name: String = @enumFromInt(0),
5942 next_unique_name: std.AutoHashMap(String, String),
5943 builder: *Builder,
62415944
6242 fn map(wip_name: *@This(), old_name: String) String {5945 fn map(wip_name: *@This(), name: String, sep: []const u8) Allocator.Error!String {
6243 if (old_name != .empty) return old_name;5946 switch (name) {
5947 .none => return .none,
5948 .empty => {
5949 assert(wip_name.next_name != .none);
5950 defer wip_name.next_name = @enumFromInt(@intFromEnum(wip_name.next_name) + 1);
5951 return wip_name.next_name;
5952 },
5953 _ => {
5954 assert(!name.isAnon());
5955 const gop = try wip_name.next_unique_name.getOrPut(name);
5956 if (!gop.found_existing) {
5957 gop.value_ptr.* = @enumFromInt(0);
5958 return name;
5959 }
62445960
6245 const new_name = wip_name.next_name;5961 while (true) {
6246 wip_name.next_name = @enumFromInt(@intFromEnum(new_name) + 1);5962 gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1);
6247 return new_name;5963 const unique_name = try wip_name.builder.fmt("{r}{s}{r}", .{
5964 name.fmt(wip_name.builder),
5965 sep,
5966 gop.value_ptr.fmt(wip_name.builder),
5967 });
5968 const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name);
5969 if (!unique_gop.found_existing) {
5970 unique_gop.value_ptr.* = @enumFromInt(0);
5971 return unique_name;
5972 }
5973 }
5974 },
5975 }
6248 }5976 }
6249 } = .{};5977 } = .{
5978 .next_unique_name = std.AutoHashMap(String, String).init(gpa),
5979 .builder = self.builder,
5980 };
5981 defer wip_name.next_unique_name.deinit();
5982
5983 var value_index: u32 = 0;
6250 for (0..params_len) |param_index| {5984 for (0..params_len) |param_index| {
6251 const old_argument_index: Instruction.Index = @enumFromInt(param_index);5985 const old_argument_index: Instruction.Index = @enumFromInt(param_index);
6252 const new_argument_index: Instruction.Index = @enumFromInt(function.instructions.len);5986 const new_argument_index: Instruction.Index = @enumFromInt(function.instructions.len);
6253 const argument = self.instructions.get(@intFromEnum(old_argument_index));5987 const argument = self.instructions.get(@intFromEnum(old_argument_index));
6254 assert(argument.tag == .arg);5988 assert(argument.tag == .arg);
6255 assert(argument.data == param_index);5989 assert(argument.data == param_index);
5990 value_indices[function.instructions.len] = value_index;
5991 value_index += 1;
6256 function.instructions.appendAssumeCapacity(argument);5992 function.instructions.appendAssumeCapacity(argument);
6257 names[@intFromEnum(new_argument_index)] = wip_name.map(5993 names[@intFromEnum(new_argument_index)] = try wip_name.map(
6258 if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)],5994 if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)],
5995 ".",
6259 );5996 );
5997 if (self.debug_locations.get(old_argument_index)) |location| {
5998 debug_locations.putAssumeCapacity(new_argument_index, location);
5999 }
6000 if (self.debug_values.getIndex(old_argument_index)) |index| {
6001 debug_values[index] = new_argument_index;
6002 }
6260 }6003 }
6261 for (self.blocks.items) |current_block| {6004 for (self.blocks.items) |current_block| {
6262 const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len);6005 const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len);
6006 value_indices[function.instructions.len] = value_index;
6263 function.instructions.appendAssumeCapacity(.{6007 function.instructions.appendAssumeCapacity(.{
6264 .tag = .block,6008 .tag = .block,
6265 .data = current_block.incoming,6009 .data = current_block.incoming,
6266 });6010 });
6267 names[@intFromEnum(new_block_index)] = wip_name.map(current_block.name);6011 names[@intFromEnum(new_block_index)] = try wip_name.map(current_block.name, "");
6268 for (current_block.instructions.items) |old_instruction_index| {6012 for (current_block.instructions.items) |old_instruction_index| {
6269 const new_instruction_index: Instruction.Index =6013 const new_instruction_index: Instruction.Index =
6270 @enumFromInt(function.instructions.len);6014 @enumFromInt(function.instructions.len);
...@@ -6565,10 +6309,21 @@ pub const WipFunction = struct {...@@ -6565,10 +6309,21 @@ pub const WipFunction = struct {
6565 },6309 },
6566 }6310 }
6567 function.instructions.appendAssumeCapacity(instruction);6311 function.instructions.appendAssumeCapacity(instruction);
6568 names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)6312 names[@intFromEnum(new_instruction_index)] = try wip_name.map(if (self.builder.strip)
6569 if (old_instruction_index.hasResultWip(self)) .empty else .none6313 if (old_instruction_index.hasResultWip(self)) .empty else .none
6570 else6314 else
6571 self.names.items[@intFromEnum(old_instruction_index)]);6315 self.names.items[@intFromEnum(old_instruction_index)], ".");
6316
6317 if (self.debug_locations.get(old_instruction_index)) |location| {
6318 debug_locations.putAssumeCapacity(new_instruction_index, location);
6319 }
6320
6321 if (self.debug_values.getIndex(old_instruction_index)) |index| {
6322 debug_values[index] = new_instruction_index;
6323 }
6324
6325 value_indices[@intFromEnum(new_instruction_index)] = value_index;
6326 if (old_instruction_index.hasResultWip(self)) value_index += 1;
6572 }6327 }
6573 }6328 }
65746329
...@@ -6576,28 +6331,25 @@ pub const WipFunction = struct {...@@ -6576,28 +6331,25 @@ pub const WipFunction = struct {
6576 function.extra = wip_extra.finish();6331 function.extra = wip_extra.finish();
6577 function.blocks = blocks;6332 function.blocks = blocks;
6578 function.names = names.ptr;6333 function.names = names.ptr;
6579 function.metadata = if (metadata) |new_metadata| new_metadata.ptr else null;6334 function.value_indices = value_indices.ptr;
6335 function.debug_locations = debug_locations;
6336 function.debug_values = debug_values;
6580 }6337 }
65816338
6582 pub fn deinit(self: *WipFunction) void {6339 pub fn deinit(self: *WipFunction) void {
6583 self.extra.deinit(self.builder.gpa);6340 self.extra.deinit(self.builder.gpa);
6584 self.metadata.deinit(self.builder.gpa);6341 self.debug_values.deinit(self.builder.gpa);
6342 self.debug_locations.deinit(self.builder.gpa);
6585 self.names.deinit(self.builder.gpa);6343 self.names.deinit(self.builder.gpa);
6586 self.instructions.deinit(self.builder.gpa);6344 self.instructions.deinit(self.builder.gpa);
6587 for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa);6345 for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa);
6588 self.blocks.deinit(self.builder.gpa);6346 self.blocks.deinit(self.builder.gpa);
6589 if (self.builder.useLibLlvm()) {
6590 self.llvm.instructions.deinit(self.builder.gpa);
6591 self.llvm.blocks.deinit(self.builder.gpa);
6592 self.llvm.builder.dispose();
6593 }
6594 self.* = undefined;6347 self.* = undefined;
6595 }6348 }
65966349
6597 fn cmpTag(6350 fn cmpTag(
6598 self: *WipFunction,6351 self: *WipFunction,
6599 tag: Instruction.Tag,6352 tag: Instruction.Tag,
6600 cond: u32,
6601 lhs: Value,6353 lhs: Value,
6602 rhs: Value,6354 rhs: Value,
6603 name: []const u8,6355 name: []const u8,
...@@ -6657,113 +6409,6 @@ pub const WipFunction = struct {...@@ -6657,113 +6409,6 @@ pub const WipFunction = struct {
6657 .rhs = rhs,6409 .rhs = rhs,
6658 }),6410 }),
6659 });6411 });
6660 if (self.builder.useLibLlvm()) {
6661 switch (tag) {
6662 .@"fcmp false",
6663 .@"fcmp oeq",
6664 .@"fcmp oge",
6665 .@"fcmp ogt",
6666 .@"fcmp ole",
6667 .@"fcmp olt",
6668 .@"fcmp one",
6669 .@"fcmp ord",
6670 .@"fcmp true",
6671 .@"fcmp ueq",
6672 .@"fcmp uge",
6673 .@"fcmp ugt",
6674 .@"fcmp ule",
6675 .@"fcmp ult",
6676 .@"fcmp une",
6677 .@"fcmp uno",
6678 => self.llvm.builder.setFastMath(false),
6679 .@"fcmp fast false",
6680 .@"fcmp fast oeq",
6681 .@"fcmp fast oge",
6682 .@"fcmp fast ogt",
6683 .@"fcmp fast ole",
6684 .@"fcmp fast olt",
6685 .@"fcmp fast one",
6686 .@"fcmp fast ord",
6687 .@"fcmp fast true",
6688 .@"fcmp fast ueq",
6689 .@"fcmp fast uge",
6690 .@"fcmp fast ugt",
6691 .@"fcmp fast ule",
6692 .@"fcmp fast ult",
6693 .@"fcmp fast une",
6694 .@"fcmp fast uno",
6695 => self.llvm.builder.setFastMath(true),
6696 .@"icmp eq",
6697 .@"icmp ne",
6698 .@"icmp sge",
6699 .@"icmp sgt",
6700 .@"icmp sle",
6701 .@"icmp slt",
6702 .@"icmp uge",
6703 .@"icmp ugt",
6704 .@"icmp ule",
6705 .@"icmp ult",
6706 => {},
6707 else => unreachable,
6708 }
6709 self.llvm.instructions.appendAssumeCapacity(switch (tag) {
6710 .@"fcmp false",
6711 .@"fcmp fast false",
6712 .@"fcmp fast oeq",
6713 .@"fcmp fast oge",
6714 .@"fcmp fast ogt",
6715 .@"fcmp fast ole",
6716 .@"fcmp fast olt",
6717 .@"fcmp fast one",
6718 .@"fcmp fast ord",
6719 .@"fcmp fast true",
6720 .@"fcmp fast ueq",
6721 .@"fcmp fast uge",
6722 .@"fcmp fast ugt",
6723 .@"fcmp fast ule",
6724 .@"fcmp fast ult",
6725 .@"fcmp fast une",
6726 .@"fcmp fast uno",
6727 .@"fcmp oeq",
6728 .@"fcmp oge",
6729 .@"fcmp ogt",
6730 .@"fcmp ole",
6731 .@"fcmp olt",
6732 .@"fcmp one",
6733 .@"fcmp ord",
6734 .@"fcmp true",
6735 .@"fcmp ueq",
6736 .@"fcmp uge",
6737 .@"fcmp ugt",
6738 .@"fcmp ule",
6739 .@"fcmp ult",
6740 .@"fcmp une",
6741 .@"fcmp uno",
6742 => self.llvm.builder.buildFCmp(
6743 @enumFromInt(cond),
6744 lhs.toLlvm(self),
6745 rhs.toLlvm(self),
6746 instruction.llvmName(self),
6747 ),
6748 .@"icmp eq",
6749 .@"icmp ne",
6750 .@"icmp sge",
6751 .@"icmp sgt",
6752 .@"icmp sle",
6753 .@"icmp slt",
6754 .@"icmp uge",
6755 .@"icmp ugt",
6756 .@"icmp ule",
6757 .@"icmp ult",
6758 => self.llvm.builder.buildICmp(
6759 @enumFromInt(cond),
6760 lhs.toLlvm(self),
6761 rhs.toLlvm(self),
6762 instruction.llvmName(self),
6763 ),
6764 else => unreachable,
6765 });
6766 }
6767 return instruction.toValue();6412 return instruction.toValue();
6768 }6413 }
67696414
...@@ -6785,16 +6430,6 @@ pub const WipFunction = struct {...@@ -6785,16 +6430,6 @@ pub const WipFunction = struct {
6785 .data = self.addExtraAssumeCapacity(Instruction.Phi{ .type = ty }),6430 .data = self.addExtraAssumeCapacity(Instruction.Phi{ .type = ty }),
6786 });6431 });
6787 _ = self.extra.addManyAsSliceAssumeCapacity(incoming * 2);6432 _ = self.extra.addManyAsSliceAssumeCapacity(incoming * 2);
6788 if (self.builder.useLibLlvm()) {
6789 switch (tag) {
6790 .phi => self.llvm.builder.setFastMath(false),
6791 .@"phi fast" => self.llvm.builder.setFastMath(true),
6792 else => unreachable,
6793 }
6794 self.llvm.instructions.appendAssumeCapacity(
6795 self.llvm.builder.buildPhi(ty.toLlvm(self.builder), instruction.llvmName(self)),
6796 );
6797 }
6798 return .{ .block = self.cursor.block, .instruction = instruction };6433 return .{ .block = self.cursor.block, .instruction = instruction };
6799 }6434 }
68006435
...@@ -6822,19 +6457,6 @@ pub const WipFunction = struct {...@@ -6822,19 +6457,6 @@ pub const WipFunction = struct {
6822 .rhs = rhs,6457 .rhs = rhs,
6823 }),6458 }),
6824 });6459 });
6825 if (self.builder.useLibLlvm()) {
6826 switch (tag) {
6827 .select => self.llvm.builder.setFastMath(false),
6828 .@"select fast" => self.llvm.builder.setFastMath(true),
6829 else => unreachable,
6830 }
6831 self.llvm.instructions.appendAssumeCapacity(self.llvm.builder.buildSelect(
6832 cond.toLlvm(self),
6833 lhs.toLlvm(self),
6834 rhs.toLlvm(self),
6835 instruction.llvmName(self),
6836 ));
6837 }
6838 return instruction.toValue();6460 return instruction.toValue();
6839 }6461 }
68406462
...@@ -6857,28 +6479,27 @@ pub const WipFunction = struct {...@@ -6857,28 +6479,27 @@ pub const WipFunction = struct {
6857 ) Allocator.Error!Instruction.Index {6479 ) Allocator.Error!Instruction.Index {
6858 const block_instructions = &self.cursor.block.ptr(self).instructions;6480 const block_instructions = &self.cursor.block.ptr(self).instructions;
6859 try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1);6481 try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
6860 if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, 1);6482 if (!self.builder.strip) {
6483 try self.names.ensureUnusedCapacity(self.builder.gpa, 1);
6484 try self.debug_locations.ensureUnusedCapacity(self.builder.gpa, 1);
6485 }
6861 try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1);6486 try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1);
6862 if (self.builder.useLibLlvm())
6863 try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
6864 const final_name = if (name) |n|6487 const final_name = if (name) |n|
6865 if (self.builder.strip) .empty else try self.builder.string(n)6488 if (self.builder.strip) .empty else try self.builder.string(n)
6866 else6489 else
6867 .none;6490 .none;
68686491
6869 if (self.builder.useLibLlvm()) self.llvm.builder.positionBuilder(
6870 self.cursor.block.toLlvm(self),
6871 for (block_instructions.items[self.cursor.instruction..]) |instruction_index| {
6872 const llvm_instruction =
6873 self.llvm.instructions.items[@intFromEnum(instruction_index)];
6874 // TODO: remove when constant propagation is implemented
6875 if (!llvm_instruction.isConstant().toBool()) break llvm_instruction;
6876 } else null,
6877 );
6878
6879 const index: Instruction.Index = @enumFromInt(self.instructions.len);6492 const index: Instruction.Index = @enumFromInt(self.instructions.len);
6880 self.instructions.appendAssumeCapacity(instruction);6493 self.instructions.appendAssumeCapacity(instruction);
6881 if (!self.builder.strip) self.names.appendAssumeCapacity(final_name);6494 if (!self.builder.strip) {
6495 self.names.appendAssumeCapacity(final_name);
6496 if (block_instructions.items.len == 0 or
6497 self.current_debug_location != self.last_debug_location)
6498 {
6499 self.debug_locations.putAssumeCapacity(index, self.current_debug_location);
6500 self.last_debug_location = self.current_debug_location;
6501 }
6502 }
6882 block_instructions.insertAssumeCapacity(self.cursor.instruction, index);6503 block_instructions.insertAssumeCapacity(self.cursor.instruction, index);
6883 self.cursor.instruction += 1;6504 self.cursor.instruction += 1;
6884 return index;6505 return index;
...@@ -6901,7 +6522,7 @@ pub const WipFunction = struct {...@@ -6901,7 +6522,7 @@ pub const WipFunction = struct {
6901 Instruction.Alloca.Info,6522 Instruction.Alloca.Info,
6902 Instruction.Call.Info,6523 Instruction.Call.Info,
6903 => @bitCast(value),6524 => @bitCast(value),
6904 else => @compileError("bad field type: " ++ @typeName(field.type)),6525 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
6905 });6526 });
6906 }6527 }
6907 return result;6528 return result;
...@@ -6949,7 +6570,7 @@ pub const WipFunction = struct {...@@ -6949,7 +6570,7 @@ pub const WipFunction = struct {
6949 Instruction.Alloca.Info,6570 Instruction.Alloca.Info,
6950 Instruction.Call.Info,6571 Instruction.Call.Info,
6951 => @bitCast(value),6572 => @bitCast(value),
6952 else => @compileError("bad field type: " ++ @typeName(field.type)),6573 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
6953 };6574 };
6954 return .{6575 return .{
6955 .data = result,6576 .data = result,
...@@ -6977,24 +6598,6 @@ pub const FloatCondition = enum(u4) {...@@ -6977,24 +6598,6 @@ pub const FloatCondition = enum(u4) {
6977 ult = 12,6598 ult = 12,
6978 ule = 13,6599 ule = 13,
6979 une = 14,6600 une = 14,
6980
6981 fn toLlvm(self: FloatCondition) llvm.RealPredicate {
6982 return switch (self) {
6983 .oeq => .OEQ,
6984 .ogt => .OGT,
6985 .oge => .OGE,
6986 .olt => .OLT,
6987 .ole => .OLE,
6988 .one => .ONE,
6989 .ord => .ORD,
6990 .uno => .UNO,
6991 .ueq => .UEQ,
6992 .ugt => .UGT,
6993 .uge => .UGE,
6994 .ult => .ULT,
6995 .uno => .UNE,
6996 };
6997 }
6998};6601};
69996602
7000pub const IntegerCondition = enum(u6) {6603pub const IntegerCondition = enum(u6) {
...@@ -7008,20 +6611,6 @@ pub const IntegerCondition = enum(u6) {...@@ -7008,20 +6611,6 @@ pub const IntegerCondition = enum(u6) {
7008 sge = 39,6611 sge = 39,
7009 slt = 40,6612 slt = 40,
7010 sle = 41,6613 sle = 41,
7011
7012 fn toLlvm(self: IntegerCondition) llvm.IntPredicate {
7013 return switch (self) {
7014 .eq => .EQ,
7015 .ne => .NE,
7016 .ugt => .UGT,
7017 .uge => .UGE,
7018 .ult => .ULT,
7019 .sgt => .SGT,
7020 .sge => .SGE,
7021 .slt => .SLT,
7022 .sle => .SLE,
7023 };
7024 }
7025};6614};
70266615
7027pub const MemoryAccessKind = enum(u1) {6616pub const MemoryAccessKind = enum(u1) {
...@@ -7058,10 +6647,10 @@ pub const AtomicOrdering = enum(u3) {...@@ -7058,10 +6647,10 @@ pub const AtomicOrdering = enum(u3) {
7058 none = 0,6647 none = 0,
7059 unordered = 1,6648 unordered = 1,
7060 monotonic = 2,6649 monotonic = 2,
7061 acquire = 4,6650 acquire = 3,
7062 release = 5,6651 release = 4,
7063 acq_rel = 6,6652 acq_rel = 5,
7064 seq_cst = 7,6653 seq_cst = 6,
70656654
7066 pub fn format(6655 pub fn format(
7067 self: AtomicOrdering,6656 self: AtomicOrdering,
...@@ -7071,18 +6660,6 @@ pub const AtomicOrdering = enum(u3) {...@@ -7071,18 +6660,6 @@ pub const AtomicOrdering = enum(u3) {
7071 ) @TypeOf(writer).Error!void {6660 ) @TypeOf(writer).Error!void {
7072 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });6661 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
7073 }6662 }
7074
7075 fn toLlvm(self: AtomicOrdering) llvm.AtomicOrdering {
7076 return switch (self) {
7077 .none => .NotAtomic,
7078 .unordered => .Unordered,
7079 .monotonic => .Monotonic,
7080 .acquire => .Acquire,
7081 .release => .Release,
7082 .acq_rel => .AcquireRelease,
7083 .seq_cst => .SequentiallyConsistent,
7084 };
7085 }
7086};6663};
70876664
7088const MemoryAccessInfo = packed struct(u32) {6665const MemoryAccessInfo = packed struct(u32) {
...@@ -7095,7 +6672,8 @@ const MemoryAccessInfo = packed struct(u32) {...@@ -7095,7 +6672,8 @@ const MemoryAccessInfo = packed struct(u32) {
7095 _: u13 = undefined,6672 _: u13 = undefined,
7096};6673};
70976674
7098pub const FastMath = packed struct(u32) {6675pub const FastMath = packed struct(u8) {
6676 unsafe_algebra: bool = false, // Legacy
7099 nnan: bool = false,6677 nnan: bool = false,
7100 ninf: bool = false,6678 ninf: bool = false,
7101 nsz: bool = false,6679 nsz: bool = false,
...@@ -7130,11 +6708,13 @@ pub const FastMathKind = enum {...@@ -7130,11 +6708,13 @@ pub const FastMathKind = enum {
7130pub const Constant = enum(u32) {6708pub const Constant = enum(u32) {
7131 false,6709 false,
7132 true,6710 true,
6711 @"0",
6712 @"1",
7133 none,6713 none,
7134 no_init = 1 << 31,6714 no_init = (1 << 30) - 1,
7135 _,6715 _,
71366716
7137 const first_global: Constant = @enumFromInt(1 << 30);6717 const first_global: Constant = @enumFromInt(1 << 29);
71386718
7139 pub const Tag = enum(u7) {6719 pub const Tag = enum(u7) {
7140 positive_integer,6720 positive_integer,
...@@ -7152,7 +6732,6 @@ pub const Constant = enum(u32) {...@@ -7152,7 +6732,6 @@ pub const Constant = enum(u32) {
7152 packed_structure,6732 packed_structure,
7153 array,6733 array,
7154 string,6734 string,
7155 string_null,
7156 vector,6735 vector,
7157 splat,6736 splat,
7158 zeroinitializer,6737 zeroinitializer,
...@@ -7212,6 +6791,49 @@ pub const Constant = enum(u32) {...@@ -7212,6 +6791,49 @@ pub const Constant = enum(u32) {
7212 @"asm sideeffect inteldialect unwind",6791 @"asm sideeffect inteldialect unwind",
7213 @"asm alignstack inteldialect unwind",6792 @"asm alignstack inteldialect unwind",
7214 @"asm sideeffect alignstack inteldialect unwind",6793 @"asm sideeffect alignstack inteldialect unwind",
6794
6795 pub fn toBinaryOpcode(self: Tag) BinaryOpcode {
6796 return switch (self) {
6797 .add,
6798 .@"add nsw",
6799 .@"add nuw",
6800 => .add,
6801 .sub,
6802 .@"sub nsw",
6803 .@"sub nuw",
6804 => .sub,
6805 .mul,
6806 .@"mul nsw",
6807 .@"mul nuw",
6808 => .mul,
6809 .shl => .shl,
6810 .lshr => .lshr,
6811 .ashr => .ashr,
6812 .@"and" => .@"and",
6813 .@"or" => .@"or",
6814 .xor => .xor,
6815 else => unreachable,
6816 };
6817 }
6818
6819 pub fn toCastOpcode(self: Tag) CastOpcode {
6820 return switch (self) {
6821 .trunc => .trunc,
6822 .zext => .zext,
6823 .sext => .sext,
6824 .fptoui => .fptoui,
6825 .fptosi => .fptosi,
6826 .uitofp => .uitofp,
6827 .sitofp => .sitofp,
6828 .fptrunc => .fptrunc,
6829 .fpext => .fpext,
6830 .ptrtoint => .ptrtoint,
6831 .inttoptr => .inttoptr,
6832 .bitcast => .bitcast,
6833 .addrspacecast => .addrspacecast,
6834 else => unreachable,
6835 };
6836 }
7215 };6837 };
72166838
7217 pub const Item = struct {6839 pub const Item = struct {
...@@ -7364,11 +6986,8 @@ pub const Constant = enum(u32) {...@@ -7364,11 +6986,8 @@ pub const Constant = enum(u32) {
7364 .vector,6986 .vector,
7365 => builder.constantExtraData(Aggregate, item.data).type,6987 => builder.constantExtraData(Aggregate, item.data).type,
7366 .splat => builder.constantExtraData(Splat, item.data).type,6988 .splat => builder.constantExtraData(Splat, item.data).type,
7367 .string,6989 .string => builder.arrayTypeAssumeCapacity(
7368 .string_null,6990 @as(String, @enumFromInt(item.data)).slice(builder).?.len,
7369 => builder.arrayTypeAssumeCapacity(
7370 @as(String, @enumFromInt(item.data)).slice(builder).?.len +
7371 @intFromBool(item.tag == .string_null),
7372 .i8,6991 .i8,
7373 ),6992 ),
7374 .blockaddress => builder.ptrTypeAssumeCapacity(6993 .blockaddress => builder.ptrTypeAssumeCapacity(
...@@ -7574,7 +7193,7 @@ pub const Constant = enum(u32) {...@@ -7574,7 +7193,7 @@ pub const Constant = enum(u32) {
7574 @ptrCast(data.builder.constant_limbs.items[item.data..][0..Integer.limbs]);7193 @ptrCast(data.builder.constant_limbs.items[item.data..][0..Integer.limbs]);
7575 const limbs = data.builder.constant_limbs7194 const limbs = data.builder.constant_limbs
7576 .items[item.data + Integer.limbs ..][0..extra.limbs_len];7195 .items[item.data + Integer.limbs ..][0..extra.limbs_len];
7577 const bigint = std.math.big.int.Const{7196 const bigint: std.math.big.int.Const = .{
7578 .limbs = limbs,7197 .limbs = limbs,
7579 .positive = tag == .positive_integer,7198 .positive = tag == .positive_integer,
7580 };7199 };
...@@ -7616,17 +7235,31 @@ pub const Constant = enum(u32) {...@@ -7616,17 +7235,31 @@ pub const Constant = enum(u32) {
7616 };7235 };
7617 }7236 }
7618 };7237 };
7238 const Mantissa64 = std.meta.FieldType(Float.Repr(f64), .mantissa);
7619 const Exponent32 = std.meta.FieldType(Float.Repr(f32), .exponent);7239 const Exponent32 = std.meta.FieldType(Float.Repr(f32), .exponent);
7620 const Exponent64 = std.meta.FieldType(Float.Repr(f64), .exponent);7240 const Exponent64 = std.meta.FieldType(Float.Repr(f64), .exponent);
7241
7621 const repr: Float.Repr(f32) = @bitCast(item.data);7242 const repr: Float.Repr(f32) = @bitCast(item.data);
7243 const denormal_shift = switch (repr.exponent) {
7244 std.math.minInt(Exponent32) => @as(
7245 std.math.Log2Int(Mantissa64),
7246 @clz(repr.mantissa),
7247 ) + 1,
7248 else => 0,
7249 };
7622 try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){7250 try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){
7623 .mantissa = std.math.shl(7251 .mantissa = std.math.shl(
7624 std.meta.FieldType(Float.Repr(f64), .mantissa),7252 Mantissa64,
7625 repr.mantissa,7253 repr.mantissa,
7626 std.math.floatMantissaBits(f64) - std.math.floatMantissaBits(f32),7254 std.math.floatMantissaBits(f64) - std.math.floatMantissaBits(f32) +
7255 denormal_shift,
7627 ),7256 ),
7628 .exponent = switch (repr.exponent) {7257 .exponent = switch (repr.exponent) {
7629 std.math.minInt(Exponent32) => std.math.minInt(Exponent64),7258 std.math.minInt(Exponent32) => if (repr.mantissa > 0)
7259 @as(Exponent64, std.math.floatExponentMin(f32) +
7260 std.math.floatExponentMax(f64)) - denormal_shift
7261 else
7262 std.math.minInt(Exponent64),
7630 else => @as(Exponent64, repr.exponent) +7263 else => @as(Exponent64, repr.exponent) +
7631 (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)),7264 (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)),
7632 std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64),7265 std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64),
...@@ -7703,13 +7336,9 @@ pub const Constant = enum(u32) {...@@ -7703,13 +7336,9 @@ pub const Constant = enum(u32) {
7703 }7336 }
7704 try writer.writeByte('>');7337 try writer.writeByte('>');
7705 },7338 },
7706 inline .string,7339 .string => try writer.print("c{\"}", .{
7707 .string_null,7340 @as(String, @enumFromInt(item.data)).fmt(data.builder),
7708 => |tag| try writer.print("c{\"" ++ switch (tag) {7341 }),
7709 .string => "",
7710 .string_null => "@",
7711 else => unreachable,
7712 } ++ "}", .{@as(String, @enumFromInt(item.data)).fmt(data.builder)}),
7713 .blockaddress => |tag| {7342 .blockaddress => |tag| {
7714 const extra = data.builder.constantExtraData(BlockAddress, item.data);7343 const extra = data.builder.constantExtraData(BlockAddress, item.data);
7715 const function = extra.function.ptrConst(data.builder);7344 const function = extra.function.ptrConst(data.builder);
...@@ -7859,40 +7488,37 @@ pub const Constant = enum(u32) {...@@ -7859,40 +7488,37 @@ pub const Constant = enum(u32) {
7859 pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) {7488 pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) {
7860 return .{ .data = .{ .constant = self, .builder = builder } };7489 return .{ .data = .{ .constant = self, .builder = builder } };
7861 }7490 }
7862
7863 pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value {
7864 assert(builder.useLibLlvm());
7865 const llvm_value = switch (self.unwrap()) {
7866 .constant => |constant| builder.llvm.constants.items[constant],
7867 .global => |global| return global.toLlvm(builder),
7868 };
7869 const global = builder.llvm.replacements.get(llvm_value) orelse return llvm_value;
7870 return global.toLlvm(builder);
7871 }
7872};7491};
78737492
7874pub const Value = enum(u32) {7493pub const Value = enum(u32) {
7875 none = std.math.maxInt(u31),7494 none = std.math.maxInt(u31),
7876 false = first_constant + @intFromEnum(Constant.false),7495 false = first_constant + @intFromEnum(Constant.false),
7877 true = first_constant + @intFromEnum(Constant.true),7496 true = first_constant + @intFromEnum(Constant.true),
7497 @"0" = first_constant + @intFromEnum(Constant.@"0"),
7498 @"1" = first_constant + @intFromEnum(Constant.@"1"),
7878 _,7499 _,
78797500
7880 const first_constant = 1 << 31;7501 const first_constant = 1 << 30;
7502 const first_metadata = 1 << 31;
78817503
7882 pub fn unwrap(self: Value) union(enum) {7504 pub fn unwrap(self: Value) union(enum) {
7883 instruction: Function.Instruction.Index,7505 instruction: Function.Instruction.Index,
7884 constant: Constant,7506 constant: Constant,
7507 metadata: Metadata,
7885 } {7508 } {
7886 return if (@intFromEnum(self) < first_constant)7509 return if (@intFromEnum(self) < first_constant)
7887 .{ .instruction = @enumFromInt(@intFromEnum(self)) }7510 .{ .instruction = @enumFromInt(@intFromEnum(self)) }
7511 else if (@intFromEnum(self) < first_metadata)
7512 .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) }
7888 else7513 else
7889 .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) };7514 .{ .metadata = @enumFromInt(@intFromEnum(self) - first_metadata) };
7890 }7515 }
78917516
7892 pub fn typeOfWip(self: Value, wip: *const WipFunction) Type {7517 pub fn typeOfWip(self: Value, wip: *const WipFunction) Type {
7893 return switch (self.unwrap()) {7518 return switch (self.unwrap()) {
7894 .instruction => |instruction| instruction.typeOfWip(wip),7519 .instruction => |instruction| instruction.typeOfWip(wip),
7895 .constant => |constant| constant.typeOf(wip.builder),7520 .constant => |constant| constant.typeOf(wip.builder),
7521 .metadata => .metadata,
7896 };7522 };
7897 }7523 }
78987524
...@@ -7900,12 +7526,13 @@ pub const Value = enum(u32) {...@@ -7900,12 +7526,13 @@ pub const Value = enum(u32) {
7900 return switch (self.unwrap()) {7526 return switch (self.unwrap()) {
7901 .instruction => |instruction| instruction.typeOf(function, builder),7527 .instruction => |instruction| instruction.typeOf(function, builder),
7902 .constant => |constant| constant.typeOf(builder),7528 .constant => |constant| constant.typeOf(builder),
7529 .metadata => .metadata,
7903 };7530 };
7904 }7531 }
79057532
7906 pub fn toConst(self: Value) ?Constant {7533 pub fn toConst(self: Value) ?Constant {
7907 return switch (self.unwrap()) {7534 return switch (self.unwrap()) {
7908 .instruction => null,7535 .instruction, .metadata => null,
7909 .constant => |constant| constant,7536 .constant => |constant| constant,
7910 };7537 };
7911 }7538 }
...@@ -7931,397 +7558,854 @@ pub const Value = enum(u32) {...@@ -7931,397 +7558,854 @@ pub const Value = enum(u32) {
7931 .constant = constant,7558 .constant = constant,
7932 .builder = data.builder,7559 .builder = data.builder,
7933 }, fmt_str, fmt_opts, writer),7560 }, fmt_str, fmt_opts, writer),
7561 .metadata => unreachable,
7934 }7562 }
7935 }7563 }
7936 pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) {7564 pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) {
7937 return .{ .data = .{ .value = self, .function = function, .builder = builder } };7565 return .{ .data = .{ .value = self, .function = function, .builder = builder } };
7938 }7566 }
7567};
79397568
7940 pub fn toLlvm(self: Value, wip: *const WipFunction) *llvm.Value {7569pub const MetadataString = enum(u32) {
7941 return switch (self.unwrap()) {7570 none = 0,
7942 .instruction => |instruction| instruction.toLlvm(wip),7571 _,
7943 .constant => |constant| constant.toLlvm(wip.builder),7572
7944 };7573 pub fn slice(self: MetadataString, builder: *const Builder) []const u8 {
7574 const index = @intFromEnum(self);
7575 const start = builder.metadata_string_indices.items[index];
7576 const end = builder.metadata_string_indices.items[index + 1];
7577 return builder.metadata_string_bytes.items[start..end];
7945 }7578 }
7946};
79477579
7948pub const Metadata = enum(u32) { _ };7580 const Adapter = struct {
7581 builder: *const Builder,
7582 pub fn hash(_: Adapter, key: []const u8) u32 {
7583 return @truncate(std.hash.Wyhash.hash(0, key));
7584 }
7585 pub fn eql(ctx: Adapter, lhs_key: []const u8, _: void, rhs_index: usize) bool {
7586 const rhs_metadata_string: MetadataString = @enumFromInt(rhs_index);
7587 return std.mem.eql(u8, lhs_key, rhs_metadata_string.slice(ctx.builder));
7588 }
7589 };
79497590
7950pub const InitError = error{7591 const FormatData = struct {
7951 InvalidLlvmTriple,7592 metadata_string: MetadataString,
7952} || Allocator.Error;7593 builder: *const Builder,
7594 };
7595 fn format(
7596 data: FormatData,
7597 comptime _: []const u8,
7598 _: std.fmt.FormatOptions,
7599 writer: anytype,
7600 ) @TypeOf(writer).Error!void {
7601 try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, writer);
7602 }
7603 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(format) {
7604 return .{ .data = .{ .metadata_string = self, .builder = builder } };
7605 }
7606};
79537607
7954pub fn init(options: Options) InitError!Builder {7608pub const Metadata = enum(u32) {
7955 var self = Builder{7609 none = 0,
7956 .gpa = options.allocator,7610 _,
7957 .use_lib_llvm = options.use_lib_llvm,
7958 .strip = options.strip,
79597611
7960 .llvm = undefined,7612 const first_forward_reference = 1 << 29;
7613 const first_local_metadata = 1 << 30;
79617614
7962 .source_filename = .none,7615 pub const Tag = enum(u6) {
7963 .data_layout = .none,7616 none,
7964 .target_triple = .none,7617 file,
7965 .module_asm = .{},7618 compile_unit,
7619 @"compile_unit optimized",
7620 subprogram,
7621 @"subprogram local",
7622 @"subprogram definition",
7623 @"subprogram local definition",
7624 @"subprogram optimized",
7625 @"subprogram optimized local",
7626 @"subprogram optimized definition",
7627 @"subprogram optimized local definition",
7628 lexical_block,
7629 location,
7630 basic_bool_type,
7631 basic_unsigned_type,
7632 basic_signed_type,
7633 basic_float_type,
7634 composite_struct_type,
7635 composite_union_type,
7636 composite_enumeration_type,
7637 composite_array_type,
7638 composite_vector_type,
7639 derived_pointer_type,
7640 derived_member_type,
7641 subroutine_type,
7642 enumerator_unsigned,
7643 enumerator_signed_positive,
7644 enumerator_signed_negative,
7645 subrange,
7646 tuple,
7647 module_flag,
7648 expression,
7649 local_var,
7650 parameter,
7651 global_var,
7652 @"global_var local",
7653 global_var_expression,
7654 constant,
7655
7656 pub fn isInline(tag: Tag) bool {
7657 return switch (tag) {
7658 .none,
7659 .expression,
7660 .constant,
7661 => true,
7662 .file,
7663 .compile_unit,
7664 .@"compile_unit optimized",
7665 .subprogram,
7666 .@"subprogram local",
7667 .@"subprogram definition",
7668 .@"subprogram local definition",
7669 .@"subprogram optimized",
7670 .@"subprogram optimized local",
7671 .@"subprogram optimized definition",
7672 .@"subprogram optimized local definition",
7673 .lexical_block,
7674 .location,
7675 .basic_bool_type,
7676 .basic_unsigned_type,
7677 .basic_signed_type,
7678 .basic_float_type,
7679 .composite_struct_type,
7680 .composite_union_type,
7681 .composite_enumeration_type,
7682 .composite_array_type,
7683 .composite_vector_type,
7684 .derived_pointer_type,
7685 .derived_member_type,
7686 .subroutine_type,
7687 .enumerator_unsigned,
7688 .enumerator_signed_positive,
7689 .enumerator_signed_negative,
7690 .subrange,
7691 .tuple,
7692 .module_flag,
7693 .local_var,
7694 .parameter,
7695 .global_var,
7696 .@"global_var local",
7697 .global_var_expression,
7698 => false,
7699 };
7700 }
7701 };
79667702
7967 .string_map = .{},7703 pub fn isInline(self: Metadata, builder: *const Builder) bool {
7968 .string_indices = .{},7704 return builder.metadata_items.items(.tag)[@intFromEnum(self)].isInline();
7969 .string_bytes = .{},7705 }
79707706
7971 .types = .{},7707 pub fn unwrap(self: Metadata, builder: *const Builder) Metadata {
7972 .next_unnamed_type = @enumFromInt(0),7708 var metadata = self;
7973 .next_unique_type_id = .{},7709 while (@intFromEnum(metadata) >= Metadata.first_forward_reference and
7974 .type_map = .{},7710 @intFromEnum(metadata) < Metadata.first_local_metadata)
7975 .type_items = .{},7711 {
7976 .type_extra = .{},7712 const index = @intFromEnum(metadata) - Metadata.first_forward_reference;
7713 metadata = builder.metadata_forward_references.items[index];
7714 assert(metadata != .none);
7715 }
7716 return metadata;
7717 }
79777718
7978 .attributes = .{},7719 pub const Item = struct {
7979 .attributes_map = .{},7720 tag: Tag,
7980 .attributes_indices = .{},7721 data: ExtraIndex,
7981 .attributes_extra = .{},
79827722
7983 .globals = .{},7723 const ExtraIndex = u32;
7984 .next_unnamed_global = @enumFromInt(0),7724 };
7985 .next_replaced_global = .none,
7986 .next_unique_global_id = .{},
7987 .aliases = .{},
7988 .variables = .{},
7989 .functions = .{},
79907725
7991 .constant_map = .{},7726 pub const DIFlags = packed struct(u32) {
7992 .constant_items = .{},7727 Visibility: enum(u2) { Zero, Private, Protected, Public } = .Zero,
7993 .constant_extra = .{},7728 FwdDecl: bool = false,
7994 .constant_limbs = .{},7729 AppleBlock: bool = false,
7730 ReservedBit4: u1 = 0,
7731 Virtual: bool = false,
7732 Artificial: bool = false,
7733 Explicit: bool = false,
7734 Prototyped: bool = false,
7735 ObjcClassComplete: bool = false,
7736 ObjectPointer: bool = false,
7737 Vector: bool = false,
7738 StaticMember: bool = false,
7739 LValueReference: bool = false,
7740 RValueReference: bool = false,
7741 ExportSymbols: bool = false,
7742 Inheritance: enum(u2) {
7743 Zero,
7744 SingleInheritance,
7745 MultipleInheritance,
7746 VirtualInheritance,
7747 } = .Zero,
7748 IntroducedVirtual: bool = false,
7749 BitField: bool = false,
7750 NoReturn: bool = false,
7751 ReservedBit21: u1 = 0,
7752 TypePassbyValue: bool = false,
7753 TypePassbyReference: bool = false,
7754 EnumClass: bool = false,
7755 Thunk: bool = false,
7756 NonTrivial: bool = false,
7757 BigEndian: bool = false,
7758 LittleEndian: bool = false,
7759 AllCallsDescribed: bool = false,
7760 Unused: u2 = 0,
7761
7762 pub fn format(
7763 self: DIFlags,
7764 comptime _: []const u8,
7765 _: std.fmt.FormatOptions,
7766 writer: anytype,
7767 ) @TypeOf(writer).Error!void {
7768 var need_pipe = false;
7769 inline for (@typeInfo(DIFlags).Struct.fields) |field| {
7770 switch (@typeInfo(field.type)) {
7771 .Bool => if (@field(self, field.name)) {
7772 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;
7773 try writer.print("DIFlag{s}", .{field.name});
7774 },
7775 .Enum => if (@field(self, field.name) != .Zero) {
7776 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;
7777 try writer.print("DIFlag{s}", .{@tagName(@field(self, field.name))});
7778 },
7779 .Int => assert(@field(self, field.name) == 0),
7780 else => @compileError("bad field type: " ++ field.name ++ ": " ++
7781 @typeName(field.type)),
7782 }
7783 }
7784 if (!need_pipe) try writer.writeByte('0');
7785 }
7995 };7786 };
7996 if (self.useLibLlvm()) self.llvm = .{7787
7997 .context = llvm.Context.create(),7788 pub const File = struct {
7998 .module = null,7789 filename: MetadataString,
7999 .target = null,7790 directory: MetadataString,
8000 .di_builder = null,
8001 .di_compile_unit = null,
8002 .attribute_kind_ids = null,
8003 .attributes = .{},
8004 .types = .{},
8005 .globals = .{},
8006 .constants = .{},
8007 .replacements = .{},
8008 };7791 };
8009 errdefer self.deinit();
80107792
8011 try self.string_indices.append(self.gpa, 0);7793 pub const CompileUnit = struct {
8012 assert(try self.string("") == .empty);7794 pub const Options = struct {
7795 optimized: bool,
7796 };
80137797
8014 if (options.name.len > 0) self.source_filename = try self.string(options.name);7798 file: Metadata,
8015 if (self.useLibLlvm()) {7799 producer: MetadataString,
8016 initializeLLVMTarget(options.target.cpu.arch);7800 enums: Metadata,
8017 self.llvm.module = llvm.Module.createWithName(7801 globals: Metadata,
8018 (self.source_filename.slice(&self) orelse ""),7802 };
8019 self.llvm.context,
8020 );
8021 }
80227803
8023 if (options.triple.len > 0) {7804 pub const Subprogram = struct {
8024 self.target_triple = try self.string(options.triple);7805 pub const Options = struct {
7806 di_flags: DIFlags,
7807 sp_flags: DISPFlags,
7808 };
80257809
8026 if (self.useLibLlvm()) {7810 pub const DISPFlags = packed struct(u32) {
8027 var error_message: [*:0]const u8 = undefined;7811 Virtuality: enum(u2) { Zero, Virtual, PureVirtual } = .Zero,
8028 var target: *llvm.Target = undefined;7812 LocalToUnit: bool = false,
8029 if (llvm.Target.getFromTriple(7813 Definition: bool = false,
8030 self.target_triple.slice(&self).?,7814 Optimized: bool = false,
8031 &target,7815 Pure: bool = false,
8032 &error_message,7816 Elemental: bool = false,
8033 ).toBool()) {7817 Recursive: bool = false,
8034 defer llvm.disposeMessage(error_message);7818 MainSubprogram: bool = false,
80357819 Deleted: bool = false,
8036 log.err("LLVM failed to parse '{s}': {s}", .{7820 ReservedBit10: u1 = 0,
8037 self.target_triple.slice(&self).?,7821 ObjCDirect: bool = false,
8038 error_message,7822 Unused: u20 = 0,
8039 });7823
8040 return InitError.InvalidLlvmTriple;7824 pub fn format(
7825 self: DISPFlags,
7826 comptime _: []const u8,
7827 _: std.fmt.FormatOptions,
7828 writer: anytype,
7829 ) @TypeOf(writer).Error!void {
7830 var need_pipe = false;
7831 inline for (@typeInfo(DISPFlags).Struct.fields) |field| {
7832 switch (@typeInfo(field.type)) {
7833 .Bool => if (@field(self, field.name)) {
7834 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;
7835 try writer.print("DISPFlag{s}", .{field.name});
7836 },
7837 .Enum => if (@field(self, field.name) != .Zero) {
7838 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;
7839 try writer.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});
7840 },
7841 .Int => assert(@field(self, field.name) == 0),
7842 else => @compileError("bad field type: " ++ field.name ++ ": " ++
7843 @typeName(field.type)),
7844 }
7845 }
7846 if (!need_pipe) try writer.writeByte('0');
8041 }7847 }
8042 self.llvm.target = target;7848 };
8043 self.llvm.module.?.setTarget(self.target_triple.slice(&self).?);7849
7850 file: Metadata,
7851 name: MetadataString,
7852 linkage_name: MetadataString,
7853 line: u32,
7854 scope_line: u32,
7855 ty: Metadata,
7856 di_flags: DIFlags,
7857 compile_unit: Metadata,
7858 };
7859
7860 pub const LexicalBlock = struct {
7861 scope: Metadata,
7862 file: Metadata,
7863 line: u32,
7864 column: u32,
7865 };
7866
7867 pub const Location = struct {
7868 line: u32,
7869 column: u32,
7870 scope: Metadata,
7871 inlined_at: Metadata,
7872 };
7873
7874 pub const BasicType = struct {
7875 name: MetadataString,
7876 size_in_bits_lo: u32,
7877 size_in_bits_hi: u32,
7878
7879 pub fn bitSize(self: BasicType) u64 {
7880 return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo;
8044 }7881 }
8045 }7882 };
80467883
8047 {7884 pub const CompositeType = struct {
8048 const static_len = @typeInfo(Type).Enum.fields.len - 1;7885 name: MetadataString,
8049 try self.type_map.ensureTotalCapacity(self.gpa, static_len);7886 file: Metadata,
8050 try self.type_items.ensureTotalCapacity(self.gpa, static_len);7887 scope: Metadata,
8051 if (self.useLibLlvm()) try self.llvm.types.ensureTotalCapacity(self.gpa, static_len);7888 line: u32,
8052 inline for (@typeInfo(Type.Simple).Enum.fields) |simple_field| {7889 underlying_type: Metadata,
8053 const result = self.getOrPutTypeNoExtraAssumeCapacity(7890 size_in_bits_lo: u32,
8054 .{ .tag = .simple, .data = simple_field.value },7891 size_in_bits_hi: u32,
8055 );7892 align_in_bits_lo: u32,
8056 assert(result.new and result.type == @field(Type, simple_field.name));7893 align_in_bits_hi: u32,
8057 if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity(7894 fields_tuple: Metadata,
8058 @field(llvm.Context, simple_field.name ++ "Type")(self.llvm.context),7895
8059 );7896 pub fn bitSize(self: CompositeType) u64 {
7897 return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo;
8060 }7898 }
8061 inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits|7899 pub fn bitAlign(self: CompositeType) u64 {
8062 assert(self.intTypeAssumeCapacity(bits) ==7900 return @as(u64, self.align_in_bits_hi) << 32 | self.align_in_bits_lo;
8063 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
8064 inline for (.{ 0, 4 }) |addr_space_index| {
8065 const addr_space: AddrSpace = @enumFromInt(addr_space_index);
8066 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8067 @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space})));
8068 }7901 }
8069 }7902 };
80707903
8071 {7904 pub const DerivedType = struct {
8072 if (self.useLibLlvm()) {7905 name: MetadataString,
8073 self.llvm.attribute_kind_ids = try self.gpa.create([Attribute.Kind.len]c_uint);7906 file: Metadata,
8074 @memset(self.llvm.attribute_kind_ids.?, 0);7907 scope: Metadata,
7908 line: u32,
7909 underlying_type: Metadata,
7910 size_in_bits_lo: u32,
7911 size_in_bits_hi: u32,
7912 align_in_bits_lo: u32,
7913 align_in_bits_hi: u32,
7914 offset_in_bits_lo: u32,
7915 offset_in_bits_hi: u32,
7916
7917 pub fn bitSize(self: DerivedType) u64 {
7918 return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo;
8075 }7919 }
8076 try self.attributes_indices.append(self.gpa, 0);7920 pub fn bitAlign(self: DerivedType) u64 {
8077 assert(try self.attrs(&.{}) == .none);7921 return @as(u64, self.align_in_bits_hi) << 32 | self.align_in_bits_lo;
8078 assert(try self.fnAttrs(&.{}) == .none);7922 }
8079 }7923 pub fn bitOffset(self: DerivedType) u64 {
7924 return @as(u64, self.offset_in_bits_hi) << 32 | self.offset_in_bits_lo;
7925 }
7926 };
80807927
8081 assert(try self.intConst(.i1, 0) == .false);7928 pub const SubroutineType = struct {
8082 assert(try self.intConst(.i1, 1) == .true);7929 types_tuple: Metadata,
8083 assert(try self.noneConst(.token) == .none);7930 };
80847931
8085 return self;7932 pub const Enumerator = struct {
8086}7933 name: MetadataString,
7934 bit_width: u32,
7935 limbs_index: u32,
7936 limbs_len: u32,
7937 };
80877938
8088pub fn deinit(self: *Builder) void {7939 pub const Subrange = struct {
8089 if (self.useLibLlvm()) {7940 lower_bound: Metadata,
8090 var replacement_it = self.llvm.replacements.keyIterator();7941 count: Metadata,
8091 while (replacement_it.next()) |replacement| replacement.*.deleteGlobalValue();7942 };
8092 self.llvm.replacements.deinit(self.gpa);
8093 self.llvm.constants.deinit(self.gpa);
8094 self.llvm.globals.deinit(self.gpa);
8095 self.llvm.types.deinit(self.gpa);
8096 self.llvm.attributes.deinit(self.gpa);
8097 if (self.llvm.attribute_kind_ids) |attribute_kind_ids| self.gpa.destroy(attribute_kind_ids);
8098 if (self.llvm.di_builder) |di_builder| di_builder.dispose();
8099 if (self.llvm.module) |module| module.dispose();
8100 self.llvm.context.dispose();
8101 }
81027943
8103 self.module_asm.deinit(self.gpa);7944 pub const Expression = struct {
7945 elements_len: u32,
81047946
8105 self.string_map.deinit(self.gpa);7947 // elements: [elements_len]u32
8106 self.string_indices.deinit(self.gpa);7948 };
8107 self.string_bytes.deinit(self.gpa);
81087949
8109 self.types.deinit(self.gpa);7950 pub const Tuple = struct {
8110 self.next_unique_type_id.deinit(self.gpa);7951 elements_len: u32,
8111 self.type_map.deinit(self.gpa);
8112 self.type_items.deinit(self.gpa);
8113 self.type_extra.deinit(self.gpa);
81147952
8115 self.attributes.deinit(self.gpa);7953 // elements: [elements_len]Metadata
8116 self.attributes_map.deinit(self.gpa);7954 };
8117 self.attributes_indices.deinit(self.gpa);
8118 self.attributes_extra.deinit(self.gpa);
81197955
8120 self.globals.deinit(self.gpa);7956 pub const ModuleFlag = struct {
8121 self.next_unique_global_id.deinit(self.gpa);7957 behavior: Metadata,
8122 self.aliases.deinit(self.gpa);7958 name: MetadataString,
8123 self.variables.deinit(self.gpa);7959 constant: Metadata,
8124 for (self.functions.items) |*function| function.deinit(self.gpa);7960 };
8125 self.functions.deinit(self.gpa);
81267961
8127 self.constant_map.deinit(self.gpa);7962 pub const LocalVar = struct {
8128 self.constant_items.deinit(self.gpa);7963 name: MetadataString,
8129 self.constant_extra.deinit(self.gpa);7964 file: Metadata,
8130 self.constant_limbs.deinit(self.gpa);7965 scope: Metadata,
7966 line: u32,
7967 ty: Metadata,
7968 };
81317969
8132 self.* = undefined;7970 pub const Parameter = struct {
8133}7971 name: MetadataString,
7972 file: Metadata,
7973 scope: Metadata,
7974 line: u32,
7975 ty: Metadata,
7976 arg_no: u32,
7977 };
7978
7979 pub const GlobalVar = struct {
7980 pub const Options = struct {
7981 local: bool,
7982 };
7983
7984 name: MetadataString,
7985 linkage_name: MetadataString,
7986 file: Metadata,
7987 scope: Metadata,
7988 line: u32,
7989 ty: Metadata,
7990 variable: Variable.Index,
7991 };
7992
7993 pub const GlobalVarExpression = struct {
7994 variable: Metadata,
7995 expression: Metadata,
7996 };
7997
7998 pub fn toValue(self: Metadata) Value {
7999 return @enumFromInt(Value.first_metadata + @intFromEnum(self));
8000 }
8001
8002 const Formatter = struct {
8003 builder: *Builder,
8004 need_comma: bool,
8005 map: std.AutoArrayHashMapUnmanaged(Metadata, void) = .{},
8006
8007 const FormatData = struct {
8008 formatter: *Formatter,
8009 prefix: []const u8 = "",
8010 node: Node,
8011
8012 const Node = union(enum) {
8013 none,
8014 @"inline": Metadata,
8015 index: u32,
8016
8017 local_value: ValueData,
8018 local_metadata: ValueData,
8019 local_inline: Metadata,
8020 local_index: u32,
8021
8022 string: MetadataString,
8023 bool: bool,
8024 u32: u32,
8025 u64: u64,
8026 di_flags: DIFlags,
8027 sp_flags: Subprogram.DISPFlags,
8028 raw: []const u8,
8029
8030 const ValueData = struct {
8031 value: Value,
8032 function: Function.Index,
8033 };
8034 };
8035 };
8036 fn format(
8037 data: FormatData,
8038 comptime fmt_str: []const u8,
8039 fmt_opts: std.fmt.FormatOptions,
8040 writer: anytype,
8041 ) @TypeOf(writer).Error!void {
8042 if (data.node == .none) return;
8043
8044 const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S';
8045 const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str;
8046
8047 if (data.formatter.need_comma) try writer.writeAll(", ");
8048 defer data.formatter.need_comma = true;
8049 try writer.writeAll(data.prefix);
81348050
8135pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void {8051 const builder = data.formatter.builder;
8136 switch (arch) {8052 switch (data.node) {
8137 .aarch64, .aarch64_be, .aarch64_32 => {8053 .none => unreachable,
8138 llvm.LLVMInitializeAArch64Target();8054 .@"inline" => |node| {
8139 llvm.LLVMInitializeAArch64TargetInfo();8055 const needed_comma = data.formatter.need_comma;
8140 llvm.LLVMInitializeAArch64TargetMC();8056 defer data.formatter.need_comma = needed_comma;
8141 llvm.LLVMInitializeAArch64AsmPrinter();8057 data.formatter.need_comma = false;
8142 llvm.LLVMInitializeAArch64AsmParser();8058
8143 },8059 const item = builder.metadata_items.get(@intFromEnum(node));
8144 .amdgcn => {8060 switch (item.tag) {
8145 llvm.LLVMInitializeAMDGPUTarget();8061 .expression => {
8146 llvm.LLVMInitializeAMDGPUTargetInfo();8062 var extra = builder.metadataExtraDataTrail(Expression, item.data);
8147 llvm.LLVMInitializeAMDGPUTargetMC();8063 const elements = extra.trail.next(extra.data.elements_len, u32, builder);
8148 llvm.LLVMInitializeAMDGPUAsmPrinter();8064 try writer.writeAll("!DIExpression(");
8149 llvm.LLVMInitializeAMDGPUAsmParser();8065 for (elements) |element| try format(.{
8150 },8066 .formatter = data.formatter,
8151 .thumb, .thumbeb, .arm, .armeb => {8067 .node = .{ .u64 = element },
8152 llvm.LLVMInitializeARMTarget();8068 }, "%", fmt_opts, writer);
8153 llvm.LLVMInitializeARMTargetInfo();8069 try writer.writeByte(')');
8154 llvm.LLVMInitializeARMTargetMC();8070 },
8155 llvm.LLVMInitializeARMAsmPrinter();8071 .constant => try Constant.format(.{
8156 llvm.LLVMInitializeARMAsmParser();8072 .constant = @enumFromInt(item.data),
8157 },8073 .builder = builder,
8158 .avr => {8074 }, recurse_fmt_str, fmt_opts, writer),
8159 llvm.LLVMInitializeAVRTarget();8075 else => unreachable,
8160 llvm.LLVMInitializeAVRTargetInfo();8076 }
8161 llvm.LLVMInitializeAVRTargetMC();8077 },
8162 llvm.LLVMInitializeAVRAsmPrinter();8078 .index => |node| try writer.print("!{d}", .{node}),
8163 llvm.LLVMInitializeAVRAsmParser();8079 inline .local_value, .local_metadata => |node, tag| try Value.format(.{
8164 },8080 .value = node.value,
8165 .bpfel, .bpfeb => {8081 .function = node.function,
8166 llvm.LLVMInitializeBPFTarget();8082 .builder = builder,
8167 llvm.LLVMInitializeBPFTargetInfo();8083 }, switch (tag) {
8168 llvm.LLVMInitializeBPFTargetMC();8084 .local_value => recurse_fmt_str,
8169 llvm.LLVMInitializeBPFAsmPrinter();8085 .local_metadata => "%",
8170 llvm.LLVMInitializeBPFAsmParser();8086 else => unreachable,
8171 },8087 }, fmt_opts, writer),
8172 .hexagon => {8088 inline .local_inline, .local_index => |node, tag| {
8173 llvm.LLVMInitializeHexagonTarget();8089 if (comptime std.mem.eql(u8, recurse_fmt_str, "%"))
8174 llvm.LLVMInitializeHexagonTargetInfo();8090 try writer.print("{%} ", .{Type.metadata.fmt(builder)});
8175 llvm.LLVMInitializeHexagonTargetMC();8091 try format(.{
8176 llvm.LLVMInitializeHexagonAsmPrinter();8092 .formatter = data.formatter,
8177 llvm.LLVMInitializeHexagonAsmParser();8093 .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node),
8178 },8094 }, "%", fmt_opts, writer);
8179 .lanai => {8095 },
8180 llvm.LLVMInitializeLanaiTarget();8096 .string => |node| try writer.print((if (is_specialized) "" else "!") ++ "{}", .{
8181 llvm.LLVMInitializeLanaiTargetInfo();8097 node.fmt(builder),
8182 llvm.LLVMInitializeLanaiTargetMC();8098 }),
8183 llvm.LLVMInitializeLanaiAsmPrinter();8099 inline .bool,
8184 llvm.LLVMInitializeLanaiAsmParser();8100 .u32,
8185 },8101 .u64,
8186 .mips, .mipsel, .mips64, .mips64el => {8102 .di_flags,
8187 llvm.LLVMInitializeMipsTarget();8103 .sp_flags,
8188 llvm.LLVMInitializeMipsTargetInfo();8104 => |node| try writer.print("{}", .{node}),
8189 llvm.LLVMInitializeMipsTargetMC();8105 .raw => |node| try writer.writeAll(node),
8190 llvm.LLVMInitializeMipsAsmPrinter();
8191 llvm.LLVMInitializeMipsAsmParser();
8192 },
8193 .msp430 => {
8194 llvm.LLVMInitializeMSP430Target();
8195 llvm.LLVMInitializeMSP430TargetInfo();
8196 llvm.LLVMInitializeMSP430TargetMC();
8197 llvm.LLVMInitializeMSP430AsmPrinter();
8198 llvm.LLVMInitializeMSP430AsmParser();
8199 },
8200 .nvptx, .nvptx64 => {
8201 llvm.LLVMInitializeNVPTXTarget();
8202 llvm.LLVMInitializeNVPTXTargetInfo();
8203 llvm.LLVMInitializeNVPTXTargetMC();
8204 llvm.LLVMInitializeNVPTXAsmPrinter();
8205 // There is no LLVMInitializeNVPTXAsmParser function available.
8206 },
8207 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {
8208 llvm.LLVMInitializePowerPCTarget();
8209 llvm.LLVMInitializePowerPCTargetInfo();
8210 llvm.LLVMInitializePowerPCTargetMC();
8211 llvm.LLVMInitializePowerPCAsmPrinter();
8212 llvm.LLVMInitializePowerPCAsmParser();
8213 },
8214 .riscv32, .riscv64 => {
8215 llvm.LLVMInitializeRISCVTarget();
8216 llvm.LLVMInitializeRISCVTargetInfo();
8217 llvm.LLVMInitializeRISCVTargetMC();
8218 llvm.LLVMInitializeRISCVAsmPrinter();
8219 llvm.LLVMInitializeRISCVAsmParser();
8220 },
8221 .sparc, .sparc64, .sparcel => {
8222 llvm.LLVMInitializeSparcTarget();
8223 llvm.LLVMInitializeSparcTargetInfo();
8224 llvm.LLVMInitializeSparcTargetMC();
8225 llvm.LLVMInitializeSparcAsmPrinter();
8226 llvm.LLVMInitializeSparcAsmParser();
8227 },
8228 .s390x => {
8229 llvm.LLVMInitializeSystemZTarget();
8230 llvm.LLVMInitializeSystemZTargetInfo();
8231 llvm.LLVMInitializeSystemZTargetMC();
8232 llvm.LLVMInitializeSystemZAsmPrinter();
8233 llvm.LLVMInitializeSystemZAsmParser();
8234 },
8235 .wasm32, .wasm64 => {
8236 llvm.LLVMInitializeWebAssemblyTarget();
8237 llvm.LLVMInitializeWebAssemblyTargetInfo();
8238 llvm.LLVMInitializeWebAssemblyTargetMC();
8239 llvm.LLVMInitializeWebAssemblyAsmPrinter();
8240 llvm.LLVMInitializeWebAssemblyAsmParser();
8241 },
8242 .x86, .x86_64 => {
8243 llvm.LLVMInitializeX86Target();
8244 llvm.LLVMInitializeX86TargetInfo();
8245 llvm.LLVMInitializeX86TargetMC();
8246 llvm.LLVMInitializeX86AsmPrinter();
8247 llvm.LLVMInitializeX86AsmParser();
8248 },
8249 .xtensa => {
8250 if (build_options.llvm_has_xtensa) {
8251 llvm.LLVMInitializeXtensaTarget();
8252 llvm.LLVMInitializeXtensaTargetInfo();
8253 llvm.LLVMInitializeXtensaTargetMC();
8254 // There is no LLVMInitializeXtensaAsmPrinter function.
8255 llvm.LLVMInitializeXtensaAsmParser();
8256 }8106 }
8257 },8107 }
8258 .xcore => {8108 inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) {
8259 llvm.LLVMInitializeXCoreTarget();8109 Metadata => Allocator.Error,
8260 llvm.LLVMInitializeXCoreTargetInfo();8110 else => error{},
8261 llvm.LLVMInitializeXCoreTargetMC();8111 }!std.fmt.Formatter(format) {
8262 llvm.LLVMInitializeXCoreAsmPrinter();8112 const Node = @TypeOf(node);
8263 // There is no LLVMInitializeXCoreAsmParser function.8113 const MaybeNode = switch (@typeInfo(Node)) {
8264 },8114 .Optional => Node,
8265 .m68k => {8115 .Null => ?noreturn,
8266 if (build_options.llvm_has_m68k) {8116 else => ?Node,
8267 llvm.LLVMInitializeM68kTarget();8117 };
8268 llvm.LLVMInitializeM68kTargetInfo();8118 const Some = @typeInfo(MaybeNode).Optional.child;
8269 llvm.LLVMInitializeM68kTargetMC();8119 return .{ .data = .{
8270 llvm.LLVMInitializeM68kAsmPrinter();8120 .formatter = formatter,
8271 llvm.LLVMInitializeM68kAsmParser();8121 .prefix = prefix,
8122 .node = if (@as(MaybeNode, node)) |some| switch (@typeInfo(Some)) {
8123 .Enum => |enum_info| switch (Some) {
8124 Metadata => switch (some) {
8125 .none => .none,
8126 else => try formatter.refUnwrapped(some.unwrap(formatter.builder)),
8127 },
8128 MetadataString => .{ .string = some },
8129 else => if (enum_info.is_exhaustive)
8130 .{ .raw = @tagName(some) }
8131 else
8132 @compileError("unknown type to format: " ++ @typeName(Node)),
8133 },
8134 .EnumLiteral => .{ .raw = @tagName(some) },
8135 .Bool => .{ .bool = some },
8136 .Struct => switch (Some) {
8137 DIFlags => .{ .di_flags = some },
8138 Subprogram.DISPFlags => .{ .sp_flags = some },
8139 else => @compileError("unknown type to format: " ++ @typeName(Node)),
8140 },
8141 .Int, .ComptimeInt => .{ .u64 = some },
8142 .Pointer => .{ .raw = some },
8143 else => @compileError("unknown type to format: " ++ @typeName(Node)),
8144 } else switch (@typeInfo(Node)) {
8145 .Optional, .Null => .none,
8146 else => unreachable,
8147 },
8148 } };
8149 }
8150 inline fn fmtLocal(
8151 formatter: *Formatter,
8152 prefix: []const u8,
8153 value: Value,
8154 function: Function.Index,
8155 ) Allocator.Error!std.fmt.Formatter(format) {
8156 return .{ .data = .{
8157 .formatter = formatter,
8158 .prefix = prefix,
8159 .node = switch (value.unwrap()) {
8160 .instruction, .constant => .{ .local_value = .{
8161 .value = value,
8162 .function = function,
8163 } },
8164 .metadata => |metadata| if (value == .none) .none else node: {
8165 const unwrapped = metadata.unwrap(formatter.builder);
8166 break :node if (@intFromEnum(unwrapped) >= first_local_metadata)
8167 .{ .local_metadata = .{
8168 .value = function.ptrConst(formatter.builder).debug_values[
8169 @intFromEnum(unwrapped) - first_local_metadata
8170 ].toValue(),
8171 .function = function,
8172 } }
8173 else switch (try formatter.refUnwrapped(unwrapped)) {
8174 .@"inline" => |node| .{ .local_inline = node },
8175 .index => |node| .{ .local_index = node },
8176 else => unreachable,
8177 };
8178 },
8179 },
8180 } };
8181 }
8182 fn refUnwrapped(formatter: *Formatter, node: Metadata) Allocator.Error!FormatData.Node {
8183 assert(node != .none);
8184 assert(@intFromEnum(node) < first_forward_reference);
8185 const builder = formatter.builder;
8186 const unwrapped_metadata = node.unwrap(builder);
8187 const tag = formatter.builder.metadata_items.items(.tag)[@intFromEnum(unwrapped_metadata)];
8188 switch (tag) {
8189 .none => unreachable,
8190 .expression, .constant => return .{ .@"inline" = unwrapped_metadata },
8191 else => {
8192 assert(!tag.isInline());
8193 const gop = try formatter.map.getOrPutValue(builder.gpa, unwrapped_metadata, {});
8194 return .{ .index = @intCast(gop.index) };
8195 },
8272 }8196 }
8273 },8197 }
8274 .csky => {8198
8275 if (build_options.llvm_has_csky) {8199 inline fn specialized(
8276 llvm.LLVMInitializeCSKYTarget();8200 formatter: *Formatter,
8277 llvm.LLVMInitializeCSKYTargetInfo();8201 distinct: enum { @"!", @"distinct !" },
8278 llvm.LLVMInitializeCSKYTargetMC();8202 node: enum {
8279 // There is no LLVMInitializeCSKYAsmPrinter function.8203 DIFile,
8280 llvm.LLVMInitializeCSKYAsmParser();8204 DICompileUnit,
8205 DISubprogram,
8206 DILexicalBlock,
8207 DILocation,
8208 DIBasicType,
8209 DICompositeType,
8210 DIDerivedType,
8211 DISubroutineType,
8212 DIEnumerator,
8213 DISubrange,
8214 DILocalVariable,
8215 DIGlobalVariable,
8216 DIGlobalVariableExpression,
8217 },
8218 nodes: anytype,
8219 writer: anytype,
8220 ) !void {
8221 comptime var fmt_str: []const u8 = "";
8222 const names = comptime std.meta.fieldNames(@TypeOf(nodes));
8223 comptime var fields: [2 + names.len]std.builtin.Type.StructField = undefined;
8224 inline for (fields[0..2], .{ "distinct", "node" }) |*field, name| {
8225 fmt_str = fmt_str ++ "{[" ++ name ++ "]s}";
8226 field.* = .{
8227 .name = name,
8228 .type = []const u8,
8229 .default_value = null,
8230 .is_comptime = false,
8231 .alignment = 0,
8232 };
8281 }8233 }
8282 },8234 fmt_str = fmt_str ++ "(";
8283 .ve => {8235 inline for (fields[2..], names) |*field, name| {
8284 llvm.LLVMInitializeVETarget();8236 fmt_str = fmt_str ++ "{[" ++ name ++ "]S}";
8285 llvm.LLVMInitializeVETargetInfo();8237 field.* = .{
8286 llvm.LLVMInitializeVETargetMC();8238 .name = name,
8287 llvm.LLVMInitializeVEAsmPrinter();8239 .type = std.fmt.Formatter(format),
8288 llvm.LLVMInitializeVEAsmParser();8240 .default_value = null,
8289 },8241 .is_comptime = false,
8290 .arc => {8242 .alignment = 0,
8291 if (build_options.llvm_has_arc) {8243 };
8292 llvm.LLVMInitializeARCTarget();
8293 llvm.LLVMInitializeARCTargetInfo();
8294 llvm.LLVMInitializeARCTargetMC();
8295 llvm.LLVMInitializeARCAsmPrinter();
8296 // There is no LLVMInitializeARCAsmParser function.
8297 }8244 }
8298 },8245 fmt_str = fmt_str ++ ")\n";
8246
8247 var fmt_args: @Type(.{ .Struct = .{
8248 .layout = .Auto,
8249 .fields = &fields,
8250 .decls = &.{},
8251 .is_tuple = false,
8252 } }) = undefined;
8253 fmt_args.distinct = @tagName(distinct);
8254 fmt_args.node = @tagName(node);
8255 inline for (names) |name| @field(fmt_args, name) = try formatter.fmt(
8256 name ++ ": ",
8257 @field(nodes, name),
8258 );
8259 try writer.print(fmt_str, fmt_args);
8260 }
8261 };
8262};
82998263
8300 // LLVM backends that have no initialization functions.8264pub fn init(options: Options) Allocator.Error!Builder {
8301 .tce,8265 var self = Builder{
8302 .tcele,8266 .gpa = options.allocator,
8303 .r600,8267 .strip = options.strip,
8304 .le32,8268
8305 .le64,8269 .source_filename = .none,
8306 .amdil,8270 .data_layout = .none,
8307 .amdil64,8271 .target_triple = .none,
8308 .hsail,8272 .module_asm = .{},
8309 .hsail64,8273
8310 .shave,8274 .string_map = .{},
8311 .spir,8275 .string_indices = .{},
8312 .spir64,8276 .string_bytes = .{},
8313 .kalimba,8277
8314 .renderscript32,8278 .types = .{},
8315 .renderscript64,8279 .next_unnamed_type = @enumFromInt(0),
8316 .dxil,8280 .next_unique_type_id = .{},
8317 .loongarch32,8281 .type_map = .{},
8318 .loongarch64,8282 .type_items = .{},
8319 => {},8283 .type_extra = .{},
8284
8285 .attributes = .{},
8286 .attributes_map = .{},
8287 .attributes_indices = .{},
8288 .attributes_extra = .{},
8289
8290 .function_attributes_set = .{},
8291
8292 .globals = .{},
8293 .next_unnamed_global = @enumFromInt(0),
8294 .next_replaced_global = .none,
8295 .next_unique_global_id = .{},
8296 .aliases = .{},
8297 .variables = .{},
8298 .functions = .{},
8299
8300 .constant_map = .{},
8301 .constant_items = .{},
8302 .constant_extra = .{},
8303 .constant_limbs = .{},
8304
8305 .metadata_map = .{},
8306 .metadata_items = .{},
8307 .metadata_extra = .{},
8308 .metadata_limbs = .{},
8309 .metadata_forward_references = .{},
8310 .metadata_named = .{},
8311 .metadata_string_map = .{},
8312 .metadata_string_indices = .{},
8313 .metadata_string_bytes = .{},
8314 };
8315 errdefer self.deinit();
8316
8317 try self.string_indices.append(self.gpa, 0);
8318 assert(try self.string("") == .empty);
8319
8320 if (options.name.len > 0) self.source_filename = try self.string(options.name);
8321
8322 if (options.triple.len > 0) {
8323 self.target_triple = try self.string(options.triple);
8324 }
8325
8326 {
8327 const static_len = @typeInfo(Type).Enum.fields.len - 1;
8328 try self.type_map.ensureTotalCapacity(self.gpa, static_len);
8329 try self.type_items.ensureTotalCapacity(self.gpa, static_len);
8330 inline for (@typeInfo(Type.Simple).Enum.fields) |simple_field| {
8331 const result = self.getOrPutTypeNoExtraAssumeCapacity(
8332 .{ .tag = .simple, .data = simple_field.value },
8333 );
8334 assert(result.new and result.type == @field(Type, simple_field.name));
8335 }
8336 inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits|
8337 assert(self.intTypeAssumeCapacity(bits) ==
8338 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
8339 inline for (.{ 0, 4 }) |addr_space_index| {
8340 const addr_space: AddrSpace = @enumFromInt(addr_space_index);
8341 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8342 @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space})));
8343 }
8344 }
83208345
8321 .spu_2 => unreachable, // LLVM does not support this backend8346 {
8322 .spirv32 => unreachable, // LLVM does not support this backend8347 try self.attributes_indices.append(self.gpa, 0);
8323 .spirv64 => unreachable, // LLVM does not support this backend8348 assert(try self.attrs(&.{}) == .none);
8349 assert(try self.fnAttrs(&.{}) == .none);
8324 }8350 }
8351
8352 assert(try self.intConst(.i1, 0) == .false);
8353 assert(try self.intConst(.i1, 1) == .true);
8354 assert(try self.intConst(.i32, 0) == .@"0");
8355 assert(try self.intConst(.i32, 1) == .@"1");
8356 assert(try self.noneConst(.token) == .none);
8357 if (!self.strip) assert(try self.debugNone() == .none);
8358
8359 try self.metadata_string_indices.append(self.gpa, 0);
8360 assert(try self.metadataString("") == .none);
8361
8362 return self;
8363}
8364
8365pub fn deinit(self: *Builder) void {
8366 self.module_asm.deinit(self.gpa);
8367
8368 self.string_map.deinit(self.gpa);
8369 self.string_indices.deinit(self.gpa);
8370 self.string_bytes.deinit(self.gpa);
8371
8372 self.types.deinit(self.gpa);
8373 self.next_unique_type_id.deinit(self.gpa);
8374 self.type_map.deinit(self.gpa);
8375 self.type_items.deinit(self.gpa);
8376 self.type_extra.deinit(self.gpa);
8377
8378 self.attributes.deinit(self.gpa);
8379 self.attributes_map.deinit(self.gpa);
8380 self.attributes_indices.deinit(self.gpa);
8381 self.attributes_extra.deinit(self.gpa);
8382
8383 self.function_attributes_set.deinit(self.gpa);
8384
8385 self.globals.deinit(self.gpa);
8386 self.next_unique_global_id.deinit(self.gpa);
8387 self.aliases.deinit(self.gpa);
8388 self.variables.deinit(self.gpa);
8389 for (self.functions.items) |*function| function.deinit(self.gpa);
8390 self.functions.deinit(self.gpa);
8391
8392 self.constant_map.deinit(self.gpa);
8393 self.constant_items.deinit(self.gpa);
8394 self.constant_extra.deinit(self.gpa);
8395 self.constant_limbs.deinit(self.gpa);
8396
8397 self.metadata_map.deinit(self.gpa);
8398 self.metadata_items.deinit(self.gpa);
8399 self.metadata_extra.deinit(self.gpa);
8400 self.metadata_limbs.deinit(self.gpa);
8401 self.metadata_forward_references.deinit(self.gpa);
8402 self.metadata_named.deinit(self.gpa);
8403
8404 self.metadata_string_map.deinit(self.gpa);
8405 self.metadata_string_indices.deinit(self.gpa);
8406 self.metadata_string_bytes.deinit(self.gpa);
8407
8408 self.* = undefined;
8325}8409}
83268410
8327pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {8411pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {
...@@ -8336,24 +8420,25 @@ pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {...@@ -8336,24 +8420,25 @@ pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {
8336pub fn finishModuleAsm(self: *Builder) Allocator.Error!void {8420pub fn finishModuleAsm(self: *Builder) Allocator.Error!void {
8337 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')8421 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')
8338 try self.module_asm.append(self.gpa, '\n');8422 try self.module_asm.append(self.gpa, '\n');
8339 if (self.useLibLlvm())
8340 self.llvm.module.?.setModuleInlineAsm(self.module_asm.items.ptr, self.module_asm.items.len);
8341}8423}
83428424
8343pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String {8425pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String {
8344 try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len + 1);8426 try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len);
8345 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);8427 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
8346 try self.string_map.ensureUnusedCapacity(self.gpa, 1);8428 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
83478429
8348 const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });8430 const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
8349 if (!gop.found_existing) {8431 if (!gop.found_existing) {
8350 self.string_bytes.appendSliceAssumeCapacity(bytes);8432 self.string_bytes.appendSliceAssumeCapacity(bytes);
8351 self.string_bytes.appendAssumeCapacity(0);
8352 self.string_indices.appendAssumeCapacity(@intCast(self.string_bytes.items.len));8433 self.string_indices.appendAssumeCapacity(@intCast(self.string_bytes.items.len));
8353 }8434 }
8354 return String.fromIndex(gop.index);8435 return String.fromIndex(gop.index);
8355}8436}
83568437
8438pub fn stringNull(self: *Builder, bytes: [:0]const u8) Allocator.Error!String {
8439 return self.string(bytes[0 .. bytes.len + 1]);
8440}
8441
8357pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String {8442pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String {
8358 return String.fromIndex(8443 return String.fromIndex(
8359 self.string_map.getIndexAdapted(bytes, String.Adapter{ .builder = self }) orelse return null,8444 self.string_map.getIndexAdapted(bytes, String.Adapter{ .builder = self }) orelse return null,
...@@ -8362,16 +8447,25 @@ pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String {...@@ -8362,16 +8447,25 @@ pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String {
83628447
8363pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!String {8448pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!String {
8364 try self.string_map.ensureUnusedCapacity(self.gpa, 1);8449 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
8365 try self.string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str ++ .{0}, fmt_args)));8450 try self.string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str, fmt_args)));
8366 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);8451 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
8367 return self.fmtAssumeCapacity(fmt_str, fmt_args);8452 return self.fmtAssumeCapacity(fmt_str, fmt_args);
8368}8453}
83698454
8370pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String {8455pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String {
8371 const start = self.string_bytes.items.len;8456 self.string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;
8372 self.string_bytes.writer(self.gpa).print(fmt_str ++ .{0}, fmt_args) catch unreachable;8457 return self.trailingStringAssumeCapacity();
8373 const bytes: []const u8 = self.string_bytes.items[start .. self.string_bytes.items.len - 1];8458}
8459
8460pub fn trailingString(self: *Builder) Allocator.Error!String {
8461 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
8462 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
8463 return self.trailingStringAssumeCapacity();
8464}
83748465
8466pub fn trailingStringAssumeCapacity(self: *Builder) String {
8467 const start = self.string_indices.getLast();
8468 const bytes: []const u8 = self.string_bytes.items[start..];
8375 const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });8469 const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
8376 if (gop.found_existing) {8470 if (gop.found_existing) {
8377 self.string_bytes.shrinkRetainingCapacity(start);8471 self.string_bytes.shrinkRetainingCapacity(start);
...@@ -8435,7 +8529,7 @@ pub fn structType(...@@ -8435,7 +8529,7 @@ pub fn structType(
8435pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type {8529pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type {
8436 try self.string_map.ensureUnusedCapacity(self.gpa, 1);8530 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
8437 if (name.slice(self)) |id| {8531 if (name.slice(self)) |id| {
8438 const count: usize = comptime std.fmt.count("{d}" ++ .{0}, .{std.math.maxInt(u32)});8532 const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)});
8439 try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count);8533 try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count);
8440 }8534 }
8441 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);8535 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
...@@ -8449,98 +8543,17 @@ pub fn namedTypeSetBody(...@@ -8449,98 +8543,17 @@ pub fn namedTypeSetBody(
8449 self: *Builder,8543 self: *Builder,
8450 named_type: Type,8544 named_type: Type,
8451 body_type: Type,8545 body_type: Type,
8452) (if (build_options.have_llvm) Allocator.Error else error{})!void {8546) void {
8453 const named_item = self.type_items.items[@intFromEnum(named_type)];8547 const named_item = self.type_items.items[@intFromEnum(named_type)];
8454 self.type_extra.items[named_item.data + std.meta.fieldIndex(Type.NamedStructure, "body").?] =8548 self.type_extra.items[named_item.data + std.meta.fieldIndex(Type.NamedStructure, "body").?] =
8455 @intFromEnum(body_type);8549 @intFromEnum(body_type);
8456 if (self.useLibLlvm()) {
8457 const body_item = self.type_items.items[@intFromEnum(body_type)];
8458 var body_extra = self.typeExtraDataTrail(Type.Structure, body_item.data);
8459 const body_fields = body_extra.trail.next(body_extra.data.fields_len, Type, self);
8460 const llvm_fields = try self.gpa.alloc(*llvm.Type, body_fields.len);
8461 defer self.gpa.free(llvm_fields);
8462 for (llvm_fields, body_fields) |*llvm_field, body_field| llvm_field.* = body_field.toLlvm(self);
8463 self.llvm.types.items[@intFromEnum(named_type)].structSetBody(
8464 llvm_fields.ptr,
8465 @intCast(llvm_fields.len),
8466 switch (body_item.tag) {
8467 .structure => .False,
8468 .packed_structure => .True,
8469 else => unreachable,
8470 },
8471 );
8472 }
8473}8550}
84748551
8475pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Index {8552pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Index {
8476 try self.attributes.ensureUnusedCapacity(self.gpa, 1);8553 try self.attributes.ensureUnusedCapacity(self.gpa, 1);
8477 if (self.useLibLlvm()) try self.llvm.attributes.ensureUnusedCapacity(self.gpa, 1);
84788554
8479 const gop = self.attributes.getOrPutAssumeCapacity(attribute.toStorage());8555 const gop = self.attributes.getOrPutAssumeCapacity(attribute.toStorage());
8480 if (!gop.found_existing) {8556 if (!gop.found_existing) gop.value_ptr.* = {};
8481 gop.value_ptr.* = {};
8482 if (self.useLibLlvm()) self.llvm.attributes.appendAssumeCapacity(switch (attribute) {
8483 else => llvm_attr: {
8484 const llvm_kind_id = attribute.getKind().toLlvm(self);
8485 if (llvm_kind_id.* == 0) {
8486 const name = @tagName(attribute);
8487 llvm_kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);
8488 assert(llvm_kind_id.* != 0);
8489 }
8490 break :llvm_attr switch (attribute) {
8491 else => switch (attribute) {
8492 inline else => |value| self.llvm.context.createEnumAttribute(
8493 llvm_kind_id.*,
8494 switch (@TypeOf(value)) {
8495 void => 0,
8496 u32 => value,
8497 Attribute.FpClass,
8498 Attribute.AllocKind,
8499 Attribute.Memory,
8500 => @as(u32, @bitCast(value)),
8501 Alignment => value.toByteUnits() orelse 0,
8502 Attribute.AllocSize,
8503 Attribute.VScaleRange,
8504 => @bitCast(value.toLlvm()),
8505 Attribute.UwTable => @intFromEnum(value),
8506 else => @compileError(
8507 "bad payload type: " ++ @typeName(@TypeOf(value)),
8508 ),
8509 },
8510 ),
8511 .byval,
8512 .byref,
8513 .preallocated,
8514 .inalloca,
8515 .sret,
8516 .elementtype,
8517 .string,
8518 .none,
8519 => unreachable,
8520 },
8521 .byval,
8522 .byref,
8523 .preallocated,
8524 .inalloca,
8525 .sret,
8526 .elementtype,
8527 => |ty| self.llvm.context.createTypeAttribute(llvm_kind_id.*, ty.toLlvm(self)),
8528 .string, .none => unreachable,
8529 };
8530 },
8531 .string => |string_attr| llvm_attr: {
8532 const kind = string_attr.kind.slice(self).?;
8533 const value = string_attr.value.slice(self).?;
8534 break :llvm_attr self.llvm.context.createStringAttribute(
8535 kind.ptr,
8536 @intCast(kind.len),
8537 value.ptr,
8538 @intCast(value.len),
8539 );
8540 },
8541 .none => unreachable,
8542 });
8543 }
8544 return @enumFromInt(gop.index);8557 return @enumFromInt(gop.index);
8545}8558}
85468559
...@@ -8557,12 +8570,16 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr...@@ -8557,12 +8570,16 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr
8557}8570}
85588571
8559pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes {8572pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes {
8560 return @enumFromInt(try self.attrGeneric(@ptrCast(8573 try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1);
8574 const function_attributes: FunctionAttributes = @enumFromInt(try self.attrGeneric(@ptrCast(
8561 fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last|8575 fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last|
8562 last + 18576 last + 1
8563 else8577 else
8564 0],8578 0],
8565 )));8579 )));
8580
8581 _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes);
8582 return function_attributes;
8566}8583}
85678584
8568pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index {8585pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index {
...@@ -8586,7 +8603,6 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo...@@ -8586,7 +8603,6 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo
8586 global_gop.value_ptr.* = global;8603 global_gop.value_ptr.* = global;
8587 const global_index: Global.Index = @enumFromInt(global_gop.index);8604 const global_index: Global.Index = @enumFromInt(global_gop.index);
8588 global_index.updateDsoLocal(self);8605 global_index.updateDsoLocal(self);
8589 global_index.updateName(self);
8590 return global_index;8606 return global_index;
8591 }8607 }
85928608
...@@ -8622,12 +8638,6 @@ pub fn addAliasAssumeCapacity(...@@ -8622,12 +8638,6 @@ pub fn addAliasAssumeCapacity(
8622 addr_space: AddrSpace,8638 addr_space: AddrSpace,
8623 aliasee: Constant,8639 aliasee: Constant,
8624) Alias.Index {8640) Alias.Index {
8625 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(self.llvm.module.?.addAlias(
8626 ty.toLlvm(self),
8627 @intFromEnum(addr_space),
8628 aliasee.toLlvm(self),
8629 name.slice(self).?,
8630 ));
8631 const alias_index: Alias.Index = @enumFromInt(self.aliases.items.len);8641 const alias_index: Alias.Index = @enumFromInt(self.aliases.items.len);
8632 self.aliases.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{8642 self.aliases.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8633 .addr_space = addr_space,8643 .addr_space = addr_space,
...@@ -8656,13 +8666,6 @@ pub fn addVariableAssumeCapacity(...@@ -8656,13 +8666,6 @@ pub fn addVariableAssumeCapacity(
8656 name: String,8666 name: String,
8657 addr_space: AddrSpace,8667 addr_space: AddrSpace,
8658) Variable.Index {8668) Variable.Index {
8659 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(
8660 self.llvm.module.?.addGlobalInAddressSpace(
8661 ty.toLlvm(self),
8662 name.slice(self).?,
8663 @intFromEnum(addr_space),
8664 ),
8665 );
8666 const variable_index: Variable.Index = @enumFromInt(self.variables.items.len);8669 const variable_index: Variable.Index = @enumFromInt(self.variables.items.len);
8667 self.variables.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{8670 self.variables.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8668 .addr_space = addr_space,8671 .addr_space = addr_space,
...@@ -8692,13 +8695,6 @@ pub fn addFunctionAssumeCapacity(...@@ -8692,13 +8695,6 @@ pub fn addFunctionAssumeCapacity(
8692 addr_space: AddrSpace,8695 addr_space: AddrSpace,
8693) Function.Index {8696) Function.Index {
8694 assert(ty.isFunction(self));8697 assert(ty.isFunction(self));
8695 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(
8696 self.llvm.module.?.addFunctionInAddressSpace(
8697 name.slice(self).?,
8698 ty.toLlvm(self),
8699 @intFromEnum(addr_space),
8700 ),
8701 );
8702 const function_index: Function.Index = @enumFromInt(self.functions.items.len);8698 const function_index: Function.Index = @enumFromInt(self.functions.items.len);
8703 self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{8699 self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8704 .addr_space = addr_space,8700 .addr_space = addr_space,
...@@ -8714,7 +8710,6 @@ pub fn getIntrinsic(...@@ -8714,7 +8710,6 @@ pub fn getIntrinsic(
8714 overload: []const Type,8710 overload: []const Type,
8715) Allocator.Error!Function.Index {8711) Allocator.Error!Function.Index {
8716 const ExpectedContents = extern union {8712 const ExpectedContents = extern union {
8717 name: [expected_intrinsic_name_len]u8,
8718 attrs: extern struct {8713 attrs: extern struct {
8719 params: [expected_args_len]Type,8714 params: [expected_args_len]Type,
8720 fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes,8715 fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes,
...@@ -8727,12 +8722,10 @@ pub fn getIntrinsic(...@@ -8727,12 +8722,10 @@ pub fn getIntrinsic(
8727 const allocator = stack.get();8722 const allocator = stack.get();
87288723
8729 const name = name: {8724 const name = name: {
8730 var buffer = std.ArrayList(u8).init(allocator);8725 const writer = self.string_bytes.writer(self.gpa);
8731 defer buffer.deinit();8726 try writer.print("llvm.{s}", .{@tagName(id)});
87328727 for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)});
8733 try buffer.writer().print("llvm.{s}", .{@tagName(id)});8728 break :name try self.trailingString();
8734 for (overload) |ty| try buffer.writer().print(".{m}", .{ty.fmt(self)});
8735 break :name try self.string(buffer.items);
8736 };8729 };
8737 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;8730 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;
87388731
...@@ -8826,7 +8819,6 @@ pub fn bigIntConst(self: *Builder, ty: Type, value: std.math.big.int.Const) Allo...@@ -8826,7 +8819,6 @@ pub fn bigIntConst(self: *Builder, ty: Type, value: std.math.big.int.Const) Allo
8826 try self.constant_map.ensureUnusedCapacity(self.gpa, 1);8819 try self.constant_map.ensureUnusedCapacity(self.gpa, 1);
8827 try self.constant_items.ensureUnusedCapacity(self.gpa, 1);8820 try self.constant_items.ensureUnusedCapacity(self.gpa, 1);
8828 try self.constant_limbs.ensureUnusedCapacity(self.gpa, Constant.Integer.limbs + value.limbs.len);8821 try self.constant_limbs.ensureUnusedCapacity(self.gpa, Constant.Integer.limbs + value.limbs.len);
8829 if (self.useLibLlvm()) try self.llvm.constants.ensureUnusedCapacity(self.gpa, 1);
8830 return self.bigIntConstAssumeCapacity(ty, value);8822 return self.bigIntConstAssumeCapacity(ty, value);
8831}8823}
88328824
...@@ -8977,16 +8969,6 @@ pub fn stringValue(self: *Builder, val: String) Allocator.Error!Value {...@@ -8977,16 +8969,6 @@ pub fn stringValue(self: *Builder, val: String) Allocator.Error!Value {
8977 return (try self.stringConst(val)).toValue();8969 return (try self.stringConst(val)).toValue();
8978}8970}
89798971
8980pub fn stringNullConst(self: *Builder, val: String) Allocator.Error!Constant {
8981 try self.ensureUnusedTypeCapacity(1, Type.Array, 0);
8982 try self.ensureUnusedConstantCapacity(1, NoExtra, 0);
8983 return self.stringNullConstAssumeCapacity(val);
8984}
8985
8986pub fn stringNullValue(self: *Builder, val: String) Allocator.Error!Value {
8987 return (try self.stringNullConst(val)).toValue();
8988}
8989
8990pub fn vectorConst(self: *Builder, ty: Type, vals: []const Constant) Allocator.Error!Constant {8972pub fn vectorConst(self: *Builder, ty: Type, vals: []const Constant) Allocator.Error!Constant {
8991 try self.ensureUnusedConstantCapacity(1, Constant.Aggregate, vals.len);8973 try self.ensureUnusedConstantCapacity(1, Constant.Aggregate, vals.len);
8992 return self.vectorConstAssumeCapacity(ty, vals);8974 return self.vectorConstAssumeCapacity(ty, vals);
...@@ -9244,72 +9226,20 @@ pub fn asmValue(...@@ -9244,72 +9226,20 @@ pub fn asmValue(
9244 return (try self.asmConst(ty, info, assembly, constraints)).toValue();9226 return (try self.asmConst(ty, info, assembly, constraints)).toValue();
9245}9227}
92469228
9247pub fn verify(self: *Builder) error{}!bool {
9248 if (self.useLibLlvm()) {
9249 var error_message: [*:0]const u8 = undefined;
9250 // verifyModule always allocs the error_message even if there is no error
9251 defer llvm.disposeMessage(error_message);
9252
9253 if (self.llvm.module.?.verify(.ReturnStatus, &error_message).toBool()) {
9254 log.err("failed verification of LLVM module:\n{s}\n", .{error_message});
9255 return false;
9256 }
9257 }
9258 return true;
9259}
9260
9261pub fn writeBitcodeToFile(self: *Builder, path: []const u8) Allocator.Error!bool {
9262 const path_z = try self.gpa.dupeZ(u8, path);
9263 defer self.gpa.free(path_z);
9264 return self.writeBitcodeToFileZ(path_z);
9265}
9266
9267pub fn writeBitcodeToFileZ(self: *Builder, path: [*:0]const u8) bool {
9268 if (self.useLibLlvm()) {
9269 const error_code = self.llvm.module.?.writeBitcodeToFile(path);
9270 if (error_code != 0) {
9271 log.err("failed dumping LLVM module to \"{s}\": {d}", .{ path, error_code });
9272 return false;
9273 }
9274 } else {
9275 log.err("writing bitcode without libllvm not implemented", .{});
9276 return false;
9277 }
9278 return true;
9279}
9280
9281pub fn dump(self: *Builder) void {9229pub fn dump(self: *Builder) void {
9282 if (self.useLibLlvm())9230 self.print(std.io.getStdErr().writer()) catch {};
9283 self.llvm.module.?.dump()
9284 else
9285 self.print(std.io.getStdErr().writer()) catch {};
9286}9231}
92879232
9288pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool {9233pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool {
9289 const path_z = try self.gpa.dupeZ(u8, path);9234 var file = std.fs.cwd().createFile(path, .{}) catch |err| {
9290 defer self.gpa.free(path_z);9235 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9291 return self.printToFileZ(path_z);9236 return false;
9292}9237 };
92939238 defer file.close();
9294pub fn printToFileZ(self: *Builder, path: [*:0]const u8) bool {9239 self.print(file.writer()) catch |err| {
9295 if (self.useLibLlvm()) {9240 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9296 var error_message: [*:0]const u8 = undefined;9241 return false;
9297 if (self.llvm.module.?.printModuleToFile(path, &error_message).toBool()) {9242 };
9298 defer llvm.disposeMessage(error_message);
9299 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, error_message });
9300 return false;
9301 }
9302 } else {
9303 var file = std.fs.cwd().createFileZ(path, .{}) catch |err| {
9304 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9305 return false;
9306 };
9307 defer file.close();
9308 self.print(file.writer()) catch |err| {
9309 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9310 return false;
9311 };
9312 }
9313 return true;9243 return true;
9314}9244}
93159245
...@@ -9324,9 +9254,11 @@ pub fn printUnbuffered(...@@ -9324,9 +9254,11 @@ pub fn printUnbuffered(
9324 writer: anytype,9254 writer: anytype,
9325) (@TypeOf(writer).Error || Allocator.Error)!void {9255) (@TypeOf(writer).Error || Allocator.Error)!void {
9326 var need_newline = false;9256 var need_newline = false;
9257 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
9258 defer metadata_formatter.map.deinit(self.gpa);
93279259
9328 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {9260 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
9329 if (need_newline) try writer.writeByte('\n');9261 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9330 if (self.source_filename != .none) try writer.print(9262 if (self.source_filename != .none) try writer.print(
9331 \\; ModuleID = '{s}'9263 \\; ModuleID = '{s}'
9332 \\source_filename = {"}9264 \\source_filename = {"}
...@@ -9340,40 +9272,40 @@ pub fn printUnbuffered(...@@ -9340,40 +9272,40 @@ pub fn printUnbuffered(
9340 \\target triple = {"}9272 \\target triple = {"}
9341 \\9273 \\
9342 , .{self.target_triple.fmt(self)});9274 , .{self.target_triple.fmt(self)});
9343 need_newline = true;
9344 }9275 }
93459276
9346 if (self.module_asm.items.len > 0) {9277 if (self.module_asm.items.len > 0) {
9347 if (need_newline) try writer.writeByte('\n');9278 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9348 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');9279 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');
9349 while (line_it.next()) |line| {9280 while (line_it.next()) |line| {
9350 try writer.writeAll("module asm ");9281 try writer.writeAll("module asm ");
9351 try printEscapedString(line, .always_quote, writer);9282 try printEscapedString(line, .always_quote, writer);
9352 try writer.writeByte('\n');9283 try writer.writeByte('\n');
9353 }9284 }
9354 need_newline = true;
9355 }9285 }
93569286
9357 if (self.types.count() > 0) {9287 if (self.types.count() > 0) {
9358 if (need_newline) try writer.writeByte('\n');9288 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9359 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(9289 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(
9360 \\%{} = type {}9290 \\%{} = type {}
9361 \\9291 \\
9362 , .{ id.fmt(self), ty.fmt(self) });9292 , .{ id.fmt(self), ty.fmt(self) });
9363 need_newline = true;
9364 }9293 }
93659294
9366 if (self.variables.items.len > 0) {9295 if (self.variables.items.len > 0) {
9367 if (need_newline) try writer.writeByte('\n');9296 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9368 for (self.variables.items) |variable| {9297 for (self.variables.items) |variable| {
9369 if (variable.global.getReplacement(self) != .none) continue;9298 if (variable.global.getReplacement(self) != .none) continue;
9370 const global = variable.global.ptrConst(self);9299 const global = variable.global.ptrConst(self);
9300 metadata_formatter.need_comma = true;
9301 defer metadata_formatter.need_comma = undefined;
9371 try writer.print(9302 try writer.print(
9372 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }9303 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{}
9373 \\9304 \\
9374 , .{9305 , .{
9375 variable.global.fmt(self),9306 variable.global.fmt(self),
9376 global.linkage,9307 Linkage.fmtOptional(if (global.linkage == .external and
9308 variable.init != .no_init) null else global.linkage),
9377 global.preemption,9309 global.preemption,
9378 global.visibility,9310 global.visibility,
9379 global.dll_storage_class,9311 global.dll_storage_class,
...@@ -9385,18 +9317,20 @@ pub fn printUnbuffered(...@@ -9385,18 +9317,20 @@ pub fn printUnbuffered(
9385 global.type.fmt(self),9317 global.type.fmt(self),
9386 variable.init.fmt(self),9318 variable.init.fmt(self),
9387 variable.alignment,9319 variable.alignment,
9320 try metadata_formatter.fmt("!dbg ", global.dbg),
9388 });9321 });
9389 }9322 }
9390 need_newline = true;
9391 }9323 }
93929324
9393 if (self.aliases.items.len > 0) {9325 if (self.aliases.items.len > 0) {
9394 if (need_newline) try writer.writeByte('\n');9326 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9395 for (self.aliases.items) |alias| {9327 for (self.aliases.items) |alias| {
9396 if (alias.global.getReplacement(self) != .none) continue;9328 if (alias.global.getReplacement(self) != .none) continue;
9397 const global = alias.global.ptrConst(self);9329 const global = alias.global.ptrConst(self);
9330 metadata_formatter.need_comma = true;
9331 defer metadata_formatter.need_comma = undefined;
9398 try writer.print(9332 try writer.print(
9399 \\{} ={}{}{}{}{ }{} alias {%}, {%}9333 \\{} ={}{}{}{}{ }{} alias {%}, {%}{}
9400 \\9334 \\
9401 , .{9335 , .{
9402 alias.global.fmt(self),9336 alias.global.fmt(self),
...@@ -9408,9 +9342,9 @@ pub fn printUnbuffered(...@@ -9408,9 +9342,9 @@ pub fn printUnbuffered(
9408 global.unnamed_addr,9342 global.unnamed_addr,
9409 global.type.fmt(self),9343 global.type.fmt(self),
9410 alias.aliasee.fmt(self),9344 alias.aliasee.fmt(self),
9345 try metadata_formatter.fmt("!dbg ", global.dbg),
9411 });9346 });
9412 }9347 }
9413 need_newline = true;
9414 }9348 }
94159349
9416 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};9350 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
...@@ -9418,7 +9352,7 @@ pub fn printUnbuffered(...@@ -9418,7 +9352,7 @@ pub fn printUnbuffered(
94189352
9419 for (0.., self.functions.items) |function_i, function| {9353 for (0.., self.functions.items) |function_i, function| {
9420 if (function.global.getReplacement(self) != .none) continue;9354 if (function.global.getReplacement(self) != .none) continue;
9421 if (need_newline) try writer.writeByte('\n');9355 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9422 const function_index: Function.Index = @enumFromInt(function_i);9356 const function_index: Function.Index = @enumFromInt(function_i);
9423 const global = function.global.ptrConst(self);9357 const global = function.global.ptrConst(self);
9424 const params_len = global.type.functionParameters(self).len;9358 const params_len = global.type.functionParameters(self).len;
...@@ -9464,13 +9398,23 @@ pub fn printUnbuffered(...@@ -9464,13 +9398,23 @@ pub fn printUnbuffered(
9464 if (function_attributes != .none) try writer.print(" #{d}", .{9398 if (function_attributes != .none) try writer.print(" #{d}", .{
9465 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,9399 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9466 });9400 });
9467 try writer.print("{ }", .{function.alignment});9401 {
9402 metadata_formatter.need_comma = false;
9403 defer metadata_formatter.need_comma = undefined;
9404 try writer.print("{ }{}", .{
9405 function.alignment,
9406 try metadata_formatter.fmt(" !dbg ", global.dbg),
9407 });
9408 }
9468 if (function.instructions.len > 0) {9409 if (function.instructions.len > 0) {
9469 var block_incoming_len: u32 = undefined;9410 var block_incoming_len: u32 = undefined;
9470 try writer.writeAll(" {\n");9411 try writer.writeAll(" {\n");
9412 var dbg: Metadata = .none;
9471 for (params_len..function.instructions.len) |instruction_i| {9413 for (params_len..function.instructions.len) |instruction_i| {
9472 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);9414 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
9473 const instruction = function.instructions.get(@intFromEnum(instruction_index));9415 const instruction = function.instructions.get(@intFromEnum(instruction_index));
9416 if (function.debug_locations.get(instruction_index)) |debug_location|
9417 dbg = debug_location;
9474 switch (instruction.tag) {9418 switch (instruction.tag) {
9475 .add,9419 .add,
9476 .@"add nsw",9420 .@"add nsw",
...@@ -9555,7 +9499,7 @@ pub fn printUnbuffered(...@@ -9555,7 +9499,7 @@ pub fn printUnbuffered(
9555 .xor,9499 .xor,
9556 => |tag| {9500 => |tag| {
9557 const extra = function.extraData(Function.Instruction.Binary, instruction.data);9501 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
9558 try writer.print(" %{} = {s} {%}, {}\n", .{9502 try writer.print(" %{} = {s} {%}, {}", .{
9559 instruction_index.name(&function).fmt(self),9503 instruction_index.name(&function).fmt(self),
9560 @tagName(tag),9504 @tagName(tag),
9561 extra.lhs.fmt(function_index, self),9505 extra.lhs.fmt(function_index, self),
...@@ -9577,7 +9521,7 @@ pub fn printUnbuffered(...@@ -9577,7 +9521,7 @@ pub fn printUnbuffered(
9577 .zext,9521 .zext,
9578 => |tag| {9522 => |tag| {
9579 const extra = function.extraData(Function.Instruction.Cast, instruction.data);9523 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
9580 try writer.print(" %{} = {s} {%} to {%}\n", .{9524 try writer.print(" %{} = {s} {%} to {%}", .{
9581 instruction_index.name(&function).fmt(self),9525 instruction_index.name(&function).fmt(self),
9582 @tagName(tag),9526 @tagName(tag),
9583 extra.val.fmt(function_index, self),9527 extra.val.fmt(function_index, self),
...@@ -9588,11 +9532,14 @@ pub fn printUnbuffered(...@@ -9588,11 +9532,14 @@ pub fn printUnbuffered(
9588 .@"alloca inalloca",9532 .@"alloca inalloca",
9589 => |tag| {9533 => |tag| {
9590 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);9534 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
9591 try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{9535 try writer.print(" %{} = {s} {%}{,%}{, }{, }", .{
9592 instruction_index.name(&function).fmt(self),9536 instruction_index.name(&function).fmt(self),
9593 @tagName(tag),9537 @tagName(tag),
9594 extra.type.fmt(self),9538 extra.type.fmt(self),
9595 extra.len.fmt(function_index, self),9539 Value.fmt(switch (extra.len) {
9540 .@"1" => .none,
9541 else => extra.len,
9542 }, function_index, self),
9596 extra.info.alignment,9543 extra.info.alignment,
9597 extra.info.addr_space,9544 extra.info.addr_space,
9598 });9545 });
...@@ -9601,7 +9548,7 @@ pub fn printUnbuffered(...@@ -9601,7 +9548,7 @@ pub fn printUnbuffered(
9601 .atomicrmw => |tag| {9548 .atomicrmw => |tag| {
9602 const extra =9549 const extra =
9603 function.extraData(Function.Instruction.AtomicRmw, instruction.data);9550 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9604 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{9551 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }", .{
9605 instruction_index.name(&function).fmt(self),9552 instruction_index.name(&function).fmt(self),
9606 @tagName(tag),9553 @tagName(tag),
9607 extra.info.access_kind,9554 extra.info.access_kind,
...@@ -9619,16 +9566,17 @@ pub fn printUnbuffered(...@@ -9619,16 +9566,17 @@ pub fn printUnbuffered(
9619 if (@intFromEnum(instruction_index) > params_len)9566 if (@intFromEnum(instruction_index) > params_len)
9620 try writer.writeByte('\n');9567 try writer.writeByte('\n');
9621 try writer.print("{}:\n", .{name.fmt(self)});9568 try writer.print("{}:\n", .{name.fmt(self)});
9569 continue;
9622 },9570 },
9623 .br => |tag| {9571 .br => |tag| {
9624 const target: Function.Block.Index = @enumFromInt(instruction.data);9572 const target: Function.Block.Index = @enumFromInt(instruction.data);
9625 try writer.print(" {s} {%}\n", .{9573 try writer.print(" {s} {%}", .{
9626 @tagName(tag), target.toInst(&function).fmt(function_index, self),9574 @tagName(tag), target.toInst(&function).fmt(function_index, self),
9627 });9575 });
9628 },9576 },
9629 .br_cond => {9577 .br_cond => {
9630 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);9578 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
9631 try writer.print(" br {%}, {%}, {%}\n", .{9579 try writer.print(" br {%}, {%}, {%}", .{
9632 extra.cond.fmt(function_index, self),9580 extra.cond.fmt(function_index, self),
9633 extra.then.toInst(&function).fmt(function_index, self),9581 extra.then.toInst(&function).fmt(function_index, self),
9634 extra.@"else".toInst(&function).fmt(function_index, self),9582 extra.@"else".toInst(&function).fmt(function_index, self),
...@@ -9668,10 +9616,12 @@ pub fn printUnbuffered(...@@ -9668,10 +9616,12 @@ pub fn printUnbuffered(
9668 });9616 });
9669 for (0.., args) |arg_index, arg| {9617 for (0.., args) |arg_index, arg| {
9670 if (arg_index > 0) try writer.writeAll(", ");9618 if (arg_index > 0) try writer.writeAll(", ");
9671 try writer.print("{%}{} {}", .{9619 metadata_formatter.need_comma = false;
9620 defer metadata_formatter.need_comma = undefined;
9621 try writer.print("{%}{}{}", .{
9672 arg.typeOf(function_index, self).fmt(self),9622 arg.typeOf(function_index, self).fmt(self),
9673 extra.data.attributes.param(arg_index, self).fmt(self),9623 extra.data.attributes.param(arg_index, self).fmt(self),
9674 arg.fmt(function_index, self),9624 try metadata_formatter.fmtLocal(" ", arg, function_index),
9675 });9625 });
9676 }9626 }
9677 try writer.writeByte(')');9627 try writer.writeByte(')');
...@@ -9683,14 +9633,13 @@ pub fn printUnbuffered(...@@ -9683,14 +9633,13 @@ pub fn printUnbuffered(
9683 {},9633 {},
9684 )).index,9634 )).index,
9685 });9635 });
9686 try writer.writeByte('\n');
9687 },9636 },
9688 .cmpxchg,9637 .cmpxchg,
9689 .@"cmpxchg weak",9638 .@"cmpxchg weak",
9690 => |tag| {9639 => |tag| {
9691 const extra =9640 const extra =
9692 function.extraData(Function.Instruction.CmpXchg, instruction.data);9641 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9693 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{9642 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }", .{
9694 instruction_index.name(&function).fmt(self),9643 instruction_index.name(&function).fmt(self),
9695 @tagName(tag),9644 @tagName(tag),
9696 extra.info.access_kind,9645 extra.info.access_kind,
...@@ -9706,7 +9655,7 @@ pub fn printUnbuffered(...@@ -9706,7 +9655,7 @@ pub fn printUnbuffered(
9706 .extractelement => |tag| {9655 .extractelement => |tag| {
9707 const extra =9656 const extra =
9708 function.extraData(Function.Instruction.ExtractElement, instruction.data);9657 function.extraData(Function.Instruction.ExtractElement, instruction.data);
9709 try writer.print(" %{} = {s} {%}, {%}\n", .{9658 try writer.print(" %{} = {s} {%}, {%}", .{
9710 instruction_index.name(&function).fmt(self),9659 instruction_index.name(&function).fmt(self),
9711 @tagName(tag),9660 @tagName(tag),
9712 extra.val.fmt(function_index, self),9661 extra.val.fmt(function_index, self),
...@@ -9725,7 +9674,6 @@ pub fn printUnbuffered(...@@ -9725,7 +9674,6 @@ pub fn printUnbuffered(
9725 extra.data.val.fmt(function_index, self),9674 extra.data.val.fmt(function_index, self),
9726 });9675 });
9727 for (indices) |index| try writer.print(", {d}", .{index});9676 for (indices) |index| try writer.print(", {d}", .{index});
9728 try writer.writeByte('\n');
9729 },9677 },
9730 .fence => |tag| {9678 .fence => |tag| {
9731 const info: MemoryAccessInfo = @bitCast(instruction.data);9679 const info: MemoryAccessInfo = @bitCast(instruction.data);
...@@ -9739,7 +9687,7 @@ pub fn printUnbuffered(...@@ -9739,7 +9687,7 @@ pub fn printUnbuffered(
9739 .@"fneg fast",9687 .@"fneg fast",
9740 => |tag| {9688 => |tag| {
9741 const val: Value = @enumFromInt(instruction.data);9689 const val: Value = @enumFromInt(instruction.data);
9742 try writer.print(" %{} = {s} {%}\n", .{9690 try writer.print(" %{} = {s} {%}", .{
9743 instruction_index.name(&function).fmt(self),9691 instruction_index.name(&function).fmt(self),
9744 @tagName(tag),9692 @tagName(tag),
9745 val.fmt(function_index, self),9693 val.fmt(function_index, self),
...@@ -9762,12 +9710,11 @@ pub fn printUnbuffered(...@@ -9762,12 +9710,11 @@ pub fn printUnbuffered(
9762 for (indices) |index| try writer.print(", {%}", .{9710 for (indices) |index| try writer.print(", {%}", .{
9763 index.fmt(function_index, self),9711 index.fmt(function_index, self),
9764 });9712 });
9765 try writer.writeByte('\n');
9766 },9713 },
9767 .insertelement => |tag| {9714 .insertelement => |tag| {
9768 const extra =9715 const extra =
9769 function.extraData(Function.Instruction.InsertElement, instruction.data);9716 function.extraData(Function.Instruction.InsertElement, instruction.data);
9770 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{9717 try writer.print(" %{} = {s} {%}, {%}, {%}", .{
9771 instruction_index.name(&function).fmt(self),9718 instruction_index.name(&function).fmt(self),
9772 @tagName(tag),9719 @tagName(tag),
9773 extra.val.fmt(function_index, self),9720 extra.val.fmt(function_index, self),
...@@ -9786,13 +9733,12 @@ pub fn printUnbuffered(...@@ -9786,13 +9733,12 @@ pub fn printUnbuffered(
9786 extra.data.elem.fmt(function_index, self),9733 extra.data.elem.fmt(function_index, self),
9787 });9734 });
9788 for (indices) |index| try writer.print(", {d}", .{index});9735 for (indices) |index| try writer.print(", {d}", .{index});
9789 try writer.writeByte('\n');
9790 },9736 },
9791 .load,9737 .load,
9792 .@"load atomic",9738 .@"load atomic",
9793 => |tag| {9739 => |tag| {
9794 const extra = function.extraData(Function.Instruction.Load, instruction.data);9740 const extra = function.extraData(Function.Instruction.Load, instruction.data);
9795 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{9741 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }", .{
9796 instruction_index.name(&function).fmt(self),9742 instruction_index.name(&function).fmt(self),
9797 @tagName(tag),9743 @tagName(tag),
9798 extra.info.access_kind,9744 extra.info.access_kind,
...@@ -9822,23 +9768,22 @@ pub fn printUnbuffered(...@@ -9822,23 +9768,22 @@ pub fn printUnbuffered(
9822 incoming_block.toInst(&function).fmt(function_index, self),9768 incoming_block.toInst(&function).fmt(function_index, self),
9823 });9769 });
9824 }9770 }
9825 try writer.writeByte('\n');
9826 },9771 },
9827 .ret => |tag| {9772 .ret => |tag| {
9828 const val: Value = @enumFromInt(instruction.data);9773 const val: Value = @enumFromInt(instruction.data);
9829 try writer.print(" {s} {%}\n", .{9774 try writer.print(" {s} {%}", .{
9830 @tagName(tag),9775 @tagName(tag),
9831 val.fmt(function_index, self),9776 val.fmt(function_index, self),
9832 });9777 });
9833 },9778 },
9834 .@"ret void",9779 .@"ret void",
9835 .@"unreachable",9780 .@"unreachable",
9836 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),9781 => |tag| try writer.print(" {s}", .{@tagName(tag)}),
9837 .select,9782 .select,
9838 .@"select fast",9783 .@"select fast",
9839 => |tag| {9784 => |tag| {
9840 const extra = function.extraData(Function.Instruction.Select, instruction.data);9785 const extra = function.extraData(Function.Instruction.Select, instruction.data);
9841 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{9786 try writer.print(" %{} = {s} {%}, {%}, {%}", .{
9842 instruction_index.name(&function).fmt(self),9787 instruction_index.name(&function).fmt(self),
9843 @tagName(tag),9788 @tagName(tag),
9844 extra.cond.fmt(function_index, self),9789 extra.cond.fmt(function_index, self),
...@@ -9849,7 +9794,7 @@ pub fn printUnbuffered(...@@ -9849,7 +9794,7 @@ pub fn printUnbuffered(
9849 .shufflevector => |tag| {9794 .shufflevector => |tag| {
9850 const extra =9795 const extra =
9851 function.extraData(Function.Instruction.ShuffleVector, instruction.data);9796 function.extraData(Function.Instruction.ShuffleVector, instruction.data);
9852 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{9797 try writer.print(" %{} = {s} {%}, {%}, {%}", .{
9853 instruction_index.name(&function).fmt(self),9798 instruction_index.name(&function).fmt(self),
9854 @tagName(tag),9799 @tagName(tag),
9855 extra.lhs.fmt(function_index, self),9800 extra.lhs.fmt(function_index, self),
...@@ -9861,7 +9806,7 @@ pub fn printUnbuffered(...@@ -9861,7 +9806,7 @@ pub fn printUnbuffered(
9861 .@"store atomic",9806 .@"store atomic",
9862 => |tag| {9807 => |tag| {
9863 const extra = function.extraData(Function.Instruction.Store, instruction.data);9808 const extra = function.extraData(Function.Instruction.Store, instruction.data);
9864 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{9809 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }", .{
9865 @tagName(tag),9810 @tagName(tag),
9866 extra.info.access_kind,9811 extra.info.access_kind,
9867 extra.val.fmt(function_index, self),9812 extra.val.fmt(function_index, self),
...@@ -9889,11 +9834,11 @@ pub fn printUnbuffered(...@@ -9889,11 +9834,11 @@ pub fn printUnbuffered(
9889 case_block.toInst(&function).fmt(function_index, self),9834 case_block.toInst(&function).fmt(function_index, self),
9890 },9835 },
9891 );9836 );
9892 try writer.writeAll(" ]\n");9837 try writer.writeAll(" ]");
9893 },9838 },
9894 .va_arg => |tag| {9839 .va_arg => |tag| {
9895 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);9840 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
9896 try writer.print(" %{} = {s} {%}, {%}\n", .{9841 try writer.print(" %{} = {s} {%}, {%}", .{
9897 instruction_index.name(&function).fmt(self),9842 instruction_index.name(&function).fmt(self),
9898 @tagName(tag),9843 @tagName(tag),
9899 extra.list.fmt(function_index, self),9844 extra.list.fmt(function_index, self),
...@@ -9901,11 +9846,13 @@ pub fn printUnbuffered(...@@ -9901,11 +9846,13 @@ pub fn printUnbuffered(
9901 });9846 });
9902 },9847 },
9903 }9848 }
9849 metadata_formatter.need_comma = true;
9850 defer metadata_formatter.need_comma = undefined;
9851 try writer.print("{}\n", .{try metadata_formatter.fmt("!dbg ", dbg)});
9904 }9852 }
9905 try writer.writeByte('}');9853 try writer.writeByte('}');
9906 }9854 }
9907 try writer.writeByte('\n');9855 try writer.writeByte('\n');
9908 need_newline = true;
9909 }9856 }
99109857
9911 if (attribute_groups.count() > 0) {9858 if (attribute_groups.count() > 0) {
...@@ -9915,12 +9862,375 @@ pub fn printUnbuffered(...@@ -9915,12 +9862,375 @@ pub fn printUnbuffered(
9915 \\attributes #{d} = {{{#"} }}9862 \\attributes #{d} = {{{#"} }}
9916 \\9863 \\
9917 , .{ attribute_group_index, attribute_group.fmt(self) });9864 , .{ attribute_group_index, attribute_group.fmt(self) });
9918 need_newline = true;
9919 }9865 }
9920}
99219866
9922pub inline fn useLibLlvm(self: *const Builder) bool {9867 if (self.metadata_named.count() > 0) {
9923 return build_options.have_llvm and self.use_lib_llvm;9868 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9869 for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {
9870 const elements: []const Metadata =
9871 @ptrCast(self.metadata_extra.items[data.index..][0..data.len]);
9872 try writer.writeByte('!');
9873 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, writer);
9874 try writer.writeAll(" = !{");
9875 metadata_formatter.need_comma = false;
9876 defer metadata_formatter.need_comma = undefined;
9877 for (elements) |element| try writer.print("{}", .{try metadata_formatter.fmt("", element)});
9878 try writer.writeAll("}\n");
9879 }
9880 }
9881
9882 if (metadata_formatter.map.count() > 0) {
9883 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9884 var metadata_index: usize = 0;
9885 while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {
9886 @setEvalBranchQuota(10_000);
9887 const metadata_item =
9888 self.metadata_items.get(@intFromEnum(metadata_formatter.map.keys()[metadata_index]));
9889 try writer.print("!{} = ", .{metadata_index});
9890 metadata_formatter.need_comma = false;
9891 defer metadata_formatter.need_comma = undefined;
9892 switch (metadata_item.tag) {
9893 .none, .expression, .constant => unreachable,
9894 .file => {
9895 const extra = self.metadataExtraData(Metadata.File, metadata_item.data);
9896 try metadata_formatter.specialized(.@"!", .DIFile, .{
9897 .filename = extra.filename,
9898 .directory = extra.directory,
9899 .checksumkind = null,
9900 .checksum = null,
9901 .source = null,
9902 }, writer);
9903 },
9904 .compile_unit,
9905 .@"compile_unit optimized",
9906 => |kind| {
9907 const extra = self.metadataExtraData(Metadata.CompileUnit, metadata_item.data);
9908 try metadata_formatter.specialized(.@"distinct !", .DICompileUnit, .{
9909 .language = .DW_LANG_C99,
9910 .file = extra.file,
9911 .producer = extra.producer,
9912 .isOptimized = switch (kind) {
9913 .compile_unit => false,
9914 .@"compile_unit optimized" => true,
9915 else => unreachable,
9916 },
9917 .flags = null,
9918 .runtimeVersion = 0,
9919 .splitDebugFilename = null,
9920 .emissionKind = .FullDebug,
9921 .enums = extra.enums,
9922 .retainedTypes = null,
9923 .globals = extra.globals,
9924 .imports = null,
9925 .macros = null,
9926 .dwoId = null,
9927 .splitDebugInlining = false,
9928 .debugInfoForProfiling = null,
9929 .nameTableKind = null,
9930 .rangesBaseAddress = null,
9931 .sysroot = null,
9932 .sdk = null,
9933 }, writer);
9934 },
9935 .subprogram,
9936 .@"subprogram local",
9937 .@"subprogram definition",
9938 .@"subprogram local definition",
9939 .@"subprogram optimized",
9940 .@"subprogram optimized local",
9941 .@"subprogram optimized definition",
9942 .@"subprogram optimized local definition",
9943 => |kind| {
9944 const extra = self.metadataExtraData(Metadata.Subprogram, metadata_item.data);
9945 try metadata_formatter.specialized(.@"distinct !", .DISubprogram, .{
9946 .name = extra.name,
9947 .linkageName = extra.linkage_name,
9948 .scope = extra.file,
9949 .file = extra.file,
9950 .line = extra.line,
9951 .type = extra.ty,
9952 .scopeLine = extra.scope_line,
9953 .containingType = null,
9954 .virtualIndex = null,
9955 .thisAdjustment = null,
9956 .flags = extra.di_flags,
9957 .spFlags = @as(Metadata.Subprogram.DISPFlags, @bitCast(@as(u32, @as(u3, @intCast(
9958 @intFromEnum(kind) - @intFromEnum(Metadata.Tag.subprogram),
9959 ))) << 2)),
9960 .unit = extra.compile_unit,
9961 .templateParams = null,
9962 .declaration = null,
9963 .retainedNodes = null,
9964 .thrownTypes = null,
9965 .annotations = null,
9966 .targetFuncName = null,
9967 }, writer);
9968 },
9969 .lexical_block => {
9970 const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);
9971 try metadata_formatter.specialized(.@"distinct !", .DILexicalBlock, .{
9972 .scope = extra.scope,
9973 .file = extra.file,
9974 .line = extra.line,
9975 .column = extra.column,
9976 }, writer);
9977 },
9978 .location => {
9979 const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);
9980 try metadata_formatter.specialized(.@"!", .DILocation, .{
9981 .line = extra.line,
9982 .column = extra.column,
9983 .scope = extra.scope,
9984 .inlinedAt = extra.inlined_at,
9985 .isImplicitCode = false,
9986 }, writer);
9987 },
9988 .basic_bool_type,
9989 .basic_unsigned_type,
9990 .basic_signed_type,
9991 .basic_float_type,
9992 => |kind| {
9993 const extra = self.metadataExtraData(Metadata.BasicType, metadata_item.data);
9994 try metadata_formatter.specialized(.@"!", .DIBasicType, .{
9995 .tag = null,
9996 .name = switch (extra.name) {
9997 .none => null,
9998 else => extra.name,
9999 },
10000 .size = extra.bitSize(),
10001 .@"align" = null,
10002 .encoding = @as(enum {
10003 DW_ATE_boolean,
10004 DW_ATE_unsigned,
10005 DW_ATE_signed,
10006 DW_ATE_float,
10007 }, switch (kind) {
10008 .basic_bool_type => .DW_ATE_boolean,
10009 .basic_unsigned_type => .DW_ATE_unsigned,
10010 .basic_signed_type => .DW_ATE_signed,
10011 .basic_float_type => .DW_ATE_float,
10012 else => unreachable,
10013 }),
10014 .flags = null,
10015 }, writer);
10016 },
10017 .composite_struct_type,
10018 .composite_union_type,
10019 .composite_enumeration_type,
10020 .composite_array_type,
10021 .composite_vector_type,
10022 => |kind| {
10023 const extra = self.metadataExtraData(Metadata.CompositeType, metadata_item.data);
10024 try metadata_formatter.specialized(.@"!", .DICompositeType, .{
10025 .tag = @as(enum {
10026 DW_TAG_structure_type,
10027 DW_TAG_union_type,
10028 DW_TAG_enumeration_type,
10029 DW_TAG_array_type,
10030 }, switch (kind) {
10031 .composite_struct_type => .DW_TAG_structure_type,
10032 .composite_union_type => .DW_TAG_union_type,
10033 .composite_enumeration_type => .DW_TAG_enumeration_type,
10034 .composite_array_type, .composite_vector_type => .DW_TAG_array_type,
10035 else => unreachable,
10036 }),
10037 .name = switch (extra.name) {
10038 .none => null,
10039 else => extra.name,
10040 },
10041 .scope = extra.scope,
10042 .file = null,
10043 .line = null,
10044 .baseType = extra.underlying_type,
10045 .size = extra.bitSize(),
10046 .@"align" = extra.bitAlign(),
10047 .offset = null,
10048 .flags = null,
10049 .elements = extra.fields_tuple,
10050 .runtimeLang = null,
10051 .vtableHolder = null,
10052 .templateParams = null,
10053 .identifier = null,
10054 .discriminator = null,
10055 .dataLocation = null,
10056 .associated = null,
10057 .allocated = null,
10058 .rank = null,
10059 .annotations = null,
10060 }, writer);
10061 },
10062 .derived_pointer_type,
10063 .derived_member_type,
10064 => |kind| {
10065 const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data);
10066 try metadata_formatter.specialized(.@"!", .DIDerivedType, .{
10067 .tag = @as(enum {
10068 DW_TAG_pointer_type,
10069 DW_TAG_member,
10070 }, switch (kind) {
10071 .derived_pointer_type => .DW_TAG_pointer_type,
10072 .derived_member_type => .DW_TAG_member,
10073 else => unreachable,
10074 }),
10075 .name = switch (extra.name) {
10076 .none => null,
10077 else => extra.name,
10078 },
10079 .scope = extra.scope,
10080 .file = null,
10081 .line = null,
10082 .baseType = extra.underlying_type,
10083 .size = extra.bitSize(),
10084 .@"align" = extra.bitAlign(),
10085 .offset = switch (extra.bitOffset()) {
10086 0 => null,
10087 else => |bit_offset| bit_offset,
10088 },
10089 .flags = null,
10090 .extraData = null,
10091 .dwarfAddressSpace = null,
10092 .annotations = null,
10093 }, writer);
10094 },
10095 .subroutine_type => {
10096 const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);
10097 try metadata_formatter.specialized(.@"!", .DISubroutineType, .{
10098 .flags = null,
10099 .cc = null,
10100 .types = extra.types_tuple,
10101 }, writer);
10102 },
10103 .enumerator_unsigned,
10104 .enumerator_signed_positive,
10105 .enumerator_signed_negative,
10106 => |kind| {
10107 const extra = self.metadataExtraData(Metadata.Enumerator, metadata_item.data);
10108
10109 const ExpectedContents = extern struct {
10110 string: [(64 * 8 / std.math.log2(10)) + 2]u8,
10111 limbs: [
10112 std.math.big.int.calcToStringLimbsBufferLen(
10113 64 / @sizeOf(std.math.big.Limb),
10114 10,
10115 )
10116 ]std.math.big.Limb,
10117 };
10118 var stack align(@alignOf(ExpectedContents)) =
10119 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
10120 const allocator = stack.get();
10121
10122 const limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len];
10123 const bigint: std.math.big.int.Const = .{
10124 .limbs = limbs,
10125 .positive = switch (kind) {
10126 .enumerator_unsigned,
10127 .enumerator_signed_positive,
10128 => true,
10129 .enumerator_signed_negative => false,
10130 else => unreachable,
10131 },
10132 };
10133 const str = try bigint.toStringAlloc(allocator, 10, undefined);
10134 defer allocator.free(str);
10135
10136 try metadata_formatter.specialized(.@"!", .DIEnumerator, .{
10137 .name = extra.name,
10138 .value = str,
10139 .isUnsigned = switch (kind) {
10140 .enumerator_unsigned => true,
10141 .enumerator_signed_positive, .enumerator_signed_negative => false,
10142 else => unreachable,
10143 },
10144 }, writer);
10145 },
10146 .subrange => {
10147 const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);
10148 try metadata_formatter.specialized(.@"!", .DISubrange, .{
10149 .count = extra.count,
10150 .lowerBound = extra.lower_bound,
10151 .upperBound = null,
10152 .stride = null,
10153 }, writer);
10154 },
10155 .tuple => {
10156 var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);
10157 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10158 try writer.writeAll("!{");
10159 for (elements) |element| try writer.print("{[element]%}", .{
10160 .element = try metadata_formatter.fmt("", element),
10161 });
10162 try writer.writeAll("}\n");
10163 },
10164 .module_flag => {
10165 const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data);
10166 try writer.print("!{{{[behavior]%}{[name]%}{[constant]%}}}\n", .{
10167 .behavior = try metadata_formatter.fmt("", extra.behavior),
10168 .name = try metadata_formatter.fmt("", extra.name),
10169 .constant = try metadata_formatter.fmt("", extra.constant),
10170 });
10171 },
10172 .local_var => {
10173 const extra = self.metadataExtraData(Metadata.LocalVar, metadata_item.data);
10174 try metadata_formatter.specialized(.@"!", .DILocalVariable, .{
10175 .name = extra.name,
10176 .arg = null,
10177 .scope = extra.scope,
10178 .file = extra.file,
10179 .line = extra.line,
10180 .type = extra.ty,
10181 .flags = null,
10182 .@"align" = null,
10183 .annotations = null,
10184 }, writer);
10185 },
10186 .parameter => {
10187 const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);
10188 try metadata_formatter.specialized(.@"!", .DILocalVariable, .{
10189 .name = extra.name,
10190 .arg = extra.arg_no,
10191 .scope = extra.scope,
10192 .file = extra.file,
10193 .line = extra.line,
10194 .type = extra.ty,
10195 .flags = null,
10196 .@"align" = null,
10197 .annotations = null,
10198 }, writer);
10199 },
10200 .global_var,
10201 .@"global_var local",
10202 => |kind| {
10203 const extra = self.metadataExtraData(Metadata.GlobalVar, metadata_item.data);
10204 try metadata_formatter.specialized(.@"distinct !", .DIGlobalVariable, .{
10205 .name = extra.name,
10206 .linkageName = extra.linkage_name,
10207 .scope = extra.scope,
10208 .file = extra.file,
10209 .line = extra.line,
10210 .type = extra.ty,
10211 .isLocal = switch (kind) {
10212 .global_var => false,
10213 .@"global_var local" => true,
10214 else => unreachable,
10215 },
10216 .isDefinition = true,
10217 .declaration = null,
10218 .templateParams = null,
10219 .@"align" = null,
10220 .annotations = null,
10221 }, writer);
10222 },
10223 .global_var_expression => {
10224 const extra =
10225 self.metadataExtraData(Metadata.GlobalVarExpression, metadata_item.data);
10226 try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{
10227 .@"var" = extra.variable,
10228 .expr = extra.expression,
10229 }, writer);
10230 },
10231 }
10232 }
10233 }
9924}10234}
992510235
9926const NoExtra = struct {};10236const NoExtra = struct {};
...@@ -9954,10 +10264,9 @@ fn printEscapedString(...@@ -9954,10 +10264,9 @@ fn printEscapedString(
9954}10264}
995510265
9956fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void {10266fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void {
9957 if (self.useLibLlvm()) try self.llvm.globals.ensureUnusedCapacity(self.gpa, 1);
9958 try self.string_map.ensureUnusedCapacity(self.gpa, 1);10267 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
9959 if (name.slice(self)) |id| {10268 if (name.slice(self)) |id| {
9960 const count: usize = comptime std.fmt.count("{d}" ++ .{0}, .{std.math.maxInt(u32)});10269 const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)});
9961 try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count);10270 try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count);
9962 }10271 }
9963 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);10272 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
...@@ -9970,7 +10279,7 @@ fn fnTypeAssumeCapacity(...@@ -9970,7 +10279,7 @@ fn fnTypeAssumeCapacity(
9970 ret: Type,10279 ret: Type,
9971 params: []const Type,10280 params: []const Type,
9972 comptime kind: Type.Function.Kind,10281 comptime kind: Type.Function.Kind,
9973) (if (build_options.have_llvm) Allocator.Error else error{})!Type {10282) Type {
9974 const tag: Type.Tag = switch (kind) {10283 const tag: Type.Tag = switch (kind) {
9975 .normal => .function,10284 .normal => .function,
9976 .vararg => .vararg_function,10285 .vararg => .vararg_function,
...@@ -10007,20 +10316,6 @@ fn fnTypeAssumeCapacity(...@@ -10007,20 +10316,6 @@ fn fnTypeAssumeCapacity(
10007 }),10316 }),
10008 });10317 });
10009 self.type_extra.appendSliceAssumeCapacity(@ptrCast(params));10318 self.type_extra.appendSliceAssumeCapacity(@ptrCast(params));
10010 if (self.useLibLlvm()) {
10011 const llvm_params = try self.gpa.alloc(*llvm.Type, params.len);
10012 defer self.gpa.free(llvm_params);
10013 for (llvm_params, params) |*llvm_param, param| llvm_param.* = param.toLlvm(self);
10014 self.llvm.types.appendAssumeCapacity(llvm.functionType(
10015 ret.toLlvm(self),
10016 llvm_params.ptr,
10017 @intCast(llvm_params.len),
10018 switch (kind) {
10019 .normal => .False,
10020 .vararg => .True,
10021 },
10022 ));
10023 }
10024 }10319 }
10025 return @enumFromInt(gop.index);10320 return @enumFromInt(gop.index);
10026}10321}
...@@ -10028,8 +10323,6 @@ fn fnTypeAssumeCapacity(...@@ -10028,8 +10323,6 @@ fn fnTypeAssumeCapacity(
10028fn intTypeAssumeCapacity(self: *Builder, bits: u24) Type {10323fn intTypeAssumeCapacity(self: *Builder, bits: u24) Type {
10029 assert(bits > 0);10324 assert(bits > 0);
10030 const result = self.getOrPutTypeNoExtraAssumeCapacity(.{ .tag = .integer, .data = bits });10325 const result = self.getOrPutTypeNoExtraAssumeCapacity(.{ .tag = .integer, .data = bits });
10031 if (self.useLibLlvm() and result.new)
10032 self.llvm.types.appendAssumeCapacity(self.llvm.context.intType(bits));
10033 return result.type;10326 return result.type;
10034}10327}
1003510328
...@@ -10037,8 +10330,6 @@ fn ptrTypeAssumeCapacity(self: *Builder, addr_space: AddrSpace) Type {...@@ -10037,8 +10330,6 @@ fn ptrTypeAssumeCapacity(self: *Builder, addr_space: AddrSpace) Type {
10037 const result = self.getOrPutTypeNoExtraAssumeCapacity(10330 const result = self.getOrPutTypeNoExtraAssumeCapacity(
10038 .{ .tag = .pointer, .data = @intFromEnum(addr_space) },10331 .{ .tag = .pointer, .data = @intFromEnum(addr_space) },
10039 );10332 );
10040 if (self.useLibLlvm() and result.new)
10041 self.llvm.types.appendAssumeCapacity(self.llvm.context.pointerType(@intFromEnum(addr_space)));
10042 return result.type;10333 return result.type;
10043}10334}
1004410335
...@@ -10076,10 +10367,6 @@ fn vectorTypeAssumeCapacity(...@@ -10076,10 +10367,6 @@ fn vectorTypeAssumeCapacity(
10076 .tag = tag,10367 .tag = tag,
10077 .data = self.addTypeExtraAssumeCapacity(data),10368 .data = self.addTypeExtraAssumeCapacity(data),
10078 });10369 });
10079 if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity(switch (kind) {
10080 .normal => &llvm.Type.vectorType,
10081 .scalable => &llvm.Type.scalableVectorType,
10082 }(child.toLlvm(self), @intCast(len)));
10083 }10370 }
10084 return @enumFromInt(gop.index);10371 return @enumFromInt(gop.index);
10085}10372}
...@@ -10109,9 +10396,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type {...@@ -10109,9 +10396,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type {
10109 .tag = .small_array,10396 .tag = .small_array,
10110 .data = self.addTypeExtraAssumeCapacity(data),10397 .data = self.addTypeExtraAssumeCapacity(data),
10111 });10398 });
10112 if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity(
10113 child.toLlvm(self).arrayType2(len),
10114 );
10115 }10399 }
10116 return @enumFromInt(gop.index);10400 return @enumFromInt(gop.index);
10117 } else {10401 } else {
...@@ -10142,9 +10426,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type {...@@ -10142,9 +10426,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type {
10142 .tag = .array,10426 .tag = .array,
10143 .data = self.addTypeExtraAssumeCapacity(data),10427 .data = self.addTypeExtraAssumeCapacity(data),
10144 });10428 });
10145 if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity(
10146 child.toLlvm(self).arrayType2(len),
10147 );
10148 }10429 }
10149 return @enumFromInt(gop.index);10430 return @enumFromInt(gop.index);
10150 }10431 }
...@@ -10154,7 +10435,7 @@ fn structTypeAssumeCapacity(...@@ -10154,7 +10435,7 @@ fn structTypeAssumeCapacity(
10154 self: *Builder,10435 self: *Builder,
10155 comptime kind: Type.Structure.Kind,10436 comptime kind: Type.Structure.Kind,
10156 fields: []const Type,10437 fields: []const Type,
10157) (if (build_options.have_llvm) Allocator.Error else error{})!Type {10438) Type {
10158 const tag: Type.Tag = switch (kind) {10439 const tag: Type.Tag = switch (kind) {
10159 .normal => .structure,10440 .normal => .structure,
10160 .@"packed" => .packed_structure,10441 .@"packed" => .packed_structure,
...@@ -10186,25 +10467,6 @@ fn structTypeAssumeCapacity(...@@ -10186,25 +10467,6 @@ fn structTypeAssumeCapacity(
10186 }),10467 }),
10187 });10468 });
10188 self.type_extra.appendSliceAssumeCapacity(@ptrCast(fields));10469 self.type_extra.appendSliceAssumeCapacity(@ptrCast(fields));
10189 if (self.useLibLlvm()) {
10190 const ExpectedContents = [expected_fields_len]*llvm.Type;
10191 var stack align(@alignOf(ExpectedContents)) =
10192 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
10193 const allocator = stack.get();
10194
10195 const llvm_fields = try allocator.alloc(*llvm.Type, fields.len);
10196 defer allocator.free(llvm_fields);
10197 for (llvm_fields, fields) |*llvm_field, field| llvm_field.* = field.toLlvm(self);
10198
10199 self.llvm.types.appendAssumeCapacity(self.llvm.context.structType(
10200 llvm_fields.ptr,
10201 @intCast(llvm_fields.len),
10202 switch (kind) {
10203 .normal => .False,
10204 .@"packed" => .True,
10205 },
10206 ));
10207 }
10208 }10470 }
10209 return @enumFromInt(gop.index);10471 return @enumFromInt(gop.index);
10210}10472}
...@@ -10246,9 +10508,6 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {...@@ -10246,9 +10508,6 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {
10246 });10508 });
10247 const result: Type = @enumFromInt(gop.index);10509 const result: Type = @enumFromInt(gop.index);
10248 type_gop.value_ptr.* = result;10510 type_gop.value_ptr.* = result;
10249 if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity(
10250 self.llvm.context.structCreateNamed(id.slice(self) orelse ""),
10251 );
10252 return result;10511 return result;
10253 }10512 }
1025410513
...@@ -10271,7 +10530,6 @@ fn ensureUnusedTypeCapacity(...@@ -10271,7 +10530,6 @@ fn ensureUnusedTypeCapacity(
10271 self.gpa,10530 self.gpa,
10272 count * (@typeInfo(Extra).Struct.fields.len + trail_len),10531 count * (@typeInfo(Extra).Struct.fields.len + trail_len),
10273 );10532 );
10274 if (self.useLibLlvm()) try self.llvm.types.ensureUnusedCapacity(self.gpa, count);
10275}10533}
1027610534
10277fn getOrPutTypeNoExtraAssumeCapacity(self: *Builder, item: Type.Item) struct { new: bool, type: Type } {10535fn getOrPutTypeNoExtraAssumeCapacity(self: *Builder, item: Type.Item) struct { new: bool, type: Type } {
...@@ -10305,7 +10563,7 @@ fn addTypeExtraAssumeCapacity(self: *Builder, extra: anytype) Type.Item.ExtraInd...@@ -10305,7 +10563,7 @@ fn addTypeExtraAssumeCapacity(self: *Builder, extra: anytype) Type.Item.ExtraInd
10305 self.type_extra.appendAssumeCapacity(switch (field.type) {10563 self.type_extra.appendAssumeCapacity(switch (field.type) {
10306 u32 => value,10564 u32 => value,
10307 String, Type => @intFromEnum(value),10565 String, Type => @intFromEnum(value),
10308 else => @compileError("bad field type: " ++ @typeName(field.type)),10566 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
10309 });10567 });
10310 }10568 }
10311 return result;10569 return result;
...@@ -10388,10 +10646,7 @@ fn bigIntConstAssumeCapacity(...@@ -10388,10 +10646,7 @@ fn bigIntConstAssumeCapacity(
10388 assert(type_item.tag == .integer);10646 assert(type_item.tag == .integer);
10389 const bits = type_item.data;10647 const bits = type_item.data;
1039010648
10391 const ExpectedContents = extern struct {10649 const ExpectedContents = [64 / @sizeOf(std.math.big.Limb)]std.math.big.Limb;
10392 limbs: [64 / @sizeOf(std.math.big.Limb)]std.math.big.Limb,
10393 llvm_limbs: if (build_options.have_llvm) [64 / @sizeOf(u64)]u64 else void,
10394 };
10395 var stack align(@alignOf(ExpectedContents)) =10650 var stack align(@alignOf(ExpectedContents)) =
10396 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);10651 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
10397 const allocator = stack.get();10652 const allocator = stack.get();
...@@ -10448,44 +10703,6 @@ fn bigIntConstAssumeCapacity(...@@ -10448,44 +10703,6 @@ fn bigIntConstAssumeCapacity(
10448 @ptrCast(self.constant_limbs.addManyAsArrayAssumeCapacity(Constant.Integer.limbs));10703 @ptrCast(self.constant_limbs.addManyAsArrayAssumeCapacity(Constant.Integer.limbs));
10449 extra.* = .{ .type = ty, .limbs_len = @intCast(canonical_value.limbs.len) };10704 extra.* = .{ .type = ty, .limbs_len = @intCast(canonical_value.limbs.len) };
10450 self.constant_limbs.appendSliceAssumeCapacity(canonical_value.limbs);10705 self.constant_limbs.appendSliceAssumeCapacity(canonical_value.limbs);
10451 if (self.useLibLlvm()) {
10452 const llvm_type = ty.toLlvm(self);
10453 if (canonical_value.to(c_longlong)) |small| {
10454 self.llvm.constants.appendAssumeCapacity(llvm_type.constInt(@bitCast(small), .True));
10455 } else |_| if (canonical_value.to(c_ulonglong)) |small| {
10456 self.llvm.constants.appendAssumeCapacity(llvm_type.constInt(small, .False));
10457 } else |_| {
10458 const llvm_limbs = try allocator.alloc(u64, std.math.divCeil(
10459 usize,
10460 if (canonical_value.positive) canonical_value.bitCountAbs() else bits,
10461 @bitSizeOf(u64),
10462 ) catch unreachable);
10463 defer allocator.free(llvm_limbs);
10464 var limb_index: usize = 0;
10465 var borrow: std.math.big.Limb = 0;
10466 for (llvm_limbs) |*result_limb| {
10467 var llvm_limb: u64 = 0;
10468 inline for (0..Constant.Integer.limbs) |shift| {
10469 const limb = if (limb_index < canonical_value.limbs.len)
10470 canonical_value.limbs[limb_index]
10471 else
10472 0;
10473 limb_index += 1;
10474 llvm_limb |= @as(u64, limb) << shift * @bitSizeOf(std.math.big.Limb);
10475 }
10476 if (!canonical_value.positive) {
10477 const overflow = @subWithOverflow(borrow, llvm_limb);
10478 llvm_limb = overflow[0];
10479 borrow -%= overflow[1];
10480 assert(borrow == 0 or borrow == std.math.maxInt(std.math.big.Limb));
10481 }
10482 result_limb.* = llvm_limb;
10483 }
10484 self.llvm.constants.appendAssumeCapacity(
10485 llvm_type.constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), llvm_limbs.ptr),
10486 );
10487 }
10488 }
10489 }10706 }
10490 return @enumFromInt(gop.index);10707 return @enumFromInt(gop.index);
10491}10708}
...@@ -10494,13 +10711,6 @@ fn halfConstAssumeCapacity(self: *Builder, val: f16) Constant {...@@ -10494,13 +10711,6 @@ fn halfConstAssumeCapacity(self: *Builder, val: f16) Constant {
10494 const result = self.getOrPutConstantNoExtraAssumeCapacity(10711 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10495 .{ .tag = .half, .data = @as(u16, @bitCast(val)) },10712 .{ .tag = .half, .data = @as(u16, @bitCast(val)) },
10496 );10713 );
10497 if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(
10498 if (std.math.isSignalNan(val))
10499 Type.i16.toLlvm(self).constInt(@as(u16, @bitCast(val)), .False)
10500 .constBitCast(Type.half.toLlvm(self))
10501 else
10502 Type.half.toLlvm(self).constReal(val),
10503 );
10504 return result.constant;10714 return result.constant;
10505}10715}
1050610716
...@@ -10509,16 +10719,6 @@ fn bfloatConstAssumeCapacity(self: *Builder, val: f32) Constant {...@@ -10509,16 +10719,6 @@ fn bfloatConstAssumeCapacity(self: *Builder, val: f32) Constant {
10509 const result = self.getOrPutConstantNoExtraAssumeCapacity(10719 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10510 .{ .tag = .bfloat, .data = @bitCast(val) },10720 .{ .tag = .bfloat, .data = @bitCast(val) },
10511 );10721 );
10512 if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(
10513 if (std.math.isSignalNan(val))
10514 Type.i16.toLlvm(self).constInt(@as(u32, @bitCast(val)) >> 16, .False)
10515 .constBitCast(Type.bfloat.toLlvm(self))
10516 else
10517 Type.bfloat.toLlvm(self).constReal(val),
10518 );
10519
10520 if (self.useLibLlvm() and result.new)
10521 self.llvm.constants.appendAssumeCapacity(Type.bfloat.toLlvm(self).constReal(val));
10522 return result.constant;10722 return result.constant;
10523}10723}
1052410724
...@@ -10526,13 +10726,6 @@ fn floatConstAssumeCapacity(self: *Builder, val: f32) Constant {...@@ -10526,13 +10726,6 @@ fn floatConstAssumeCapacity(self: *Builder, val: f32) Constant {
10526 const result = self.getOrPutConstantNoExtraAssumeCapacity(10726 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10527 .{ .tag = .float, .data = @bitCast(val) },10727 .{ .tag = .float, .data = @bitCast(val) },
10528 );10728 );
10529 if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(
10530 if (std.math.isSignalNan(val))
10531 Type.i32.toLlvm(self).constInt(@as(u32, @bitCast(val)), .False)
10532 .constBitCast(Type.float.toLlvm(self))
10533 else
10534 Type.float.toLlvm(self).constReal(val),
10535 );
10536 return result.constant;10729 return result.constant;
10537}10730}
1053810731
...@@ -10563,13 +10756,6 @@ fn doubleConstAssumeCapacity(self: *Builder, val: f64) Constant {...@@ -10563,13 +10756,6 @@ fn doubleConstAssumeCapacity(self: *Builder, val: f64) Constant {
10563 .hi = @intCast(@as(u64, @bitCast(val)) >> 32),10756 .hi = @intCast(@as(u64, @bitCast(val)) >> 32),
10564 }),10757 }),
10565 });10758 });
10566 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
10567 if (std.math.isSignalNan(val))
10568 Type.i64.toLlvm(self).constInt(@as(u64, @bitCast(val)), .False)
10569 .constBitCast(Type.double.toLlvm(self))
10570 else
10571 Type.double.toLlvm(self).constReal(val),
10572 );
10573 }10759 }
10574 return @enumFromInt(gop.index);10760 return @enumFromInt(gop.index);
10575}10761}
...@@ -10604,17 +10790,6 @@ fn fp128ConstAssumeCapacity(self: *Builder, val: f128) Constant {...@@ -10604,17 +10790,6 @@ fn fp128ConstAssumeCapacity(self: *Builder, val: f128) Constant {
10604 .hi_hi = @intCast(@as(u128, @bitCast(val)) >> 96),10790 .hi_hi = @intCast(@as(u128, @bitCast(val)) >> 96),
10605 }),10791 }),
10606 });10792 });
10607 if (self.useLibLlvm()) {
10608 const llvm_limbs = [_]u64{
10609 @truncate(@as(u128, @bitCast(val))),
10610 @intCast(@as(u128, @bitCast(val)) >> 64),
10611 };
10612 self.llvm.constants.appendAssumeCapacity(
10613 Type.i128.toLlvm(self)
10614 .constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), &llvm_limbs)
10615 .constBitCast(Type.fp128.toLlvm(self)),
10616 );
10617 }
10618 }10793 }
10619 return @enumFromInt(gop.index);10794 return @enumFromInt(gop.index);
10620}10795}
...@@ -10648,17 +10823,6 @@ fn x86_fp80ConstAssumeCapacity(self: *Builder, val: f80) Constant {...@@ -10648,17 +10823,6 @@ fn x86_fp80ConstAssumeCapacity(self: *Builder, val: f80) Constant {
10648 .hi = @intCast(@as(u80, @bitCast(val)) >> 64),10823 .hi = @intCast(@as(u80, @bitCast(val)) >> 64),
10649 }),10824 }),
10650 });10825 });
10651 if (self.useLibLlvm()) {
10652 const llvm_limbs = [_]u64{
10653 @truncate(@as(u80, @bitCast(val))),
10654 @intCast(@as(u80, @bitCast(val)) >> 64),
10655 };
10656 self.llvm.constants.appendAssumeCapacity(
10657 Type.i80.toLlvm(self)
10658 .constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), &llvm_limbs)
10659 .constBitCast(Type.x86_fp80.toLlvm(self)),
10660 );
10661 }
10662 }10826 }
10663 return @enumFromInt(gop.index);10827 return @enumFromInt(gop.index);
10664}10828}
...@@ -10693,14 +10857,6 @@ fn ppc_fp128ConstAssumeCapacity(self: *Builder, val: [2]f64) Constant {...@@ -10693,14 +10857,6 @@ fn ppc_fp128ConstAssumeCapacity(self: *Builder, val: [2]f64) Constant {
10693 .hi_hi = @intCast(@as(u64, @bitCast(val[1])) >> 32),10857 .hi_hi = @intCast(@as(u64, @bitCast(val[1])) >> 32),
10694 }),10858 }),
10695 });10859 });
10696 if (self.useLibLlvm()) {
10697 const llvm_limbs: [2]u64 = @bitCast(val);
10698 self.llvm.constants.appendAssumeCapacity(
10699 Type.i128.toLlvm(self)
10700 .constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), &llvm_limbs)
10701 .constBitCast(Type.ppc_fp128.toLlvm(self)),
10702 );
10703 }
10704 }10860 }
10705 return @enumFromInt(gop.index);10861 return @enumFromInt(gop.index);
10706}10862}
...@@ -10710,8 +10866,6 @@ fn nullConstAssumeCapacity(self: *Builder, ty: Type) Constant {...@@ -10710,8 +10866,6 @@ fn nullConstAssumeCapacity(self: *Builder, ty: Type) Constant {
10710 const result = self.getOrPutConstantNoExtraAssumeCapacity(10866 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10711 .{ .tag = .null, .data = @intFromEnum(ty) },10867 .{ .tag = .null, .data = @intFromEnum(ty) },
10712 );10868 );
10713 if (self.useLibLlvm() and result.new)
10714 self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).constNull());
10715 return result.constant;10869 return result.constant;
10716}10870}
1071710871
...@@ -10720,16 +10874,10 @@ fn noneConstAssumeCapacity(self: *Builder, ty: Type) Constant {...@@ -10720,16 +10874,10 @@ fn noneConstAssumeCapacity(self: *Builder, ty: Type) Constant {
10720 const result = self.getOrPutConstantNoExtraAssumeCapacity(10874 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10721 .{ .tag = .none, .data = @intFromEnum(ty) },10875 .{ .tag = .none, .data = @intFromEnum(ty) },
10722 );10876 );
10723 if (self.useLibLlvm() and result.new)
10724 self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).constNull());
10725 return result.constant;10877 return result.constant;
10726}10878}
1072710879
10728fn structConstAssumeCapacity(10880fn structConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant {
10729 self: *Builder,
10730 ty: Type,
10731 vals: []const Constant,
10732) (if (build_options.have_llvm) Allocator.Error else error{})!Constant {
10733 const type_item = self.type_items.items[@intFromEnum(ty)];10881 const type_item = self.type_items.items[@intFromEnum(ty)];
10734 var extra = self.typeExtraDataTrail(Type.Structure, switch (type_item.tag) {10882 var extra = self.typeExtraDataTrail(Type.Structure, switch (type_item.tag) {
10735 .structure, .packed_structure => type_item.data,10883 .structure, .packed_structure => type_item.data,
...@@ -10756,28 +10904,10 @@ fn structConstAssumeCapacity(...@@ -10756,28 +10904,10 @@ fn structConstAssumeCapacity(
10756 else => unreachable,10904 else => unreachable,
10757 };10905 };
10758 const result = self.getOrPutConstantAggregateAssumeCapacity(tag, ty, vals);10906 const result = self.getOrPutConstantAggregateAssumeCapacity(tag, ty, vals);
10759 if (self.useLibLlvm() and result.new) {
10760 const ExpectedContents = [expected_fields_len]*llvm.Value;
10761 var stack align(@alignOf(ExpectedContents)) =
10762 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
10763 const allocator = stack.get();
10764
10765 const llvm_vals = try allocator.alloc(*llvm.Value, vals.len);
10766 defer allocator.free(llvm_vals);
10767 for (llvm_vals, vals) |*llvm_val, val| llvm_val.* = val.toLlvm(self);
10768
10769 self.llvm.constants.appendAssumeCapacity(
10770 ty.toLlvm(self).constNamedStruct(llvm_vals.ptr, @intCast(llvm_vals.len)),
10771 );
10772 }
10773 return result.constant;10907 return result.constant;
10774}10908}
1077510909
10776fn arrayConstAssumeCapacity(10910fn arrayConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant {
10777 self: *Builder,
10778 ty: Type,
10779 vals: []const Constant,
10780) (if (build_options.have_llvm) Allocator.Error else error{})!Constant {
10781 const type_item = self.type_items.items[@intFromEnum(ty)];10911 const type_item = self.type_items.items[@intFromEnum(ty)];
10782 const type_extra: struct { len: u64, child: Type } = switch (type_item.tag) {10912 const type_extra: struct { len: u64, child: Type } = switch (type_item.tag) {
10783 inline .small_array, .array => |kind| extra: {10913 inline .small_array, .array => |kind| extra: {
...@@ -10798,20 +10928,6 @@ fn arrayConstAssumeCapacity(...@@ -10798,20 +10928,6 @@ fn arrayConstAssumeCapacity(
10798 } else return self.zeroInitConstAssumeCapacity(ty);10928 } else return self.zeroInitConstAssumeCapacity(ty);
1079910929
10800 const result = self.getOrPutConstantAggregateAssumeCapacity(.array, ty, vals);10930 const result = self.getOrPutConstantAggregateAssumeCapacity(.array, ty, vals);
10801 if (self.useLibLlvm() and result.new) {
10802 const ExpectedContents = [expected_fields_len]*llvm.Value;
10803 var stack align(@alignOf(ExpectedContents)) =
10804 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
10805 const allocator = stack.get();
10806
10807 const llvm_vals = try allocator.alloc(*llvm.Value, vals.len);
10808 defer allocator.free(llvm_vals);
10809 for (llvm_vals, vals) |*llvm_val, val| llvm_val.* = val.toLlvm(self);
10810
10811 self.llvm.constants.appendAssumeCapacity(
10812 type_extra.child.toLlvm(self).constArray2(llvm_vals.ptr, llvm_vals.len),
10813 );
10814 }
10815 return result.constant;10931 return result.constant;
10816}10932}
1081710933
...@@ -10822,30 +10938,10 @@ fn stringConstAssumeCapacity(self: *Builder, val: String) Constant {...@@ -10822,30 +10938,10 @@ fn stringConstAssumeCapacity(self: *Builder, val: String) Constant {
10822 const result = self.getOrPutConstantNoExtraAssumeCapacity(10938 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10823 .{ .tag = .string, .data = @intFromEnum(val) },10939 .{ .tag = .string, .data = @intFromEnum(val) },
10824 );10940 );
10825 if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(
10826 self.llvm.context.constString(slice.ptr, @intCast(slice.len), .True),
10827 );
10828 return result.constant;
10829}
10830
10831fn stringNullConstAssumeCapacity(self: *Builder, val: String) Constant {
10832 const slice = val.slice(self).?;
10833 const ty = self.arrayTypeAssumeCapacity(slice.len + 1, .i8);
10834 if (std.mem.allEqual(u8, slice, 0)) return self.zeroInitConstAssumeCapacity(ty);
10835 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10836 .{ .tag = .string_null, .data = @intFromEnum(val) },
10837 );
10838 if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(
10839 self.llvm.context.constString(slice.ptr, @intCast(slice.len + 1), .True),
10840 );
10841 return result.constant;10941 return result.constant;
10842}10942}
1084310943
10844fn vectorConstAssumeCapacity(10944fn vectorConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant {
10845 self: *Builder,
10846 ty: Type,
10847 vals: []const Constant,
10848) (if (build_options.have_llvm) Allocator.Error else error{})!Constant {
10849 assert(ty.isVector(self));10945 assert(ty.isVector(self));
10850 assert(ty.vectorLen(self) == vals.len);10946 assert(ty.vectorLen(self) == vals.len);
10851 for (vals) |val| assert(ty.childType(self) == val.typeOf(self));10947 for (vals) |val| assert(ty.childType(self) == val.typeOf(self));
...@@ -10858,28 +10954,10 @@ fn vectorConstAssumeCapacity(...@@ -10858,28 +10954,10 @@ fn vectorConstAssumeCapacity(
10858 } else return self.zeroInitConstAssumeCapacity(ty);10954 } else return self.zeroInitConstAssumeCapacity(ty);
1085910955
10860 const result = self.getOrPutConstantAggregateAssumeCapacity(.vector, ty, vals);10956 const result = self.getOrPutConstantAggregateAssumeCapacity(.vector, ty, vals);
10861 if (self.useLibLlvm() and result.new) {
10862 const ExpectedContents = [expected_fields_len]*llvm.Value;
10863 var stack align(@alignOf(ExpectedContents)) =
10864 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
10865 const allocator = stack.get();
10866
10867 const llvm_vals = try allocator.alloc(*llvm.Value, vals.len);
10868 defer allocator.free(llvm_vals);
10869 for (llvm_vals, vals) |*llvm_val, val| llvm_val.* = val.toLlvm(self);
10870
10871 self.llvm.constants.appendAssumeCapacity(
10872 llvm.constVector(llvm_vals.ptr, @intCast(llvm_vals.len)),
10873 );
10874 }
10875 return result.constant;10957 return result.constant;
10876}10958}
1087710959
10878fn splatConstAssumeCapacity(10960fn splatConstAssumeCapacity(self: *Builder, ty: Type, val: Constant) Constant {
10879 self: *Builder,
10880 ty: Type,
10881 val: Constant,
10882) (if (build_options.have_llvm) Allocator.Error else error{})!Constant {
10883 assert(ty.scalarType(self) == val.typeOf(self));10961 assert(ty.scalarType(self) == val.typeOf(self));
1088410962
10885 if (!ty.isVector(self)) return val;10963 if (!ty.isVector(self)) return val;
...@@ -10909,20 +10987,6 @@ fn splatConstAssumeCapacity(...@@ -10909,20 +10987,6 @@ fn splatConstAssumeCapacity(
10909 .tag = .splat,10987 .tag = .splat,
10910 .data = self.addConstantExtraAssumeCapacity(data),10988 .data = self.addConstantExtraAssumeCapacity(data),
10911 });10989 });
10912 if (self.useLibLlvm()) {
10913 const ExpectedContents = [expected_fields_len]*llvm.Value;
10914 var stack align(@alignOf(ExpectedContents)) =
10915 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
10916 const allocator = stack.get();
10917
10918 const llvm_vals = try allocator.alloc(*llvm.Value, ty.vectorLen(self));
10919 defer allocator.free(llvm_vals);
10920 @memset(llvm_vals, val.toLlvm(self));
10921
10922 self.llvm.constants.appendAssumeCapacity(
10923 llvm.constVector(llvm_vals.ptr, @intCast(llvm_vals.len)),
10924 );
10925 }
10926 }10990 }
10927 return @enumFromInt(gop.index);10991 return @enumFromInt(gop.index);
10928}10992}
...@@ -10964,8 +11028,6 @@ fn zeroInitConstAssumeCapacity(self: *Builder, ty: Type) Constant {...@@ -10964,8 +11028,6 @@ fn zeroInitConstAssumeCapacity(self: *Builder, ty: Type) Constant {
10964 const result = self.getOrPutConstantNoExtraAssumeCapacity(11028 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10965 .{ .tag = .zeroinitializer, .data = @intFromEnum(ty) },11029 .{ .tag = .zeroinitializer, .data = @intFromEnum(ty) },
10966 );11030 );
10967 if (self.useLibLlvm() and result.new)
10968 self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).constNull());
10969 return result.constant;11031 return result.constant;
10970}11032}
1097111033
...@@ -10981,8 +11043,6 @@ fn undefConstAssumeCapacity(self: *Builder, ty: Type) Constant {...@@ -10981,8 +11043,6 @@ fn undefConstAssumeCapacity(self: *Builder, ty: Type) Constant {
10981 const result = self.getOrPutConstantNoExtraAssumeCapacity(11043 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10982 .{ .tag = .undef, .data = @intFromEnum(ty) },11044 .{ .tag = .undef, .data = @intFromEnum(ty) },
10983 );11045 );
10984 if (self.useLibLlvm() and result.new)
10985 self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).getUndef());
10986 return result.constant;11046 return result.constant;
10987}11047}
1098811048
...@@ -10998,8 +11058,6 @@ fn poisonConstAssumeCapacity(self: *Builder, ty: Type) Constant {...@@ -10998,8 +11058,6 @@ fn poisonConstAssumeCapacity(self: *Builder, ty: Type) Constant {
10998 const result = self.getOrPutConstantNoExtraAssumeCapacity(11058 const result = self.getOrPutConstantNoExtraAssumeCapacity(
10999 .{ .tag = .poison, .data = @intFromEnum(ty) },11059 .{ .tag = .poison, .data = @intFromEnum(ty) },
11000 );11060 );
11001 if (self.useLibLlvm() and result.new)
11002 self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).getPoison());
11003 return result.constant;11061 return result.constant;
11004}11062}
1100511063
...@@ -11032,9 +11090,6 @@ fn blockAddrConstAssumeCapacity(...@@ -11032,9 +11090,6 @@ fn blockAddrConstAssumeCapacity(
11032 .tag = .blockaddress,11090 .tag = .blockaddress,
11033 .data = self.addConstantExtraAssumeCapacity(data),11091 .data = self.addConstantExtraAssumeCapacity(data),
11034 });11092 });
11035 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
11036 function.toLlvm(self).blockAddress(block.toValue(self, function).toLlvm(self, function)),
11037 );
11038 }11093 }
11039 return @enumFromInt(gop.index);11094 return @enumFromInt(gop.index);
11040}11095}
...@@ -11043,7 +11098,6 @@ fn dsoLocalEquivalentConstAssumeCapacity(self: *Builder, function: Function.Inde...@@ -11043,7 +11098,6 @@ fn dsoLocalEquivalentConstAssumeCapacity(self: *Builder, function: Function.Inde
11043 const result = self.getOrPutConstantNoExtraAssumeCapacity(11098 const result = self.getOrPutConstantNoExtraAssumeCapacity(
11044 .{ .tag = .dso_local_equivalent, .data = @intFromEnum(function) },11099 .{ .tag = .dso_local_equivalent, .data = @intFromEnum(function) },
11045 );11100 );
11046 if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(undefined);
11047 return result.constant;11101 return result.constant;
11048}11102}
1104911103
...@@ -11051,7 +11105,6 @@ fn noCfiConstAssumeCapacity(self: *Builder, function: Function.Index) Constant {...@@ -11051,7 +11105,6 @@ fn noCfiConstAssumeCapacity(self: *Builder, function: Function.Index) Constant {
11051 const result = self.getOrPutConstantNoExtraAssumeCapacity(11105 const result = self.getOrPutConstantNoExtraAssumeCapacity(
11052 .{ .tag = .no_cfi, .data = @intFromEnum(function) },11106 .{ .tag = .no_cfi, .data = @intFromEnum(function) },
11053 );11107 );
11054 if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(undefined);
11055 return result.constant;11108 return result.constant;
11056}11109}
1105711110
...@@ -11141,22 +11194,6 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty:...@@ -11141,22 +11194,6 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty:
11141 .tag = tag,11194 .tag = tag,
11142 .data = self.addConstantExtraAssumeCapacity(data.cast),11195 .data = self.addConstantExtraAssumeCapacity(data.cast),
11143 });11196 });
11144 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(switch (tag) {
11145 .trunc => &llvm.Value.constTrunc,
11146 .zext => &llvm.Value.constZExt,
11147 .sext => &llvm.Value.constSExt,
11148 .fptrunc => &llvm.Value.constFPTrunc,
11149 .fpext => &llvm.Value.constFPExt,
11150 .fptoui => &llvm.Value.constFPToUI,
11151 .fptosi => &llvm.Value.constFPToSI,
11152 .uitofp => &llvm.Value.constUIToFP,
11153 .sitofp => &llvm.Value.constSIToFP,
11154 .ptrtoint => &llvm.Value.constPtrToInt,
11155 .inttoptr => &llvm.Value.constIntToPtr,
11156 .bitcast => &llvm.Value.constBitCast,
11157 .addrspacecast => &llvm.Value.constAddrSpaceCast,
11158 else => unreachable,
11159 }(val.toLlvm(self), ty.toLlvm(self)));
11160 }11197 }
11161 return @enumFromInt(gop.index);11198 return @enumFromInt(gop.index);
11162}11199}
...@@ -11168,7 +11205,7 @@ fn gepConstAssumeCapacity(...@@ -11168,7 +11205,7 @@ fn gepConstAssumeCapacity(
11168 base: Constant,11205 base: Constant,
11169 inrange: ?u16,11206 inrange: ?u16,
11170 indices: []const Constant,11207 indices: []const Constant,
11171) (if (build_options.have_llvm) Allocator.Error else error{})!Constant {11208) Constant {
11172 const tag: Constant.Tag = switch (kind) {11209 const tag: Constant.Tag = switch (kind) {
11173 .normal => .getelementptr,11210 .normal => .getelementptr,
11174 .inbounds => .@"getelementptr inbounds",11211 .inbounds => .@"getelementptr inbounds",
...@@ -11249,21 +11286,6 @@ fn gepConstAssumeCapacity(...@@ -11249,21 +11286,6 @@ fn gepConstAssumeCapacity(
11249 }),11286 }),
11250 });11287 });
11251 self.constant_extra.appendSliceAssumeCapacity(@ptrCast(indices));11288 self.constant_extra.appendSliceAssumeCapacity(@ptrCast(indices));
11252 if (self.useLibLlvm()) {
11253 const ExpectedContents = [expected_gep_indices_len]*llvm.Value;
11254 var stack align(@alignOf(ExpectedContents)) =
11255 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
11256 const allocator = stack.get();
11257
11258 const llvm_indices = try allocator.alloc(*llvm.Value, indices.len);
11259 defer allocator.free(llvm_indices);
11260 for (llvm_indices, indices) |*llvm_index, index| llvm_index.* = index.toLlvm(self);
11261
11262 self.llvm.constants.appendAssumeCapacity(switch (kind) {
11263 .normal => &llvm.Type.constGEP,
11264 .inbounds => &llvm.Type.constInBoundsGEP,
11265 }(ty.toLlvm(self), base.toLlvm(self), llvm_indices.ptr, @intCast(llvm_indices.len)));
11266 }
11267 }11289 }
11268 return @enumFromInt(gop.index);11290 return @enumFromInt(gop.index);
11269}11291}
...@@ -11298,9 +11320,6 @@ fn icmpConstAssumeCapacity(...@@ -11298,9 +11320,6 @@ fn icmpConstAssumeCapacity(
11298 .tag = .icmp,11320 .tag = .icmp,
11299 .data = self.addConstantExtraAssumeCapacity(data),11321 .data = self.addConstantExtraAssumeCapacity(data),
11300 });11322 });
11301 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
11302 llvm.constICmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)),
11303 );
11304 }11323 }
11305 return @enumFromInt(gop.index);11324 return @enumFromInt(gop.index);
11306}11325}
...@@ -11335,9 +11354,6 @@ fn fcmpConstAssumeCapacity(...@@ -11335,9 +11354,6 @@ fn fcmpConstAssumeCapacity(
11335 .tag = .fcmp,11354 .tag = .fcmp,
11336 .data = self.addConstantExtraAssumeCapacity(data),11355 .data = self.addConstantExtraAssumeCapacity(data),
11337 });11356 });
11338 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
11339 llvm.constFCmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)),
11340 );
11341 }11357 }
11342 return @enumFromInt(gop.index);11358 return @enumFromInt(gop.index);
11343}11359}
...@@ -11371,9 +11387,6 @@ fn extractElementConstAssumeCapacity(...@@ -11371,9 +11387,6 @@ fn extractElementConstAssumeCapacity(
11371 .tag = .extractelement,11387 .tag = .extractelement,
11372 .data = self.addConstantExtraAssumeCapacity(data),11388 .data = self.addConstantExtraAssumeCapacity(data),
11373 });11389 });
11374 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
11375 val.toLlvm(self).constExtractElement(index.toLlvm(self)),
11376 );
11377 }11390 }
11378 return @enumFromInt(gop.index);11391 return @enumFromInt(gop.index);
11379}11392}
...@@ -11408,9 +11421,6 @@ fn insertElementConstAssumeCapacity(...@@ -11408,9 +11421,6 @@ fn insertElementConstAssumeCapacity(
11408 .tag = .insertelement,11421 .tag = .insertelement,
11409 .data = self.addConstantExtraAssumeCapacity(data),11422 .data = self.addConstantExtraAssumeCapacity(data),
11410 });11423 });
11411 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
11412 val.toLlvm(self).constInsertElement(elem.toLlvm(self), index.toLlvm(self)),
11413 );
11414 }11424 }
11415 return @enumFromInt(gop.index);11425 return @enumFromInt(gop.index);
11416}11426}
...@@ -11449,9 +11459,6 @@ fn shuffleVectorConstAssumeCapacity(...@@ -11449,9 +11459,6 @@ fn shuffleVectorConstAssumeCapacity(
11449 .tag = .shufflevector,11459 .tag = .shufflevector,
11450 .data = self.addConstantExtraAssumeCapacity(data),11460 .data = self.addConstantExtraAssumeCapacity(data),
11451 });11461 });
11452 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
11453 lhs.toLlvm(self).constShuffleVector(rhs.toLlvm(self), mask.toLlvm(self)),
11454 );
11455 }11462 }
11456 return @enumFromInt(gop.index);11463 return @enumFromInt(gop.index);
11457}11464}
...@@ -11506,18 +11513,6 @@ fn binConstAssumeCapacity(...@@ -11506,18 +11513,6 @@ fn binConstAssumeCapacity(
11506 .tag = tag,11513 .tag = tag,
11507 .data = self.addConstantExtraAssumeCapacity(data.extra),11514 .data = self.addConstantExtraAssumeCapacity(data.extra),
11508 });11515 });
11509 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(switch (tag) {
11510 .add => &llvm.Value.constAdd,
11511 .sub => &llvm.Value.constSub,
11512 .mul => &llvm.Value.constMul,
11513 .shl => &llvm.Value.constShl,
11514 .lshr => &llvm.Value.constLShr,
11515 .ashr => &llvm.Value.constAShr,
11516 .@"and" => &llvm.Value.constAnd,
11517 .@"or" => &llvm.Value.constOr,
11518 .xor => &llvm.Value.constXor,
11519 else => unreachable,
11520 }(lhs.toLlvm(self), rhs.toLlvm(self)));
11521 }11516 }
11522 return @enumFromInt(gop.index);11517 return @enumFromInt(gop.index);
11523}11518}
...@@ -11560,21 +11555,6 @@ fn asmConstAssumeCapacity(...@@ -11560,21 +11555,6 @@ fn asmConstAssumeCapacity(
11560 .tag = data.tag,11555 .tag = data.tag,
11561 .data = self.addConstantExtraAssumeCapacity(data.extra),11556 .data = self.addConstantExtraAssumeCapacity(data.extra),
11562 });11557 });
11563 if (self.useLibLlvm()) {
11564 const assembly_slice = assembly.slice(self).?;
11565 const constraints_slice = constraints.slice(self).?;
11566 self.llvm.constants.appendAssumeCapacity(llvm.getInlineAsm(
11567 ty.toLlvm(self),
11568 assembly_slice.ptr,
11569 assembly_slice.len,
11570 constraints_slice.ptr,
11571 constraints_slice.len,
11572 llvm.Bool.fromBool(info.sideeffect),
11573 llvm.Bool.fromBool(info.alignstack),
11574 if (info.inteldialect) .Intel else .ATT,
11575 llvm.Bool.fromBool(info.unwind),
11576 ));
11577 }
11578 }11558 }
11579 return @enumFromInt(gop.index);11559 return @enumFromInt(gop.index);
11580}11560}
...@@ -11591,7 +11571,6 @@ fn ensureUnusedConstantCapacity(...@@ -11591,7 +11571,6 @@ fn ensureUnusedConstantCapacity(
11591 self.gpa,11571 self.gpa,
11592 count * (@typeInfo(Extra).Struct.fields.len + trail_len),11572 count * (@typeInfo(Extra).Struct.fields.len + trail_len),
11593 );11573 );
11594 if (self.useLibLlvm()) try self.llvm.constants.ensureUnusedCapacity(self.gpa, count);
11595}11574}
1159611575
11597fn getOrPutConstantNoExtraAssumeCapacity(11576fn getOrPutConstantNoExtraAssumeCapacity(
...@@ -11722,15 +11701,3260 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite...@@ -11722,15 +11701,3260 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite
11722 return self.constantExtraDataTrail(T, index).data;11701 return self.constantExtraDataTrail(T, index).data;
11723}11702}
1172411703
11725const assert = std.debug.assert;11704fn ensureUnusedMetadataCapacity(
11726const build_options = @import("build_options");11705 self: *Builder,
11727const builtin = @import("builtin");11706 count: usize,
11728const llvm = if (build_options.have_llvm)11707 comptime Extra: type,
11729 @import("bindings.zig")11708 trail_len: usize,
11730else11709) Allocator.Error!void {
11731 @compileError("LLVM unavailable");11710 try self.metadata_map.ensureUnusedCapacity(self.gpa, count);
11732const log = std.log.scoped(.llvm);11711 try self.metadata_items.ensureUnusedCapacity(self.gpa, count);
11733const std = @import("std");11712 try self.metadata_extra.ensureUnusedCapacity(
11713 self.gpa,
11714 count * (@typeInfo(Extra).Struct.fields.len + trail_len),
11715 );
11716}
1173411717
11735const Allocator = std.mem.Allocator;11718fn addMetadataExtraAssumeCapacity(self: *Builder, extra: anytype) Metadata.Item.ExtraIndex {
11736const Builder = @This();11719 const result: Metadata.Item.ExtraIndex = @intCast(self.metadata_extra.items.len);
11720 inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| {
11721 const value = @field(extra, field.name);
11722 self.metadata_extra.appendAssumeCapacity(switch (field.type) {
11723 u32 => value,
11724 MetadataString, Metadata, Variable.Index, Value => @intFromEnum(value),
11725 Metadata.DIFlags => @bitCast(value),
11726 else => @compileError("bad field type: " ++ @typeName(field.type)),
11727 });
11728 }
11729 return result;
11730}
11731
11732const MetadataExtraDataTrail = struct {
11733 index: Metadata.Item.ExtraIndex,
11734
11735 fn nextMut(self: *MetadataExtraDataTrail, len: u32, comptime Item: type, builder: *Builder) []Item {
11736 const items: []Item = @ptrCast(builder.metadata_extra.items[self.index..][0..len]);
11737 self.index += @intCast(len);
11738 return items;
11739 }
11740
11741 fn next(
11742 self: *MetadataExtraDataTrail,
11743 len: u32,
11744 comptime Item: type,
11745 builder: *const Builder,
11746 ) []const Item {
11747 const items: []const Item = @ptrCast(builder.metadata_extra.items[self.index..][0..len]);
11748 self.index += @intCast(len);
11749 return items;
11750 }
11751};
11752
11753fn metadataExtraDataTrail(
11754 self: *const Builder,
11755 comptime T: type,
11756 index: Metadata.Item.ExtraIndex,
11757) struct { data: T, trail: MetadataExtraDataTrail } {
11758 var result: T = undefined;
11759 const fields = @typeInfo(T).Struct.fields;
11760 inline for (fields, self.metadata_extra.items[index..][0..fields.len]) |field, value|
11761 @field(result, field.name) = switch (field.type) {
11762 u32 => value,
11763 MetadataString, Metadata, Variable.Index, Value => @enumFromInt(value),
11764 Metadata.DIFlags => @bitCast(value),
11765 else => @compileError("bad field type: " ++ @typeName(field.type)),
11766 };
11767 return .{
11768 .data = result,
11769 .trail = .{ .index = index + @as(Metadata.Item.ExtraIndex, @intCast(fields.len)) },
11770 };
11771}
11772
11773fn metadataExtraData(self: *const Builder, comptime T: type, index: Metadata.Item.ExtraIndex) T {
11774 return self.metadataExtraDataTrail(T, index).data;
11775}
11776
11777pub fn metadataString(self: *Builder, bytes: []const u8) Allocator.Error!MetadataString {
11778 try self.metadata_string_bytes.ensureUnusedCapacity(self.gpa, bytes.len);
11779 try self.metadata_string_indices.ensureUnusedCapacity(self.gpa, 1);
11780 try self.metadata_string_map.ensureUnusedCapacity(self.gpa, 1);
11781
11782 const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(
11783 bytes,
11784 MetadataString.Adapter{ .builder = self },
11785 );
11786 if (!gop.found_existing) {
11787 self.metadata_string_bytes.appendSliceAssumeCapacity(bytes);
11788 self.metadata_string_indices.appendAssumeCapacity(@intCast(self.metadata_string_bytes.items.len));
11789 }
11790 return @enumFromInt(gop.index);
11791}
11792
11793pub fn metadataStringFromString(self: *Builder, str: String) Allocator.Error!MetadataString {
11794 if (str == .none or str == .empty) return MetadataString.none;
11795 return try self.metadataString(str.slice(self).?);
11796}
11797
11798pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!MetadataString {
11799 try self.metadata_string_map.ensureUnusedCapacity(self.gpa, 1);
11800 try self.metadata_string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str, fmt_args)));
11801 try self.metadata_string_indices.ensureUnusedCapacity(self.gpa, 1);
11802 return self.metadataStringFmtAssumeCapacity(fmt_str, fmt_args);
11803}
11804
11805pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString {
11806 self.metadata_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;
11807 return self.trailingMetadataStringAssumeCapacity();
11808}
11809
11810pub fn trailingMetadataString(self: *Builder) Allocator.Error!MetadataString {
11811 try self.metadata_string_indices.ensureUnusedCapacity(self.gpa, 1);
11812 try self.metadata_string_map.ensureUnusedCapacity(self.gpa, 1);
11813 return self.trailingMetadataStringAssumeCapacity();
11814}
11815
11816pub fn trailingMetadataStringAssumeCapacity(self: *Builder) MetadataString {
11817 const start = self.metadata_string_indices.getLast();
11818 const bytes: []const u8 = self.metadata_string_bytes.items[start..];
11819 const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
11820 if (gop.found_existing) {
11821 self.metadata_string_bytes.shrinkRetainingCapacity(start);
11822 } else {
11823 self.metadata_string_indices.appendAssumeCapacity(@intCast(self.metadata_string_bytes.items.len));
11824 }
11825 return @enumFromInt(gop.index);
11826}
11827
11828pub fn debugNamed(self: *Builder, name: MetadataString, operands: []const Metadata) Allocator.Error!void {
11829 try self.metadata_extra.ensureUnusedCapacity(self.gpa, operands.len);
11830 try self.metadata_named.ensureUnusedCapacity(self.gpa, 1);
11831 self.debugNamedAssumeCapacity(name, operands);
11832}
11833
11834fn debugNone(self: *Builder) Allocator.Error!Metadata {
11835 try self.ensureUnusedMetadataCapacity(1, NoExtra, 0);
11836 return self.debugNoneAssumeCapacity();
11837}
11838
11839pub fn debugFile(
11840 self: *Builder,
11841 filename: MetadataString,
11842 directory: MetadataString,
11843) Allocator.Error!Metadata {
11844 try self.ensureUnusedMetadataCapacity(1, Metadata.File, 0);
11845 return self.debugFileAssumeCapacity(filename, directory);
11846}
11847
11848pub fn debugCompileUnit(
11849 self: *Builder,
11850 file: Metadata,
11851 producer: MetadataString,
11852 enums: Metadata,
11853 globals: Metadata,
11854 options: Metadata.CompileUnit.Options,
11855) Allocator.Error!Metadata {
11856 try self.ensureUnusedMetadataCapacity(1, Metadata.CompileUnit, 0);
11857 return self.debugCompileUnitAssumeCapacity(file, producer, enums, globals, options);
11858}
11859
11860pub fn debugSubprogram(
11861 self: *Builder,
11862 file: Metadata,
11863 name: MetadataString,
11864 linkage_name: MetadataString,
11865 line: u32,
11866 scope_line: u32,
11867 ty: Metadata,
11868 options: Metadata.Subprogram.Options,
11869 compile_unit: Metadata,
11870) Allocator.Error!Metadata {
11871 try self.ensureUnusedMetadataCapacity(1, Metadata.Subprogram, 0);
11872 return self.debugSubprogramAssumeCapacity(
11873 file,
11874 name,
11875 linkage_name,
11876 line,
11877 scope_line,
11878 ty,
11879 options,
11880 compile_unit,
11881 );
11882}
11883
11884pub fn debugLexicalBlock(self: *Builder, scope: Metadata, file: Metadata, line: u32, column: u32) Allocator.Error!Metadata {
11885 try self.ensureUnusedMetadataCapacity(1, Metadata.LexicalBlock, 0);
11886 return self.debugLexicalBlockAssumeCapacity(scope, file, line, column);
11887}
11888
11889pub fn debugLocation(self: *Builder, line: u32, column: u32, scope: Metadata, inlined_at: Metadata) Allocator.Error!Metadata {
11890 try self.ensureUnusedMetadataCapacity(1, Metadata.Location, 0);
11891 return self.debugLocationAssumeCapacity(line, column, scope, inlined_at);
11892}
11893
11894pub fn debugBoolType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata {
11895 try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0);
11896 return self.debugBoolTypeAssumeCapacity(name, size_in_bits);
11897}
11898
11899pub fn debugUnsignedType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata {
11900 try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0);
11901 return self.debugUnsignedTypeAssumeCapacity(name, size_in_bits);
11902}
11903
11904pub fn debugSignedType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata {
11905 try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0);
11906 return self.debugSignedTypeAssumeCapacity(name, size_in_bits);
11907}
11908
11909pub fn debugFloatType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata {
11910 try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0);
11911 return self.debugFloatTypeAssumeCapacity(name, size_in_bits);
11912}
11913
11914pub fn debugForwardReference(self: *Builder) Allocator.Error!Metadata {
11915 try self.metadata_forward_references.ensureUnusedCapacity(self.gpa, 1);
11916 return self.debugForwardReferenceAssumeCapacity();
11917}
11918
11919pub fn debugStructType(
11920 self: *Builder,
11921 name: MetadataString,
11922 file: Metadata,
11923 scope: Metadata,
11924 line: u32,
11925 underlying_type: Metadata,
11926 size_in_bits: u64,
11927 align_in_bits: u64,
11928 fields_tuple: Metadata,
11929) Allocator.Error!Metadata {
11930 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
11931 return self.debugStructTypeAssumeCapacity(
11932 name,
11933 file,
11934 scope,
11935 line,
11936 underlying_type,
11937 size_in_bits,
11938 align_in_bits,
11939 fields_tuple,
11940 );
11941}
11942
11943pub fn debugUnionType(
11944 self: *Builder,
11945 name: MetadataString,
11946 file: Metadata,
11947 scope: Metadata,
11948 line: u32,
11949 underlying_type: Metadata,
11950 size_in_bits: u64,
11951 align_in_bits: u64,
11952 fields_tuple: Metadata,
11953) Allocator.Error!Metadata {
11954 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
11955 return self.debugUnionTypeAssumeCapacity(
11956 name,
11957 file,
11958 scope,
11959 line,
11960 underlying_type,
11961 size_in_bits,
11962 align_in_bits,
11963 fields_tuple,
11964 );
11965}
11966
11967pub fn debugEnumerationType(
11968 self: *Builder,
11969 name: MetadataString,
11970 file: Metadata,
11971 scope: Metadata,
11972 line: u32,
11973 underlying_type: Metadata,
11974 size_in_bits: u64,
11975 align_in_bits: u64,
11976 fields_tuple: Metadata,
11977) Allocator.Error!Metadata {
11978 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
11979 return self.debugEnumerationTypeAssumeCapacity(
11980 name,
11981 file,
11982 scope,
11983 line,
11984 underlying_type,
11985 size_in_bits,
11986 align_in_bits,
11987 fields_tuple,
11988 );
11989}
11990
11991pub fn debugArrayType(
11992 self: *Builder,
11993 name: MetadataString,
11994 file: Metadata,
11995 scope: Metadata,
11996 line: u32,
11997 underlying_type: Metadata,
11998 size_in_bits: u64,
11999 align_in_bits: u64,
12000 fields_tuple: Metadata,
12001) Allocator.Error!Metadata {
12002 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
12003 return self.debugArrayTypeAssumeCapacity(
12004 name,
12005 file,
12006 scope,
12007 line,
12008 underlying_type,
12009 size_in_bits,
12010 align_in_bits,
12011 fields_tuple,
12012 );
12013}
12014
12015pub fn debugVectorType(
12016 self: *Builder,
12017 name: MetadataString,
12018 file: Metadata,
12019 scope: Metadata,
12020 line: u32,
12021 underlying_type: Metadata,
12022 size_in_bits: u64,
12023 align_in_bits: u64,
12024 fields_tuple: Metadata,
12025) Allocator.Error!Metadata {
12026 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
12027 return self.debugVectorTypeAssumeCapacity(
12028 name,
12029 file,
12030 scope,
12031 line,
12032 underlying_type,
12033 size_in_bits,
12034 align_in_bits,
12035 fields_tuple,
12036 );
12037}
12038
12039pub fn debugPointerType(
12040 self: *Builder,
12041 name: MetadataString,
12042 file: Metadata,
12043 scope: Metadata,
12044 line: u32,
12045 underlying_type: Metadata,
12046 size_in_bits: u64,
12047 align_in_bits: u64,
12048 offset_in_bits: u64,
12049) Allocator.Error!Metadata {
12050 try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0);
12051 return self.debugPointerTypeAssumeCapacity(
12052 name,
12053 file,
12054 scope,
12055 line,
12056 underlying_type,
12057 size_in_bits,
12058 align_in_bits,
12059 offset_in_bits,
12060 );
12061}
12062
12063pub fn debugMemberType(
12064 self: *Builder,
12065 name: MetadataString,
12066 file: Metadata,
12067 scope: Metadata,
12068 line: u32,
12069 underlying_type: Metadata,
12070 size_in_bits: u64,
12071 align_in_bits: u64,
12072 offset_in_bits: u64,
12073) Allocator.Error!Metadata {
12074 try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0);
12075 return self.debugMemberTypeAssumeCapacity(
12076 name,
12077 file,
12078 scope,
12079 line,
12080 underlying_type,
12081 size_in_bits,
12082 align_in_bits,
12083 offset_in_bits,
12084 );
12085}
12086
12087pub fn debugSubroutineType(
12088 self: *Builder,
12089 types_tuple: Metadata,
12090) Allocator.Error!Metadata {
12091 try self.ensureUnusedMetadataCapacity(1, Metadata.SubroutineType, 0);
12092 return self.debugSubroutineTypeAssumeCapacity(types_tuple);
12093}
12094
12095pub fn debugEnumerator(
12096 self: *Builder,
12097 name: MetadataString,
12098 unsigned: bool,
12099 bit_width: u32,
12100 value: std.math.big.int.Const,
12101) Allocator.Error!Metadata {
12102 assert(!(unsigned and !value.positive));
12103 try self.ensureUnusedMetadataCapacity(1, Metadata.Enumerator, 0);
12104 try self.metadata_limbs.ensureUnusedCapacity(self.gpa, value.limbs.len);
12105 return self.debugEnumeratorAssumeCapacity(name, unsigned, bit_width, value);
12106}
12107
12108pub fn debugSubrange(
12109 self: *Builder,
12110 lower_bound: Metadata,
12111 count: Metadata,
12112) Allocator.Error!Metadata {
12113 try self.ensureUnusedMetadataCapacity(1, Metadata.Subrange, 0);
12114 return self.debugSubrangeAssumeCapacity(lower_bound, count);
12115}
12116
12117pub fn debugExpression(
12118 self: *Builder,
12119 elements: []const u32,
12120) Allocator.Error!Metadata {
12121 try self.ensureUnusedMetadataCapacity(1, Metadata.Expression, elements.len * @sizeOf(u32));
12122 return self.debugExpressionAssumeCapacity(elements);
12123}
12124
12125pub fn debugTuple(
12126 self: *Builder,
12127 elements: []const Metadata,
12128) Allocator.Error!Metadata {
12129 try self.ensureUnusedMetadataCapacity(1, Metadata.Tuple, elements.len * @sizeOf(Metadata));
12130 return self.debugTupleAssumeCapacity(elements);
12131}
12132
12133pub fn debugModuleFlag(
12134 self: *Builder,
12135 behavior: Metadata,
12136 name: MetadataString,
12137 constant: Metadata,
12138) Allocator.Error!Metadata {
12139 try self.ensureUnusedMetadataCapacity(1, Metadata.ModuleFlag, 0);
12140 return self.debugModuleFlagAssumeCapacity(behavior, name, constant);
12141}
12142
12143pub fn debugLocalVar(
12144 self: *Builder,
12145 name: MetadataString,
12146 file: Metadata,
12147 scope: Metadata,
12148 line: u32,
12149 ty: Metadata,
12150) Allocator.Error!Metadata {
12151 try self.ensureUnusedMetadataCapacity(1, Metadata.LocalVar, 0);
12152 return self.debugLocalVarAssumeCapacity(name, file, scope, line, ty);
12153}
12154
12155pub fn debugParameter(
12156 self: *Builder,
12157 name: MetadataString,
12158 file: Metadata,
12159 scope: Metadata,
12160 line: u32,
12161 ty: Metadata,
12162 arg_no: u32,
12163) Allocator.Error!Metadata {
12164 try self.ensureUnusedMetadataCapacity(1, Metadata.Parameter, 0);
12165 return self.debugParameterAssumeCapacity(name, file, scope, line, ty, arg_no);
12166}
12167
12168pub fn debugGlobalVar(
12169 self: *Builder,
12170 name: MetadataString,
12171 linkage_name: MetadataString,
12172 file: Metadata,
12173 scope: Metadata,
12174 line: u32,
12175 ty: Metadata,
12176 variable: Variable.Index,
12177 options: Metadata.GlobalVar.Options,
12178) Allocator.Error!Metadata {
12179 try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVar, 0);
12180 return self.debugGlobalVarAssumeCapacity(
12181 name,
12182 linkage_name,
12183 file,
12184 scope,
12185 line,
12186 ty,
12187 variable,
12188 options,
12189 );
12190}
12191
12192pub fn debugGlobalVarExpression(
12193 self: *Builder,
12194 variable: Metadata,
12195 expression: Metadata,
12196) Allocator.Error!Metadata {
12197 try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVarExpression, 0);
12198 return self.debugGlobalVarExpressionAssumeCapacity(variable, expression);
12199}
12200
12201pub fn debugConstant(self: *Builder, value: Constant) Allocator.Error!Metadata {
12202 try self.ensureUnusedMetadataCapacity(1, NoExtra, 0);
12203 return self.debugConstantAssumeCapacity(value);
12204}
12205
12206pub fn debugForwardReferenceSetType(self: *Builder, fwd_ref: Metadata, ty: Metadata) void {
12207 assert(
12208 @intFromEnum(fwd_ref) >= Metadata.first_forward_reference and
12209 @intFromEnum(fwd_ref) <= Metadata.first_local_metadata,
12210 );
12211 const index = @intFromEnum(fwd_ref) - Metadata.first_forward_reference;
12212 self.metadata_forward_references.items[index] = ty;
12213}
12214
12215fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata {
12216 const Key = struct {
12217 tag: Metadata.Tag,
12218 value: @TypeOf(value),
12219 };
12220 const Adapter = struct {
12221 builder: *const Builder,
12222 pub fn hash(_: @This(), key: Key) u32 {
12223 var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag)));
12224 inline for (std.meta.fields(@TypeOf(value))) |field| {
12225 hasher.update(std.mem.asBytes(&@field(key.value, field.name)));
12226 }
12227 return @truncate(hasher.final());
12228 }
12229
12230 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
12231 if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
12232 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
12233 const rhs_extra = ctx.builder.metadataExtraData(@TypeOf(value), rhs_data);
12234 return std.meta.eql(lhs_key.value, rhs_extra);
12235 }
12236 };
12237
12238 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
12239 Key{ .tag = tag, .value = value },
12240 Adapter{ .builder = self },
12241 );
12242
12243 if (!gop.found_existing) {
12244 gop.key_ptr.* = {};
12245 gop.value_ptr.* = {};
12246 self.metadata_items.appendAssumeCapacity(.{
12247 .tag = tag,
12248 .data = self.addMetadataExtraAssumeCapacity(value),
12249 });
12250 }
12251 return @enumFromInt(gop.index);
12252}
12253
12254fn metadataDistinctAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata {
12255 const Key = struct { tag: Metadata.Tag, index: Metadata };
12256 const Adapter = struct {
12257 pub fn hash(_: @This(), key: Key) u32 {
12258 return @truncate(std.hash.Wyhash.hash(
12259 std.hash.uint32(@intFromEnum(key.tag)),
12260 std.mem.asBytes(&key.index),
12261 ));
12262 }
12263
12264 pub fn eql(_: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
12265 return @intFromEnum(lhs_key.index) == rhs_index;
12266 }
12267 };
12268
12269 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
12270 Key{ .tag = tag, .index = @enumFromInt(self.metadata_map.count()) },
12271 Adapter{},
12272 );
12273
12274 if (!gop.found_existing) {
12275 gop.key_ptr.* = {};
12276 gop.value_ptr.* = {};
12277 self.metadata_items.appendAssumeCapacity(.{
12278 .tag = tag,
12279 .data = self.addMetadataExtraAssumeCapacity(value),
12280 });
12281 }
12282 return @enumFromInt(gop.index);
12283}
12284
12285fn debugNamedAssumeCapacity(self: *Builder, name: MetadataString, operands: []const Metadata) void {
12286 assert(!self.strip);
12287 assert(name != .none);
12288 const extra_index: u32 = @intCast(self.metadata_extra.items.len);
12289 self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(operands));
12290
12291 const gop = self.metadata_named.getOrPutAssumeCapacity(name);
12292 gop.value_ptr.* = .{
12293 .index = extra_index,
12294 .len = @intCast(operands.len),
12295 };
12296}
12297
12298pub fn debugNoneAssumeCapacity(self: *Builder) Metadata {
12299 assert(!self.strip);
12300 return self.metadataSimpleAssumeCapacity(.none, .{});
12301}
12302
12303fn debugFileAssumeCapacity(
12304 self: *Builder,
12305 filename: MetadataString,
12306 directory: MetadataString,
12307) Metadata {
12308 assert(!self.strip);
12309 return self.metadataSimpleAssumeCapacity(.file, Metadata.File{
12310 .filename = filename,
12311 .directory = directory,
12312 });
12313}
12314
12315pub fn debugCompileUnitAssumeCapacity(
12316 self: *Builder,
12317 file: Metadata,
12318 producer: MetadataString,
12319 enums: Metadata,
12320 globals: Metadata,
12321 options: Metadata.CompileUnit.Options,
12322) Metadata {
12323 assert(!self.strip);
12324 return self.metadataDistinctAssumeCapacity(
12325 if (options.optimized) .@"compile_unit optimized" else .compile_unit,
12326 Metadata.CompileUnit{
12327 .file = file,
12328 .producer = producer,
12329 .enums = enums,
12330 .globals = globals,
12331 },
12332 );
12333}
12334
12335fn debugSubprogramAssumeCapacity(
12336 self: *Builder,
12337 file: Metadata,
12338 name: MetadataString,
12339 linkage_name: MetadataString,
12340 line: u32,
12341 scope_line: u32,
12342 ty: Metadata,
12343 options: Metadata.Subprogram.Options,
12344 compile_unit: Metadata,
12345) Metadata {
12346 assert(!self.strip);
12347 const tag: Metadata.Tag = @enumFromInt(@intFromEnum(Metadata.Tag.subprogram) +
12348 @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)));
12349 return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{
12350 .file = file,
12351 .name = name,
12352 .linkage_name = linkage_name,
12353 .line = line,
12354 .scope_line = scope_line,
12355 .ty = ty,
12356 .di_flags = options.di_flags,
12357 .compile_unit = compile_unit,
12358 });
12359}
12360
12361fn debugLexicalBlockAssumeCapacity(self: *Builder, scope: Metadata, file: Metadata, line: u32, column: u32) Metadata {
12362 assert(!self.strip);
12363 return self.metadataSimpleAssumeCapacity(.lexical_block, Metadata.LexicalBlock{
12364 .scope = scope,
12365 .file = file,
12366 .line = line,
12367 .column = column,
12368 });
12369}
12370
12371fn debugLocationAssumeCapacity(self: *Builder, line: u32, column: u32, scope: Metadata, inlined_at: Metadata) Metadata {
12372 assert(!self.strip);
12373 return self.metadataSimpleAssumeCapacity(.location, Metadata.Location{
12374 .line = line,
12375 .column = column,
12376 .scope = scope,
12377 .inlined_at = inlined_at,
12378 });
12379}
12380
12381fn debugBoolTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
12382 assert(!self.strip);
12383 return self.metadataSimpleAssumeCapacity(.basic_bool_type, Metadata.BasicType{
12384 .name = name,
12385 .size_in_bits_lo = @truncate(size_in_bits),
12386 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12387 });
12388}
12389
12390fn debugUnsignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
12391 assert(!self.strip);
12392 return self.metadataSimpleAssumeCapacity(.basic_unsigned_type, Metadata.BasicType{
12393 .name = name,
12394 .size_in_bits_lo = @truncate(size_in_bits),
12395 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12396 });
12397}
12398
12399fn debugSignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
12400 assert(!self.strip);
12401 return self.metadataSimpleAssumeCapacity(.basic_signed_type, Metadata.BasicType{
12402 .name = name,
12403 .size_in_bits_lo = @truncate(size_in_bits),
12404 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12405 });
12406}
12407
12408fn debugFloatTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
12409 assert(!self.strip);
12410 return self.metadataSimpleAssumeCapacity(.basic_float_type, Metadata.BasicType{
12411 .name = name,
12412 .size_in_bits_lo = @truncate(size_in_bits),
12413 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12414 });
12415}
12416
12417fn debugForwardReferenceAssumeCapacity(self: *Builder) Metadata {
12418 assert(!self.strip);
12419 const index = Metadata.first_forward_reference + self.metadata_forward_references.items.len;
12420 self.metadata_forward_references.appendAssumeCapacity(.none);
12421 return @enumFromInt(index);
12422}
12423
12424fn debugStructTypeAssumeCapacity(
12425 self: *Builder,
12426 name: MetadataString,
12427 file: Metadata,
12428 scope: Metadata,
12429 line: u32,
12430 underlying_type: Metadata,
12431 size_in_bits: u64,
12432 align_in_bits: u64,
12433 fields_tuple: Metadata,
12434) Metadata {
12435 assert(!self.strip);
12436 return self.debugCompositeTypeAssumeCapacity(
12437 .composite_struct_type,
12438 name,
12439 file,
12440 scope,
12441 line,
12442 underlying_type,
12443 size_in_bits,
12444 align_in_bits,
12445 fields_tuple,
12446 );
12447}
12448
12449fn debugUnionTypeAssumeCapacity(
12450 self: *Builder,
12451 name: MetadataString,
12452 file: Metadata,
12453 scope: Metadata,
12454 line: u32,
12455 underlying_type: Metadata,
12456 size_in_bits: u64,
12457 align_in_bits: u64,
12458 fields_tuple: Metadata,
12459) Metadata {
12460 assert(!self.strip);
12461 return self.debugCompositeTypeAssumeCapacity(
12462 .composite_union_type,
12463 name,
12464 file,
12465 scope,
12466 line,
12467 underlying_type,
12468 size_in_bits,
12469 align_in_bits,
12470 fields_tuple,
12471 );
12472}
12473
12474fn debugEnumerationTypeAssumeCapacity(
12475 self: *Builder,
12476 name: MetadataString,
12477 file: Metadata,
12478 scope: Metadata,
12479 line: u32,
12480 underlying_type: Metadata,
12481 size_in_bits: u64,
12482 align_in_bits: u64,
12483 fields_tuple: Metadata,
12484) Metadata {
12485 assert(!self.strip);
12486 return self.debugCompositeTypeAssumeCapacity(
12487 .composite_enumeration_type,
12488 name,
12489 file,
12490 scope,
12491 line,
12492 underlying_type,
12493 size_in_bits,
12494 align_in_bits,
12495 fields_tuple,
12496 );
12497}
12498
12499fn debugArrayTypeAssumeCapacity(
12500 self: *Builder,
12501 name: MetadataString,
12502 file: Metadata,
12503 scope: Metadata,
12504 line: u32,
12505 underlying_type: Metadata,
12506 size_in_bits: u64,
12507 align_in_bits: u64,
12508 fields_tuple: Metadata,
12509) Metadata {
12510 assert(!self.strip);
12511 return self.debugCompositeTypeAssumeCapacity(
12512 .composite_array_type,
12513 name,
12514 file,
12515 scope,
12516 line,
12517 underlying_type,
12518 size_in_bits,
12519 align_in_bits,
12520 fields_tuple,
12521 );
12522}
12523
12524fn debugVectorTypeAssumeCapacity(
12525 self: *Builder,
12526 name: MetadataString,
12527 file: Metadata,
12528 scope: Metadata,
12529 line: u32,
12530 underlying_type: Metadata,
12531 size_in_bits: u64,
12532 align_in_bits: u64,
12533 fields_tuple: Metadata,
12534) Metadata {
12535 assert(!self.strip);
12536 return self.debugCompositeTypeAssumeCapacity(
12537 .composite_vector_type,
12538 name,
12539 file,
12540 scope,
12541 line,
12542 underlying_type,
12543 size_in_bits,
12544 align_in_bits,
12545 fields_tuple,
12546 );
12547}
12548
12549fn debugCompositeTypeAssumeCapacity(
12550 self: *Builder,
12551 tag: Metadata.Tag,
12552 name: MetadataString,
12553 file: Metadata,
12554 scope: Metadata,
12555 line: u32,
12556 underlying_type: Metadata,
12557 size_in_bits: u64,
12558 align_in_bits: u64,
12559 fields_tuple: Metadata,
12560) Metadata {
12561 assert(!self.strip);
12562 return self.metadataSimpleAssumeCapacity(tag, Metadata.CompositeType{
12563 .name = name,
12564 .file = file,
12565 .scope = scope,
12566 .line = line,
12567 .underlying_type = underlying_type,
12568 .size_in_bits_lo = @truncate(size_in_bits),
12569 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12570 .align_in_bits_lo = @truncate(align_in_bits),
12571 .align_in_bits_hi = @truncate(align_in_bits >> 32),
12572 .fields_tuple = fields_tuple,
12573 });
12574}
12575
12576fn debugPointerTypeAssumeCapacity(
12577 self: *Builder,
12578 name: MetadataString,
12579 file: Metadata,
12580 scope: Metadata,
12581 line: u32,
12582 underlying_type: Metadata,
12583 size_in_bits: u64,
12584 align_in_bits: u64,
12585 offset_in_bits: u64,
12586) Metadata {
12587 assert(!self.strip);
12588 return self.metadataSimpleAssumeCapacity(.derived_pointer_type, Metadata.DerivedType{
12589 .name = name,
12590 .file = file,
12591 .scope = scope,
12592 .line = line,
12593 .underlying_type = underlying_type,
12594 .size_in_bits_lo = @truncate(size_in_bits),
12595 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12596 .align_in_bits_lo = @truncate(align_in_bits),
12597 .align_in_bits_hi = @truncate(align_in_bits >> 32),
12598 .offset_in_bits_lo = @truncate(offset_in_bits),
12599 .offset_in_bits_hi = @truncate(offset_in_bits >> 32),
12600 });
12601}
12602
12603fn debugMemberTypeAssumeCapacity(
12604 self: *Builder,
12605 name: MetadataString,
12606 file: Metadata,
12607 scope: Metadata,
12608 line: u32,
12609 underlying_type: Metadata,
12610 size_in_bits: u64,
12611 align_in_bits: u64,
12612 offset_in_bits: u64,
12613) Metadata {
12614 assert(!self.strip);
12615 return self.metadataSimpleAssumeCapacity(.derived_member_type, Metadata.DerivedType{
12616 .name = name,
12617 .file = file,
12618 .scope = scope,
12619 .line = line,
12620 .underlying_type = underlying_type,
12621 .size_in_bits_lo = @truncate(size_in_bits),
12622 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12623 .align_in_bits_lo = @truncate(align_in_bits),
12624 .align_in_bits_hi = @truncate(align_in_bits >> 32),
12625 .offset_in_bits_lo = @truncate(offset_in_bits),
12626 .offset_in_bits_hi = @truncate(offset_in_bits >> 32),
12627 });
12628}
12629
12630fn debugSubroutineTypeAssumeCapacity(
12631 self: *Builder,
12632 types_tuple: Metadata,
12633) Metadata {
12634 assert(!self.strip);
12635 return self.metadataSimpleAssumeCapacity(.subroutine_type, Metadata.SubroutineType{
12636 .types_tuple = types_tuple,
12637 });
12638}
12639
12640fn debugEnumeratorAssumeCapacity(
12641 self: *Builder,
12642 name: MetadataString,
12643 unsigned: bool,
12644 bit_width: u32,
12645 value: std.math.big.int.Const,
12646) Metadata {
12647 assert(!self.strip);
12648 const Key = struct {
12649 tag: Metadata.Tag,
12650 name: MetadataString,
12651 bit_width: u32,
12652 value: std.math.big.int.Const,
12653 };
12654 const Adapter = struct {
12655 builder: *const Builder,
12656 pub fn hash(_: @This(), key: Key) u32 {
12657 var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag)));
12658 hasher.update(std.mem.asBytes(&key.name));
12659 hasher.update(std.mem.asBytes(&key.bit_width));
12660 hasher.update(std.mem.sliceAsBytes(key.value.limbs));
12661 return @truncate(hasher.final());
12662 }
12663
12664 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
12665 if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
12666 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
12667 const rhs_extra = ctx.builder.metadataExtraData(Metadata.Enumerator, rhs_data);
12668 const limbs = ctx.builder.metadata_limbs
12669 .items[rhs_extra.limbs_index..][0..rhs_extra.limbs_len];
12670 const rhs_value = std.math.big.int.Const{
12671 .limbs = limbs,
12672 .positive = lhs_key.value.positive,
12673 };
12674 return lhs_key.name == rhs_extra.name and
12675 lhs_key.bit_width == rhs_extra.bit_width and
12676 lhs_key.value.eql(rhs_value);
12677 }
12678 };
12679
12680 const tag: Metadata.Tag = if (unsigned)
12681 .enumerator_unsigned
12682 else if (value.positive)
12683 .enumerator_signed_positive
12684 else
12685 .enumerator_signed_negative;
12686
12687 assert(!(tag == .enumerator_unsigned and !value.positive));
12688
12689 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
12690 Key{
12691 .tag = tag,
12692 .name = name,
12693 .bit_width = bit_width,
12694 .value = value,
12695 },
12696 Adapter{ .builder = self },
12697 );
12698
12699 if (!gop.found_existing) {
12700 gop.key_ptr.* = {};
12701 gop.value_ptr.* = {};
12702 self.metadata_items.appendAssumeCapacity(.{
12703 .tag = tag,
12704 .data = self.addMetadataExtraAssumeCapacity(Metadata.Enumerator{
12705 .name = name,
12706 .bit_width = bit_width,
12707 .limbs_index = @intCast(self.metadata_limbs.items.len),
12708 .limbs_len = @intCast(value.limbs.len),
12709 }),
12710 });
12711 self.metadata_limbs.appendSliceAssumeCapacity(value.limbs);
12712 }
12713 return @enumFromInt(gop.index);
12714}
12715
12716fn debugSubrangeAssumeCapacity(
12717 self: *Builder,
12718 lower_bound: Metadata,
12719 count: Metadata,
12720) Metadata {
12721 assert(!self.strip);
12722 return self.metadataSimpleAssumeCapacity(.subrange, Metadata.Subrange{
12723 .lower_bound = lower_bound,
12724 .count = count,
12725 });
12726}
12727
12728fn debugExpressionAssumeCapacity(
12729 self: *Builder,
12730 elements: []const u32,
12731) Metadata {
12732 assert(!self.strip);
12733 const Key = struct {
12734 elements: []const u32,
12735 };
12736 const Adapter = struct {
12737 builder: *const Builder,
12738 pub fn hash(_: @This(), key: Key) u32 {
12739 var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.expression)));
12740 hasher.update(std.mem.sliceAsBytes(key.elements));
12741 return @truncate(hasher.final());
12742 }
12743
12744 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
12745 if (Metadata.Tag.expression != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
12746 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
12747 var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Expression, rhs_data);
12748 return std.mem.eql(
12749 u32,
12750 lhs_key.elements,
12751 rhs_extra.trail.next(rhs_extra.data.elements_len, u32, ctx.builder),
12752 );
12753 }
12754 };
12755
12756 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
12757 Key{ .elements = elements },
12758 Adapter{ .builder = self },
12759 );
12760
12761 if (!gop.found_existing) {
12762 gop.key_ptr.* = {};
12763 gop.value_ptr.* = {};
12764 self.metadata_items.appendAssumeCapacity(.{
12765 .tag = .expression,
12766 .data = self.addMetadataExtraAssumeCapacity(Metadata.Expression{
12767 .elements_len = @intCast(elements.len),
12768 }),
12769 });
12770 self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(elements));
12771 }
12772 return @enumFromInt(gop.index);
12773}
12774
12775fn debugTupleAssumeCapacity(
12776 self: *Builder,
12777 elements: []const Metadata,
12778) Metadata {
12779 assert(!self.strip);
12780 const Key = struct {
12781 elements: []const Metadata,
12782 };
12783 const Adapter = struct {
12784 builder: *const Builder,
12785 pub fn hash(_: @This(), key: Key) u32 {
12786 var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.tuple)));
12787 hasher.update(std.mem.sliceAsBytes(key.elements));
12788 return @truncate(hasher.final());
12789 }
12790
12791 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
12792 if (Metadata.Tag.tuple != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
12793 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
12794 var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Tuple, rhs_data);
12795 return std.mem.eql(
12796 Metadata,
12797 lhs_key.elements,
12798 rhs_extra.trail.next(rhs_extra.data.elements_len, Metadata, ctx.builder),
12799 );
12800 }
12801 };
12802
12803 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
12804 Key{ .elements = elements },
12805 Adapter{ .builder = self },
12806 );
12807
12808 if (!gop.found_existing) {
12809 gop.key_ptr.* = {};
12810 gop.value_ptr.* = {};
12811 self.metadata_items.appendAssumeCapacity(.{
12812 .tag = .tuple,
12813 .data = self.addMetadataExtraAssumeCapacity(Metadata.Tuple{
12814 .elements_len = @intCast(elements.len),
12815 }),
12816 });
12817 self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(elements));
12818 }
12819 return @enumFromInt(gop.index);
12820}
12821
12822fn debugModuleFlagAssumeCapacity(
12823 self: *Builder,
12824 behavior: Metadata,
12825 name: MetadataString,
12826 constant: Metadata,
12827) Metadata {
12828 assert(!self.strip);
12829 return self.metadataSimpleAssumeCapacity(.module_flag, Metadata.ModuleFlag{
12830 .behavior = behavior,
12831 .name = name,
12832 .constant = constant,
12833 });
12834}
12835
12836fn debugLocalVarAssumeCapacity(
12837 self: *Builder,
12838 name: MetadataString,
12839 file: Metadata,
12840 scope: Metadata,
12841 line: u32,
12842 ty: Metadata,
12843) Metadata {
12844 assert(!self.strip);
12845 return self.metadataSimpleAssumeCapacity(.local_var, Metadata.LocalVar{
12846 .name = name,
12847 .file = file,
12848 .scope = scope,
12849 .line = line,
12850 .ty = ty,
12851 });
12852}
12853
12854fn debugParameterAssumeCapacity(
12855 self: *Builder,
12856 name: MetadataString,
12857 file: Metadata,
12858 scope: Metadata,
12859 line: u32,
12860 ty: Metadata,
12861 arg_no: u32,
12862) Metadata {
12863 assert(!self.strip);
12864 return self.metadataSimpleAssumeCapacity(.parameter, Metadata.Parameter{
12865 .name = name,
12866 .file = file,
12867 .scope = scope,
12868 .line = line,
12869 .ty = ty,
12870 .arg_no = arg_no,
12871 });
12872}
12873
12874fn debugGlobalVarAssumeCapacity(
12875 self: *Builder,
12876 name: MetadataString,
12877 linkage_name: MetadataString,
12878 file: Metadata,
12879 scope: Metadata,
12880 line: u32,
12881 ty: Metadata,
12882 variable: Variable.Index,
12883 options: Metadata.GlobalVar.Options,
12884) Metadata {
12885 assert(!self.strip);
12886 return self.metadataDistinctAssumeCapacity(
12887 if (options.local) .@"global_var local" else .global_var,
12888 Metadata.GlobalVar{
12889 .name = name,
12890 .linkage_name = linkage_name,
12891 .file = file,
12892 .scope = scope,
12893 .line = line,
12894 .ty = ty,
12895 .variable = variable,
12896 },
12897 );
12898}
12899
12900fn debugGlobalVarExpressionAssumeCapacity(
12901 self: *Builder,
12902 variable: Metadata,
12903 expression: Metadata,
12904) Metadata {
12905 assert(!self.strip);
12906 return self.metadataSimpleAssumeCapacity(.global_var_expression, Metadata.GlobalVarExpression{
12907 .variable = variable,
12908 .expression = expression,
12909 });
12910}
12911
12912fn debugConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata {
12913 assert(!self.strip);
12914 const Adapter = struct {
12915 builder: *const Builder,
12916 pub fn hash(_: @This(), key: Constant) u32 {
12917 var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.constant)));
12918 hasher.update(std.mem.asBytes(&key));
12919 return @truncate(hasher.final());
12920 }
12921
12922 pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool {
12923 if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
12924 const rhs_data: Constant = @enumFromInt(ctx.builder.metadata_items.items(.data)[rhs_index]);
12925 return rhs_data == lhs_key;
12926 }
12927 };
12928
12929 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
12930 constant,
12931 Adapter{ .builder = self },
12932 );
12933
12934 if (!gop.found_existing) {
12935 gop.key_ptr.* = {};
12936 gop.value_ptr.* = {};
12937 self.metadata_items.appendAssumeCapacity(.{
12938 .tag = .constant,
12939 .data = @intFromEnum(constant),
12940 });
12941 }
12942 return @enumFromInt(gop.index);
12943}
12944
12945pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]const u32 {
12946 const BitcodeWriter = bitcode_writer.BitcodeWriter(&.{ Type, FunctionAttributes });
12947 var bitcode = BitcodeWriter.init(allocator, .{
12948 std.math.log2_int_ceil(usize, self.type_items.items.len),
12949 std.math.log2_int_ceil(usize, 1 + self.function_attributes_set.count()),
12950 });
12951 errdefer bitcode.deinit();
12952
12953 // Write LLVM IR magic
12954 try bitcode.writeBits(ir.MAGIC, 32);
12955
12956 var record: std.ArrayListUnmanaged(u64) = .{};
12957 defer record.deinit(self.gpa);
12958
12959 // IDENTIFICATION_BLOCK
12960 {
12961 const Identification = ir.Identification;
12962 var identification_block = try bitcode.enterTopBlock(Identification);
12963
12964 const producer = try std.fmt.allocPrint(self.gpa, "zig {d}.{d}.{d}", .{
12965 build_options.semver.major,
12966 build_options.semver.minor,
12967 build_options.semver.patch,
12968 });
12969 defer self.gpa.free(producer);
12970
12971 try identification_block.writeAbbrev(Identification.Version{ .string = producer });
12972 try identification_block.writeAbbrev(Identification.Epoch{ .epoch = 0 });
12973
12974 try identification_block.end();
12975 }
12976
12977 // MODULE_BLOCK
12978 {
12979 const Module = ir.Module;
12980 var module_block = try bitcode.enterTopBlock(Module);
12981
12982 try module_block.writeAbbrev(Module.Version{});
12983
12984 if (self.target_triple.slice(self)) |triple| {
12985 try module_block.writeAbbrev(Module.String{
12986 .code = 2,
12987 .string = triple,
12988 });
12989 }
12990
12991 if (self.data_layout.slice(self)) |data_layout| {
12992 try module_block.writeAbbrev(Module.String{
12993 .code = 3,
12994 .string = data_layout,
12995 });
12996 }
12997
12998 if (self.source_filename.slice(self)) |source_filename| {
12999 try module_block.writeAbbrev(Module.String{
13000 .code = 16,
13001 .string = source_filename,
13002 });
13003 }
13004
13005 if (self.module_asm.items.len != 0) {
13006 try module_block.writeAbbrev(Module.String{
13007 .code = 4,
13008 .string = self.module_asm.items,
13009 });
13010 }
13011
13012 // TYPE_BLOCK
13013 {
13014 var type_block = try module_block.enterSubBlock(ir.Type);
13015
13016 try type_block.writeAbbrev(ir.Type.NumEntry{ .num = @intCast(self.type_items.items.len) });
13017
13018 for (self.type_items.items, 0..) |item, i| {
13019 const ty: Type = @enumFromInt(i);
13020
13021 switch (item.tag) {
13022 .simple => try type_block.writeAbbrev(ir.Type.Simple{ .code = @truncate(item.data) }),
13023 .integer => try type_block.writeAbbrev(ir.Type.Integer{ .width = item.data }),
13024 .structure,
13025 .packed_structure,
13026 => |kind| {
13027 const is_packed = switch (kind) {
13028 .structure => false,
13029 .packed_structure => true,
13030 else => unreachable,
13031 };
13032 var extra = self.typeExtraDataTrail(Type.Structure, item.data);
13033 try type_block.writeAbbrev(ir.Type.StructAnon{
13034 .is_packed = is_packed,
13035 .types = extra.trail.next(extra.data.fields_len, Type, self),
13036 });
13037 },
13038 .named_structure => {
13039 const extra = self.typeExtraData(Type.NamedStructure, item.data);
13040 try type_block.writeAbbrev(ir.Type.StructName{
13041 .string = extra.id.slice(self).?,
13042 });
13043
13044 switch (extra.body) {
13045 .none => try type_block.writeAbbrev(ir.Type.Opaque{}),
13046 else => {
13047 const real_struct = self.type_items.items[@intFromEnum(extra.body)];
13048 const is_packed: bool = switch (real_struct.tag) {
13049 .structure => false,
13050 .packed_structure => true,
13051 else => unreachable,
13052 };
13053
13054 var real_extra = self.typeExtraDataTrail(Type.Structure, real_struct.data);
13055 try type_block.writeAbbrev(ir.Type.StructNamed{
13056 .is_packed = is_packed,
13057 .types = real_extra.trail.next(real_extra.data.fields_len, Type, self),
13058 });
13059 },
13060 }
13061 },
13062 .array,
13063 .small_array,
13064 => try type_block.writeAbbrev(ir.Type.Array{
13065 .len = ty.aggregateLen(self),
13066 .child = ty.childType(self),
13067 }),
13068 .vector,
13069 .scalable_vector,
13070 => try type_block.writeAbbrev(ir.Type.Vector{
13071 .len = ty.aggregateLen(self),
13072 .child = ty.childType(self),
13073 }),
13074 .pointer => try type_block.writeAbbrev(ir.Type.Pointer{
13075 .addr_space = ty.pointerAddrSpace(self),
13076 }),
13077 .target => {
13078 var extra = self.typeExtraDataTrail(Type.Target, item.data);
13079 try type_block.writeAbbrev(ir.Type.StructName{
13080 .string = extra.data.name.slice(self).?,
13081 });
13082
13083 const types = extra.trail.next(extra.data.types_len, Type, self);
13084 const ints = extra.trail.next(extra.data.ints_len, u32, self);
13085
13086 try type_block.writeAbbrev(ir.Type.Target{
13087 .num_types = extra.data.types_len,
13088 .types = types,
13089 .ints = ints,
13090 });
13091 },
13092 .function, .vararg_function => |kind| {
13093 const is_vararg = switch (kind) {
13094 .function => false,
13095 .vararg_function => true,
13096 else => unreachable,
13097 };
13098 var extra = self.typeExtraDataTrail(Type.Function, item.data);
13099 try type_block.writeAbbrev(ir.Type.Function{
13100 .is_vararg = is_vararg,
13101 .return_type = extra.data.ret,
13102 .param_types = extra.trail.next(extra.data.params_len, Type, self),
13103 });
13104 },
13105 }
13106 }
13107
13108 try type_block.end();
13109 }
13110
13111 var attributes_set: std.AutoArrayHashMapUnmanaged(struct {
13112 attributes: Attributes,
13113 index: u32,
13114 }, void) = .{};
13115 defer attributes_set.deinit(self.gpa);
13116
13117 // PARAMATTR_GROUP_BLOCK
13118 {
13119 const ParamattrGroup = ir.ParamattrGroup;
13120
13121 var paramattr_group_block = try module_block.enterSubBlock(ParamattrGroup);
13122
13123 for (self.function_attributes_set.keys()) |func_attributes| {
13124 for (func_attributes.slice(self), 0..) |attributes, i| {
13125 const attributes_slice = attributes.slice(self);
13126 if (attributes_slice.len == 0) continue;
13127
13128 const attr_gop = try attributes_set.getOrPut(self.gpa, .{
13129 .attributes = attributes,
13130 .index = @intCast(i),
13131 });
13132
13133 if (attr_gop.found_existing) continue;
13134
13135 record.clearRetainingCapacity();
13136 try record.ensureUnusedCapacity(self.gpa, 2);
13137
13138 record.appendAssumeCapacity(attr_gop.index);
13139 record.appendAssumeCapacity(switch (i) {
13140 0 => 0xffffffff,
13141 else => i - 1,
13142 });
13143
13144 for (attributes_slice) |attr_index| {
13145 const kind = attr_index.getKind(self);
13146 switch (attr_index.toAttribute(self)) {
13147 .zeroext,
13148 .signext,
13149 .inreg,
13150 .@"noalias",
13151 .nocapture,
13152 .nofree,
13153 .nest,
13154 .returned,
13155 .nonnull,
13156 .swiftself,
13157 .swiftasync,
13158 .swifterror,
13159 .immarg,
13160 .noundef,
13161 .allocalign,
13162 .allocptr,
13163 .readnone,
13164 .readonly,
13165 .writeonly,
13166 .alwaysinline,
13167 .builtin,
13168 .cold,
13169 .convergent,
13170 .disable_sanitizer_information,
13171 .fn_ret_thunk_extern,
13172 .hot,
13173 .inlinehint,
13174 .jumptable,
13175 .minsize,
13176 .naked,
13177 .nobuiltin,
13178 .nocallback,
13179 .noduplicate,
13180 .noimplicitfloat,
13181 .@"noinline",
13182 .nomerge,
13183 .nonlazybind,
13184 .noprofile,
13185 .skipprofile,
13186 .noredzone,
13187 .noreturn,
13188 .norecurse,
13189 .willreturn,
13190 .nosync,
13191 .nounwind,
13192 .nosanitize_bounds,
13193 .nosanitize_coverage,
13194 .null_pointer_is_valid,
13195 .optforfuzzing,
13196 .optnone,
13197 .optsize,
13198 .returns_twice,
13199 .safestack,
13200 .sanitize_address,
13201 .sanitize_memory,
13202 .sanitize_thread,
13203 .sanitize_hwaddress,
13204 .sanitize_memtag,
13205 .speculative_load_hardening,
13206 .speculatable,
13207 .ssp,
13208 .sspstrong,
13209 .sspreq,
13210 .strictfp,
13211 .nocf_check,
13212 .shadowcallstack,
13213 .mustprogress,
13214 .no_sanitize_address,
13215 .no_sanitize_hwaddress,
13216 .sanitize_address_dyninit,
13217 => {
13218 try record.ensureUnusedCapacity(self.gpa, 2);
13219 record.appendAssumeCapacity(0);
13220 record.appendAssumeCapacity(@intFromEnum(kind));
13221 },
13222 .byval,
13223 .byref,
13224 .preallocated,
13225 .inalloca,
13226 .sret,
13227 .elementtype,
13228 => |ty| {
13229 try record.ensureUnusedCapacity(self.gpa, 3);
13230 record.appendAssumeCapacity(6);
13231 record.appendAssumeCapacity(@intFromEnum(kind));
13232 record.appendAssumeCapacity(@intFromEnum(ty));
13233 },
13234 .@"align",
13235 .alignstack,
13236 => |alignment| {
13237 try record.ensureUnusedCapacity(self.gpa, 3);
13238 record.appendAssumeCapacity(1);
13239 record.appendAssumeCapacity(@intFromEnum(kind));
13240 record.appendAssumeCapacity(alignment.toByteUnits() orelse 0);
13241 },
13242 .dereferenceable,
13243 .dereferenceable_or_null,
13244 => |size| {
13245 try record.ensureUnusedCapacity(self.gpa, 3);
13246 record.appendAssumeCapacity(1);
13247 record.appendAssumeCapacity(@intFromEnum(kind));
13248 record.appendAssumeCapacity(size);
13249 },
13250 .nofpclass => |fpclass| {
13251 try record.ensureUnusedCapacity(self.gpa, 3);
13252 record.appendAssumeCapacity(1);
13253 record.appendAssumeCapacity(@intFromEnum(kind));
13254 record.appendAssumeCapacity(@as(u32, @bitCast(fpclass)));
13255 },
13256 .allockind => |allockind| {
13257 try record.ensureUnusedCapacity(self.gpa, 3);
13258 record.appendAssumeCapacity(1);
13259 record.appendAssumeCapacity(@intFromEnum(kind));
13260 record.appendAssumeCapacity(@as(u32, @bitCast(allockind)));
13261 },
13262
13263 .allocsize => |allocsize| {
13264 try record.ensureUnusedCapacity(self.gpa, 3);
13265 record.appendAssumeCapacity(1);
13266 record.appendAssumeCapacity(@intFromEnum(kind));
13267 record.appendAssumeCapacity(@bitCast(allocsize.toLlvm()));
13268 },
13269 .memory => |memory| {
13270 try record.ensureUnusedCapacity(self.gpa, 3);
13271 record.appendAssumeCapacity(1);
13272 record.appendAssumeCapacity(@intFromEnum(kind));
13273 record.appendAssumeCapacity(@as(u32, @bitCast(memory)));
13274 },
13275 .uwtable => |uwtable| if (uwtable != .none) {
13276 try record.ensureUnusedCapacity(self.gpa, 3);
13277 record.appendAssumeCapacity(1);
13278 record.appendAssumeCapacity(@intFromEnum(kind));
13279 record.appendAssumeCapacity(@intFromEnum(uwtable));
13280 },
13281 .vscale_range => |vscale_range| {
13282 try record.ensureUnusedCapacity(self.gpa, 3);
13283 record.appendAssumeCapacity(1);
13284 record.appendAssumeCapacity(@intFromEnum(kind));
13285 record.appendAssumeCapacity(@bitCast(vscale_range.toLlvm()));
13286 },
13287 .string => |string_attr| {
13288 const string_attr_kind_slice = string_attr.kind.slice(self).?;
13289 const string_attr_value_slice = if (string_attr.value != .none)
13290 string_attr.value.slice(self).?
13291 else
13292 null;
13293
13294 try record.ensureUnusedCapacity(
13295 self.gpa,
13296 2 + string_attr_kind_slice.len + if (string_attr_value_slice) |slice| slice.len + 1 else 0,
13297 );
13298 record.appendAssumeCapacity(if (string_attr.value == .none) 3 else 4);
13299 for (string_attr.kind.slice(self).?) |c| {
13300 record.appendAssumeCapacity(c);
13301 }
13302 record.appendAssumeCapacity(0);
13303 if (string_attr_value_slice) |slice| {
13304 for (slice) |c| {
13305 record.appendAssumeCapacity(c);
13306 }
13307 record.appendAssumeCapacity(0);
13308 }
13309 },
13310 .none => unreachable,
13311 }
13312 }
13313
13314 try paramattr_group_block.writeUnabbrev(3, record.items);
13315 }
13316 }
13317
13318 try paramattr_group_block.end();
13319 }
13320
13321 // PARAMATTR_BLOCK
13322 {
13323 const Paramattr = ir.Paramattr;
13324 var paramattr_block = try module_block.enterSubBlock(Paramattr);
13325
13326 for (self.function_attributes_set.keys()) |func_attributes| {
13327 const func_attributes_slice = func_attributes.slice(self);
13328 record.clearRetainingCapacity();
13329 try record.ensureUnusedCapacity(self.gpa, func_attributes_slice.len);
13330 for (func_attributes_slice, 0..) |attributes, i| {
13331 const attributes_slice = attributes.slice(self);
13332 if (attributes_slice.len == 0) continue;
13333
13334 const group_index = attributes_set.getIndex(.{
13335 .attributes = attributes,
13336 .index = @intCast(i),
13337 }).?;
13338 record.appendAssumeCapacity(@intCast(group_index));
13339 }
13340
13341 try paramattr_block.writeAbbrev(Paramattr.Entry{ .group_indices = record.items });
13342 }
13343
13344 try paramattr_block.end();
13345 }
13346
13347 var globals: std.AutoArrayHashMapUnmanaged(Global.Index, void) = .{};
13348 defer globals.deinit(self.gpa);
13349 try globals.ensureUnusedCapacity(
13350 self.gpa,
13351 self.variables.items.len +
13352 self.functions.items.len +
13353 self.aliases.items.len,
13354 );
13355
13356 for (self.variables.items) |variable| {
13357 if (variable.global.getReplacement(self) != .none) continue;
13358
13359 globals.putAssumeCapacity(variable.global, {});
13360 }
13361
13362 for (self.functions.items) |function| {
13363 if (function.global.getReplacement(self) != .none) continue;
13364
13365 globals.putAssumeCapacity(function.global, {});
13366 }
13367
13368 for (self.aliases.items) |alias| {
13369 if (alias.global.getReplacement(self) != .none) continue;
13370
13371 globals.putAssumeCapacity(alias.global, {});
13372 }
13373
13374 const ConstantAdapter = struct {
13375 const ConstantAdapter = @This();
13376 builder: *const Builder,
13377 globals: *const std.AutoArrayHashMapUnmanaged(Global.Index, void),
13378
13379 pub fn get(adapter: @This(), param: anytype, comptime field_name: []const u8) @TypeOf(param) {
13380 _ = field_name;
13381 return switch (@TypeOf(param)) {
13382 Constant => @enumFromInt(adapter.getConstantIndex(param)),
13383 else => param,
13384 };
13385 }
13386
13387 pub fn getConstantIndex(adapter: ConstantAdapter, constant: Constant) u32 {
13388 return switch (constant.unwrap()) {
13389 .constant => |c| c + adapter.numGlobals(),
13390 .global => |global| @intCast(adapter.globals.getIndex(global.unwrap(adapter.builder)).?),
13391 };
13392 }
13393
13394 pub fn numConstants(adapter: ConstantAdapter) u32 {
13395 return @intCast(adapter.globals.count() + adapter.builder.constant_items.len);
13396 }
13397
13398 pub fn numGlobals(adapter: ConstantAdapter) u32 {
13399 return @intCast(adapter.globals.count());
13400 }
13401 };
13402
13403 const constant_adapter = ConstantAdapter{
13404 .builder = self,
13405 .globals = &globals,
13406 };
13407
13408 // Globals
13409 {
13410 var section_map: std.AutoArrayHashMapUnmanaged(String, void) = .{};
13411 defer section_map.deinit(self.gpa);
13412 try section_map.ensureUnusedCapacity(self.gpa, globals.count());
13413
13414 for (self.variables.items) |variable| {
13415 if (variable.global.getReplacement(self) != .none) continue;
13416
13417 const section = blk: {
13418 if (variable.section == .none) break :blk 0;
13419 const gop = section_map.getOrPutAssumeCapacity(variable.section);
13420 if (!gop.found_existing) {
13421 try module_block.writeAbbrev(Module.String{
13422 .code = 5,
13423 .string = variable.section.slice(self).?,
13424 });
13425 }
13426 break :blk gop.index + 1;
13427 };
13428
13429 const initid = if (variable.init == .no_init)
13430 0
13431 else
13432 (constant_adapter.getConstantIndex(variable.init) + 1);
13433
13434 const strtab = variable.global.strtab(self);
13435
13436 const global = variable.global.ptrConst(self);
13437 try module_block.writeAbbrev(Module.Variable{
13438 .strtab_offset = strtab.offset,
13439 .strtab_size = strtab.size,
13440 .type_index = global.type,
13441 .is_const = .{
13442 .is_const = switch (variable.mutability) {
13443 .global => false,
13444 .constant => true,
13445 },
13446 .addr_space = global.addr_space,
13447 },
13448 .initid = initid,
13449 .linkage = global.linkage,
13450 .alignment = variable.alignment.toLlvm(),
13451 .section = section,
13452 .visibility = global.visibility,
13453 .thread_local = variable.thread_local,
13454 .unnamed_addr = global.unnamed_addr,
13455 .externally_initialized = global.externally_initialized,
13456 .dllstorageclass = global.dll_storage_class,
13457 .preemption = global.preemption,
13458 });
13459 }
13460
13461 for (self.functions.items) |func| {
13462 if (func.global.getReplacement(self) != .none) continue;
13463
13464 const section = blk: {
13465 if (func.section == .none) break :blk 0;
13466 const gop = section_map.getOrPutAssumeCapacity(func.section);
13467 if (!gop.found_existing) {
13468 try module_block.writeAbbrev(Module.String{
13469 .code = 5,
13470 .string = func.section.slice(self).?,
13471 });
13472 }
13473 break :blk gop.index + 1;
13474 };
13475
13476 const paramattr_index = if (self.function_attributes_set.getIndex(func.attributes)) |index|
13477 index + 1
13478 else
13479 0;
13480
13481 const strtab = func.global.strtab(self);
13482
13483 const global = func.global.ptrConst(self);
13484 try module_block.writeAbbrev(Module.Function{
13485 .strtab_offset = strtab.offset,
13486 .strtab_size = strtab.size,
13487 .type_index = global.type,
13488 .call_conv = func.call_conv,
13489 .is_proto = func.instructions.len == 0,
13490 .linkage = global.linkage,
13491 .paramattr = paramattr_index,
13492 .alignment = func.alignment.toLlvm(),
13493 .section = section,
13494 .visibility = global.visibility,
13495 .unnamed_addr = global.unnamed_addr,
13496 .dllstorageclass = global.dll_storage_class,
13497 .preemption = global.preemption,
13498 .addr_space = global.addr_space,
13499 });
13500 }
13501
13502 for (self.aliases.items) |alias| {
13503 if (alias.global.getReplacement(self) != .none) continue;
13504
13505 const strtab = alias.global.strtab(self);
13506
13507 const global = alias.global.ptrConst(self);
13508 try module_block.writeAbbrev(Module.Alias{
13509 .strtab_offset = strtab.offset,
13510 .strtab_size = strtab.size,
13511 .type_index = global.type,
13512 .addr_space = global.addr_space,
13513 .aliasee = constant_adapter.getConstantIndex(alias.aliasee),
13514 .linkage = global.linkage,
13515 .visibility = global.visibility,
13516 .thread_local = alias.thread_local,
13517 .unnamed_addr = global.unnamed_addr,
13518 .dllstorageclass = global.dll_storage_class,
13519 .preemption = global.preemption,
13520 });
13521 }
13522 }
13523
13524 // CONSTANTS_BLOCK
13525 {
13526 const Constants = ir.Constants;
13527 var constants_block = try module_block.enterSubBlock(Constants);
13528
13529 var current_type: Type = .none;
13530 const tags = self.constant_items.items(.tag);
13531 const datas = self.constant_items.items(.data);
13532 for (0..self.constant_items.len) |index| {
13533 record.clearRetainingCapacity();
13534 const constant: Constant = @enumFromInt(index);
13535 const constant_type = constant.typeOf(self);
13536 if (constant_type != current_type) {
13537 try constants_block.writeAbbrev(Constants.SetType{ .type_id = constant_type });
13538 current_type = constant_type;
13539 }
13540 const data = datas[index];
13541 switch (tags[index]) {
13542 .null,
13543 .zeroinitializer,
13544 .none,
13545 => try constants_block.writeAbbrev(Constants.Null{}),
13546 .undef => try constants_block.writeAbbrev(Constants.Undef{}),
13547 .poison => try constants_block.writeAbbrev(Constants.Poison{}),
13548 .positive_integer,
13549 .negative_integer,
13550 => |tag| {
13551 const extra: *align(@alignOf(std.math.big.Limb)) Constant.Integer =
13552 @ptrCast(self.constant_limbs.items[data..][0..Constant.Integer.limbs]);
13553 const limbs = self.constant_limbs
13554 .items[data + Constant.Integer.limbs ..][0..extra.limbs_len];
13555 const bigint: std.math.big.int.Const = .{
13556 .limbs = limbs,
13557 .positive = tag == .positive_integer,
13558 };
13559
13560 const bit_count = extra.type.scalarBits(self);
13561 if (bit_count <= 64) {
13562 const val = bigint.to(i64) catch unreachable;
13563 const emit_val = if (tag == .positive_integer)
13564 @shlWithOverflow(val, 1)[0]
13565 else
13566 (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
13567 try constants_block.writeAbbrev(Constants.Integer{ .value = @bitCast(emit_val) });
13568 } else {
13569 const word_count = std.mem.alignForward(u24, bit_count, 64) / 64;
13570 try record.ensureUnusedCapacity(self.gpa, word_count);
13571 const buffer: [*]u8 = @ptrCast(record.items.ptr);
13572 bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little);
13573
13574 const signed_buffer: [*]i64 = @ptrCast(record.items.ptr);
13575 for (signed_buffer[0..word_count], 0..) |val, i| {
13576 signed_buffer[i] = if (val >= 0)
13577 @shlWithOverflow(val, 1)[0]
13578 else
13579 (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
13580 }
13581
13582 try constants_block.writeUnabbrev(5, record.items.ptr[0..word_count]);
13583 }
13584 },
13585 .half,
13586 .bfloat,
13587 => try constants_block.writeAbbrev(Constants.Half{ .value = @truncate(data) }),
13588 .float => try constants_block.writeAbbrev(Constants.Float{ .value = data }),
13589 .double => {
13590 const extra = self.constantExtraData(Constant.Double, data);
13591 try constants_block.writeAbbrev(Constants.Double{
13592 .value = (@as(u64, extra.hi) << 32) | extra.lo,
13593 });
13594 },
13595 .x86_fp80 => {
13596 const extra = self.constantExtraData(Constant.Fp80, data);
13597 try constants_block.writeAbbrev(Constants.Fp80{
13598 .hi = @as(u64, extra.hi) << 48 | @as(u64, extra.lo_hi) << 16 |
13599 extra.lo_lo >> 16,
13600 .lo = @truncate(extra.lo_lo),
13601 });
13602 },
13603 .fp128,
13604 .ppc_fp128,
13605 => {
13606 const extra = self.constantExtraData(Constant.Fp128, data);
13607 try constants_block.writeAbbrev(Constants.Fp128{
13608 .lo = @as(u64, extra.lo_hi) << 32 | @as(u64, extra.lo_lo),
13609 .hi = @as(u64, extra.hi_hi) << 32 | @as(u64, extra.hi_lo),
13610 });
13611 },
13612 .array,
13613 .vector,
13614 .structure,
13615 .packed_structure,
13616 => {
13617 var extra = self.constantExtraDataTrail(Constant.Aggregate, data);
13618 const len: u32 = @intCast(extra.data.type.aggregateLen(self));
13619 const values = extra.trail.next(len, Constant, self);
13620
13621 try constants_block.writeAbbrevAdapted(
13622 Constants.Aggregate{ .values = values },
13623 constant_adapter,
13624 );
13625 },
13626 .splat => {
13627 const ConstantsWriter = @TypeOf(constants_block);
13628 const extra = self.constantExtraData(Constant.Splat, data);
13629 const vector_len = extra.type.vectorLen(self);
13630 const c = constant_adapter.getConstantIndex(extra.value);
13631
13632 try bitcode.writeBits(
13633 ConstantsWriter.abbrevId(Constants.Aggregate),
13634 ConstantsWriter.abbrev_len,
13635 );
13636 try bitcode.writeVBR(vector_len, 6);
13637 for (0..vector_len) |_| {
13638 try bitcode.writeBits(c, Constants.Aggregate.ops[1].array_fixed);
13639 }
13640 },
13641 .string => {
13642 const str: String = @enumFromInt(data);
13643 if (str == .none) {
13644 try constants_block.writeAbbrev(Constants.Null{});
13645 } else {
13646 const slice = str.slice(self).?;
13647 if (slice.len > 0 and slice[slice.len - 1] == 0)
13648 try constants_block.writeAbbrev(Constants.CString{ .string = slice[0 .. slice.len - 1] })
13649 else
13650 try constants_block.writeAbbrev(Constants.String{ .string = slice });
13651 }
13652 },
13653 .bitcast,
13654 .inttoptr,
13655 .ptrtoint,
13656 .fptosi,
13657 .fptoui,
13658 .sitofp,
13659 .uitofp,
13660 .addrspacecast,
13661 .fptrunc,
13662 .trunc,
13663 .fpext,
13664 .sext,
13665 .zext,
13666 => |tag| {
13667 const extra = self.constantExtraData(Constant.Cast, data);
13668 try constants_block.writeAbbrevAdapted(Constants.Cast{
13669 .type_index = extra.type,
13670 .val = extra.val,
13671 .opcode = tag.toCastOpcode(),
13672 }, constant_adapter);
13673 },
13674 .add,
13675 .@"add nsw",
13676 .@"add nuw",
13677 .sub,
13678 .@"sub nsw",
13679 .@"sub nuw",
13680 .mul,
13681 .@"mul nsw",
13682 .@"mul nuw",
13683 .shl,
13684 .lshr,
13685 .ashr,
13686 .@"and",
13687 .@"or",
13688 .xor,
13689 => |tag| {
13690 const extra = self.constantExtraData(Constant.Binary, data);
13691 try constants_block.writeAbbrevAdapted(Constants.Binary{
13692 .opcode = tag.toBinaryOpcode(),
13693 .lhs = extra.lhs,
13694 .rhs = extra.rhs,
13695 }, constant_adapter);
13696 },
13697 .icmp,
13698 .fcmp,
13699 => {
13700 const extra = self.constantExtraData(Constant.Compare, data);
13701 try constants_block.writeAbbrevAdapted(Constants.Cmp{
13702 .ty = extra.lhs.typeOf(self),
13703 .lhs = extra.lhs,
13704 .rhs = extra.rhs,
13705 .pred = extra.cond,
13706 }, constant_adapter);
13707 },
13708 .extractelement => {
13709 const extra = self.constantExtraData(Constant.ExtractElement, data);
13710 try constants_block.writeAbbrevAdapted(Constants.ExtractElement{
13711 .val_type = extra.val.typeOf(self),
13712 .val = extra.val,
13713 .index_type = extra.index.typeOf(self),
13714 .index = extra.index,
13715 }, constant_adapter);
13716 },
13717 .insertelement => {
13718 const extra = self.constantExtraData(Constant.InsertElement, data);
13719 try constants_block.writeAbbrevAdapted(Constants.InsertElement{
13720 .val = extra.val,
13721 .elem = extra.elem,
13722 .index_type = extra.index.typeOf(self),
13723 .index = extra.index,
13724 }, constant_adapter);
13725 },
13726 .shufflevector => {
13727 const extra = self.constantExtraData(Constant.ShuffleVector, data);
13728 const ty = constant.typeOf(self);
13729 const lhs_type = extra.lhs.typeOf(self);
13730 // Check if instruction is widening, truncating or not
13731 if (ty == lhs_type) {
13732 try constants_block.writeAbbrevAdapted(Constants.ShuffleVector{
13733 .lhs = extra.lhs,
13734 .rhs = extra.rhs,
13735 .mask = extra.mask,
13736 }, constant_adapter);
13737 } else {
13738 try constants_block.writeAbbrevAdapted(Constants.ShuffleVectorEx{
13739 .ty = ty,
13740 .lhs = extra.lhs,
13741 .rhs = extra.rhs,
13742 .mask = extra.mask,
13743 }, constant_adapter);
13744 }
13745 },
13746 .getelementptr,
13747 .@"getelementptr inbounds",
13748 => |tag| {
13749 var extra = self.constantExtraDataTrail(Constant.GetElementPtr, data);
13750 const indices = extra.trail.next(extra.data.info.indices_len, Constant, self);
13751 try record.ensureUnusedCapacity(self.gpa, 1 + 2 + 2 * indices.len);
13752
13753 record.appendAssumeCapacity(@intFromEnum(extra.data.type));
13754
13755 record.appendAssumeCapacity(@intFromEnum(extra.data.base.typeOf(self)));
13756 record.appendAssumeCapacity(constant_adapter.getConstantIndex(extra.data.base));
13757
13758 for (indices) |i| {
13759 record.appendAssumeCapacity(@intFromEnum(i.typeOf(self)));
13760 record.appendAssumeCapacity(constant_adapter.getConstantIndex(i));
13761 }
13762
13763 try constants_block.writeUnabbrev(switch (tag) {
13764 .getelementptr => 12,
13765 .@"getelementptr inbounds" => 20,
13766 else => unreachable,
13767 }, record.items);
13768 },
13769 .@"asm",
13770 .@"asm sideeffect",
13771 .@"asm alignstack",
13772 .@"asm sideeffect alignstack",
13773 .@"asm inteldialect",
13774 .@"asm sideeffect inteldialect",
13775 .@"asm alignstack inteldialect",
13776 .@"asm sideeffect alignstack inteldialect",
13777 .@"asm unwind",
13778 .@"asm sideeffect unwind",
13779 .@"asm alignstack unwind",
13780 .@"asm sideeffect alignstack unwind",
13781 .@"asm inteldialect unwind",
13782 .@"asm sideeffect inteldialect unwind",
13783 .@"asm alignstack inteldialect unwind",
13784 .@"asm sideeffect alignstack inteldialect unwind",
13785 => |tag| {
13786 const extra = self.constantExtraData(Constant.Assembly, data);
13787
13788 const assembly_slice = extra.assembly.slice(self).?;
13789 const constraints_slice = extra.constraints.slice(self).?;
13790
13791 try record.ensureUnusedCapacity(self.gpa, 4 + assembly_slice.len + constraints_slice.len);
13792
13793 record.appendAssumeCapacity(@intFromEnum(extra.type));
13794 record.appendAssumeCapacity(switch (tag) {
13795 .@"asm" => 0,
13796 .@"asm sideeffect" => 0b0001,
13797 .@"asm sideeffect alignstack" => 0b0011,
13798 .@"asm sideeffect inteldialect" => 0b0101,
13799 .@"asm sideeffect alignstack inteldialect" => 0b0111,
13800 .@"asm sideeffect unwind" => 0b1001,
13801 .@"asm sideeffect alignstack unwind" => 0b1011,
13802 .@"asm sideeffect inteldialect unwind" => 0b1101,
13803 .@"asm sideeffect alignstack inteldialect unwind" => 0b1111,
13804 .@"asm alignstack" => 0b0010,
13805 .@"asm inteldialect" => 0b0100,
13806 .@"asm alignstack inteldialect" => 0b0110,
13807 .@"asm unwind" => 0b1000,
13808 .@"asm alignstack unwind" => 0b1010,
13809 .@"asm inteldialect unwind" => 0b1100,
13810 .@"asm alignstack inteldialect unwind" => 0b1110,
13811 else => unreachable,
13812 });
13813
13814 record.appendAssumeCapacity(assembly_slice.len);
13815 for (assembly_slice) |c| record.appendAssumeCapacity(c);
13816
13817 record.appendAssumeCapacity(constraints_slice.len);
13818 for (constraints_slice) |c| record.appendAssumeCapacity(c);
13819
13820 try constants_block.writeUnabbrev(30, record.items);
13821 },
13822 .blockaddress => {
13823 const extra = self.constantExtraData(Constant.BlockAddress, data);
13824 try constants_block.writeAbbrev(Constants.BlockAddress{
13825 .type_id = extra.function.typeOf(self),
13826 .function = constant_adapter.getConstantIndex(extra.function.toConst(self)),
13827 .block = @intFromEnum(extra.block),
13828 });
13829 },
13830 .dso_local_equivalent,
13831 .no_cfi,
13832 => |tag| {
13833 const function: Function.Index = @enumFromInt(data);
13834 try constants_block.writeAbbrev(Constants.DsoLocalEquivalentOrNoCfi{
13835 .code = switch (tag) {
13836 .dso_local_equivalent => 27,
13837 .no_cfi => 29,
13838 else => unreachable,
13839 },
13840 .type_id = function.typeOf(self),
13841 .function = constant_adapter.getConstantIndex(function.toConst(self)),
13842 });
13843 },
13844 }
13845 }
13846
13847 try constants_block.end();
13848 }
13849
13850 // METADATA_KIND_BLOCK
13851 if (!self.strip) {
13852 const MetadataKindBlock = ir.MetadataKindBlock;
13853 var metadata_kind_block = try module_block.enterSubBlock(MetadataKindBlock);
13854
13855 inline for (@typeInfo(ir.MetadataKind).Enum.fields) |field| {
13856 try metadata_kind_block.writeAbbrev(MetadataKindBlock.Kind{
13857 .id = field.value,
13858 .name = field.name,
13859 });
13860 }
13861
13862 try metadata_kind_block.end();
13863 }
13864
13865 const MetadataAdapter = struct {
13866 builder: *const Builder,
13867 constant_adapter: ConstantAdapter,
13868
13869 pub fn init(
13870 builder: *const Builder,
13871 const_adapter: ConstantAdapter,
13872 ) @This() {
13873 return .{
13874 .builder = builder,
13875 .constant_adapter = const_adapter,
13876 };
13877 }
13878
13879 pub fn get(adapter: @This(), value: anytype, comptime field_name: []const u8) @TypeOf(value) {
13880 _ = field_name;
13881 const Ty = @TypeOf(value);
13882 return switch (Ty) {
13883 Metadata => @enumFromInt(adapter.getMetadataIndex(value)),
13884 MetadataString => @enumFromInt(adapter.getMetadataStringIndex(value)),
13885 Constant => @enumFromInt(adapter.constant_adapter.getConstantIndex(value)),
13886 else => value,
13887 };
13888 }
13889
13890 pub fn getMetadataIndex(adapter: @This(), metadata: Metadata) u32 {
13891 if (metadata == .none) return 0;
13892 return @intCast(adapter.builder.metadata_string_map.count() +
13893 @intFromEnum(metadata.unwrap(adapter.builder)) - 1);
13894 }
13895
13896 pub fn getMetadataStringIndex(_: @This(), metadata_string: MetadataString) u32 {
13897 return @intFromEnum(metadata_string);
13898 }
13899 };
13900
13901 const metadata_adapter = MetadataAdapter.init(self, constant_adapter);
13902
13903 // METADATA_BLOCK
13904 if (!self.strip) {
13905 const MetadataBlock = ir.MetadataBlock;
13906 var metadata_block = try module_block.enterSubBlock(MetadataBlock);
13907
13908 const MetadataBlockWriter = @TypeOf(metadata_block);
13909
13910 // Emit all MetadataStrings
13911 {
13912 const strings_offset, const strings_size = blk: {
13913 var strings_offset: u32 = 0;
13914 var strings_size: u32 = 0;
13915 for (1..self.metadata_string_map.count()) |metadata_string_index| {
13916 const metadata_string: MetadataString = @enumFromInt(metadata_string_index);
13917 const slice = metadata_string.slice(self);
13918 strings_offset += bitcode.bitsVBR(@as(u32, @intCast(slice.len)), 6);
13919 strings_size += @intCast(slice.len * 8);
13920 }
13921 break :blk .{
13922 std.mem.alignForward(u32, strings_offset, 32) / 8,
13923 std.mem.alignForward(u32, strings_size, 32) / 8,
13924 };
13925 };
13926
13927 try bitcode.writeBits(
13928 comptime MetadataBlockWriter.abbrevId(MetadataBlock.Strings),
13929 MetadataBlockWriter.abbrev_len,
13930 );
13931
13932 try bitcode.writeVBR(@as(u32, @intCast(self.metadata_string_map.count() - 1)), 6);
13933 try bitcode.writeVBR(strings_offset, 6);
13934
13935 try bitcode.writeVBR(strings_size + strings_offset, 6);
13936
13937 try bitcode.alignTo32();
13938
13939 for (1..self.metadata_string_map.count()) |metadata_string_index| {
13940 const metadata_string: MetadataString = @enumFromInt(metadata_string_index);
13941 const slice = metadata_string.slice(self);
13942 try bitcode.writeVBR(@as(u32, @intCast(slice.len)), 6);
13943 }
13944
13945 try bitcode.alignTo32();
13946
13947 for (1..self.metadata_string_map.count()) |metadata_string_index| {
13948 const metadata_string: MetadataString = @enumFromInt(metadata_string_index);
13949 const slice = metadata_string.slice(self);
13950 for (slice) |c| {
13951 try bitcode.writeBits(c, 8);
13952 }
13953 }
13954
13955 try bitcode.alignTo32();
13956 }
13957
13958 for (
13959 self.metadata_items.items(.tag)[1..],
13960 self.metadata_items.items(.data)[1..],
13961 ) |tag, data| {
13962 switch (tag) {
13963 .none => unreachable,
13964 .file => {
13965 const extra = self.metadataExtraData(Metadata.File, data);
13966
13967 try metadata_block.writeAbbrevAdapted(MetadataBlock.File{
13968 .filename = extra.filename,
13969 .directory = extra.directory,
13970 }, metadata_adapter);
13971 },
13972 .compile_unit,
13973 .@"compile_unit optimized",
13974 => |kind| {
13975 const extra = self.metadataExtraData(Metadata.CompileUnit, data);
13976 try metadata_block.writeAbbrevAdapted(MetadataBlock.CompileUnit{
13977 .file = extra.file,
13978 .producer = extra.producer,
13979 .is_optimized = switch (kind) {
13980 .compile_unit => false,
13981 .@"compile_unit optimized" => true,
13982 else => unreachable,
13983 },
13984 .enums = extra.enums,
13985 .globals = extra.globals,
13986 }, metadata_adapter);
13987 },
13988 .subprogram,
13989 .@"subprogram local",
13990 .@"subprogram definition",
13991 .@"subprogram local definition",
13992 .@"subprogram optimized",
13993 .@"subprogram optimized local",
13994 .@"subprogram optimized definition",
13995 .@"subprogram optimized local definition",
13996 => |kind| {
13997 const extra = self.metadataExtraData(Metadata.Subprogram, data);
13998
13999 try metadata_block.writeAbbrevAdapted(MetadataBlock.Subprogram{
14000 .scope = extra.file,
14001 .name = extra.name,
14002 .linkage_name = extra.linkage_name,
14003 .file = extra.file,
14004 .line = extra.line,
14005 .ty = extra.ty,
14006 .scope_line = extra.scope_line,
14007 .sp_flags = @bitCast(@as(u32, @as(u3, @intCast(
14008 @intFromEnum(kind) - @intFromEnum(Metadata.Tag.subprogram),
14009 ))) << 2),
14010 .flags = extra.di_flags,
14011 .compile_unit = extra.compile_unit,
14012 }, metadata_adapter);
14013 },
14014 .lexical_block => {
14015 const extra = self.metadataExtraData(Metadata.LexicalBlock, data);
14016 try metadata_block.writeAbbrevAdapted(MetadataBlock.LexicalBlock{
14017 .scope = extra.scope,
14018 .file = extra.file,
14019 .line = extra.line,
14020 .column = extra.column,
14021 }, metadata_adapter);
14022 },
14023 .location => {
14024 const extra = self.metadataExtraData(Metadata.Location, data);
14025 assert(extra.scope != .none);
14026 try metadata_block.writeAbbrev(MetadataBlock.Location{
14027 .line = extra.line,
14028 .column = extra.column,
14029 .scope = metadata_adapter.getMetadataIndex(extra.scope) - 1,
14030 .inlined_at = @enumFromInt(metadata_adapter.getMetadataIndex(extra.inlined_at)),
14031 });
14032 },
14033 .basic_bool_type,
14034 .basic_unsigned_type,
14035 .basic_signed_type,
14036 .basic_float_type,
14037 => |kind| {
14038 const extra = self.metadataExtraData(Metadata.BasicType, data);
14039 try metadata_block.writeAbbrevAdapted(MetadataBlock.BasicType{
14040 .name = extra.name,
14041 .size_in_bits = extra.bitSize(),
14042 .encoding = switch (kind) {
14043 .basic_bool_type => DW.ATE.boolean,
14044 .basic_unsigned_type => DW.ATE.unsigned,
14045 .basic_signed_type => DW.ATE.signed,
14046 .basic_float_type => DW.ATE.float,
14047 else => unreachable,
14048 },
14049 }, metadata_adapter);
14050 },
14051 .composite_struct_type,
14052 .composite_union_type,
14053 .composite_enumeration_type,
14054 .composite_array_type,
14055 .composite_vector_type,
14056 => |kind| {
14057 const extra = self.metadataExtraData(Metadata.CompositeType, data);
14058
14059 try metadata_block.writeAbbrevAdapted(MetadataBlock.CompositeType{
14060 .tag = switch (kind) {
14061 .composite_struct_type => DW.TAG.structure_type,
14062 .composite_union_type => DW.TAG.union_type,
14063 .composite_enumeration_type => DW.TAG.enumeration_type,
14064 .composite_array_type, .composite_vector_type => DW.TAG.array_type,
14065 else => unreachable,
14066 },
14067 .name = extra.name,
14068 .file = extra.file,
14069 .line = extra.line,
14070 .scope = extra.scope,
14071 .underlying_type = extra.underlying_type,
14072 .size_in_bits = extra.bitSize(),
14073 .align_in_bits = extra.bitAlign(),
14074 .flags = if (kind == .composite_vector_type) .{ .Vector = true } else .{},
14075 .elements = extra.fields_tuple,
14076 }, metadata_adapter);
14077 },
14078 .derived_pointer_type,
14079 .derived_member_type,
14080 => |kind| {
14081 const extra = self.metadataExtraData(Metadata.DerivedType, data);
14082 try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{
14083 .tag = switch (kind) {
14084 .derived_pointer_type => DW.TAG.pointer_type,
14085 .derived_member_type => DW.TAG.member,
14086 else => unreachable,
14087 },
14088 .name = extra.name,
14089 .file = extra.file,
14090 .line = extra.line,
14091 .scope = extra.scope,
14092 .underlying_type = extra.underlying_type,
14093 .size_in_bits = extra.bitSize(),
14094 .align_in_bits = extra.bitAlign(),
14095 .offset_in_bits = extra.bitOffset(),
14096 }, metadata_adapter);
14097 },
14098 .subroutine_type => {
14099 const extra = self.metadataExtraData(Metadata.SubroutineType, data);
14100
14101 try metadata_block.writeAbbrevAdapted(MetadataBlock.SubroutineType{
14102 .types = extra.types_tuple,
14103 }, metadata_adapter);
14104 },
14105 .enumerator_unsigned,
14106 .enumerator_signed_positive,
14107 .enumerator_signed_negative,
14108 => |kind| {
14109 const positive = switch (kind) {
14110 .enumerator_unsigned,
14111 .enumerator_signed_positive,
14112 => true,
14113 .enumerator_signed_negative => false,
14114 else => unreachable,
14115 };
14116
14117 const unsigned = switch (kind) {
14118 .enumerator_unsigned => true,
14119 .enumerator_signed_positive,
14120 .enumerator_signed_negative,
14121 => false,
14122 else => unreachable,
14123 };
14124
14125 const extra = self.metadataExtraData(Metadata.Enumerator, data);
14126
14127 const limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len];
14128
14129 const bigint: std.math.big.int.Const = .{
14130 .limbs = limbs,
14131 .positive = positive,
14132 };
14133
14134 if (extra.bit_width <= 64) {
14135 const val = bigint.to(i64) catch unreachable;
14136 const emit_val = if (positive)
14137 @shlWithOverflow(val, 1)[0]
14138 else
14139 (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
14140 try metadata_block.writeAbbrevAdapted(MetadataBlock.Enumerator{
14141 .flags = .{
14142 .unsigned = unsigned,
14143 .bigint = false,
14144 },
14145 .bit_width = extra.bit_width,
14146 .name = extra.name,
14147 .value = @bitCast(emit_val),
14148 }, metadata_adapter);
14149 } else {
14150 const word_count = std.mem.alignForward(u32, extra.bit_width, 64) / 64;
14151 try record.ensureUnusedCapacity(self.gpa, 3 + word_count);
14152
14153 const flags: MetadataBlock.Enumerator.Flags = .{
14154 .unsigned = unsigned,
14155 .bigint = true,
14156 };
14157
14158 const FlagsInt = @typeInfo(MetadataBlock.Enumerator.Flags).Struct.backing_integer.?;
14159
14160 const flags_int: FlagsInt = @bitCast(flags);
14161
14162 record.appendAssumeCapacity(@intCast(flags_int));
14163 record.appendAssumeCapacity(@intCast(extra.bit_width));
14164 record.appendAssumeCapacity(metadata_adapter.getMetadataStringIndex(extra.name));
14165
14166 const buffer: [*]u8 = @ptrCast(record.items.ptr);
14167 bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little);
14168
14169 const signed_buffer: [*]i64 = @ptrCast(record.items.ptr);
14170 for (signed_buffer[0..word_count], 0..) |val, i| {
14171 signed_buffer[i] = if (val >= 0)
14172 @shlWithOverflow(val, 1)[0]
14173 else
14174 (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
14175 }
14176
14177 try metadata_block.writeUnabbrev(
14178 MetadataBlock.Enumerator.id,
14179 record.items.ptr[0..(3 + word_count)],
14180 );
14181 }
14182 },
14183 .subrange => {
14184 const extra = self.metadataExtraData(Metadata.Subrange, data);
14185
14186 try metadata_block.writeAbbrevAdapted(MetadataBlock.Subrange{
14187 .count = extra.count,
14188 .lower_bound = extra.lower_bound,
14189 }, metadata_adapter);
14190 },
14191 .expression => {
14192 var extra = self.metadataExtraDataTrail(Metadata.Expression, data);
14193
14194 const elements = extra.trail.next(extra.data.elements_len, u32, self);
14195
14196 try metadata_block.writeAbbrevAdapted(MetadataBlock.Expression{
14197 .elements = elements,
14198 }, metadata_adapter);
14199 },
14200 .tuple => {
14201 var extra = self.metadataExtraDataTrail(Metadata.Tuple, data);
14202
14203 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
14204
14205 try metadata_block.writeAbbrevAdapted(MetadataBlock.Node{
14206 .elements = elements,
14207 }, metadata_adapter);
14208 },
14209 .module_flag => {
14210 const extra = self.metadataExtraData(Metadata.ModuleFlag, data);
14211 try metadata_block.writeAbbrev(MetadataBlock.Node{
14212 .elements = &.{
14213 @enumFromInt(metadata_adapter.getMetadataIndex(extra.behavior)),
14214 @enumFromInt(metadata_adapter.getMetadataStringIndex(extra.name)),
14215 @enumFromInt(metadata_adapter.getMetadataIndex(extra.constant)),
14216 },
14217 });
14218 },
14219 .local_var => {
14220 const extra = self.metadataExtraData(Metadata.LocalVar, data);
14221 try metadata_block.writeAbbrevAdapted(MetadataBlock.LocalVar{
14222 .scope = extra.scope,
14223 .name = extra.name,
14224 .file = extra.file,
14225 .line = extra.line,
14226 .ty = extra.ty,
14227 }, metadata_adapter);
14228 },
14229 .parameter => {
14230 const extra = self.metadataExtraData(Metadata.Parameter, data);
14231 try metadata_block.writeAbbrevAdapted(MetadataBlock.Parameter{
14232 .scope = extra.scope,
14233 .name = extra.name,
14234 .file = extra.file,
14235 .line = extra.line,
14236 .ty = extra.ty,
14237 .arg = extra.arg_no,
14238 }, metadata_adapter);
14239 },
14240 .global_var,
14241 .@"global_var local",
14242 => |kind| {
14243 const extra = self.metadataExtraData(Metadata.GlobalVar, data);
14244 try metadata_block.writeAbbrevAdapted(MetadataBlock.GlobalVar{
14245 .scope = extra.scope,
14246 .name = extra.name,
14247 .linkage_name = extra.linkage_name,
14248 .file = extra.file,
14249 .line = extra.line,
14250 .ty = extra.ty,
14251 .local = kind == .@"global_var local",
14252 }, metadata_adapter);
14253 },
14254 .global_var_expression => {
14255 const extra = self.metadataExtraData(Metadata.GlobalVarExpression, data);
14256 try metadata_block.writeAbbrevAdapted(MetadataBlock.GlobalVarExpression{
14257 .variable = extra.variable,
14258 .expression = extra.expression,
14259 }, metadata_adapter);
14260 },
14261 .constant => {
14262 const constant: Constant = @enumFromInt(data);
14263 try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{
14264 .ty = constant.typeOf(self),
14265 .constant = constant,
14266 }, metadata_adapter);
14267 },
14268 }
14269 record.clearRetainingCapacity();
14270 }
14271
14272 // Write named metadata
14273 for (self.metadata_named.keys(), self.metadata_named.values()) |name, operands| {
14274 const slice = name.slice(self);
14275 try metadata_block.writeAbbrev(MetadataBlock.Name{
14276 .name = slice,
14277 });
14278
14279 const elements = self.metadata_extra.items[operands.index..][0..operands.len];
14280 for (elements) |*e| {
14281 e.* = metadata_adapter.getMetadataIndex(@enumFromInt(e.*)) - 1;
14282 }
14283
14284 try metadata_block.writeAbbrev(MetadataBlock.NamedNode{
14285 .elements = @ptrCast(elements),
14286 });
14287 }
14288
14289 // Write global attached metadata
14290 {
14291 for (globals.keys()) |global| {
14292 const global_ptr = global.ptrConst(self);
14293 if (global_ptr.dbg == .none) continue;
14294
14295 switch (global_ptr.kind) {
14296 .function => |f| if (f.ptrConst(self).instructions.len != 0) continue,
14297 else => {},
14298 }
14299
14300 try metadata_block.writeAbbrev(MetadataBlock.GlobalDeclAttachment{
14301 .value = @enumFromInt(constant_adapter.getConstantIndex(global.toConst())),
14302 .kind = ir.MetadataKind.dbg,
14303 .metadata = @enumFromInt(metadata_adapter.getMetadataIndex(global_ptr.dbg) - 1),
14304 });
14305 }
14306 }
14307
14308 try metadata_block.end();
14309 }
14310
14311 // FUNCTION_BLOCKS
14312 {
14313 const FunctionAdapter = struct {
14314 constant_adapter: ConstantAdapter,
14315 metadata_adapter: MetadataAdapter,
14316 func: *const Function,
14317 instruction_index: u32 = 0,
14318
14319 pub fn init(
14320 const_adapter: ConstantAdapter,
14321 meta_adapter: MetadataAdapter,
14322 func: *const Function,
14323 ) @This() {
14324 return .{
14325 .constant_adapter = const_adapter,
14326 .metadata_adapter = meta_adapter,
14327 .func = func,
14328 .instruction_index = 0,
14329 };
14330 }
14331
14332 pub fn get(adapter: @This(), value: anytype, comptime field_name: []const u8) @TypeOf(value) {
14333 _ = field_name;
14334 const Ty = @TypeOf(value);
14335 return switch (Ty) {
14336 Value => @enumFromInt(adapter.getOffsetValueIndex(value)),
14337 Constant => @enumFromInt(adapter.getOffsetConstantIndex(value)),
14338 FunctionAttributes => @enumFromInt(switch (value) {
14339 .none => 0,
14340 else => 1 + adapter.constant_adapter.builder.function_attributes_set.getIndex(value).?,
14341 }),
14342 else => value,
14343 };
14344 }
14345
14346 pub fn getValueIndex(adapter: @This(), value: Value) u32 {
14347 return @intCast(switch (value.unwrap()) {
14348 .instruction => |instruction| instruction.valueIndex(adapter.func) + adapter.firstInstr(),
14349 .constant => |constant| adapter.constant_adapter.getConstantIndex(constant),
14350 .metadata => |metadata| if (!adapter.metadata_adapter.builder.strip) blk: {
14351 const real_metadata = metadata.unwrap(adapter.metadata_adapter.builder);
14352 if (@intFromEnum(real_metadata) < Metadata.first_local_metadata)
14353 break :blk adapter.metadata_adapter.getMetadataIndex(real_metadata) - 1;
14354
14355 return @intCast(@intFromEnum(metadata) -
14356 Metadata.first_local_metadata +
14357 adapter.metadata_adapter.builder.metadata_string_map.count() - 1 +
14358 adapter.metadata_adapter.builder.metadata_map.count() - 1);
14359 } else unreachable,
14360 });
14361 }
14362
14363 pub fn getOffsetValueIndex(adapter: @This(), value: Value) u32 {
14364 return @subWithOverflow(adapter.offset(), adapter.getValueIndex(value))[0];
14365 }
14366
14367 pub fn getOffsetValueSignedIndex(adapter: @This(), value: Value) i32 {
14368 const signed_offset: i32 = @intCast(adapter.offset());
14369 const signed_value: i32 = @intCast(adapter.getValueIndex(value));
14370 return signed_offset - signed_value;
14371 }
14372
14373 pub fn getOffsetConstantIndex(adapter: @This(), constant: Constant) u32 {
14374 return adapter.offset() - adapter.constant_adapter.getConstantIndex(constant);
14375 }
14376
14377 pub fn offset(adapter: @This()) u32 {
14378 return @as(
14379 Function.Instruction.Index,
14380 @enumFromInt(adapter.instruction_index),
14381 ).valueIndex(adapter.func) + adapter.firstInstr();
14382 }
14383
14384 fn firstInstr(adapter: @This()) u32 {
14385 return adapter.constant_adapter.numConstants();
14386 }
14387
14388 pub fn next(adapter: *@This()) void {
14389 adapter.instruction_index += 1;
14390 }
14391 };
14392
14393 for (self.functions.items, 0..) |func, func_index| {
14394 const FunctionBlock = ir.FunctionBlock;
14395 if (func.global.getReplacement(self) != .none) continue;
14396
14397 if (func.instructions.len == 0) continue;
14398
14399 var function_block = try module_block.enterSubBlock(FunctionBlock);
14400
14401 try function_block.writeAbbrev(FunctionBlock.DeclareBlocks{ .num_blocks = func.blocks.len });
14402
14403 var adapter = FunctionAdapter.init(constant_adapter, metadata_adapter, &func);
14404
14405 // Emit function level metadata block
14406 if (!self.strip and func.debug_values.len != 0) {
14407 const MetadataBlock = ir.FunctionMetadataBlock;
14408 var metadata_block = try function_block.enterSubBlock(MetadataBlock);
14409
14410 for (func.debug_values) |value| {
14411 try metadata_block.writeAbbrev(MetadataBlock.Value{
14412 .ty = value.typeOf(@enumFromInt(func_index), self),
14413 .value = @enumFromInt(adapter.getValueIndex(value.toValue())),
14414 });
14415 }
14416
14417 try metadata_block.end();
14418 }
14419
14420 const tags = func.instructions.items(.tag);
14421 const datas = func.instructions.items(.data);
14422
14423 var has_location = false;
14424
14425 var block_incoming_len: u32 = undefined;
14426 for (0..func.instructions.len) |instr_index| {
14427 const tag = tags[instr_index];
14428
14429 record.clearRetainingCapacity();
14430
14431 switch (tag) {
14432 .block => block_incoming_len = datas[instr_index],
14433 .arg => {},
14434 .@"unreachable" => try function_block.writeAbbrev(FunctionBlock.Unreachable{}),
14435 .call,
14436 .@"musttail call",
14437 .@"notail call",
14438 .@"tail call",
14439 => |kind| {
14440 var extra = func.extraDataTrail(Function.Instruction.Call, datas[instr_index]);
14441
14442 const call_conv = extra.data.info.call_conv;
14443 const args = extra.trail.next(extra.data.args_len, Value, &func);
14444 try function_block.writeAbbrevAdapted(FunctionBlock.Call{
14445 .attributes = extra.data.attributes,
14446 .call_type = switch (kind) {
14447 .call => .{ .call_conv = call_conv },
14448 .@"tail call" => .{ .tail = true, .call_conv = call_conv },
14449 .@"musttail call" => .{ .must_tail = true, .call_conv = call_conv },
14450 .@"notail call" => .{ .no_tail = true, .call_conv = call_conv },
14451 else => unreachable,
14452 },
14453 .type_id = extra.data.ty,
14454 .callee = extra.data.callee,
14455 .args = args,
14456 }, adapter);
14457 },
14458 .@"call fast",
14459 .@"musttail call fast",
14460 .@"notail call fast",
14461 .@"tail call fast",
14462 => |kind| {
14463 var extra = func.extraDataTrail(Function.Instruction.Call, datas[instr_index]);
14464
14465 const call_conv = extra.data.info.call_conv;
14466 const args = extra.trail.next(extra.data.args_len, Value, &func);
14467 try function_block.writeAbbrevAdapted(FunctionBlock.CallFast{
14468 .attributes = extra.data.attributes,
14469 .call_type = switch (kind) {
14470 .call => .{ .call_conv = call_conv },
14471 .@"tail call" => .{ .tail = true, .call_conv = call_conv },
14472 .@"musttail call" => .{ .must_tail = true, .call_conv = call_conv },
14473 .@"notail call" => .{ .no_tail = true, .call_conv = call_conv },
14474 else => unreachable,
14475 },
14476 .fast_math = .{},
14477 .type_id = extra.data.ty,
14478 .callee = extra.data.callee,
14479 .args = args,
14480 }, adapter);
14481 },
14482 .add,
14483 .@"add nsw",
14484 .@"add nuw",
14485 .@"add nuw nsw",
14486 .@"and",
14487 .fadd,
14488 .fdiv,
14489 .fmul,
14490 .mul,
14491 .@"mul nsw",
14492 .@"mul nuw",
14493 .@"mul nuw nsw",
14494 .frem,
14495 .fsub,
14496 .sdiv,
14497 .@"sdiv exact",
14498 .sub,
14499 .@"sub nsw",
14500 .@"sub nuw",
14501 .@"sub nuw nsw",
14502 .udiv,
14503 .@"udiv exact",
14504 .xor,
14505 .shl,
14506 .@"shl nsw",
14507 .@"shl nuw",
14508 .@"shl nuw nsw",
14509 .lshr,
14510 .@"lshr exact",
14511 .@"or",
14512 .urem,
14513 .srem,
14514 .ashr,
14515 .@"ashr exact",
14516 => |kind| {
14517 const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]);
14518 try function_block.writeAbbrev(FunctionBlock.Binary{
14519 .opcode = kind.toBinaryOpcode(),
14520 .lhs = adapter.getOffsetValueIndex(extra.lhs),
14521 .rhs = adapter.getOffsetValueIndex(extra.rhs),
14522 });
14523 },
14524 .@"fadd fast",
14525 .@"fdiv fast",
14526 .@"fmul fast",
14527 .@"frem fast",
14528 .@"fsub fast",
14529 => |kind| {
14530 const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]);
14531 try function_block.writeAbbrev(FunctionBlock.BinaryFast{
14532 .opcode = kind.toBinaryOpcode(),
14533 .lhs = adapter.getOffsetValueIndex(extra.lhs),
14534 .rhs = adapter.getOffsetValueIndex(extra.rhs),
14535 .fast_math = .{},
14536 });
14537 },
14538 .alloca,
14539 .@"alloca inalloca",
14540 => |kind| {
14541 const extra = func.extraData(Function.Instruction.Alloca, datas[instr_index]);
14542 const alignment = extra.info.alignment.toLlvm();
14543 try function_block.writeAbbrev(FunctionBlock.Alloca{
14544 .inst_type = extra.type,
14545 .len_type = extra.len.typeOf(@enumFromInt(func_index), self),
14546 .len_value = adapter.getValueIndex(extra.len),
14547 .flags = .{
14548 .align_lower = @truncate(alignment),
14549 .inalloca = kind == .@"alloca inalloca",
14550 .explicit_type = true,
14551 .swift_error = false,
14552 .align_upper = @truncate(alignment << 5),
14553 },
14554 });
14555 },
14556 .bitcast,
14557 .inttoptr,
14558 .ptrtoint,
14559 .fptosi,
14560 .fptoui,
14561 .sitofp,
14562 .uitofp,
14563 .addrspacecast,
14564 .fptrunc,
14565 .trunc,
14566 .fpext,
14567 .sext,
14568 .zext,
14569 => |kind| {
14570 const extra = func.extraData(Function.Instruction.Cast, datas[instr_index]);
14571 try function_block.writeAbbrev(FunctionBlock.Cast{
14572 .val = adapter.getOffsetValueIndex(extra.val),
14573 .type_index = extra.type,
14574 .opcode = kind.toCastOpcode(),
14575 });
14576 },
14577 .@"fcmp false",
14578 .@"fcmp oeq",
14579 .@"fcmp oge",
14580 .@"fcmp ogt",
14581 .@"fcmp ole",
14582 .@"fcmp olt",
14583 .@"fcmp one",
14584 .@"fcmp ord",
14585 .@"fcmp true",
14586 .@"fcmp ueq",
14587 .@"fcmp uge",
14588 .@"fcmp ugt",
14589 .@"fcmp ule",
14590 .@"fcmp ult",
14591 .@"fcmp une",
14592 .@"fcmp uno",
14593 .@"icmp eq",
14594 .@"icmp ne",
14595 .@"icmp sge",
14596 .@"icmp sgt",
14597 .@"icmp sle",
14598 .@"icmp slt",
14599 .@"icmp uge",
14600 .@"icmp ugt",
14601 .@"icmp ule",
14602 .@"icmp ult",
14603 => |kind| {
14604 const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]);
14605 try function_block.writeAbbrev(FunctionBlock.Cmp{
14606 .lhs = adapter.getOffsetValueIndex(extra.lhs),
14607 .rhs = adapter.getOffsetValueIndex(extra.rhs),
14608 .pred = kind.toCmpPredicate(),
14609 });
14610 },
14611 .@"fcmp fast false",
14612 .@"fcmp fast oeq",
14613 .@"fcmp fast oge",
14614 .@"fcmp fast ogt",
14615 .@"fcmp fast ole",
14616 .@"fcmp fast olt",
14617 .@"fcmp fast one",
14618 .@"fcmp fast ord",
14619 .@"fcmp fast true",
14620 .@"fcmp fast ueq",
14621 .@"fcmp fast uge",
14622 .@"fcmp fast ugt",
14623 .@"fcmp fast ule",
14624 .@"fcmp fast ult",
14625 .@"fcmp fast une",
14626 .@"fcmp fast uno",
14627 => |kind| {
14628 const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]);
14629 try function_block.writeAbbrev(FunctionBlock.CmpFast{
14630 .lhs = adapter.getOffsetValueIndex(extra.lhs),
14631 .rhs = adapter.getOffsetValueIndex(extra.rhs),
14632 .pred = kind.toCmpPredicate(),
14633 .fast_math = .{},
14634 });
14635 },
14636 .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{
14637 .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])),
14638 }),
14639 .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{
14640 .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])),
14641 .fast_math = .{},
14642 }),
14643 .extractvalue => {
14644 var extra = func.extraDataTrail(Function.Instruction.ExtractValue, datas[instr_index]);
14645 const indices = extra.trail.next(extra.data.indices_len, u32, &func);
14646 try function_block.writeAbbrev(FunctionBlock.ExtractValue{
14647 .val = adapter.getOffsetValueIndex(extra.data.val),
14648 .indices = indices,
14649 });
14650 },
14651 .insertvalue => {
14652 var extra = func.extraDataTrail(Function.Instruction.InsertValue, datas[instr_index]);
14653 const indices = extra.trail.next(extra.data.indices_len, u32, &func);
14654 try function_block.writeAbbrev(FunctionBlock.InsertValue{
14655 .val = adapter.getOffsetValueIndex(extra.data.val),
14656 .elem = adapter.getOffsetValueIndex(extra.data.elem),
14657 .indices = indices,
14658 });
14659 },
14660 .extractelement => {
14661 const extra = func.extraData(Function.Instruction.ExtractElement, datas[instr_index]);
14662 try function_block.writeAbbrev(FunctionBlock.ExtractElement{
14663 .val = adapter.getOffsetValueIndex(extra.val),
14664 .index = adapter.getOffsetValueIndex(extra.index),
14665 });
14666 },
14667 .insertelement => {
14668 const extra = func.extraData(Function.Instruction.InsertElement, datas[instr_index]);
14669 try function_block.writeAbbrev(FunctionBlock.InsertElement{
14670 .val = adapter.getOffsetValueIndex(extra.val),
14671 .elem = adapter.getOffsetValueIndex(extra.elem),
14672 .index = adapter.getOffsetValueIndex(extra.index),
14673 });
14674 },
14675 .select => {
14676 const extra = func.extraData(Function.Instruction.Select, datas[instr_index]);
14677 try function_block.writeAbbrev(FunctionBlock.Select{
14678 .lhs = adapter.getOffsetValueIndex(extra.lhs),
14679 .rhs = adapter.getOffsetValueIndex(extra.rhs),
14680 .cond = adapter.getOffsetValueIndex(extra.cond),
14681 });
14682 },
14683 .@"select fast" => {
14684 const extra = func.extraData(Function.Instruction.Select, datas[instr_index]);
14685 try function_block.writeAbbrev(FunctionBlock.SelectFast{
14686 .lhs = adapter.getOffsetValueIndex(extra.lhs),
14687 .rhs = adapter.getOffsetValueIndex(extra.rhs),
14688 .cond = adapter.getOffsetValueIndex(extra.cond),
14689 .fast_math = .{},
14690 });
14691 },
14692 .shufflevector => {
14693 const extra = func.extraData(Function.Instruction.ShuffleVector, datas[instr_index]);
14694 try function_block.writeAbbrev(FunctionBlock.ShuffleVector{
14695 .lhs = adapter.getOffsetValueIndex(extra.lhs),
14696 .rhs = adapter.getOffsetValueIndex(extra.rhs),
14697 .mask = adapter.getOffsetValueIndex(extra.mask),
14698 });
14699 },
14700 .getelementptr,
14701 .@"getelementptr inbounds",
14702 => |kind| {
14703 var extra = func.extraDataTrail(Function.Instruction.GetElementPtr, datas[instr_index]);
14704 const indices = extra.trail.next(extra.data.indices_len, Value, &func);
14705 try function_block.writeAbbrevAdapted(
14706 FunctionBlock.GetElementPtr{
14707 .is_inbounds = kind == .@"getelementptr inbounds",
14708 .type_index = extra.data.type,
14709 .base = extra.data.base,
14710 .indices = indices,
14711 },
14712 adapter,
14713 );
14714 },
14715 .load => {
14716 const extra = func.extraData(Function.Instruction.Load, datas[instr_index]);
14717 try function_block.writeAbbrev(FunctionBlock.Load{
14718 .ptr = adapter.getOffsetValueIndex(extra.ptr),
14719 .ty = extra.type,
14720 .alignment = extra.info.alignment.toLlvm(),
14721 .is_volatile = extra.info.access_kind == .@"volatile",
14722 });
14723 },
14724 .@"load atomic" => {
14725 const extra = func.extraData(Function.Instruction.Load, datas[instr_index]);
14726 try function_block.writeAbbrev(FunctionBlock.LoadAtomic{
14727 .ptr = adapter.getOffsetValueIndex(extra.ptr),
14728 .ty = extra.type,
14729 .alignment = extra.info.alignment.toLlvm(),
14730 .is_volatile = extra.info.access_kind == .@"volatile",
14731 .success_ordering = extra.info.success_ordering,
14732 .sync_scope = extra.info.sync_scope,
14733 });
14734 },
14735 .store => {
14736 const extra = func.extraData(Function.Instruction.Store, datas[instr_index]);
14737 try function_block.writeAbbrev(FunctionBlock.Store{
14738 .ptr = adapter.getOffsetValueIndex(extra.ptr),
14739 .val = adapter.getOffsetValueIndex(extra.val),
14740 .alignment = extra.info.alignment.toLlvm(),
14741 .is_volatile = extra.info.access_kind == .@"volatile",
14742 });
14743 },
14744 .@"store atomic" => {
14745 const extra = func.extraData(Function.Instruction.Store, datas[instr_index]);
14746 try function_block.writeAbbrev(FunctionBlock.StoreAtomic{
14747 .ptr = adapter.getOffsetValueIndex(extra.ptr),
14748 .val = adapter.getOffsetValueIndex(extra.val),
14749 .alignment = extra.info.alignment.toLlvm(),
14750 .is_volatile = extra.info.access_kind == .@"volatile",
14751 .success_ordering = extra.info.success_ordering,
14752 .sync_scope = extra.info.sync_scope,
14753 });
14754 },
14755 .br => {
14756 try function_block.writeAbbrev(FunctionBlock.BrUnconditional{
14757 .block = datas[instr_index],
14758 });
14759 },
14760 .br_cond => {
14761 const extra = func.extraData(Function.Instruction.BrCond, datas[instr_index]);
14762 try function_block.writeAbbrev(FunctionBlock.BrConditional{
14763 .then_block = @intFromEnum(extra.then),
14764 .else_block = @intFromEnum(extra.@"else"),
14765 .condition = adapter.getOffsetValueIndex(extra.cond),
14766 });
14767 },
14768 .@"switch" => {
14769 var extra = func.extraDataTrail(Function.Instruction.Switch, datas[instr_index]);
14770
14771 try record.ensureUnusedCapacity(self.gpa, 3 + extra.data.cases_len * 2);
14772
14773 // Conditional type
14774 record.appendAssumeCapacity(@intFromEnum(extra.data.val.typeOf(@enumFromInt(func_index), self)));
14775
14776 // Conditional
14777 record.appendAssumeCapacity(adapter.getOffsetValueIndex(extra.data.val));
14778
14779 // Default block
14780 record.appendAssumeCapacity(@intFromEnum(extra.data.default));
14781
14782 const vals = extra.trail.next(extra.data.cases_len, Constant, &func);
14783 const blocks = extra.trail.next(extra.data.cases_len, Function.Block.Index, &func);
14784 for (vals, blocks) |val, block| {
14785 record.appendAssumeCapacity(adapter.constant_adapter.getConstantIndex(val));
14786 record.appendAssumeCapacity(@intFromEnum(block));
14787 }
14788
14789 try function_block.writeUnabbrev(12, record.items);
14790 },
14791 .va_arg => {
14792 const extra = func.extraData(Function.Instruction.VaArg, datas[instr_index]);
14793 try function_block.writeAbbrev(FunctionBlock.VaArg{
14794 .list_type = extra.list.typeOf(@enumFromInt(func_index), self),
14795 .list = adapter.getOffsetValueIndex(extra.list),
14796 .type = extra.type,
14797 });
14798 },
14799 .phi,
14800 .@"phi fast",
14801 => |kind| {
14802 var extra = func.extraDataTrail(Function.Instruction.Phi, datas[instr_index]);
14803 const vals = extra.trail.next(block_incoming_len, Value, &func);
14804 const blocks = extra.trail.next(block_incoming_len, Function.Block.Index, &func);
14805
14806 try record.ensureUnusedCapacity(
14807 self.gpa,
14808 1 + block_incoming_len * 2 + @intFromBool(kind == .@"phi fast"),
14809 );
14810
14811 record.appendAssumeCapacity(@intFromEnum(extra.data.type));
14812
14813 for (vals, blocks) |val, block| {
14814 const offset_value = adapter.getOffsetValueSignedIndex(val);
14815 const abs_value: u32 = @intCast(@abs(offset_value));
14816 const signed_vbr = if (offset_value > 0) abs_value << 1 else ((abs_value << 1) | 1);
14817 record.appendAssumeCapacity(signed_vbr);
14818 record.appendAssumeCapacity(@intFromEnum(block));
14819 }
14820
14821 if (kind == .@"phi fast") record.appendAssumeCapacity(@as(u8, @bitCast(FastMath{})));
14822
14823 try function_block.writeUnabbrev(16, record.items);
14824 },
14825 .ret => try function_block.writeAbbrev(FunctionBlock.Ret{
14826 .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])),
14827 }),
14828 .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}),
14829 .atomicrmw => {
14830 const extra = func.extraData(Function.Instruction.AtomicRmw, datas[instr_index]);
14831 try function_block.writeAbbrev(FunctionBlock.AtomicRmw{
14832 .ptr = adapter.getOffsetValueIndex(extra.ptr),
14833 .val = adapter.getOffsetValueIndex(extra.val),
14834 .operation = extra.info.atomic_rmw_operation,
14835 .is_volatile = extra.info.access_kind == .@"volatile",
14836 .success_ordering = extra.info.success_ordering,
14837 .sync_scope = extra.info.sync_scope,
14838 .alignment = extra.info.alignment.toLlvm(),
14839 });
14840 },
14841 .cmpxchg,
14842 .@"cmpxchg weak",
14843 => |kind| {
14844 const extra = func.extraData(Function.Instruction.CmpXchg, datas[instr_index]);
14845
14846 try function_block.writeAbbrev(FunctionBlock.CmpXchg{
14847 .ptr = adapter.getOffsetValueIndex(extra.ptr),
14848 .cmp = adapter.getOffsetValueIndex(extra.cmp),
14849 .new = adapter.getOffsetValueIndex(extra.new),
14850 .is_volatile = extra.info.access_kind == .@"volatile",
14851 .success_ordering = extra.info.success_ordering,
14852 .sync_scope = extra.info.sync_scope,
14853 .failure_ordering = extra.info.failure_ordering,
14854 .is_weak = kind == .@"cmpxchg weak",
14855 .alignment = extra.info.alignment.toLlvm(),
14856 });
14857 },
14858 .fence => {
14859 const info: MemoryAccessInfo = @bitCast(datas[instr_index]);
14860 try function_block.writeAbbrev(FunctionBlock.Fence{
14861 .ordering = info.success_ordering,
14862 .sync_scope = info.sync_scope,
14863 });
14864 },
14865 }
14866
14867 if (!self.strip) {
14868 if (func.debug_locations.get(@enumFromInt(instr_index))) |debug_location| {
14869 if (debug_location != .none) {
14870 const location = self.metadata_items.get(@intFromEnum(debug_location));
14871 assert(location.tag == .location);
14872 const extra = self.metadataExtraData(Metadata.Location, location.data);
14873 try function_block.writeAbbrev(FunctionBlock.DebugLoc{
14874 .line = extra.line,
14875 .column = extra.column,
14876 .scope = @enumFromInt(metadata_adapter.getMetadataIndex(extra.scope)),
14877 .inlined_at = @enumFromInt(metadata_adapter.getMetadataIndex(extra.inlined_at)),
14878 .is_implicit = false,
14879 });
14880 has_location = true;
14881 } else {
14882 has_location = false;
14883 }
14884 } else if (has_location) {
14885 try function_block.writeAbbrev(FunctionBlock.DebugLocAgain{});
14886 }
14887 }
14888
14889 adapter.next();
14890 }
14891
14892 // VALUE_SYMTAB
14893 if (!self.strip) {
14894 const ValueSymbolTable = ir.FunctionValueSymbolTable;
14895
14896 var value_symtab_block = try function_block.enterSubBlock(ValueSymbolTable);
14897
14898 for (func.blocks, 0..) |block, block_index| {
14899 const name = block.instruction.name(&func);
14900
14901 if (name == .none or name == .empty) continue;
14902
14903 try value_symtab_block.writeAbbrev(ValueSymbolTable.BlockEntry{
14904 .value_id = @intCast(block_index),
14905 .string = name.slice(self).?,
14906 });
14907 }
14908
14909 // TODO: Emit non block entries if the builder ever starts assigning names to non blocks
14910
14911 try value_symtab_block.end();
14912 }
14913
14914 // METADATA_ATTACHMENT_BLOCK
14915 if (!self.strip) blk: {
14916 const dbg = func.global.ptrConst(self).dbg;
14917
14918 if (dbg == .none) break :blk;
14919
14920 const MetadataAttachmentBlock = ir.MetadataAttachmentBlock;
14921 var metadata_attach_block = try function_block.enterSubBlock(MetadataAttachmentBlock);
14922
14923 try metadata_attach_block.writeAbbrev(MetadataAttachmentBlock.AttachmentSingle{
14924 .kind = ir.MetadataKind.dbg,
14925 .metadata = @enumFromInt(metadata_adapter.getMetadataIndex(dbg) - 1),
14926 });
14927
14928 try metadata_attach_block.end();
14929 }
14930
14931 try function_block.end();
14932 }
14933 }
14934
14935 try module_block.end();
14936 }
14937
14938 // STRTAB_BLOCK
14939 {
14940 const Strtab = ir.Strtab;
14941 var strtab_block = try bitcode.enterTopBlock(Strtab);
14942
14943 try strtab_block.writeAbbrev(Strtab.Blob{ .blob = self.string_bytes.items });
14944
14945 try strtab_block.end();
14946 }
14947
14948 return bitcode.toSlice();
14949}
14950
14951const Allocator = std.mem.Allocator;
14952const assert = std.debug.assert;
14953const bitcode_writer = @import("bitcode_writer.zig");
14954const build_options = @import("build_options");
14955const Builder = @This();
14956const builtin = @import("builtin");
14957const DW = std.dwarf;
14958const ir = @import("ir.zig");
14959const log = std.log.scoped(.llvm);
14960const std = @import("std");
src/codegen/llvm/bindings.zig+10-1455
...@@ -15,7 +15,14 @@ pub const Bool = enum(c_int) {...@@ -15,7 +15,14 @@ pub const Bool = enum(c_int) {
15 return b != .False;15 return b != .False;
16 }16 }
17};17};
18pub const AttributeIndex = c_uint;18
19pub const MemoryBuffer = opaque {
20 pub const createMemoryBufferWithMemoryRange = LLVMCreateMemoryBufferWithMemoryRange;
21 pub const dispose = LLVMDisposeMemoryBuffer;
22
23 extern fn LLVMCreateMemoryBufferWithMemoryRange(InputData: [*]const u8, InputDataLength: usize, BufferName: ?[*:0]const u8, RequiresNullTerminator: Bool) *MemoryBuffer;
24 extern fn LLVMDisposeMemoryBuffer(MemBuf: *MemoryBuffer) void;
25};
1926
20/// Make sure to use the *InContext functions instead of the global ones.27/// Make sure to use the *InContext functions instead of the global ones.
21pub const Context = opaque {28pub const Context = opaque {
...@@ -25,382 +32,17 @@ pub const Context = opaque {...@@ -25,382 +32,17 @@ pub const Context = opaque {
25 pub const dispose = LLVMContextDispose;32 pub const dispose = LLVMContextDispose;
26 extern fn LLVMContextDispose(C: *Context) void;33 extern fn LLVMContextDispose(C: *Context) void;
2734
28 pub const createEnumAttribute = LLVMCreateEnumAttribute;35 pub const parseBitcodeInContext2 = LLVMParseBitcodeInContext2;
29 extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) *Attribute;36 extern fn LLVMParseBitcodeInContext2(C: *Context, MemBuf: *MemoryBuffer, OutModule: **Module) Bool;
30
31 pub const createTypeAttribute = LLVMCreateTypeAttribute;
32 extern fn LLVMCreateTypeAttribute(C: *Context, KindID: c_uint, Type: *Type) *Attribute;
33
34 pub const createStringAttribute = LLVMCreateStringAttribute;
35 extern fn LLVMCreateStringAttribute(C: *Context, Key: [*]const u8, Key_Len: c_uint, Value: [*]const u8, Value_Len: c_uint) *Attribute;
36
37 pub const pointerType = LLVMPointerTypeInContext;
38 extern fn LLVMPointerTypeInContext(C: *Context, AddressSpace: c_uint) *Type;
39
40 pub const intType = LLVMIntTypeInContext;
41 extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) *Type;
42
43 pub const halfType = LLVMHalfTypeInContext;
44 extern fn LLVMHalfTypeInContext(C: *Context) *Type;
45
46 pub const bfloatType = LLVMBFloatTypeInContext;
47 extern fn LLVMBFloatTypeInContext(C: *Context) *Type;
48
49 pub const floatType = LLVMFloatTypeInContext;
50 extern fn LLVMFloatTypeInContext(C: *Context) *Type;
51
52 pub const doubleType = LLVMDoubleTypeInContext;
53 extern fn LLVMDoubleTypeInContext(C: *Context) *Type;
54
55 pub const fp128Type = LLVMFP128TypeInContext;
56 extern fn LLVMFP128TypeInContext(C: *Context) *Type;
57
58 pub const x86_fp80Type = LLVMX86FP80TypeInContext;
59 extern fn LLVMX86FP80TypeInContext(C: *Context) *Type;
60
61 pub const ppc_fp128Type = LLVMPPCFP128TypeInContext;
62 extern fn LLVMPPCFP128TypeInContext(C: *Context) *Type;
63
64 pub const x86_amxType = LLVMX86AMXTypeInContext;
65 extern fn LLVMX86AMXTypeInContext(C: *Context) *Type;
66
67 pub const x86_mmxType = LLVMX86MMXTypeInContext;
68 extern fn LLVMX86MMXTypeInContext(C: *Context) *Type;
69
70 pub const voidType = LLVMVoidTypeInContext;
71 extern fn LLVMVoidTypeInContext(C: *Context) *Type;
72
73 pub const labelType = LLVMLabelTypeInContext;
74 extern fn LLVMLabelTypeInContext(C: *Context) *Type;
75
76 pub const tokenType = LLVMTokenTypeInContext;
77 extern fn LLVMTokenTypeInContext(C: *Context) *Type;
78
79 pub const metadataType = LLVMMetadataTypeInContext;
80 extern fn LLVMMetadataTypeInContext(C: *Context) *Type;
81
82 pub const structType = LLVMStructTypeInContext;
83 extern fn LLVMStructTypeInContext(
84 C: *Context,
85 ElementTypes: [*]const *Type,
86 ElementCount: c_uint,
87 Packed: Bool,
88 ) *Type;
89
90 pub const structCreateNamed = LLVMStructCreateNamed;
91 extern fn LLVMStructCreateNamed(C: *Context, Name: [*:0]const u8) *Type;
92
93 pub const constString = LLVMConstStringInContext;
94 extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) *Value;
95
96 pub const appendBasicBlock = LLVMAppendBasicBlockInContext;
97 extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*:0]const u8) *BasicBlock;
98
99 pub const createBuilder = LLVMCreateBuilderInContext;
100 extern fn LLVMCreateBuilderInContext(C: *Context) *Builder;
10137
102 pub const setOptBisectLimit = ZigLLVMSetOptBisectLimit;38 pub const setOptBisectLimit = ZigLLVMSetOptBisectLimit;
103 extern fn ZigLLVMSetOptBisectLimit(C: *Context, limit: c_int) void;39 extern fn ZigLLVMSetOptBisectLimit(C: *Context, limit: c_int) void;
104};40};
10541
106pub const Value = opaque {
107 pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
108 extern fn LLVMAddAttributeAtIndex(F: *Value, Idx: AttributeIndex, A: *Attribute) void;
109
110 pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;
111 extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void;
112
113 pub const removeStringAttributeAtIndex = LLVMRemoveStringAttributeAtIndex;
114 extern fn LLVMRemoveStringAttributeAtIndex(F: *Value, Idx: AttributeIndex, K: [*]const u8, KLen: c_uint) void;
115
116 pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;
117 extern fn LLVMGetFirstBasicBlock(Fn: *Value) ?*BasicBlock;
118
119 pub const addIncoming = LLVMAddIncoming;
120 extern fn LLVMAddIncoming(
121 PhiNode: *Value,
122 IncomingValues: [*]const *Value,
123 IncomingBlocks: [*]const *BasicBlock,
124 Count: c_uint,
125 ) void;
126
127 pub const setGlobalConstant = LLVMSetGlobalConstant;
128 extern fn LLVMSetGlobalConstant(GlobalVar: *Value, IsConstant: Bool) void;
129
130 pub const setLinkage = LLVMSetLinkage;
131 extern fn LLVMSetLinkage(Global: *Value, Linkage: Linkage) void;
132
133 pub const setVisibility = LLVMSetVisibility;
134 extern fn LLVMSetVisibility(Global: *Value, Linkage: Visibility) void;
135
136 pub const setUnnamedAddr = LLVMSetUnnamedAddr;
137 extern fn LLVMSetUnnamedAddr(Global: *Value, HasUnnamedAddr: Bool) void;
138
139 pub const setThreadLocalMode = LLVMSetThreadLocalMode;
140 extern fn LLVMSetThreadLocalMode(Global: *Value, Mode: ThreadLocalMode) void;
141
142 pub const setSection = LLVMSetSection;
143 extern fn LLVMSetSection(Global: *Value, Section: [*:0]const u8) void;
144
145 pub const removeGlobalValue = ZigLLVMRemoveGlobalValue;
146 extern fn ZigLLVMRemoveGlobalValue(GlobalVal: *Value) void;
147
148 pub const eraseGlobalValue = ZigLLVMEraseGlobalValue;
149 extern fn ZigLLVMEraseGlobalValue(GlobalVal: *Value) void;
150
151 pub const deleteGlobalValue = ZigLLVMDeleteGlobalValue;
152 extern fn ZigLLVMDeleteGlobalValue(GlobalVal: *Value) void;
153
154 pub const setAliasee = LLVMAliasSetAliasee;
155 extern fn LLVMAliasSetAliasee(Alias: *Value, Aliasee: *Value) void;
156
157 pub const constAdd = LLVMConstAdd;
158 extern fn LLVMConstAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
159
160 pub const constNSWAdd = LLVMConstNSWAdd;
161 extern fn LLVMConstNSWAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
162
163 pub const constNUWAdd = LLVMConstNUWAdd;
164 extern fn LLVMConstNUWAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
165
166 pub const constSub = LLVMConstSub;
167 extern fn LLVMConstSub(LHSConstant: *Value, RHSConstant: *Value) *Value;
168
169 pub const constNSWSub = LLVMConstNSWSub;
170 extern fn LLVMConstNSWSub(LHSConstant: *Value, RHSConstant: *Value) *Value;
171
172 pub const constNUWSub = LLVMConstNUWSub;
173 extern fn LLVMConstNUWSub(LHSConstant: *Value, RHSConstant: *Value) *Value;
174
175 pub const constMul = LLVMConstMul;
176 extern fn LLVMConstMul(LHSConstant: *Value, RHSConstant: *Value) *Value;
177
178 pub const constNSWMul = LLVMConstNSWMul;
179 extern fn LLVMConstNSWMul(LHSConstant: *Value, RHSConstant: *Value) *Value;
180
181 pub const constNUWMul = LLVMConstNUWMul;
182 extern fn LLVMConstNUWMul(LHSConstant: *Value, RHSConstant: *Value) *Value;
183
184 pub const constAnd = LLVMConstAnd;
185 extern fn LLVMConstAnd(LHSConstant: *Value, RHSConstant: *Value) *Value;
186
187 pub const constOr = LLVMConstOr;
188 extern fn LLVMConstOr(LHSConstant: *Value, RHSConstant: *Value) *Value;
189
190 pub const constXor = LLVMConstXor;
191 extern fn LLVMConstXor(LHSConstant: *Value, RHSConstant: *Value) *Value;
192
193 pub const constShl = LLVMConstShl;
194 extern fn LLVMConstShl(LHSConstant: *Value, RHSConstant: *Value) *Value;
195
196 pub const constLShr = LLVMConstLShr;
197 extern fn LLVMConstLShr(LHSConstant: *Value, RHSConstant: *Value) *Value;
198
199 pub const constAShr = LLVMConstAShr;
200 extern fn LLVMConstAShr(LHSConstant: *Value, RHSConstant: *Value) *Value;
201
202 pub const constTrunc = LLVMConstTrunc;
203 extern fn LLVMConstTrunc(ConstantVal: *Value, ToType: *Type) *Value;
204
205 pub const constSExt = LLVMConstSExt;
206 extern fn LLVMConstSExt(ConstantVal: *Value, ToType: *Type) *Value;
207
208 pub const constZExt = LLVMConstZExt;
209 extern fn LLVMConstZExt(ConstantVal: *Value, ToType: *Type) *Value;
210
211 pub const constFPTrunc = LLVMConstFPTrunc;
212 extern fn LLVMConstFPTrunc(ConstantVal: *Value, ToType: *Type) *Value;
213
214 pub const constFPExt = LLVMConstFPExt;
215 extern fn LLVMConstFPExt(ConstantVal: *Value, ToType: *Type) *Value;
216
217 pub const constUIToFP = LLVMConstUIToFP;
218 extern fn LLVMConstUIToFP(ConstantVal: *Value, ToType: *Type) *Value;
219
220 pub const constSIToFP = LLVMConstSIToFP;
221 extern fn LLVMConstSIToFP(ConstantVal: *Value, ToType: *Type) *Value;
222
223 pub const constFPToUI = LLVMConstFPToUI;
224 extern fn LLVMConstFPToUI(ConstantVal: *Value, ToType: *Type) *Value;
225
226 pub const constFPToSI = LLVMConstFPToSI;
227 extern fn LLVMConstFPToSI(ConstantVal: *Value, ToType: *Type) *Value;
228
229 pub const constPtrToInt = LLVMConstPtrToInt;
230 extern fn LLVMConstPtrToInt(ConstantVal: *Value, ToType: *Type) *Value;
231
232 pub const constIntToPtr = LLVMConstIntToPtr;
233 extern fn LLVMConstIntToPtr(ConstantVal: *Value, ToType: *Type) *Value;
234
235 pub const constBitCast = LLVMConstBitCast;
236 extern fn LLVMConstBitCast(ConstantVal: *Value, ToType: *Type) *Value;
237
238 pub const constAddrSpaceCast = LLVMConstAddrSpaceCast;
239 extern fn LLVMConstAddrSpaceCast(ConstantVal: *Value, ToType: *Type) *Value;
240
241 pub const constExtractElement = LLVMConstExtractElement;
242 extern fn LLVMConstExtractElement(VectorConstant: *Value, IndexConstant: *Value) *Value;
243
244 pub const constInsertElement = LLVMConstInsertElement;
245 extern fn LLVMConstInsertElement(
246 VectorConstant: *Value,
247 ElementValueConstant: *Value,
248 IndexConstant: *Value,
249 ) *Value;
250
251 pub const constShuffleVector = LLVMConstShuffleVector;
252 extern fn LLVMConstShuffleVector(
253 VectorAConstant: *Value,
254 VectorBConstant: *Value,
255 MaskConstant: *Value,
256 ) *Value;
257
258 pub const isConstant = LLVMIsConstant;
259 extern fn LLVMIsConstant(Val: *Value) Bool;
260
261 pub const blockAddress = LLVMBlockAddress;
262 extern fn LLVMBlockAddress(F: *Value, BB: *BasicBlock) *Value;
263
264 pub const setWeak = LLVMSetWeak;
265 extern fn LLVMSetWeak(CmpXchgInst: *Value, IsWeak: Bool) void;
266
267 pub const setOrdering = LLVMSetOrdering;
268 extern fn LLVMSetOrdering(MemoryAccessInst: *Value, Ordering: AtomicOrdering) void;
269
270 pub const setVolatile = LLVMSetVolatile;
271 extern fn LLVMSetVolatile(MemoryAccessInst: *Value, IsVolatile: Bool) void;
272
273 pub const setAlignment = LLVMSetAlignment;
274 extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void;
275
276 pub const getAlignment = LLVMGetAlignment;
277 extern fn LLVMGetAlignment(V: *Value) c_uint;
278
279 pub const setFunctionCallConv = LLVMSetFunctionCallConv;
280 extern fn LLVMSetFunctionCallConv(Fn: *Value, CC: CallConv) void;
281
282 pub const setInstructionCallConv = LLVMSetInstructionCallConv;
283 extern fn LLVMSetInstructionCallConv(Instr: *Value, CC: CallConv) void;
284
285 pub const setTailCallKind = ZigLLVMSetTailCallKind;
286 extern fn ZigLLVMSetTailCallKind(CallInst: *Value, TailCallKind: TailCallKind) void;
287
288 pub const addCallSiteAttribute = LLVMAddCallSiteAttribute;
289 extern fn LLVMAddCallSiteAttribute(C: *Value, Idx: AttributeIndex, A: *Attribute) void;
290
291 pub const fnSetSubprogram = ZigLLVMFnSetSubprogram;
292 extern fn ZigLLVMFnSetSubprogram(f: *Value, subprogram: *DISubprogram) void;
293
294 pub const setValueName = LLVMSetValueName2;
295 extern fn LLVMSetValueName2(Val: *Value, Name: [*]const u8, NameLen: usize) void;
296
297 pub const takeName = ZigLLVMTakeName;
298 extern fn ZigLLVMTakeName(new_owner: *Value, victim: *Value) void;
299
300 pub const getParam = LLVMGetParam;
301 extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
302
303 pub const setInitializer = ZigLLVMSetInitializer;
304 extern fn ZigLLVMSetInitializer(GlobalVar: *Value, ConstantVal: ?*Value) void;
305
306 pub const setDLLStorageClass = LLVMSetDLLStorageClass;
307 extern fn LLVMSetDLLStorageClass(Global: *Value, Class: DLLStorageClass) void;
308
309 pub const addCase = LLVMAddCase;
310 extern fn LLVMAddCase(Switch: *Value, OnVal: *Value, Dest: *BasicBlock) void;
311
312 pub const replaceAllUsesWith = LLVMReplaceAllUsesWith;
313 extern fn LLVMReplaceAllUsesWith(OldVal: *Value, NewVal: *Value) void;
314
315 pub const attachMetaData = ZigLLVMAttachMetaData;
316 extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;
317
318 pub const dump = LLVMDumpValue;
319 extern fn LLVMDumpValue(Val: *Value) void;
320};
321
322pub const Type = opaque {
323 pub const constNull = LLVMConstNull;
324 extern fn LLVMConstNull(Ty: *Type) *Value;
325
326 pub const constInt = LLVMConstInt;
327 extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) *Value;
328
329 pub const constIntOfArbitraryPrecision = LLVMConstIntOfArbitraryPrecision;
330 extern fn LLVMConstIntOfArbitraryPrecision(IntTy: *Type, NumWords: c_uint, Words: [*]const u64) *Value;
331
332 pub const constReal = LLVMConstReal;
333 extern fn LLVMConstReal(RealTy: *Type, N: f64) *Value;
334
335 pub const constArray2 = LLVMConstArray2;
336 extern fn LLVMConstArray2(ElementTy: *Type, ConstantVals: [*]const *Value, Length: u64) *Value;
337
338 pub const constNamedStruct = LLVMConstNamedStruct;
339 extern fn LLVMConstNamedStruct(
340 StructTy: *Type,
341 ConstantVals: [*]const *Value,
342 Count: c_uint,
343 ) *Value;
344
345 pub const getUndef = LLVMGetUndef;
346 extern fn LLVMGetUndef(Ty: *Type) *Value;
347
348 pub const getPoison = LLVMGetPoison;
349 extern fn LLVMGetPoison(Ty: *Type) *Value;
350
351 pub const arrayType2 = LLVMArrayType2;
352 extern fn LLVMArrayType2(ElementType: *Type, ElementCount: u64) *Type;
353
354 pub const vectorType = LLVMVectorType;
355 extern fn LLVMVectorType(ElementType: *Type, ElementCount: c_uint) *Type;
356
357 pub const scalableVectorType = LLVMScalableVectorType;
358 extern fn LLVMScalableVectorType(ElementType: *Type, ElementCount: c_uint) *Type;
359
360 pub const structSetBody = LLVMStructSetBody;
361 extern fn LLVMStructSetBody(
362 StructTy: *Type,
363 ElementTypes: [*]*Type,
364 ElementCount: c_uint,
365 Packed: Bool,
366 ) void;
367
368 pub const isSized = LLVMTypeIsSized;
369 extern fn LLVMTypeIsSized(Ty: *Type) Bool;
370
371 pub const constGEP = LLVMConstGEP2;
372 extern fn LLVMConstGEP2(
373 Ty: *Type,
374 ConstantVal: *Value,
375 ConstantIndices: [*]const *Value,
376 NumIndices: c_uint,
377 ) *Value;
378
379 pub const constInBoundsGEP = LLVMConstInBoundsGEP2;
380 extern fn LLVMConstInBoundsGEP2(
381 Ty: *Type,
382 ConstantVal: *Value,
383 ConstantIndices: [*]const *Value,
384 NumIndices: c_uint,
385 ) *Value;
386
387 pub const dump = LLVMDumpType;
388 extern fn LLVMDumpType(Ty: *Type) void;
389};
390
391pub const Module = opaque {42pub const Module = opaque {
392 pub const createWithName = LLVMModuleCreateWithNameInContext;
393 extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*:0]const u8, C: *Context) *Module;
394
395 pub const dispose = LLVMDisposeModule;43 pub const dispose = LLVMDisposeModule;
396 extern fn LLVMDisposeModule(*Module) void;44 extern fn LLVMDisposeModule(*Module) void;
39745
398 pub const verify = LLVMVerifyModule;
399 extern fn LLVMVerifyModule(*Module, Action: VerifierFailureAction, OutMessage: *[*:0]const u8) Bool;
400
401 pub const setModuleDataLayout = LLVMSetModuleDataLayout;
402 extern fn LLVMSetModuleDataLayout(*Module, *TargetData) void;
403
404 pub const setModulePICLevel = ZigLLVMSetModulePICLevel;46 pub const setModulePICLevel = ZigLLVMSetModulePICLevel;
405 extern fn ZigLLVMSetModulePICLevel(module: *Module) void;47 extern fn ZigLLVMSetModulePICLevel(module: *Module) void;
40648
...@@ -409,508 +51,11 @@ pub const Module = opaque {...@@ -409,508 +51,11 @@ pub const Module = opaque {
40951
410 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;52 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;
411 extern fn ZigLLVMSetModuleCodeModel(module: *Module, code_model: CodeModel) void;53 extern fn ZigLLVMSetModuleCodeModel(module: *Module, code_model: CodeModel) void;
412
413 pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace;
414 extern fn ZigLLVMAddFunctionInAddressSpace(*Module, Name: [*:0]const u8, FunctionTy: *Type, AddressSpace: c_uint) *Value;
415
416 pub const printToString = LLVMPrintModuleToString;
417 extern fn LLVMPrintModuleToString(*Module) [*:0]const u8;
418
419 pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace;
420 extern fn LLVMAddGlobalInAddressSpace(M: *Module, Ty: *Type, Name: [*:0]const u8, AddressSpace: c_uint) *Value;
421
422 pub const dump = LLVMDumpModule;
423 extern fn LLVMDumpModule(M: *Module) void;
424
425 pub const addAlias = LLVMAddAlias2;
426 extern fn LLVMAddAlias2(
427 M: *Module,
428 Ty: *Type,
429 AddrSpace: c_uint,
430 Aliasee: *Value,
431 Name: [*:0]const u8,
432 ) *Value;
433
434 pub const setTarget = LLVMSetTarget;
435 extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void;
436
437 pub const addModuleDebugInfoFlag = ZigLLVMAddModuleDebugInfoFlag;
438 extern fn ZigLLVMAddModuleDebugInfoFlag(module: *Module, dwarf64: bool) void;
439
440 pub const addModuleCodeViewFlag = ZigLLVMAddModuleCodeViewFlag;
441 extern fn ZigLLVMAddModuleCodeViewFlag(module: *Module) void;
442
443 pub const createDIBuilder = ZigLLVMCreateDIBuilder;
444 extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) *DIBuilder;
445
446 pub const setModuleInlineAsm = LLVMSetModuleInlineAsm2;
447 extern fn LLVMSetModuleInlineAsm2(M: *Module, Asm: [*]const u8, Len: usize) void;
448
449 pub const printModuleToFile = LLVMPrintModuleToFile;
450 extern fn LLVMPrintModuleToFile(M: *Module, Filename: [*:0]const u8, ErrorMessage: *[*:0]const u8) Bool;
451
452 pub const writeBitcodeToFile = LLVMWriteBitcodeToFile;
453 extern fn LLVMWriteBitcodeToFile(M: *Module, Path: [*:0]const u8) c_int;
454};54};
45555
456pub const disposeMessage = LLVMDisposeMessage;56pub const disposeMessage = LLVMDisposeMessage;
457extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;57extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;
45858
459pub const VerifierFailureAction = enum(c_int) {
460 AbortProcess,
461 PrintMessage,
462 ReturnStatus,
463};
464
465pub const constVector = LLVMConstVector;
466extern fn LLVMConstVector(
467 ScalarConstantVals: [*]*Value,
468 Size: c_uint,
469) *Value;
470
471pub const constICmp = LLVMConstICmp;
472extern fn LLVMConstICmp(Predicate: IntPredicate, LHSConstant: *Value, RHSConstant: *Value) *Value;
473
474pub const constFCmp = LLVMConstFCmp;
475extern fn LLVMConstFCmp(Predicate: RealPredicate, LHSConstant: *Value, RHSConstant: *Value) *Value;
476
477pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName;
478extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint;
479
480pub const getInlineAsm = LLVMGetInlineAsm;
481extern fn LLVMGetInlineAsm(
482 Ty: *Type,
483 AsmString: [*]const u8,
484 AsmStringSize: usize,
485 Constraints: [*]const u8,
486 ConstraintsSize: usize,
487 HasSideEffects: Bool,
488 IsAlignStack: Bool,
489 Dialect: InlineAsmDialect,
490 CanThrow: Bool,
491) *Value;
492
493pub const functionType = LLVMFunctionType;
494extern fn LLVMFunctionType(
495 ReturnType: *Type,
496 ParamTypes: [*]const *Type,
497 ParamCount: c_uint,
498 IsVarArg: Bool,
499) *Type;
500
501pub const InlineAsmDialect = enum(c_uint) { ATT, Intel };
502
503pub const Attribute = opaque {};
504
505pub const Builder = opaque {
506 pub const dispose = LLVMDisposeBuilder;
507 extern fn LLVMDisposeBuilder(Builder: *Builder) void;
508
509 pub const positionBuilder = LLVMPositionBuilder;
510 extern fn LLVMPositionBuilder(
511 Builder: *Builder,
512 Block: *BasicBlock,
513 Instr: ?*Value,
514 ) void;
515
516 pub const buildZExt = LLVMBuildZExt;
517 extern fn LLVMBuildZExt(
518 *Builder,
519 Value: *Value,
520 DestTy: *Type,
521 Name: [*:0]const u8,
522 ) *Value;
523
524 pub const buildSExt = LLVMBuildSExt;
525 extern fn LLVMBuildSExt(
526 *Builder,
527 Val: *Value,
528 DestTy: *Type,
529 Name: [*:0]const u8,
530 ) *Value;
531
532 pub const buildCall = LLVMBuildCall2;
533 extern fn LLVMBuildCall2(
534 *Builder,
535 *Type,
536 Fn: *Value,
537 Args: [*]const *Value,
538 NumArgs: c_uint,
539 Name: [*:0]const u8,
540 ) *Value;
541
542 pub const buildRetVoid = LLVMBuildRetVoid;
543 extern fn LLVMBuildRetVoid(*Builder) *Value;
544
545 pub const buildRet = LLVMBuildRet;
546 extern fn LLVMBuildRet(*Builder, V: *Value) *Value;
547
548 pub const buildUnreachable = LLVMBuildUnreachable;
549 extern fn LLVMBuildUnreachable(*Builder) *Value;
550
551 pub const buildAlloca = LLVMBuildAlloca;
552 extern fn LLVMBuildAlloca(*Builder, Ty: *Type, Name: [*:0]const u8) *Value;
553
554 pub const buildStore = LLVMBuildStore;
555 extern fn LLVMBuildStore(*Builder, Val: *Value, Ptr: *Value) *Value;
556
557 pub const buildLoad = LLVMBuildLoad2;
558 extern fn LLVMBuildLoad2(*Builder, Ty: *Type, PointerVal: *Value, Name: [*:0]const u8) *Value;
559
560 pub const buildFAdd = LLVMBuildFAdd;
561 extern fn LLVMBuildFAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
562
563 pub const buildAdd = LLVMBuildAdd;
564 extern fn LLVMBuildAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
565
566 pub const buildNSWAdd = LLVMBuildNSWAdd;
567 extern fn LLVMBuildNSWAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
568
569 pub const buildNUWAdd = LLVMBuildNUWAdd;
570 extern fn LLVMBuildNUWAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
571
572 pub const buildFSub = LLVMBuildFSub;
573 extern fn LLVMBuildFSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
574
575 pub const buildFNeg = LLVMBuildFNeg;
576 extern fn LLVMBuildFNeg(*Builder, V: *Value, Name: [*:0]const u8) *Value;
577
578 pub const buildSub = LLVMBuildSub;
579 extern fn LLVMBuildSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
580
581 pub const buildNSWSub = LLVMBuildNSWSub;
582 extern fn LLVMBuildNSWSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
583
584 pub const buildNUWSub = LLVMBuildNUWSub;
585 extern fn LLVMBuildNUWSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
586
587 pub const buildFMul = LLVMBuildFMul;
588 extern fn LLVMBuildFMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
589
590 pub const buildMul = LLVMBuildMul;
591 extern fn LLVMBuildMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
592
593 pub const buildNSWMul = LLVMBuildNSWMul;
594 extern fn LLVMBuildNSWMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
595
596 pub const buildNUWMul = LLVMBuildNUWMul;
597 extern fn LLVMBuildNUWMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
598
599 pub const buildUDiv = LLVMBuildUDiv;
600 extern fn LLVMBuildUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
601
602 pub const buildSDiv = LLVMBuildSDiv;
603 extern fn LLVMBuildSDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
604
605 pub const buildFDiv = LLVMBuildFDiv;
606 extern fn LLVMBuildFDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
607
608 pub const buildURem = LLVMBuildURem;
609 extern fn LLVMBuildURem(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
610
611 pub const buildSRem = LLVMBuildSRem;
612 extern fn LLVMBuildSRem(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
613
614 pub const buildFRem = LLVMBuildFRem;
615 extern fn LLVMBuildFRem(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
616
617 pub const buildAnd = LLVMBuildAnd;
618 extern fn LLVMBuildAnd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
619
620 pub const buildLShr = LLVMBuildLShr;
621 extern fn LLVMBuildLShr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
622
623 pub const buildAShr = LLVMBuildAShr;
624 extern fn LLVMBuildAShr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
625
626 pub const buildLShrExact = ZigLLVMBuildLShrExact;
627 extern fn ZigLLVMBuildLShrExact(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
628
629 pub const buildAShrExact = ZigLLVMBuildAShrExact;
630 extern fn ZigLLVMBuildAShrExact(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
631
632 pub const buildShl = LLVMBuildShl;
633 extern fn LLVMBuildShl(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
634
635 pub const buildNUWShl = ZigLLVMBuildNUWShl;
636 extern fn ZigLLVMBuildNUWShl(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
637
638 pub const buildNSWShl = ZigLLVMBuildNSWShl;
639 extern fn ZigLLVMBuildNSWShl(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
640
641 pub const buildOr = LLVMBuildOr;
642 extern fn LLVMBuildOr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
643
644 pub const buildXor = LLVMBuildXor;
645 extern fn LLVMBuildXor(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
646
647 pub const buildBitCast = LLVMBuildBitCast;
648 extern fn LLVMBuildBitCast(*Builder, Val: *Value, DestTy: *Type, Name: [*:0]const u8) *Value;
649
650 pub const buildGEP = LLVMBuildGEP2;
651 extern fn LLVMBuildGEP2(
652 B: *Builder,
653 Ty: *Type,
654 Pointer: *Value,
655 Indices: [*]const *Value,
656 NumIndices: c_uint,
657 Name: [*:0]const u8,
658 ) *Value;
659
660 pub const buildInBoundsGEP = LLVMBuildInBoundsGEP2;
661 extern fn LLVMBuildInBoundsGEP2(
662 B: *Builder,
663 Ty: *Type,
664 Pointer: *Value,
665 Indices: [*]const *Value,
666 NumIndices: c_uint,
667 Name: [*:0]const u8,
668 ) *Value;
669
670 pub const buildICmp = LLVMBuildICmp;
671 extern fn LLVMBuildICmp(*Builder, Op: IntPredicate, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
672
673 pub const buildFCmp = LLVMBuildFCmp;
674 extern fn LLVMBuildFCmp(*Builder, Op: RealPredicate, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
675
676 pub const buildBr = LLVMBuildBr;
677 extern fn LLVMBuildBr(*Builder, Dest: *BasicBlock) *Value;
678
679 pub const buildCondBr = LLVMBuildCondBr;
680 extern fn LLVMBuildCondBr(*Builder, If: *Value, Then: *BasicBlock, Else: *BasicBlock) *Value;
681
682 pub const buildSwitch = LLVMBuildSwitch;
683 extern fn LLVMBuildSwitch(*Builder, V: *Value, Else: *BasicBlock, NumCases: c_uint) *Value;
684
685 pub const buildPhi = LLVMBuildPhi;
686 extern fn LLVMBuildPhi(*Builder, Ty: *Type, Name: [*:0]const u8) *Value;
687
688 pub const buildExtractValue = LLVMBuildExtractValue;
689 extern fn LLVMBuildExtractValue(
690 *Builder,
691 AggVal: *Value,
692 Index: c_uint,
693 Name: [*:0]const u8,
694 ) *Value;
695
696 pub const buildExtractElement = LLVMBuildExtractElement;
697 extern fn LLVMBuildExtractElement(
698 *Builder,
699 VecVal: *Value,
700 Index: *Value,
701 Name: [*:0]const u8,
702 ) *Value;
703
704 pub const buildInsertElement = LLVMBuildInsertElement;
705 extern fn LLVMBuildInsertElement(
706 *Builder,
707 VecVal: *Value,
708 EltVal: *Value,
709 Index: *Value,
710 Name: [*:0]const u8,
711 ) *Value;
712
713 pub const buildPtrToInt = LLVMBuildPtrToInt;
714 extern fn LLVMBuildPtrToInt(
715 *Builder,
716 Val: *Value,
717 DestTy: *Type,
718 Name: [*:0]const u8,
719 ) *Value;
720
721 pub const buildIntToPtr = LLVMBuildIntToPtr;
722 extern fn LLVMBuildIntToPtr(
723 *Builder,
724 Val: *Value,
725 DestTy: *Type,
726 Name: [*:0]const u8,
727 ) *Value;
728
729 pub const buildTrunc = LLVMBuildTrunc;
730 extern fn LLVMBuildTrunc(
731 *Builder,
732 Val: *Value,
733 DestTy: *Type,
734 Name: [*:0]const u8,
735 ) *Value;
736
737 pub const buildInsertValue = LLVMBuildInsertValue;
738 extern fn LLVMBuildInsertValue(
739 *Builder,
740 AggVal: *Value,
741 EltVal: *Value,
742 Index: c_uint,
743 Name: [*:0]const u8,
744 ) *Value;
745
746 pub const buildAtomicCmpXchg = LLVMBuildAtomicCmpXchg;
747 extern fn LLVMBuildAtomicCmpXchg(
748 builder: *Builder,
749 ptr: *Value,
750 cmp: *Value,
751 new_val: *Value,
752 success_ordering: AtomicOrdering,
753 failure_ordering: AtomicOrdering,
754 is_single_threaded: Bool,
755 ) *Value;
756
757 pub const buildSelect = LLVMBuildSelect;
758 extern fn LLVMBuildSelect(
759 *Builder,
760 If: *Value,
761 Then: *Value,
762 Else: *Value,
763 Name: [*:0]const u8,
764 ) *Value;
765
766 pub const buildFence = LLVMBuildFence;
767 extern fn LLVMBuildFence(
768 B: *Builder,
769 ordering: AtomicOrdering,
770 singleThread: Bool,
771 Name: [*:0]const u8,
772 ) *Value;
773
774 pub const buildAtomicRmw = LLVMBuildAtomicRMW;
775 extern fn LLVMBuildAtomicRMW(
776 B: *Builder,
777 op: AtomicRMWBinOp,
778 PTR: *Value,
779 Val: *Value,
780 ordering: AtomicOrdering,
781 singleThread: Bool,
782 ) *Value;
783
784 pub const buildFPToUI = LLVMBuildFPToUI;
785 extern fn LLVMBuildFPToUI(
786 *Builder,
787 Val: *Value,
788 DestTy: *Type,
789 Name: [*:0]const u8,
790 ) *Value;
791
792 pub const buildFPToSI = LLVMBuildFPToSI;
793 extern fn LLVMBuildFPToSI(
794 *Builder,
795 Val: *Value,
796 DestTy: *Type,
797 Name: [*:0]const u8,
798 ) *Value;
799
800 pub const buildUIToFP = LLVMBuildUIToFP;
801 extern fn LLVMBuildUIToFP(
802 *Builder,
803 Val: *Value,
804 DestTy: *Type,
805 Name: [*:0]const u8,
806 ) *Value;
807
808 pub const buildSIToFP = LLVMBuildSIToFP;
809 extern fn LLVMBuildSIToFP(
810 *Builder,
811 Val: *Value,
812 DestTy: *Type,
813 Name: [*:0]const u8,
814 ) *Value;
815
816 pub const buildFPTrunc = LLVMBuildFPTrunc;
817 extern fn LLVMBuildFPTrunc(
818 *Builder,
819 Val: *Value,
820 DestTy: *Type,
821 Name: [*:0]const u8,
822 ) *Value;
823
824 pub const buildFPExt = LLVMBuildFPExt;
825 extern fn LLVMBuildFPExt(
826 *Builder,
827 Val: *Value,
828 DestTy: *Type,
829 Name: [*:0]const u8,
830 ) *Value;
831
832 pub const buildExactUDiv = LLVMBuildExactUDiv;
833 extern fn LLVMBuildExactUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
834
835 pub const buildExactSDiv = LLVMBuildExactSDiv;
836 extern fn LLVMBuildExactSDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
837
838 pub const setCurrentDebugLocation = ZigLLVMSetCurrentDebugLocation2;
839 extern fn ZigLLVMSetCurrentDebugLocation2(builder: *Builder, line: c_uint, column: c_uint, scope: *DIScope, inlined_at: ?*DILocation) void;
840
841 pub const clearCurrentDebugLocation = ZigLLVMClearCurrentDebugLocation;
842 extern fn ZigLLVMClearCurrentDebugLocation(builder: *Builder) void;
843
844 pub const getCurrentDebugLocation2 = LLVMGetCurrentDebugLocation2;
845 extern fn LLVMGetCurrentDebugLocation2(Builder: *Builder) *Metadata;
846
847 pub const setCurrentDebugLocation2 = LLVMSetCurrentDebugLocation2;
848 extern fn LLVMSetCurrentDebugLocation2(Builder: *Builder, Loc: *Metadata) void;
849
850 pub const buildShuffleVector = LLVMBuildShuffleVector;
851 extern fn LLVMBuildShuffleVector(*Builder, V1: *Value, V2: *Value, Mask: *Value, Name: [*:0]const u8) *Value;
852
853 pub const setFastMath = ZigLLVMSetFastMath;
854 extern fn ZigLLVMSetFastMath(B: *Builder, on_state: bool) void;
855
856 pub const buildAddrSpaceCast = LLVMBuildAddrSpaceCast;
857 extern fn LLVMBuildAddrSpaceCast(B: *Builder, Val: *Value, DestTy: *Type, Name: [*:0]const u8) *Value;
858
859 pub const buildAllocaInAddressSpace = ZigLLVMBuildAllocaInAddressSpace;
860 extern fn ZigLLVMBuildAllocaInAddressSpace(B: *Builder, Ty: *Type, AddressSpace: c_uint, Name: [*:0]const u8) *Value;
861
862 pub const buildVAArg = LLVMBuildVAArg;
863 extern fn LLVMBuildVAArg(*Builder, List: *Value, Ty: *Type, Name: [*:0]const u8) *Value;
864};
865
866pub const MDString = opaque {
867 pub const get = LLVMMDStringInContext2;
868 extern fn LLVMMDStringInContext2(C: *Context, Str: [*]const u8, SLen: usize) *MDString;
869};
870
871pub const DIScope = opaque {
872 pub const toNode = ZigLLVMScopeToNode;
873 extern fn ZigLLVMScopeToNode(scope: *DIScope) *DINode;
874};
875
876pub const DINode = opaque {};
877pub const Metadata = opaque {};
878
879pub const IntPredicate = enum(c_uint) {
880 EQ = 32,
881 NE = 33,
882 UGT = 34,
883 UGE = 35,
884 ULT = 36,
885 ULE = 37,
886 SGT = 38,
887 SGE = 39,
888 SLT = 40,
889 SLE = 41,
890};
891
892pub const RealPredicate = enum(c_uint) {
893 OEQ = 1,
894 OGT = 2,
895 OGE = 3,
896 OLT = 4,
897 OLE = 5,
898 ONE = 6,
899 ORD = 7,
900 UNO = 8,
901 UEQ = 9,
902 UGT = 10,
903 UGE = 11,
904 ULT = 12,
905 ULE = 13,
906 UNE = 14,
907};
908
909pub const BasicBlock = opaque {
910 pub const deleteBasicBlock = LLVMDeleteBasicBlock;
911 extern fn LLVMDeleteBasicBlock(BB: *BasicBlock) void;
912};
913
914pub const TargetMachine = opaque {59pub const TargetMachine = opaque {
915 pub const create = ZigLLVMCreateTargetMachine;60 pub const create = ZigLLVMCreateTargetMachine;
916 extern fn ZigLLVMCreateTargetMachine(61 extern fn ZigLLVMCreateTargetMachine(
...@@ -945,23 +90,11 @@ pub const TargetMachine = opaque {...@@ -945,23 +90,11 @@ pub const TargetMachine = opaque {
945 llvm_ir_filename: ?[*:0]const u8,90 llvm_ir_filename: ?[*:0]const u8,
946 bitcode_filename: ?[*:0]const u8,91 bitcode_filename: ?[*:0]const u8,
947 ) bool;92 ) bool;
948
949 pub const createTargetDataLayout = LLVMCreateTargetDataLayout;
950 extern fn LLVMCreateTargetDataLayout(*TargetMachine) *TargetData;
951};93};
95294
953pub const TargetData = opaque {95pub const TargetData = opaque {
954 pub const dispose = LLVMDisposeTargetData;96 pub const dispose = LLVMDisposeTargetData;
955 extern fn LLVMDisposeTargetData(*TargetData) void;97 extern fn LLVMDisposeTargetData(*TargetData) void;
956
957 pub const abiAlignmentOfType = LLVMABIAlignmentOfType;
958 extern fn LLVMABIAlignmentOfType(TD: *TargetData, Ty: *Type) c_uint;
959
960 pub const abiSizeOfType = LLVMABISizeOfType;
961 extern fn LLVMABISizeOfType(TD: *TargetData, Ty: *Type) c_ulonglong;
962
963 pub const stringRep = LLVMCopyStringRepOfTargetData;
964 extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) [*:0]const u8;
965};98};
96699
967pub const CodeModel = enum(c_int) {100pub const CodeModel = enum(c_int) {
...@@ -991,11 +124,6 @@ pub const RelocMode = enum(c_int) {...@@ -991,11 +124,6 @@ pub const RelocMode = enum(c_int) {
991 ROPI_RWPI,124 ROPI_RWPI,
992};125};
993126
994pub const CodeGenFileType = enum(c_int) {
995 AssemblyFile,
996 ObjectFile,
997};
998
999pub const ABIType = enum(c_int) {127pub const ABIType = enum(c_int) {
1000 /// Target-specific (either soft or hard depending on triple, etc).128 /// Target-specific (either soft or hard depending on triple, etc).
1001 Default,129 Default,
...@@ -1266,576 +394,3 @@ extern fn ZigLLVMWriteImportLibrary(...@@ -1266,576 +394,3 @@ extern fn ZigLLVMWriteImportLibrary(
1266 output_lib_path: [*:0]const u8,394 output_lib_path: [*:0]const u8,
1267 kill_at: bool,395 kill_at: bool,
1268) bool;396) bool;
1269
1270pub const Linkage = enum(c_uint) {
1271 External,
1272 AvailableExternally,
1273 LinkOnceAny,
1274 LinkOnceODR,
1275 LinkOnceODRAutoHide,
1276 WeakAny,
1277 WeakODR,
1278 Appending,
1279 Internal,
1280 Private,
1281 DLLImport,
1282 DLLExport,
1283 ExternalWeak,
1284 Ghost,
1285 Common,
1286 LinkerPrivate,
1287 LinkerPrivateWeak,
1288};
1289
1290pub const Visibility = enum(c_uint) {
1291 Default,
1292 Hidden,
1293 Protected,
1294};
1295
1296pub const ThreadLocalMode = enum(c_uint) {
1297 NotThreadLocal,
1298 GeneralDynamicTLSModel,
1299 LocalDynamicTLSModel,
1300 InitialExecTLSModel,
1301 LocalExecTLSModel,
1302};
1303
1304pub const AtomicOrdering = enum(c_uint) {
1305 NotAtomic = 0,
1306 Unordered = 1,
1307 Monotonic = 2,
1308 Acquire = 4,
1309 Release = 5,
1310 AcquireRelease = 6,
1311 SequentiallyConsistent = 7,
1312};
1313
1314pub const AtomicRMWBinOp = enum(c_int) {
1315 Xchg,
1316 Add,
1317 Sub,
1318 And,
1319 Nand,
1320 Or,
1321 Xor,
1322 Max,
1323 Min,
1324 UMax,
1325 UMin,
1326 FAdd,
1327 FSub,
1328 FMax,
1329 FMin,
1330};
1331
1332pub const CallConv = enum(c_uint) {
1333 C = 0,
1334 Fast = 8,
1335 Cold = 9,
1336 GHC = 10,
1337 HiPE = 11,
1338 WebKit_JS = 12,
1339 AnyReg = 13,
1340 PreserveMost = 14,
1341 PreserveAll = 15,
1342 Swift = 16,
1343 CXX_FAST_TLS = 17,
1344
1345 X86_StdCall = 64,
1346 X86_FastCall = 65,
1347 ARM_APCS = 66,
1348 ARM_AAPCS = 67,
1349 ARM_AAPCS_VFP = 68,
1350 MSP430_INTR = 69,
1351 X86_ThisCall = 70,
1352 PTX_Kernel = 71,
1353 PTX_Device = 72,
1354 SPIR_FUNC = 75,
1355 SPIR_KERNEL = 76,
1356 Intel_OCL_BI = 77,
1357 X86_64_SysV = 78,
1358 Win64 = 79,
1359 X86_VectorCall = 80,
1360 HHVM = 81,
1361 HHVM_C = 82,
1362 X86_INTR = 83,
1363 AVR_INTR = 84,
1364 AVR_SIGNAL = 85,
1365 AVR_BUILTIN = 86,
1366 AMDGPU_VS = 87,
1367 AMDGPU_GS = 88,
1368 AMDGPU_PS = 89,
1369 AMDGPU_CS = 90,
1370 AMDGPU_KERNEL = 91,
1371 X86_RegCall = 92,
1372 AMDGPU_HS = 93,
1373 MSP430_BUILTIN = 94,
1374 AMDGPU_LS = 95,
1375 AMDGPU_ES = 96,
1376 AArch64_VectorCall = 97,
1377};
1378
1379pub const CallAttr = enum(c_int) {
1380 Auto,
1381 NeverTail,
1382 NeverInline,
1383 AlwaysTail,
1384 AlwaysInline,
1385};
1386
1387pub const TailCallKind = enum(c_uint) {
1388 None,
1389 Tail,
1390 MustTail,
1391 NoTail,
1392};
1393
1394pub const DLLStorageClass = enum(c_uint) {
1395 Default,
1396 DLLImport,
1397 DLLExport,
1398};
1399
1400pub const address_space = struct {
1401 pub const default: c_uint = 0;
1402
1403 // See llvm/lib/Target/X86/X86.h
1404 pub const x86_64 = x86;
1405 pub const x86 = struct {
1406 pub const gs: c_uint = 256;
1407 pub const fs: c_uint = 257;
1408 pub const ss: c_uint = 258;
1409
1410 pub const ptr32_sptr: c_uint = 270;
1411 pub const ptr32_uptr: c_uint = 271;
1412 pub const ptr64: c_uint = 272;
1413 };
1414
1415 // See llvm/lib/Target/AVR/AVR.h
1416 pub const avr = struct {
1417 pub const flash: c_uint = 1;
1418 pub const flash1: c_uint = 2;
1419 pub const flash2: c_uint = 3;
1420 pub const flash3: c_uint = 4;
1421 pub const flash4: c_uint = 5;
1422 pub const flash5: c_uint = 6;
1423 };
1424
1425 // See llvm/lib/Target/NVPTX/NVPTX.h
1426 pub const nvptx = struct {
1427 pub const generic: c_uint = 0;
1428 pub const global: c_uint = 1;
1429 pub const constant: c_uint = 2;
1430 pub const shared: c_uint = 3;
1431 pub const param: c_uint = 4;
1432 pub const local: c_uint = 5;
1433 };
1434
1435 // See llvm/lib/Target/AMDGPU/AMDGPU.h
1436 pub const amdgpu = struct {
1437 pub const flat: c_uint = 0;
1438 pub const global: c_uint = 1;
1439 pub const region: c_uint = 2;
1440 pub const local: c_uint = 3;
1441 pub const constant: c_uint = 4;
1442 pub const private: c_uint = 5;
1443 pub const constant_32bit: c_uint = 6;
1444 pub const buffer_fat_pointer: c_uint = 7;
1445 pub const param_d: c_uint = 6;
1446 pub const param_i: c_uint = 7;
1447 pub const constant_buffer_0: c_uint = 8;
1448 pub const constant_buffer_1: c_uint = 9;
1449 pub const constant_buffer_2: c_uint = 10;
1450 pub const constant_buffer_3: c_uint = 11;
1451 pub const constant_buffer_4: c_uint = 12;
1452 pub const constant_buffer_5: c_uint = 13;
1453 pub const constant_buffer_6: c_uint = 14;
1454 pub const constant_buffer_7: c_uint = 15;
1455 pub const constant_buffer_8: c_uint = 16;
1456 pub const constant_buffer_9: c_uint = 17;
1457 pub const constant_buffer_10: c_uint = 18;
1458 pub const constant_buffer_11: c_uint = 19;
1459 pub const constant_buffer_12: c_uint = 20;
1460 pub const constant_buffer_13: c_uint = 21;
1461 pub const constant_buffer_14: c_uint = 22;
1462 pub const constant_buffer_15: c_uint = 23;
1463 };
1464
1465 // See llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypetilities.h
1466 pub const wasm = struct {
1467 pub const variable: c_uint = 1;
1468 pub const externref: c_uint = 10;
1469 pub const funcref: c_uint = 20;
1470 };
1471};
1472
1473pub const DIEnumerator = opaque {};
1474pub const DILocalVariable = opaque {};
1475pub const DILocation = opaque {};
1476pub const DIGlobalExpression = opaque {};
1477
1478pub const DIGlobalVariable = opaque {
1479 pub const toNode = ZigLLVMGlobalVariableToNode;
1480 extern fn ZigLLVMGlobalVariableToNode(global_variable: *DIGlobalVariable) *DINode;
1481
1482 pub const replaceLinkageName = ZigLLVMGlobalVariableReplaceLinkageName;
1483 extern fn ZigLLVMGlobalVariableReplaceLinkageName(global_variable: *DIGlobalVariable, linkage_name: *MDString) void;
1484};
1485pub const DIGlobalVariableExpression = opaque {
1486 pub const getVariable = ZigLLVMGlobalGetVariable;
1487 extern fn ZigLLVMGlobalGetVariable(global_variable: *DIGlobalVariableExpression) *DIGlobalVariable;
1488};
1489pub const DIType = opaque {
1490 pub const toScope = ZigLLVMTypeToScope;
1491 extern fn ZigLLVMTypeToScope(ty: *DIType) *DIScope;
1492
1493 pub const toNode = ZigLLVMTypeToNode;
1494 extern fn ZigLLVMTypeToNode(ty: *DIType) *DINode;
1495};
1496pub const DIFile = opaque {
1497 pub const toScope = ZigLLVMFileToScope;
1498 extern fn ZigLLVMFileToScope(difile: *DIFile) *DIScope;
1499
1500 pub const toNode = ZigLLVMFileToNode;
1501 extern fn ZigLLVMFileToNode(difile: *DIFile) *DINode;
1502};
1503pub const DILexicalBlock = opaque {
1504 pub const toScope = ZigLLVMLexicalBlockToScope;
1505 extern fn ZigLLVMLexicalBlockToScope(lexical_block: *DILexicalBlock) *DIScope;
1506
1507 pub const toNode = ZigLLVMLexicalBlockToNode;
1508 extern fn ZigLLVMLexicalBlockToNode(lexical_block: *DILexicalBlock) *DINode;
1509};
1510pub const DICompileUnit = opaque {
1511 pub const toScope = ZigLLVMCompileUnitToScope;
1512 extern fn ZigLLVMCompileUnitToScope(compile_unit: *DICompileUnit) *DIScope;
1513
1514 pub const toNode = ZigLLVMCompileUnitToNode;
1515 extern fn ZigLLVMCompileUnitToNode(compile_unit: *DICompileUnit) *DINode;
1516};
1517pub const DISubprogram = opaque {
1518 pub const toScope = ZigLLVMSubprogramToScope;
1519 extern fn ZigLLVMSubprogramToScope(subprogram: *DISubprogram) *DIScope;
1520
1521 pub const toNode = ZigLLVMSubprogramToNode;
1522 extern fn ZigLLVMSubprogramToNode(subprogram: *DISubprogram) *DINode;
1523
1524 pub const replaceLinkageName = ZigLLVMSubprogramReplaceLinkageName;
1525 extern fn ZigLLVMSubprogramReplaceLinkageName(subprogram: *DISubprogram, linkage_name: *MDString) void;
1526};
1527
1528pub const getDebugLoc = ZigLLVMGetDebugLoc2;
1529extern fn ZigLLVMGetDebugLoc2(line: c_uint, col: c_uint, scope: *DIScope, inlined_at: ?*DILocation) *DILocation;
1530
1531pub const DIBuilder = opaque {
1532 pub const dispose = ZigLLVMDisposeDIBuilder;
1533 extern fn ZigLLVMDisposeDIBuilder(dib: *DIBuilder) void;
1534
1535 pub const finalize = ZigLLVMDIBuilderFinalize;
1536 extern fn ZigLLVMDIBuilderFinalize(dib: *DIBuilder) void;
1537
1538 pub const createPointerType = ZigLLVMCreateDebugPointerType;
1539 extern fn ZigLLVMCreateDebugPointerType(
1540 dib: *DIBuilder,
1541 pointee_type: *DIType,
1542 size_in_bits: u64,
1543 align_in_bits: u64,
1544 name: [*:0]const u8,
1545 ) *DIType;
1546
1547 pub const createBasicType = ZigLLVMCreateDebugBasicType;
1548 extern fn ZigLLVMCreateDebugBasicType(
1549 dib: *DIBuilder,
1550 name: [*:0]const u8,
1551 size_in_bits: u64,
1552 encoding: c_uint,
1553 ) *DIType;
1554
1555 pub const createArrayType = ZigLLVMCreateDebugArrayType;
1556 extern fn ZigLLVMCreateDebugArrayType(
1557 dib: *DIBuilder,
1558 size_in_bits: u64,
1559 align_in_bits: u64,
1560 elem_type: *DIType,
1561 elem_count: i64,
1562 ) *DIType;
1563
1564 pub const createEnumerator = ZigLLVMCreateDebugEnumerator;
1565 extern fn ZigLLVMCreateDebugEnumerator(
1566 dib: *DIBuilder,
1567 name: [*:0]const u8,
1568 val: u64,
1569 is_unsigned: bool,
1570 ) *DIEnumerator;
1571
1572 pub const createEnumerator2 = ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision;
1573 extern fn ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision(
1574 dib: *DIBuilder,
1575 name: [*:0]const u8,
1576 num_words: c_uint,
1577 words: [*]const u64,
1578 bits: c_uint,
1579 is_unsigned: bool,
1580 ) *DIEnumerator;
1581
1582 pub const createEnumerationType = ZigLLVMCreateDebugEnumerationType;
1583 extern fn ZigLLVMCreateDebugEnumerationType(
1584 dib: *DIBuilder,
1585 scope: *DIScope,
1586 name: [*:0]const u8,
1587 file: *DIFile,
1588 line_number: c_uint,
1589 size_in_bits: u64,
1590 align_in_bits: u64,
1591 enumerator_array: [*]const *DIEnumerator,
1592 enumerator_array_len: c_int,
1593 underlying_type: *DIType,
1594 unique_id: [*:0]const u8,
1595 ) *DIType;
1596
1597 pub const createStructType = ZigLLVMCreateDebugStructType;
1598 extern fn ZigLLVMCreateDebugStructType(
1599 dib: *DIBuilder,
1600 scope: *DIScope,
1601 name: [*:0]const u8,
1602 file: ?*DIFile,
1603 line_number: c_uint,
1604 size_in_bits: u64,
1605 align_in_bits: u64,
1606 flags: c_uint,
1607 derived_from: ?*DIType,
1608 types_array: [*]const *DIType,
1609 types_array_len: c_int,
1610 run_time_lang: c_uint,
1611 vtable_holder: ?*DIType,
1612 unique_id: [*:0]const u8,
1613 ) *DIType;
1614
1615 pub const createUnionType = ZigLLVMCreateDebugUnionType;
1616 extern fn ZigLLVMCreateDebugUnionType(
1617 dib: *DIBuilder,
1618 scope: *DIScope,
1619 name: [*:0]const u8,
1620 file: ?*DIFile,
1621 line_number: c_uint,
1622 size_in_bits: u64,
1623 align_in_bits: u64,
1624 flags: c_uint,
1625 types_array: [*]const *DIType,
1626 types_array_len: c_int,
1627 run_time_lang: c_uint,
1628 unique_id: [*:0]const u8,
1629 ) *DIType;
1630
1631 pub const createMemberType = ZigLLVMCreateDebugMemberType;
1632 extern fn ZigLLVMCreateDebugMemberType(
1633 dib: *DIBuilder,
1634 scope: *DIScope,
1635 name: [*:0]const u8,
1636 file: ?*DIFile,
1637 line: c_uint,
1638 size_in_bits: u64,
1639 align_in_bits: u64,
1640 offset_in_bits: u64,
1641 flags: c_uint,
1642 ty: *DIType,
1643 ) *DIType;
1644
1645 pub const createReplaceableCompositeType = ZigLLVMCreateReplaceableCompositeType;
1646 extern fn ZigLLVMCreateReplaceableCompositeType(
1647 dib: *DIBuilder,
1648 tag: c_uint,
1649 name: [*:0]const u8,
1650 scope: *DIScope,
1651 file: ?*DIFile,
1652 line: c_uint,
1653 ) *DIType;
1654
1655 pub const createForwardDeclType = ZigLLVMCreateDebugForwardDeclType;
1656 extern fn ZigLLVMCreateDebugForwardDeclType(
1657 dib: *DIBuilder,
1658 tag: c_uint,
1659 name: [*:0]const u8,
1660 scope: ?*DIScope,
1661 file: ?*DIFile,
1662 line: c_uint,
1663 ) *DIType;
1664
1665 pub const replaceTemporary = ZigLLVMReplaceTemporary;
1666 extern fn ZigLLVMReplaceTemporary(dib: *DIBuilder, ty: *DIType, replacement: *DIType) void;
1667
1668 pub const replaceDebugArrays = ZigLLVMReplaceDebugArrays;
1669 extern fn ZigLLVMReplaceDebugArrays(
1670 dib: *DIBuilder,
1671 ty: *DIType,
1672 types_array: [*]const *DIType,
1673 types_array_len: c_int,
1674 ) void;
1675
1676 pub const createSubroutineType = ZigLLVMCreateSubroutineType;
1677 extern fn ZigLLVMCreateSubroutineType(
1678 dib: *DIBuilder,
1679 types_array: [*]const *DIType,
1680 types_array_len: c_int,
1681 flags: c_uint,
1682 ) *DIType;
1683
1684 pub const createAutoVariable = ZigLLVMCreateAutoVariable;
1685 extern fn ZigLLVMCreateAutoVariable(
1686 dib: *DIBuilder,
1687 scope: *DIScope,
1688 name: [*:0]const u8,
1689 file: *DIFile,
1690 line_no: c_uint,
1691 ty: *DIType,
1692 always_preserve: bool,
1693 flags: c_uint,
1694 ) *DILocalVariable;
1695
1696 pub const createGlobalVariableExpression = ZigLLVMCreateGlobalVariableExpression;
1697 extern fn ZigLLVMCreateGlobalVariableExpression(
1698 dib: *DIBuilder,
1699 scope: *DIScope,
1700 name: [*:0]const u8,
1701 linkage_name: [*:0]const u8,
1702 file: *DIFile,
1703 line_no: c_uint,
1704 di_type: *DIType,
1705 is_local_to_unit: bool,
1706 ) *DIGlobalVariableExpression;
1707
1708 pub const createParameterVariable = ZigLLVMCreateParameterVariable;
1709 extern fn ZigLLVMCreateParameterVariable(
1710 dib: *DIBuilder,
1711 scope: *DIScope,
1712 name: [*:0]const u8,
1713 file: *DIFile,
1714 line_no: c_uint,
1715 ty: *DIType,
1716 always_preserve: bool,
1717 flags: c_uint,
1718 arg_no: c_uint,
1719 ) *DILocalVariable;
1720
1721 pub const createLexicalBlock = ZigLLVMCreateLexicalBlock;
1722 extern fn ZigLLVMCreateLexicalBlock(
1723 dib: *DIBuilder,
1724 scope: *DIScope,
1725 file: *DIFile,
1726 line: c_uint,
1727 col: c_uint,
1728 ) *DILexicalBlock;
1729
1730 pub const createCompileUnit = ZigLLVMCreateCompileUnit;
1731 extern fn ZigLLVMCreateCompileUnit(
1732 dib: *DIBuilder,
1733 lang: c_uint,
1734 difile: *DIFile,
1735 producer: [*:0]const u8,
1736 is_optimized: bool,
1737 flags: [*:0]const u8,
1738 runtime_version: c_uint,
1739 split_name: [*:0]const u8,
1740 dwo_id: u64,
1741 emit_debug_info: bool,
1742 ) *DICompileUnit;
1743
1744 pub const createFile = ZigLLVMCreateFile;
1745 extern fn ZigLLVMCreateFile(
1746 dib: *DIBuilder,
1747 filename: [*:0]const u8,
1748 directory: [*:0]const u8,
1749 ) *DIFile;
1750
1751 pub const createFunction = ZigLLVMCreateFunction;
1752 extern fn ZigLLVMCreateFunction(
1753 dib: *DIBuilder,
1754 scope: *DIScope,
1755 name: [*:0]const u8,
1756 linkage_name: [*:0]const u8,
1757 file: *DIFile,
1758 lineno: c_uint,
1759 fn_di_type: *DIType,
1760 is_local_to_unit: bool,
1761 is_definition: bool,
1762 scope_line: c_uint,
1763 flags: c_uint,
1764 is_optimized: bool,
1765 decl_subprogram: ?*DISubprogram,
1766 ) *DISubprogram;
1767
1768 pub const createVectorType = ZigLLVMDIBuilderCreateVectorType;
1769 extern fn ZigLLVMDIBuilderCreateVectorType(
1770 dib: *DIBuilder,
1771 SizeInBits: u64,
1772 AlignInBits: u32,
1773 Ty: *DIType,
1774 elem_count: u32,
1775 ) *DIType;
1776
1777 pub const insertDeclareAtEnd = ZigLLVMInsertDeclareAtEnd;
1778 extern fn ZigLLVMInsertDeclareAtEnd(
1779 dib: *DIBuilder,
1780 storage: *Value,
1781 var_info: *DILocalVariable,
1782 debug_loc: *DILocation,
1783 basic_block_ref: *BasicBlock,
1784 ) *Value;
1785
1786 pub const insertDeclare = ZigLLVMInsertDeclare;
1787 extern fn ZigLLVMInsertDeclare(
1788 dib: *DIBuilder,
1789 storage: *Value,
1790 var_info: *DILocalVariable,
1791 debug_loc: *DILocation,
1792 insert_before_instr: *Value,
1793 ) *Value;
1794
1795 pub const insertDbgValueIntrinsicAtEnd = ZigLLVMInsertDbgValueIntrinsicAtEnd;
1796 extern fn ZigLLVMInsertDbgValueIntrinsicAtEnd(
1797 dib: *DIBuilder,
1798 val: *Value,
1799 var_info: *DILocalVariable,
1800 debug_loc: *DILocation,
1801 basic_block_ref: *BasicBlock,
1802 ) *Value;
1803};
1804
1805pub const DIFlags = opaque {
1806 pub const Zero = 0;
1807 pub const Private = 1;
1808 pub const Protected = 2;
1809 pub const Public = 3;
1810
1811 pub const FwdDecl = 1 << 2;
1812 pub const AppleBlock = 1 << 3;
1813 pub const BlockByrefStruct = 1 << 4;
1814 pub const Virtual = 1 << 5;
1815 pub const Artificial = 1 << 6;
1816 pub const Explicit = 1 << 7;
1817 pub const Prototyped = 1 << 8;
1818 pub const ObjcClassComplete = 1 << 9;
1819 pub const ObjectPointer = 1 << 10;
1820 pub const Vector = 1 << 11;
1821 pub const StaticMember = 1 << 12;
1822 pub const LValueReference = 1 << 13;
1823 pub const RValueReference = 1 << 14;
1824 pub const Reserved = 1 << 15;
1825
1826 pub const SingleInheritance = 1 << 16;
1827 pub const MultipleInheritance = 2 << 16;
1828 pub const VirtualInheritance = 3 << 16;
1829
1830 pub const IntroducedVirtual = 1 << 18;
1831 pub const BitField = 1 << 19;
1832 pub const NoReturn = 1 << 20;
1833 pub const TypePassByValue = 1 << 22;
1834 pub const TypePassByReference = 1 << 23;
1835 pub const EnumClass = 1 << 24;
1836 pub const Thunk = 1 << 25;
1837 pub const NonTrivial = 1 << 26;
1838 pub const BigEndian = 1 << 27;
1839 pub const LittleEndian = 1 << 28;
1840 pub const AllCallsDescribed = 1 << 29;
1841};
src/codegen/llvm/bitcode_writer.zig created+421
...@@ -0,0 +1,421 @@
1const std = @import("std");
2
3pub const AbbrevOp = union(enum) {
4 literal: u32, // 0
5 fixed: u16, // 1
6 fixed_runtime: type, // 1
7 vbr: u16, // 2
8 char6: void, // 4
9 blob: void, // 5
10 array_fixed: u16, // 3, 1
11 array_fixed_runtime: type, // 3, 1
12 array_vbr: u16, // 3, 2
13 array_char6: void, // 3, 4
14};
15
16pub const Error = error{OutOfMemory};
17
18pub fn BitcodeWriter(comptime types: []const type) type {
19 return struct {
20 const BcWriter = @This();
21
22 buffer: std.ArrayList(u32),
23 bit_buffer: u32 = 0,
24 bit_count: u5 = 0,
25
26 widths: [types.len]u16,
27
28 pub fn getTypeWidth(self: BcWriter, comptime Type: type) u16 {
29 return self.widths[comptime std.mem.indexOfScalar(type, types, Type).?];
30 }
31
32 pub fn init(allocator: std.mem.Allocator, widths: [types.len]u16) BcWriter {
33 return .{
34 .buffer = std.ArrayList(u32).init(allocator),
35 .widths = widths,
36 };
37 }
38
39 pub fn deinit(self: BcWriter) void {
40 self.buffer.deinit();
41 }
42
43 pub fn toSlice(self: BcWriter) []const u32 {
44 std.debug.assert(self.bit_count == 0);
45 return self.buffer.items;
46 }
47
48 pub fn length(self: BcWriter) usize {
49 std.debug.assert(self.bit_count == 0);
50 return self.buffer.items.len;
51 }
52
53 pub fn writeBits(self: *BcWriter, value: anytype, bits: u16) Error!void {
54 if (bits == 0) return;
55
56 var in_buffer = bufValue(value, 32);
57 var in_bits = bits;
58
59 // Store input bits in buffer if they fit otherwise store as many as possible and flush
60 if (self.bit_count > 0) {
61 const bits_remaining = 31 - self.bit_count + 1;
62 const n: u5 = @intCast(@min(bits_remaining, in_bits));
63 const v = @as(u32, @truncate(in_buffer)) << self.bit_count;
64 self.bit_buffer |= v;
65 in_buffer >>= n;
66
67 self.bit_count +%= n;
68 in_bits -= n;
69
70 if (self.bit_count != 0) return;
71 try self.buffer.append(self.bit_buffer);
72 self.bit_buffer = 0;
73 }
74
75 // Write 32-bit chunks of input bits
76 while (in_bits >= 32) {
77 try self.buffer.append(@truncate(in_buffer));
78
79 in_buffer >>= 31;
80 in_buffer >>= 1;
81 in_bits -= 32;
82 }
83
84 // Store remaining input bits in buffer
85 if (in_bits > 0) {
86 self.bit_count = @intCast(in_bits);
87 self.bit_buffer = @truncate(in_buffer);
88 }
89 }
90
91 pub fn writeVBR(self: *BcWriter, value: anytype, comptime vbr_bits: usize) Error!void {
92 comptime {
93 std.debug.assert(vbr_bits > 1);
94 if (@bitSizeOf(@TypeOf(value)) > 64) @compileError("Unsupported VBR block type: " ++ @typeName(@TypeOf(value)));
95 }
96
97 var in_buffer = bufValue(value, vbr_bits);
98
99 const continue_bit = @as(@TypeOf(in_buffer), 1) << @intCast(vbr_bits - 1);
100 const mask = continue_bit - 1;
101
102 // If input is larger than one VBR block can store
103 // then store vbr_bits - 1 bits and a continue bit
104 while (in_buffer > mask) {
105 try self.writeBits(in_buffer & mask | continue_bit, vbr_bits);
106 in_buffer >>= @intCast(vbr_bits - 1);
107 }
108
109 // Store remaining bits
110 try self.writeBits(in_buffer, vbr_bits);
111 }
112
113 pub fn bitsVBR(_: *const BcWriter, value: anytype, comptime vbr_bits: usize) u16 {
114 comptime {
115 std.debug.assert(vbr_bits > 1);
116 if (@bitSizeOf(@TypeOf(value)) > 64) @compileError("Unsupported VBR block type: " ++ @typeName(@TypeOf(value)));
117 }
118
119 var bits: u16 = 0;
120
121 var in_buffer = bufValue(value, vbr_bits);
122
123 const continue_bit = @as(@TypeOf(in_buffer), 1) << @intCast(vbr_bits - 1);
124 const mask = continue_bit - 1;
125
126 // If input is larger than one VBR block can store
127 // then store vbr_bits - 1 bits and a continue bit
128 while (in_buffer > mask) {
129 bits += @intCast(vbr_bits);
130 in_buffer >>= @intCast(vbr_bits - 1);
131 }
132
133 // Store remaining bits
134 bits += @intCast(vbr_bits);
135 return bits;
136 }
137
138 pub fn write6BitChar(self: *BcWriter, c: u8) Error!void {
139 try self.writeBits(charTo6Bit(c), 6);
140 }
141
142 pub fn alignTo32(self: *BcWriter) Error!void {
143 if (self.bit_count == 0) return;
144
145 try self.buffer.append(self.bit_buffer);
146 self.bit_buffer = 0;
147 self.bit_count = 0;
148 }
149
150 pub fn enterTopBlock(self: *BcWriter, comptime SubBlock: type) Error!BlockWriter(SubBlock) {
151 return BlockWriter(SubBlock).init(self, 2);
152 }
153
154 fn BlockWriter(comptime Block: type) type {
155 return struct {
156 const Self = @This();
157
158 // The minimum abbrev id length based on the number of abbrevs present in the block
159 pub const abbrev_len = std.math.log2_int_ceil(
160 u6,
161 4 + (if (@hasDecl(Block, "abbrevs")) Block.abbrevs.len else 0),
162 );
163
164 start: usize,
165 bitcode: *BcWriter,
166
167 pub fn init(bitcode: *BcWriter, comptime parent_abbrev_len: u6) Error!Self {
168 try bitcode.writeBits(1, parent_abbrev_len);
169 try bitcode.writeVBR(Block.id, 8);
170 try bitcode.writeVBR(abbrev_len, 4);
171 try bitcode.alignTo32();
172
173 // We store the index of the block size and store a dummy value as the number of words in the block
174 const start = bitcode.length();
175 try bitcode.writeBits(0, 32);
176
177 // Predefine all block abbrevs
178 inline for (Block.abbrevs) |Abbrev| {
179 try defineAbbrev(bitcode, &Abbrev.ops);
180 }
181
182 return .{
183 .start = start,
184 .bitcode = bitcode,
185 };
186 }
187
188 pub fn enterSubBlock(self: Self, comptime SubBlock: type) Error!BlockWriter(SubBlock) {
189 return BlockWriter(SubBlock).init(self.bitcode, abbrev_len);
190 }
191
192 pub fn end(self: *Self) Error!void {
193 try self.bitcode.writeBits(0, abbrev_len);
194 try self.bitcode.alignTo32();
195
196 // Set the number of words in the block at the start of the block
197 self.bitcode.buffer.items[self.start] = @truncate(self.bitcode.length() - self.start - 1);
198 }
199
200 pub fn writeUnabbrev(self: *Self, code: u32, values: []const u64) Error!void {
201 try self.bitcode.writeBits(3, abbrev_len);
202 try self.bitcode.writeVBR(code, 6);
203 try self.bitcode.writeVBR(values.len, 6);
204 for (values) |val| {
205 try self.bitcode.writeVBR(val, 6);
206 }
207 }
208
209 pub fn writeAbbrev(self: *Self, params: anytype) Error!void {
210 return self.writeAbbrevAdapted(params, struct {
211 pub fn get(_: @This(), param: anytype, comptime _: []const u8) @TypeOf(param) {
212 return param;
213 }
214 }{});
215 }
216
217 pub fn abbrevId(comptime Abbrev: type) u32 {
218 inline for (Block.abbrevs, 0..) |abbrev, i| {
219 if (Abbrev == abbrev) return i + 4;
220 }
221
222 @compileError("Unknown abbrev: " ++ @typeName(Abbrev));
223 }
224
225 pub fn writeAbbrevAdapted(
226 self: *Self,
227 params: anytype,
228 adapter: anytype,
229 ) Error!void {
230 const Abbrev = @TypeOf(params);
231
232 try self.bitcode.writeBits(comptime abbrevId(Abbrev), abbrev_len);
233
234 const fields = std.meta.fields(Abbrev);
235
236 // This abbreviation might only contain literals
237 if (fields.len == 0) return;
238
239 comptime var field_index: usize = 0;
240 inline for (Abbrev.ops) |ty| {
241 const field_name = fields[field_index].name;
242 const param = @field(params, field_name);
243
244 switch (ty) {
245 .literal => continue,
246 .fixed => |len| try self.bitcode.writeBits(adapter.get(param, field_name), len),
247 .fixed_runtime => |width_ty| try self.bitcode.writeBits(
248 adapter.get(param, field_name),
249 self.bitcode.getTypeWidth(width_ty),
250 ),
251 .vbr => |len| try self.bitcode.writeVBR(adapter.get(param, field_name), len),
252 .char6 => try self.bitcode.write6BitChar(adapter.get(param, field_name)),
253 .blob => {
254 try self.bitcode.writeVBR(param.len, 6);
255 try self.bitcode.alignTo32();
256 for (param) |x| {
257 try self.bitcode.writeBits(x, 8);
258 }
259 try self.bitcode.alignTo32();
260 },
261 .array_fixed => |len| {
262 try self.bitcode.writeVBR(param.len, 6);
263 for (param) |x| {
264 try self.bitcode.writeBits(adapter.get(x, field_name), len);
265 }
266 },
267 .array_fixed_runtime => |width_ty| {
268 try self.bitcode.writeVBR(param.len, 6);
269 for (param) |x| {
270 try self.bitcode.writeBits(
271 adapter.get(x, field_name),
272 self.bitcode.getTypeWidth(width_ty),
273 );
274 }
275 },
276 .array_vbr => |len| {
277 try self.bitcode.writeVBR(param.len, 6);
278 for (param) |x| {
279 try self.bitcode.writeVBR(adapter.get(x, field_name), len);
280 }
281 },
282 .array_char6 => {
283 try self.bitcode.writeVBR(param.len, 6);
284 for (param) |x| {
285 try self.bitcode.write6BitChar(adapter.get(x, field_name));
286 }
287 },
288 }
289 field_index += 1;
290 if (field_index == fields.len) break;
291 }
292 }
293
294 fn defineAbbrev(bitcode: *BcWriter, comptime ops: []const AbbrevOp) Error!void {
295 try bitcode.writeBits(2, abbrev_len);
296
297 // ops.len is not accurate because arrays are actually two ops
298 try bitcode.writeVBR(blk: {
299 var count: usize = 0;
300 inline for (ops) |op| {
301 count += switch (op) {
302 .literal, .fixed, .fixed_runtime, .vbr, .char6, .blob => 1,
303 .array_fixed, .array_fixed_runtime, .array_vbr, .array_char6 => 2,
304 };
305 }
306 break :blk count;
307 }, 5);
308
309 inline for (ops) |op| {
310 switch (op) {
311 .literal => |value| {
312 try bitcode.writeBits(1, 1);
313 try bitcode.writeVBR(value, 8);
314 },
315 .fixed => |width| {
316 try bitcode.writeBits(0, 1);
317 try bitcode.writeBits(1, 3);
318 try bitcode.writeVBR(width, 5);
319 },
320 .fixed_runtime => |width_ty| {
321 try bitcode.writeBits(0, 1);
322 try bitcode.writeBits(1, 3);
323 try bitcode.writeVBR(bitcode.getTypeWidth(width_ty), 5);
324 },
325 .vbr => |width| {
326 try bitcode.writeBits(0, 1);
327 try bitcode.writeBits(2, 3);
328 try bitcode.writeVBR(width, 5);
329 },
330 .char6 => {
331 try bitcode.writeBits(0, 1);
332 try bitcode.writeBits(4, 3);
333 },
334 .blob => {
335 try bitcode.writeBits(0, 1);
336 try bitcode.writeBits(5, 3);
337 },
338 .array_fixed => |width| {
339 // Array op
340 try bitcode.writeBits(0, 1);
341 try bitcode.writeBits(3, 3);
342
343 // Fixed or VBR op
344 try bitcode.writeBits(0, 1);
345 try bitcode.writeBits(1, 3);
346 try bitcode.writeVBR(width, 5);
347 },
348 .array_fixed_runtime => |width_ty| {
349 // Array op
350 try bitcode.writeBits(0, 1);
351 try bitcode.writeBits(3, 3);
352
353 // Fixed or VBR op
354 try bitcode.writeBits(0, 1);
355 try bitcode.writeBits(1, 3);
356 try bitcode.writeVBR(bitcode.getTypeWidth(width_ty), 5);
357 },
358 .array_vbr => |width| {
359 // Array op
360 try bitcode.writeBits(0, 1);
361 try bitcode.writeBits(3, 3);
362
363 // Fixed or VBR op
364 try bitcode.writeBits(0, 1);
365 try bitcode.writeBits(2, 3);
366 try bitcode.writeVBR(width, 5);
367 },
368 .array_char6 => {
369 // Array op
370 try bitcode.writeBits(0, 1);
371 try bitcode.writeBits(3, 3);
372
373 // Char6 op
374 try bitcode.writeBits(0, 1);
375 try bitcode.writeBits(4, 3);
376 },
377 }
378 }
379 }
380 };
381 }
382 };
383}
384
385fn charTo6Bit(c: u8) u8 {
386 return switch (c) {
387 'a'...'z' => c - 'a',
388 'A'...'Z' => c - 'A' + 26,
389 '0'...'9' => c - '0' + 52,
390 '.' => 62,
391 '_' => 63,
392 else => @panic("Failed to encode byte as 6-bit char"),
393 };
394}
395
396fn BufType(comptime T: type, comptime min_len: usize) type {
397 return std.meta.Int(.unsigned, @max(min_len, @bitSizeOf(switch (@typeInfo(T)) {
398 .ComptimeInt => u32,
399 .Int => |info| if (info.signedness == .unsigned)
400 T
401 else
402 @compileError("Unsupported type: " ++ @typeName(T)),
403 .Enum => |info| info.tag_type,
404 .Bool => u1,
405 .Struct => |info| switch (info.layout) {
406 .Auto, .Extern => @compileError("Unsupported type: " ++ @typeName(T)),
407 .Packed => std.meta.Int(.unsigned, @bitSizeOf(T)),
408 },
409 else => @compileError("Unsupported type: " ++ @typeName(T)),
410 })));
411}
412
413fn bufValue(value: anytype, comptime min_len: usize) BufType(@TypeOf(value), min_len) {
414 return switch (@typeInfo(@TypeOf(value))) {
415 .ComptimeInt, .Int => @intCast(value),
416 .Enum => @intFromEnum(value),
417 .Bool => @intFromBool(value),
418 .Struct => @intCast(@as(std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(value))), @bitCast(value))),
419 else => unreachable,
420 };
421}
src/codegen/llvm/ir.zig created+1636
...@@ -0,0 +1,1636 @@
1const std = @import("std");
2const Builder = @import("Builder.zig");
3const bitcode_writer = @import("bitcode_writer.zig");
4
5const AbbrevOp = bitcode_writer.AbbrevOp;
6
7pub const MAGIC: u32 = 0xdec04342;
8
9const ValueAbbrev = AbbrevOp{ .vbr = 6 };
10const ValueArrayAbbrev = AbbrevOp{ .array_vbr = 6 };
11
12const ConstantAbbrev = AbbrevOp{ .vbr = 6 };
13const ConstantArrayAbbrev = AbbrevOp{ .array_vbr = 6 };
14
15const MetadataAbbrev = AbbrevOp{ .vbr = 16 };
16const MetadataArrayAbbrev = AbbrevOp{ .array_vbr = 16 };
17
18const LineAbbrev = AbbrevOp{ .vbr = 8 };
19const ColumnAbbrev = AbbrevOp{ .vbr = 8 };
20
21const BlockAbbrev = AbbrevOp{ .vbr = 6 };
22
23pub const MetadataKind = enum(u1) {
24 dbg = 0,
25};
26
27pub const Identification = struct {
28 pub const id = 13;
29
30 pub const abbrevs = [_]type{
31 Version,
32 Epoch,
33 };
34
35 pub const Version = struct {
36 pub const ops = [_]AbbrevOp{
37 .{ .literal = 1 },
38 .{ .array_fixed = 8 },
39 };
40 string: []const u8,
41 };
42
43 pub const Epoch = struct {
44 pub const ops = [_]AbbrevOp{
45 .{ .literal = 2 },
46 .{ .vbr = 6 },
47 };
48 epoch: u32,
49 };
50};
51
52pub const Module = struct {
53 pub const id = 8;
54
55 pub const abbrevs = [_]type{
56 Version,
57 String,
58 Variable,
59 Function,
60 Alias,
61 };
62
63 pub const Version = struct {
64 pub const ops = [_]AbbrevOp{
65 .{ .literal = 1 },
66 .{ .literal = 2 },
67 };
68 };
69
70 pub const String = struct {
71 pub const ops = [_]AbbrevOp{
72 .{ .vbr = 4 },
73 .{ .array_fixed = 8 },
74 };
75 code: u16,
76 string: []const u8,
77 };
78
79 pub const Variable = struct {
80 const AddrSpaceAndIsConst = packed struct {
81 is_const: bool,
82 one: u1 = 1,
83 addr_space: Builder.AddrSpace,
84 };
85
86 pub const ops = [_]AbbrevOp{
87 .{ .literal = 7 }, // Code
88 .{ .vbr = 16 }, // strtab_offset
89 .{ .vbr = 16 }, // strtab_size
90 .{ .fixed_runtime = Builder.Type },
91 .{ .fixed = @bitSizeOf(AddrSpaceAndIsConst) }, // isconst
92 ConstantAbbrev, // initid
93 .{ .fixed = @bitSizeOf(Builder.Linkage) },
94 .{ .fixed = @bitSizeOf(Builder.Alignment) },
95 .{ .vbr = 16 }, // section
96 .{ .fixed = @bitSizeOf(Builder.Visibility) },
97 .{ .fixed = @bitSizeOf(Builder.ThreadLocal) }, // threadlocal
98 .{ .fixed = @bitSizeOf(Builder.UnnamedAddr) },
99 .{ .fixed = @bitSizeOf(Builder.ExternallyInitialized) },
100 .{ .fixed = @bitSizeOf(Builder.DllStorageClass) },
101 .{ .literal = 0 }, // comdat
102 .{ .literal = 0 }, // attributes
103 .{ .fixed = @bitSizeOf(Builder.Preemption) },
104 };
105 strtab_offset: usize,
106 strtab_size: usize,
107 type_index: Builder.Type,
108 is_const: AddrSpaceAndIsConst,
109 initid: u32,
110 linkage: Builder.Linkage,
111 alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)),
112 section: usize,
113 visibility: Builder.Visibility,
114 thread_local: Builder.ThreadLocal,
115 unnamed_addr: Builder.UnnamedAddr,
116 externally_initialized: Builder.ExternallyInitialized,
117 dllstorageclass: Builder.DllStorageClass,
118 preemption: Builder.Preemption,
119 };
120
121 pub const Function = struct {
122 pub const ops = [_]AbbrevOp{
123 .{ .literal = 8 }, // Code
124 .{ .vbr = 16 }, // strtab_offset
125 .{ .vbr = 16 }, // strtab_size
126 .{ .fixed_runtime = Builder.Type },
127 .{ .fixed = @bitSizeOf(Builder.CallConv) },
128 .{ .fixed = 1 }, // isproto
129 .{ .fixed = @bitSizeOf(Builder.Linkage) },
130 .{ .vbr = 16 }, // paramattr
131 .{ .fixed = @bitSizeOf(Builder.Alignment) },
132 .{ .vbr = 16 }, // section
133 .{ .fixed = @bitSizeOf(Builder.Visibility) },
134 .{ .literal = 0 }, // gc
135 .{ .fixed = @bitSizeOf(Builder.UnnamedAddr) },
136 .{ .literal = 0 }, // prologuedata
137 .{ .fixed = @bitSizeOf(Builder.DllStorageClass) },
138 .{ .literal = 0 }, // comdat
139 .{ .literal = 0 }, // prefixdata
140 .{ .literal = 0 }, // personalityfn
141 .{ .fixed = @bitSizeOf(Builder.Preemption) },
142 .{ .fixed = @bitSizeOf(Builder.AddrSpace) },
143 };
144 strtab_offset: usize,
145 strtab_size: usize,
146 type_index: Builder.Type,
147 call_conv: Builder.CallConv,
148 is_proto: bool,
149 linkage: Builder.Linkage,
150 paramattr: usize,
151 alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)),
152 section: usize,
153 visibility: Builder.Visibility,
154 unnamed_addr: Builder.UnnamedAddr,
155 dllstorageclass: Builder.DllStorageClass,
156 preemption: Builder.Preemption,
157 addr_space: Builder.AddrSpace,
158 };
159
160 pub const Alias = struct {
161 pub const ops = [_]AbbrevOp{
162 .{ .literal = 14 }, // Code
163 .{ .vbr = 16 }, // strtab_offset
164 .{ .vbr = 16 }, // strtab_size
165 .{ .fixed_runtime = Builder.Type },
166 .{ .fixed = @bitSizeOf(Builder.AddrSpace) },
167 ConstantAbbrev, // aliasee val
168 .{ .fixed = @bitSizeOf(Builder.Linkage) },
169 .{ .fixed = @bitSizeOf(Builder.Visibility) },
170 .{ .fixed = @bitSizeOf(Builder.DllStorageClass) },
171 .{ .fixed = @bitSizeOf(Builder.ThreadLocal) },
172 .{ .fixed = @bitSizeOf(Builder.UnnamedAddr) },
173 .{ .fixed = @bitSizeOf(Builder.Preemption) },
174 };
175 strtab_offset: usize,
176 strtab_size: usize,
177 type_index: Builder.Type,
178 addr_space: Builder.AddrSpace,
179 aliasee: u32,
180 linkage: Builder.Linkage,
181 visibility: Builder.Visibility,
182 dllstorageclass: Builder.DllStorageClass,
183 thread_local: Builder.ThreadLocal,
184 unnamed_addr: Builder.UnnamedAddr,
185 preemption: Builder.Preemption,
186 };
187};
188
189pub const Type = struct {
190 pub const id = 17;
191
192 pub const abbrevs = [_]type{
193 NumEntry,
194 Simple,
195 Opaque,
196 Integer,
197 StructAnon,
198 StructNamed,
199 StructName,
200 Array,
201 Vector,
202 Pointer,
203 Target,
204 Function,
205 };
206
207 pub const NumEntry = struct {
208 pub const ops = [_]AbbrevOp{
209 .{ .literal = 1 },
210 .{ .fixed = 32 },
211 };
212 num: u32,
213 };
214
215 pub const Simple = struct {
216 pub const ops = [_]AbbrevOp{
217 .{ .vbr = 4 },
218 };
219 code: u5,
220 };
221
222 pub const Opaque = struct {
223 pub const ops = [_]AbbrevOp{
224 .{ .literal = 6 },
225 .{ .literal = 0 },
226 };
227 };
228
229 pub const Integer = struct {
230 pub const ops = [_]AbbrevOp{
231 .{ .literal = 7 },
232 .{ .fixed = 28 },
233 };
234 width: u28,
235 };
236
237 pub const StructAnon = struct {
238 pub const ops = [_]AbbrevOp{
239 .{ .literal = 18 },
240 .{ .fixed = 1 },
241 .{ .array_fixed_runtime = Builder.Type },
242 };
243 is_packed: bool,
244 types: []const Builder.Type,
245 };
246
247 pub const StructNamed = struct {
248 pub const ops = [_]AbbrevOp{
249 .{ .literal = 20 },
250 .{ .fixed = 1 },
251 .{ .array_fixed_runtime = Builder.Type },
252 };
253 is_packed: bool,
254 types: []const Builder.Type,
255 };
256
257 pub const StructName = struct {
258 pub const ops = [_]AbbrevOp{
259 .{ .literal = 19 },
260 .{ .array_fixed = 8 },
261 };
262 string: []const u8,
263 };
264
265 pub const Array = struct {
266 pub const ops = [_]AbbrevOp{
267 .{ .literal = 11 },
268 .{ .vbr = 16 },
269 .{ .fixed_runtime = Builder.Type },
270 };
271 len: u64,
272 child: Builder.Type,
273 };
274
275 pub const Vector = struct {
276 pub const ops = [_]AbbrevOp{
277 .{ .literal = 12 },
278 .{ .vbr = 16 },
279 .{ .fixed_runtime = Builder.Type },
280 };
281 len: u64,
282 child: Builder.Type,
283 };
284
285 pub const Pointer = struct {
286 pub const ops = [_]AbbrevOp{
287 .{ .literal = 25 },
288 .{ .vbr = 4 },
289 };
290 addr_space: Builder.AddrSpace,
291 };
292
293 pub const Target = struct {
294 pub const ops = [_]AbbrevOp{
295 .{ .literal = 26 },
296 .{ .vbr = 4 },
297 .{ .array_fixed_runtime = Builder.Type },
298 .{ .array_fixed = 32 },
299 };
300 num_types: u32,
301 types: []const Builder.Type,
302 ints: []const u32,
303 };
304
305 pub const Function = struct {
306 pub const ops = [_]AbbrevOp{
307 .{ .literal = 21 },
308 .{ .fixed = 1 },
309 .{ .fixed_runtime = Builder.Type },
310 .{ .array_fixed_runtime = Builder.Type },
311 };
312 is_vararg: bool,
313 return_type: Builder.Type,
314 param_types: []const Builder.Type,
315 };
316};
317
318pub const Paramattr = struct {
319 pub const id = 9;
320
321 pub const abbrevs = [_]type{
322 Entry,
323 };
324
325 pub const Entry = struct {
326 pub const ops = [_]AbbrevOp{
327 .{ .literal = 2 },
328 .{ .array_vbr = 8 },
329 };
330 group_indices: []const u64,
331 };
332};
333
334pub const ParamattrGroup = struct {
335 pub const id = 10;
336
337 pub const abbrevs = [_]type{};
338};
339
340pub const Constants = struct {
341 pub const id = 11;
342
343 pub const abbrevs = [_]type{
344 SetType,
345 Null,
346 Undef,
347 Poison,
348 Integer,
349 Half,
350 Float,
351 Double,
352 Fp80,
353 Fp128,
354 Aggregate,
355 String,
356 CString,
357 Cast,
358 Binary,
359 Cmp,
360 ExtractElement,
361 InsertElement,
362 ShuffleVector,
363 ShuffleVectorEx,
364 BlockAddress,
365 DsoLocalEquivalentOrNoCfi,
366 };
367
368 pub const SetType = struct {
369 pub const ops = [_]AbbrevOp{
370 .{ .literal = 1 },
371 .{ .fixed_runtime = Builder.Type },
372 };
373 type_id: Builder.Type,
374 };
375
376 pub const Null = struct {
377 pub const ops = [_]AbbrevOp{
378 .{ .literal = 2 },
379 };
380 };
381
382 pub const Undef = struct {
383 pub const ops = [_]AbbrevOp{
384 .{ .literal = 3 },
385 };
386 };
387
388 pub const Poison = struct {
389 pub const ops = [_]AbbrevOp{
390 .{ .literal = 26 },
391 };
392 };
393
394 pub const Integer = struct {
395 pub const ops = [_]AbbrevOp{
396 .{ .literal = 4 },
397 .{ .vbr = 16 },
398 };
399 value: u64,
400 };
401
402 pub const Half = struct {
403 pub const ops = [_]AbbrevOp{
404 .{ .literal = 6 },
405 .{ .fixed = 16 },
406 };
407 value: u16,
408 };
409
410 pub const Float = struct {
411 pub const ops = [_]AbbrevOp{
412 .{ .literal = 6 },
413 .{ .fixed = 32 },
414 };
415 value: u32,
416 };
417
418 pub const Double = struct {
419 pub const ops = [_]AbbrevOp{
420 .{ .literal = 6 },
421 .{ .vbr = 6 },
422 };
423 value: u64,
424 };
425
426 pub const Fp80 = struct {
427 pub const ops = [_]AbbrevOp{
428 .{ .literal = 6 },
429 .{ .vbr = 6 },
430 .{ .vbr = 6 },
431 };
432 hi: u64,
433 lo: u16,
434 };
435
436 pub const Fp128 = struct {
437 pub const ops = [_]AbbrevOp{
438 .{ .literal = 6 },
439 .{ .vbr = 6 },
440 .{ .vbr = 6 },
441 };
442 lo: u64,
443 hi: u64,
444 };
445
446 pub const Aggregate = struct {
447 pub const ops = [_]AbbrevOp{
448 .{ .literal = 7 },
449 .{ .array_fixed = 32 },
450 };
451 values: []const Builder.Constant,
452 };
453
454 pub const String = struct {
455 pub const ops = [_]AbbrevOp{
456 .{ .literal = 8 },
457 .{ .array_fixed = 8 },
458 };
459 string: []const u8,
460 };
461
462 pub const CString = struct {
463 pub const ops = [_]AbbrevOp{
464 .{ .literal = 9 },
465 .{ .array_fixed = 8 },
466 };
467 string: []const u8,
468 };
469
470 pub const Cast = struct {
471 const CastOpcode = Builder.CastOpcode;
472 pub const ops = [_]AbbrevOp{
473 .{ .literal = 11 },
474 .{ .fixed = @bitSizeOf(CastOpcode) },
475 .{ .fixed_runtime = Builder.Type },
476 ConstantAbbrev,
477 };
478
479 opcode: CastOpcode,
480 type_index: Builder.Type,
481 val: Builder.Constant,
482 };
483
484 pub const Binary = struct {
485 const BinaryOpcode = Builder.BinaryOpcode;
486 pub const ops = [_]AbbrevOp{
487 .{ .literal = 10 },
488 .{ .fixed = @bitSizeOf(BinaryOpcode) },
489 ConstantAbbrev,
490 ConstantAbbrev,
491 };
492
493 opcode: BinaryOpcode,
494 lhs: Builder.Constant,
495 rhs: Builder.Constant,
496 };
497
498 pub const Cmp = struct {
499 pub const ops = [_]AbbrevOp{
500 .{ .literal = 17 },
501 .{ .fixed_runtime = Builder.Type },
502 ConstantAbbrev,
503 ConstantAbbrev,
504 .{ .vbr = 6 },
505 };
506
507 ty: Builder.Type,
508 lhs: Builder.Constant,
509 rhs: Builder.Constant,
510 pred: u32,
511 };
512
513 pub const ExtractElement = struct {
514 pub const ops = [_]AbbrevOp{
515 .{ .literal = 14 },
516 .{ .fixed_runtime = Builder.Type },
517 ConstantAbbrev,
518 .{ .fixed_runtime = Builder.Type },
519 ConstantAbbrev,
520 };
521
522 val_type: Builder.Type,
523 val: Builder.Constant,
524 index_type: Builder.Type,
525 index: Builder.Constant,
526 };
527
528 pub const InsertElement = struct {
529 pub const ops = [_]AbbrevOp{
530 .{ .literal = 15 },
531 ConstantAbbrev,
532 ConstantAbbrev,
533 .{ .fixed_runtime = Builder.Type },
534 ConstantAbbrev,
535 };
536
537 val: Builder.Constant,
538 elem: Builder.Constant,
539 index_type: Builder.Type,
540 index: Builder.Constant,
541 };
542
543 pub const ShuffleVector = struct {
544 pub const ops = [_]AbbrevOp{
545 .{ .literal = 16 },
546 ValueAbbrev,
547 ValueAbbrev,
548 ValueAbbrev,
549 };
550
551 lhs: Builder.Constant,
552 rhs: Builder.Constant,
553 mask: Builder.Constant,
554 };
555
556 pub const ShuffleVectorEx = struct {
557 pub const ops = [_]AbbrevOp{
558 .{ .literal = 19 },
559 .{ .fixed_runtime = Builder.Type },
560 ValueAbbrev,
561 ValueAbbrev,
562 ValueAbbrev,
563 };
564
565 ty: Builder.Type,
566 lhs: Builder.Constant,
567 rhs: Builder.Constant,
568 mask: Builder.Constant,
569 };
570
571 pub const BlockAddress = struct {
572 pub const ops = [_]AbbrevOp{
573 .{ .literal = 21 },
574 .{ .fixed_runtime = Builder.Type },
575 ConstantAbbrev,
576 BlockAbbrev,
577 };
578 type_id: Builder.Type,
579 function: u32,
580 block: u32,
581 };
582
583 pub const DsoLocalEquivalentOrNoCfi = struct {
584 pub const ops = [_]AbbrevOp{
585 .{ .fixed = 5 },
586 .{ .fixed_runtime = Builder.Type },
587 ConstantAbbrev,
588 };
589 code: u5,
590 type_id: Builder.Type,
591 function: u32,
592 };
593};
594
595pub const MetadataKindBlock = struct {
596 pub const id = 22;
597
598 pub const abbrevs = [_]type{
599 Kind,
600 };
601
602 pub const Kind = struct {
603 pub const ops = [_]AbbrevOp{
604 .{ .literal = 6 },
605 .{ .vbr = 4 },
606 .{ .array_fixed = 8 },
607 };
608 id: u32,
609 name: []const u8,
610 };
611};
612
613pub const MetadataAttachmentBlock = struct {
614 pub const id = 16;
615
616 pub const abbrevs = [_]type{
617 AttachmentSingle,
618 };
619
620 pub const AttachmentSingle = struct {
621 pub const ops = [_]AbbrevOp{
622 .{ .literal = 11 },
623 .{ .fixed = 1 },
624 MetadataAbbrev,
625 };
626 kind: MetadataKind,
627 metadata: Builder.Metadata,
628 };
629};
630
631pub const MetadataBlock = struct {
632 pub const id = 15;
633
634 pub const abbrevs = [_]type{
635 Strings,
636 File,
637 CompileUnit,
638 Subprogram,
639 LexicalBlock,
640 Location,
641 BasicType,
642 CompositeType,
643 DerivedType,
644 SubroutineType,
645 Enumerator,
646 Subrange,
647 Expression,
648 Node,
649 LocalVar,
650 Parameter,
651 GlobalVar,
652 GlobalVarExpression,
653 Constant,
654 Name,
655 NamedNode,
656 GlobalDeclAttachment,
657 };
658
659 pub const Strings = struct {
660 pub const ops = [_]AbbrevOp{
661 .{ .literal = 35 },
662 .{ .vbr = 6 },
663 .{ .vbr = 6 },
664 .blob,
665 };
666 num_strings: u32,
667 strings_offset: u32,
668 blob: []const u8,
669 };
670
671 pub const File = struct {
672 pub const ops = [_]AbbrevOp{
673 .{ .literal = 16 },
674 .{ .literal = 0 }, // is distinct
675 MetadataAbbrev, // filename
676 MetadataAbbrev, // directory
677 .{ .literal = 0 }, // checksum
678 .{ .literal = 0 }, // checksum
679 };
680
681 filename: Builder.MetadataString,
682 directory: Builder.MetadataString,
683 };
684
685 pub const CompileUnit = struct {
686 pub const ops = [_]AbbrevOp{
687 .{ .literal = 20 },
688 .{ .literal = 1 }, // is distinct
689 .{ .literal = std.dwarf.LANG.C99 }, // source language
690 MetadataAbbrev, // file
691 MetadataAbbrev, // producer
692 .{ .fixed = 1 }, // isOptimized
693 .{ .literal = 0 }, // raw flags
694 .{ .literal = 0 }, // runtime version
695 .{ .literal = 0 }, // split debug file name
696 .{ .literal = 1 }, // emission kind
697 MetadataAbbrev, // enums
698 .{ .literal = 0 }, // retained types
699 .{ .literal = 0 }, // subprograms
700 MetadataAbbrev, // globals
701 .{ .literal = 0 }, // imported entities
702 .{ .literal = 0 }, // DWO ID
703 .{ .literal = 0 }, // macros
704 .{ .literal = 0 }, // split debug inlining
705 .{ .literal = 0 }, // debug info profiling
706 .{ .literal = 0 }, // name table kind
707 .{ .literal = 0 }, // ranges base address
708 .{ .literal = 0 }, // raw sysroot
709 .{ .literal = 0 }, // raw SDK
710 };
711
712 file: Builder.Metadata,
713 producer: Builder.MetadataString,
714 is_optimized: bool,
715 enums: Builder.Metadata,
716 globals: Builder.Metadata,
717 };
718
719 pub const Subprogram = struct {
720 pub const ops = [_]AbbrevOp{
721 .{ .literal = 21 },
722 .{ .literal = 0b111 }, // is distinct | has sp flags | has flags
723 MetadataAbbrev, // scope
724 MetadataAbbrev, // name
725 MetadataAbbrev, // linkage name
726 MetadataAbbrev, // file
727 LineAbbrev, // line
728 MetadataAbbrev, // type
729 LineAbbrev, // scope line
730 .{ .literal = 0 }, // containing type
731 .{ .fixed = 32 }, // sp flags
732 .{ .literal = 0 }, // virtual index
733 .{ .fixed = 32 }, // flags
734 MetadataAbbrev, // compile unit
735 .{ .literal = 0 }, // template params
736 .{ .literal = 0 }, // declaration
737 .{ .literal = 0 }, // retained nodes
738 .{ .literal = 0 }, // this adjustment
739 .{ .literal = 0 }, // thrown types
740 .{ .literal = 0 }, // annotations
741 .{ .literal = 0 }, // target function name
742 };
743
744 scope: Builder.Metadata,
745 name: Builder.MetadataString,
746 linkage_name: Builder.MetadataString,
747 file: Builder.Metadata,
748 line: u32,
749 ty: Builder.Metadata,
750 scope_line: u32,
751 sp_flags: Builder.Metadata.Subprogram.DISPFlags,
752 flags: Builder.Metadata.DIFlags,
753 compile_unit: Builder.Metadata,
754 };
755
756 pub const LexicalBlock = struct {
757 pub const ops = [_]AbbrevOp{
758 .{ .literal = 22 },
759 .{ .literal = 0 }, // is distinct
760 MetadataAbbrev, // scope
761 MetadataAbbrev, // file
762 LineAbbrev, // line
763 ColumnAbbrev, // column
764 };
765
766 scope: Builder.Metadata,
767 file: Builder.Metadata,
768 line: u32,
769 column: u32,
770 };
771
772 pub const Location = struct {
773 pub const ops = [_]AbbrevOp{
774 .{ .literal = 7 },
775 .{ .literal = 0 }, // is distinct
776 LineAbbrev, // line
777 ColumnAbbrev, // column
778 MetadataAbbrev, // scope
779 MetadataAbbrev, // inlined at
780 .{ .literal = 0 }, // is implicit code
781 };
782
783 line: u32,
784 column: u32,
785 scope: u32,
786 inlined_at: Builder.Metadata,
787 };
788
789 pub const BasicType = struct {
790 pub const ops = [_]AbbrevOp{
791 .{ .literal = 15 },
792 .{ .literal = 0 }, // is distinct
793 .{ .literal = std.dwarf.TAG.base_type }, // tag
794 MetadataAbbrev, // name
795 .{ .vbr = 6 }, // size in bits
796 .{ .literal = 0 }, // align in bits
797 .{ .vbr = 8 }, // encoding
798 .{ .literal = 0 }, // flags
799 };
800
801 name: Builder.MetadataString,
802 size_in_bits: u64,
803 encoding: u32,
804 };
805
806 pub const CompositeType = struct {
807 pub const ops = [_]AbbrevOp{
808 .{ .literal = 18 },
809 .{ .literal = 0 | 0x2 }, // is distinct | is not used in old type ref
810 .{ .fixed = 32 }, // tag
811 MetadataAbbrev, // name
812 MetadataAbbrev, // file
813 LineAbbrev, // line
814 MetadataAbbrev, // scope
815 MetadataAbbrev, // underlying type
816 .{ .vbr = 6 }, // size in bits
817 .{ .vbr = 6 }, // align in bits
818 .{ .literal = 0 }, // offset in bits
819 .{ .fixed = 32 }, // flags
820 MetadataAbbrev, // elements
821 .{ .literal = 0 }, // runtime lang
822 .{ .literal = 0 }, // vtable holder
823 .{ .literal = 0 }, // template params
824 .{ .literal = 0 }, // raw id
825 .{ .literal = 0 }, // discriminator
826 .{ .literal = 0 }, // data location
827 .{ .literal = 0 }, // associated
828 .{ .literal = 0 }, // allocated
829 .{ .literal = 0 }, // rank
830 .{ .literal = 0 }, // annotations
831 };
832
833 tag: u32,
834 name: Builder.MetadataString,
835 file: Builder.Metadata,
836 line: u32,
837 scope: Builder.Metadata,
838 underlying_type: Builder.Metadata,
839 size_in_bits: u64,
840 align_in_bits: u64,
841 flags: Builder.Metadata.DIFlags,
842 elements: Builder.Metadata,
843 };
844
845 pub const DerivedType = struct {
846 pub const ops = [_]AbbrevOp{
847 .{ .literal = 17 },
848 .{ .literal = 0 }, // is distinct
849 .{ .fixed = 32 }, // tag
850 MetadataAbbrev, // name
851 MetadataAbbrev, // file
852 LineAbbrev, // line
853 MetadataAbbrev, // scope
854 MetadataAbbrev, // underlying type
855 .{ .vbr = 6 }, // size in bits
856 .{ .vbr = 6 }, // align in bits
857 .{ .vbr = 6 }, // offset in bits
858 .{ .literal = 0 }, // flags
859 .{ .literal = 0 }, // extra data
860 };
861
862 tag: u32,
863 name: Builder.MetadataString,
864 file: Builder.Metadata,
865 line: u32,
866 scope: Builder.Metadata,
867 underlying_type: Builder.Metadata,
868 size_in_bits: u64,
869 align_in_bits: u64,
870 offset_in_bits: u64,
871 };
872
873 pub const SubroutineType = struct {
874 pub const ops = [_]AbbrevOp{
875 .{ .literal = 19 },
876 .{ .literal = 0 | 0x2 }, // is distinct | has no old type refs
877 .{ .literal = 0 }, // flags
878 MetadataAbbrev, // types
879 .{ .literal = 0 }, // cc
880 };
881
882 types: Builder.Metadata,
883 };
884
885 pub const Enumerator = struct {
886 pub const id = 14;
887
888 pub const Flags = packed struct(u3) {
889 distinct: bool = false,
890 unsigned: bool,
891 bigint: bool,
892 };
893
894 pub const ops = [_]AbbrevOp{
895 .{ .literal = Enumerator.id },
896 .{ .fixed = @bitSizeOf(Flags) }, // flags
897 .{ .vbr = 6 }, // bit width
898 MetadataAbbrev, // name
899 .{ .vbr = 16 }, // integer value
900 };
901
902 flags: Flags,
903 bit_width: u32,
904 name: Builder.MetadataString,
905 value: u64,
906 };
907
908 pub const Subrange = struct {
909 pub const ops = [_]AbbrevOp{
910 .{ .literal = 13 },
911 .{ .literal = 0b10 }, // is distinct | version
912 MetadataAbbrev, // count
913 MetadataAbbrev, // lower bound
914 .{ .literal = 0 }, // upper bound
915 .{ .literal = 0 }, // stride
916 };
917
918 count: Builder.Metadata,
919 lower_bound: Builder.Metadata,
920 };
921
922 pub const Expression = struct {
923 pub const ops = [_]AbbrevOp{
924 .{ .literal = 29 },
925 .{ .literal = 0 | (3 << 1) }, // is distinct | version
926 MetadataArrayAbbrev, // elements
927 };
928
929 elements: []const u32,
930 };
931
932 pub const Node = struct {
933 pub const ops = [_]AbbrevOp{
934 .{ .literal = 3 },
935 MetadataArrayAbbrev, // elements
936 };
937
938 elements: []const Builder.Metadata,
939 };
940
941 pub const LocalVar = struct {
942 pub const ops = [_]AbbrevOp{
943 .{ .literal = 28 },
944 .{ .literal = 0b10 }, // is distinct | has alignment
945 MetadataAbbrev, // scope
946 MetadataAbbrev, // name
947 MetadataAbbrev, // file
948 LineAbbrev, // line
949 MetadataAbbrev, // type
950 .{ .literal = 0 }, // arg
951 .{ .literal = 0 }, // flags
952 .{ .literal = 0 }, // align bits
953 .{ .literal = 0 }, // annotations
954 };
955
956 scope: Builder.Metadata,
957 name: Builder.MetadataString,
958 file: Builder.Metadata,
959 line: u32,
960 ty: Builder.Metadata,
961 };
962
963 pub const Parameter = struct {
964 pub const ops = [_]AbbrevOp{
965 .{ .literal = 28 },
966 .{ .literal = 0b10 }, // is distinct | has alignment
967 MetadataAbbrev, // scope
968 MetadataAbbrev, // name
969 MetadataAbbrev, // file
970 LineAbbrev, // line
971 MetadataAbbrev, // type
972 .{ .vbr = 4 }, // arg
973 .{ .literal = 0 }, // flags
974 .{ .literal = 0 }, // align bits
975 .{ .literal = 0 }, // annotations
976 };
977
978 scope: Builder.Metadata,
979 name: Builder.MetadataString,
980 file: Builder.Metadata,
981 line: u32,
982 ty: Builder.Metadata,
983 arg: u32,
984 };
985
986 pub const GlobalVar = struct {
987 pub const ops = [_]AbbrevOp{
988 .{ .literal = 27 },
989 .{ .literal = 0b101 }, // is distinct | version
990 MetadataAbbrev, // scope
991 MetadataAbbrev, // name
992 MetadataAbbrev, // linkage name
993 MetadataAbbrev, // file
994 LineAbbrev, // line
995 MetadataAbbrev, // type
996 .{ .fixed = 1 }, // local
997 .{ .literal = 1 }, // defined
998 .{ .literal = 0 }, // static data members declaration
999 .{ .literal = 0 }, // template params
1000 .{ .literal = 0 }, // align in bits
1001 .{ .literal = 0 }, // annotations
1002 };
1003
1004 scope: Builder.Metadata,
1005 name: Builder.MetadataString,
1006 linkage_name: Builder.MetadataString,
1007 file: Builder.Metadata,
1008 line: u32,
1009 ty: Builder.Metadata,
1010 local: bool,
1011 };
1012
1013 pub const GlobalVarExpression = struct {
1014 pub const ops = [_]AbbrevOp{
1015 .{ .literal = 37 },
1016 .{ .literal = 0 }, // is distinct
1017 MetadataAbbrev, // variable
1018 MetadataAbbrev, // expression
1019 };
1020
1021 variable: Builder.Metadata,
1022 expression: Builder.Metadata,
1023 };
1024
1025 pub const Constant = struct {
1026 pub const ops = [_]AbbrevOp{
1027 .{ .literal = 2 },
1028 MetadataAbbrev, // type
1029 MetadataAbbrev, // value
1030 };
1031
1032 ty: Builder.Type,
1033 constant: Builder.Constant,
1034 };
1035
1036 pub const Name = struct {
1037 pub const ops = [_]AbbrevOp{
1038 .{ .literal = 4 },
1039 .{ .array_fixed = 8 }, // name
1040 };
1041
1042 name: []const u8,
1043 };
1044
1045 pub const NamedNode = struct {
1046 pub const ops = [_]AbbrevOp{
1047 .{ .literal = 10 },
1048 MetadataArrayAbbrev, // elements
1049 };
1050
1051 elements: []const Builder.Metadata,
1052 };
1053
1054 pub const GlobalDeclAttachment = struct {
1055 pub const ops = [_]AbbrevOp{
1056 .{ .literal = 36 },
1057 ValueAbbrev, // value id
1058 .{ .fixed = 1 }, // kind
1059 MetadataAbbrev, // elements
1060 };
1061
1062 value: Builder.Constant,
1063 kind: MetadataKind,
1064 metadata: Builder.Metadata,
1065 };
1066};
1067
1068pub const FunctionMetadataBlock = struct {
1069 pub const id = 15;
1070
1071 pub const abbrevs = [_]type{
1072 Value,
1073 };
1074
1075 pub const Value = struct {
1076 pub const ops = [_]AbbrevOp{
1077 .{ .literal = 2 },
1078 .{ .fixed = 32 }, // variable
1079 .{ .fixed = 32 }, // expression
1080 };
1081
1082 ty: Builder.Type,
1083 value: Builder.Value,
1084 };
1085};
1086
1087pub const FunctionBlock = struct {
1088 pub const id = 12;
1089
1090 pub const abbrevs = [_]type{
1091 DeclareBlocks,
1092 Call,
1093 CallFast,
1094 FNeg,
1095 FNegFast,
1096 Binary,
1097 BinaryFast,
1098 Cmp,
1099 CmpFast,
1100 Select,
1101 SelectFast,
1102 Cast,
1103 Alloca,
1104 GetElementPtr,
1105 ExtractValue,
1106 InsertValue,
1107 ExtractElement,
1108 InsertElement,
1109 ShuffleVector,
1110 RetVoid,
1111 Ret,
1112 Unreachable,
1113 Load,
1114 LoadAtomic,
1115 Store,
1116 StoreAtomic,
1117 BrUnconditional,
1118 BrConditional,
1119 VaArg,
1120 AtomicRmw,
1121 CmpXchg,
1122 Fence,
1123 DebugLoc,
1124 DebugLocAgain,
1125 };
1126
1127 pub const DeclareBlocks = struct {
1128 pub const ops = [_]AbbrevOp{
1129 .{ .literal = 1 },
1130 .{ .vbr = 8 },
1131 };
1132 num_blocks: usize,
1133 };
1134
1135 pub const Call = struct {
1136 pub const CallType = packed struct(u17) {
1137 tail: bool = false,
1138 call_conv: Builder.CallConv,
1139 reserved: u3 = 0,
1140 must_tail: bool = false,
1141 // We always use the explicit type version as that is what LLVM does
1142 explicit_type: bool = true,
1143 no_tail: bool = false,
1144 };
1145 pub const ops = [_]AbbrevOp{
1146 .{ .literal = 34 },
1147 .{ .fixed_runtime = Builder.FunctionAttributes },
1148 .{ .fixed = @bitSizeOf(CallType) },
1149 .{ .fixed_runtime = Builder.Type },
1150 ValueAbbrev, // Callee
1151 ValueArrayAbbrev, // Args
1152 };
1153
1154 attributes: Builder.FunctionAttributes,
1155 call_type: CallType,
1156 type_id: Builder.Type,
1157 callee: Builder.Value,
1158 args: []const Builder.Value,
1159 };
1160
1161 pub const CallFast = struct {
1162 const CallType = packed struct(u18) {
1163 tail: bool = false,
1164 call_conv: Builder.CallConv,
1165 reserved: u3 = 0,
1166 must_tail: bool = false,
1167 // We always use the explicit type version as that is what LLVM does
1168 explicit_type: bool = true,
1169 no_tail: bool = false,
1170 fast: bool = true,
1171 };
1172
1173 pub const ops = [_]AbbrevOp{
1174 .{ .literal = 34 },
1175 .{ .fixed_runtime = Builder.FunctionAttributes },
1176 .{ .fixed = @bitSizeOf(CallType) },
1177 .{ .fixed = @bitSizeOf(Builder.FastMath) },
1178 .{ .fixed_runtime = Builder.Type },
1179 ValueAbbrev, // Callee
1180 ValueArrayAbbrev, // Args
1181 };
1182
1183 attributes: Builder.FunctionAttributes,
1184 call_type: CallType,
1185 fast_math: Builder.FastMath,
1186 type_id: Builder.Type,
1187 callee: Builder.Value,
1188 args: []const Builder.Value,
1189 };
1190
1191 pub const FNeg = struct {
1192 pub const ops = [_]AbbrevOp{
1193 .{ .literal = 56 },
1194 ValueAbbrev,
1195 .{ .literal = 0 },
1196 };
1197
1198 val: u32,
1199 };
1200
1201 pub const FNegFast = struct {
1202 pub const ops = [_]AbbrevOp{
1203 .{ .literal = 56 },
1204 ValueAbbrev,
1205 .{ .literal = 0 },
1206 .{ .fixed = @bitSizeOf(Builder.FastMath) },
1207 };
1208
1209 val: u32,
1210 fast_math: Builder.FastMath,
1211 };
1212
1213 pub const Binary = struct {
1214 const BinaryOpcode = Builder.BinaryOpcode;
1215 pub const ops = [_]AbbrevOp{
1216 .{ .literal = 2 },
1217 ValueAbbrev,
1218 ValueAbbrev,
1219 .{ .fixed = @bitSizeOf(BinaryOpcode) },
1220 };
1221
1222 lhs: u32,
1223 rhs: u32,
1224 opcode: BinaryOpcode,
1225 };
1226
1227 pub const BinaryFast = struct {
1228 const BinaryOpcode = Builder.BinaryOpcode;
1229 pub const ops = [_]AbbrevOp{
1230 .{ .literal = 2 },
1231 ValueAbbrev,
1232 ValueAbbrev,
1233 .{ .fixed = @bitSizeOf(BinaryOpcode) },
1234 .{ .fixed = @bitSizeOf(Builder.FastMath) },
1235 };
1236
1237 lhs: u32,
1238 rhs: u32,
1239 opcode: BinaryOpcode,
1240 fast_math: Builder.FastMath,
1241 };
1242
1243 pub const Cmp = struct {
1244 const CmpPredicate = Builder.CmpPredicate;
1245 pub const ops = [_]AbbrevOp{
1246 .{ .literal = 28 },
1247 ValueAbbrev,
1248 ValueAbbrev,
1249 .{ .fixed = @bitSizeOf(CmpPredicate) },
1250 };
1251
1252 lhs: u32,
1253 rhs: u32,
1254 pred: CmpPredicate,
1255 };
1256
1257 pub const CmpFast = struct {
1258 const CmpPredicate = Builder.CmpPredicate;
1259 pub const ops = [_]AbbrevOp{
1260 .{ .literal = 28 },
1261 ValueAbbrev,
1262 ValueAbbrev,
1263 .{ .fixed = @bitSizeOf(CmpPredicate) },
1264 .{ .fixed = @bitSizeOf(Builder.FastMath) },
1265 };
1266
1267 lhs: u32,
1268 rhs: u32,
1269 pred: CmpPredicate,
1270 fast_math: Builder.FastMath,
1271 };
1272
1273 pub const Select = struct {
1274 pub const ops = [_]AbbrevOp{
1275 .{ .literal = 29 },
1276 ValueAbbrev,
1277 ValueAbbrev,
1278 ValueAbbrev,
1279 };
1280
1281 lhs: u32,
1282 rhs: u32,
1283 cond: u32,
1284 };
1285
1286 pub const SelectFast = struct {
1287 pub const ops = [_]AbbrevOp{
1288 .{ .literal = 29 },
1289 ValueAbbrev,
1290 ValueAbbrev,
1291 ValueAbbrev,
1292 .{ .fixed = @bitSizeOf(Builder.FastMath) },
1293 };
1294
1295 lhs: u32,
1296 rhs: u32,
1297 cond: u32,
1298 fast_math: Builder.FastMath,
1299 };
1300
1301 pub const Cast = struct {
1302 const CastOpcode = Builder.CastOpcode;
1303 pub const ops = [_]AbbrevOp{
1304 .{ .literal = 3 },
1305 ValueAbbrev,
1306 .{ .fixed_runtime = Builder.Type },
1307 .{ .fixed = @bitSizeOf(CastOpcode) },
1308 };
1309
1310 val: u32,
1311 type_index: Builder.Type,
1312 opcode: CastOpcode,
1313 };
1314
1315 pub const Alloca = struct {
1316 pub const Flags = packed struct(u11) {
1317 align_lower: u5,
1318 inalloca: bool,
1319 explicit_type: bool,
1320 swift_error: bool,
1321 align_upper: u3,
1322 };
1323 pub const ops = [_]AbbrevOp{
1324 .{ .literal = 19 },
1325 .{ .fixed_runtime = Builder.Type },
1326 .{ .fixed_runtime = Builder.Type },
1327 ValueAbbrev,
1328 .{ .fixed = @bitSizeOf(Flags) },
1329 };
1330
1331 inst_type: Builder.Type,
1332 len_type: Builder.Type,
1333 len_value: u32,
1334 flags: Flags,
1335 };
1336
1337 pub const RetVoid = struct {
1338 pub const ops = [_]AbbrevOp{
1339 .{ .literal = 10 },
1340 };
1341 };
1342
1343 pub const Ret = struct {
1344 pub const ops = [_]AbbrevOp{
1345 .{ .literal = 10 },
1346 ValueAbbrev,
1347 };
1348 val: u32,
1349 };
1350
1351 pub const GetElementPtr = struct {
1352 pub const ops = [_]AbbrevOp{
1353 .{ .literal = 43 },
1354 .{ .fixed = 1 },
1355 .{ .fixed_runtime = Builder.Type },
1356 ValueAbbrev,
1357 ValueArrayAbbrev,
1358 };
1359
1360 is_inbounds: bool,
1361 type_index: Builder.Type,
1362 base: Builder.Value,
1363 indices: []const Builder.Value,
1364 };
1365
1366 pub const ExtractValue = struct {
1367 pub const ops = [_]AbbrevOp{
1368 .{ .literal = 26 },
1369 ValueAbbrev,
1370 ValueArrayAbbrev,
1371 };
1372
1373 val: u32,
1374 indices: []const u32,
1375 };
1376
1377 pub const InsertValue = struct {
1378 pub const ops = [_]AbbrevOp{
1379 .{ .literal = 27 },
1380 ValueAbbrev,
1381 ValueAbbrev,
1382 ValueArrayAbbrev,
1383 };
1384
1385 val: u32,
1386 elem: u32,
1387 indices: []const u32,
1388 };
1389
1390 pub const ExtractElement = struct {
1391 pub const ops = [_]AbbrevOp{
1392 .{ .literal = 6 },
1393 ValueAbbrev,
1394 ValueAbbrev,
1395 };
1396
1397 val: u32,
1398 index: u32,
1399 };
1400
1401 pub const InsertElement = struct {
1402 pub const ops = [_]AbbrevOp{
1403 .{ .literal = 7 },
1404 ValueAbbrev,
1405 ValueAbbrev,
1406 ValueAbbrev,
1407 };
1408
1409 val: u32,
1410 elem: u32,
1411 index: u32,
1412 };
1413
1414 pub const ShuffleVector = struct {
1415 pub const ops = [_]AbbrevOp{
1416 .{ .literal = 8 },
1417 ValueAbbrev,
1418 ValueAbbrev,
1419 ValueAbbrev,
1420 };
1421
1422 lhs: u32,
1423 rhs: u32,
1424 mask: u32,
1425 };
1426
1427 pub const Unreachable = struct {
1428 pub const ops = [_]AbbrevOp{
1429 .{ .literal = 15 },
1430 };
1431 };
1432
1433 pub const Load = struct {
1434 pub const ops = [_]AbbrevOp{
1435 .{ .literal = 20 },
1436 ValueAbbrev,
1437 .{ .fixed_runtime = Builder.Type },
1438 .{ .fixed = @bitSizeOf(Builder.Alignment) },
1439 .{ .fixed = 1 },
1440 };
1441 ptr: u32,
1442 ty: Builder.Type,
1443 alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)),
1444 is_volatile: bool,
1445 };
1446
1447 pub const LoadAtomic = struct {
1448 pub const ops = [_]AbbrevOp{
1449 .{ .literal = 41 },
1450 ValueAbbrev,
1451 .{ .fixed_runtime = Builder.Type },
1452 .{ .fixed = @bitSizeOf(Builder.Alignment) },
1453 .{ .fixed = 1 },
1454 .{ .fixed = @bitSizeOf(Builder.AtomicOrdering) },
1455 .{ .fixed = @bitSizeOf(Builder.SyncScope) },
1456 };
1457 ptr: u32,
1458 ty: Builder.Type,
1459 alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)),
1460 is_volatile: bool,
1461 success_ordering: Builder.AtomicOrdering,
1462 sync_scope: Builder.SyncScope,
1463 };
1464
1465 pub const Store = struct {
1466 pub const ops = [_]AbbrevOp{
1467 .{ .literal = 44 },
1468 ValueAbbrev,
1469 ValueAbbrev,
1470 .{ .fixed = @bitSizeOf(Builder.Alignment) },
1471 .{ .fixed = 1 },
1472 };
1473 ptr: u32,
1474 val: u32,
1475 alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)),
1476 is_volatile: bool,
1477 };
1478
1479 pub const StoreAtomic = struct {
1480 pub const ops = [_]AbbrevOp{
1481 .{ .literal = 45 },
1482 ValueAbbrev,
1483 ValueAbbrev,
1484 .{ .fixed = @bitSizeOf(Builder.Alignment) },
1485 .{ .fixed = 1 },
1486 .{ .fixed = @bitSizeOf(Builder.AtomicOrdering) },
1487 .{ .fixed = @bitSizeOf(Builder.SyncScope) },
1488 };
1489 ptr: u32,
1490 val: u32,
1491 alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)),
1492 is_volatile: bool,
1493 success_ordering: Builder.AtomicOrdering,
1494 sync_scope: Builder.SyncScope,
1495 };
1496
1497 pub const BrUnconditional = struct {
1498 pub const ops = [_]AbbrevOp{
1499 .{ .literal = 11 },
1500 BlockAbbrev,
1501 };
1502 block: u32,
1503 };
1504
1505 pub const BrConditional = struct {
1506 pub const ops = [_]AbbrevOp{
1507 .{ .literal = 11 },
1508 BlockAbbrev,
1509 BlockAbbrev,
1510 BlockAbbrev,
1511 };
1512 then_block: u32,
1513 else_block: u32,
1514 condition: u32,
1515 };
1516
1517 pub const VaArg = struct {
1518 pub const ops = [_]AbbrevOp{
1519 .{ .literal = 23 },
1520 .{ .fixed_runtime = Builder.Type },
1521 ValueAbbrev,
1522 .{ .fixed_runtime = Builder.Type },
1523 };
1524 list_type: Builder.Type,
1525 list: u32,
1526 type: Builder.Type,
1527 };
1528
1529 pub const AtomicRmw = struct {
1530 pub const ops = [_]AbbrevOp{
1531 .{ .literal = 59 },
1532 ValueAbbrev,
1533 ValueAbbrev,
1534 .{ .fixed = @bitSizeOf(Builder.Function.Instruction.AtomicRmw.Operation) },
1535 .{ .fixed = 1 },
1536 .{ .fixed = @bitSizeOf(Builder.AtomicOrdering) },
1537 .{ .fixed = @bitSizeOf(Builder.SyncScope) },
1538 .{ .fixed = @bitSizeOf(Builder.Alignment) },
1539 };
1540 ptr: u32,
1541 val: u32,
1542 operation: Builder.Function.Instruction.AtomicRmw.Operation,
1543 is_volatile: bool,
1544 success_ordering: Builder.AtomicOrdering,
1545 sync_scope: Builder.SyncScope,
1546 alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)),
1547 };
1548
1549 pub const CmpXchg = struct {
1550 pub const ops = [_]AbbrevOp{
1551 .{ .literal = 46 },
1552 ValueAbbrev,
1553 ValueAbbrev,
1554 ValueAbbrev,
1555 .{ .fixed = 1 },
1556 .{ .fixed = @bitSizeOf(Builder.AtomicOrdering) },
1557 .{ .fixed = @bitSizeOf(Builder.SyncScope) },
1558 .{ .fixed = @bitSizeOf(Builder.AtomicOrdering) },
1559 .{ .fixed = 1 },
1560 .{ .fixed = @bitSizeOf(Builder.Alignment) },
1561 };
1562 ptr: u32,
1563 cmp: u32,
1564 new: u32,
1565 is_volatile: bool,
1566 success_ordering: Builder.AtomicOrdering,
1567 sync_scope: Builder.SyncScope,
1568 failure_ordering: Builder.AtomicOrdering,
1569 is_weak: bool,
1570 alignment: std.meta.Int(.unsigned, @bitSizeOf(Builder.Alignment)),
1571 };
1572
1573 pub const Fence = struct {
1574 pub const ops = [_]AbbrevOp{
1575 .{ .literal = 36 },
1576 .{ .fixed = @bitSizeOf(Builder.AtomicOrdering) },
1577 .{ .fixed = @bitSizeOf(Builder.SyncScope) },
1578 };
1579 ordering: Builder.AtomicOrdering,
1580 sync_scope: Builder.SyncScope,
1581 };
1582
1583 pub const DebugLoc = struct {
1584 pub const ops = [_]AbbrevOp{
1585 .{ .literal = 35 },
1586 .{ .fixed = 32 },
1587 .{ .fixed = 32 },
1588 .{ .fixed = 32 },
1589 .{ .fixed = 32 },
1590 .{ .fixed = 1 },
1591 };
1592 line: u32,
1593 column: u32,
1594 scope: Builder.Metadata,
1595 inlined_at: Builder.Metadata,
1596 is_implicit: bool,
1597 };
1598
1599 pub const DebugLocAgain = struct {
1600 pub const ops = [_]AbbrevOp{
1601 .{ .literal = 33 },
1602 };
1603 };
1604};
1605
1606pub const FunctionValueSymbolTable = struct {
1607 pub const id = 14;
1608
1609 pub const abbrevs = [_]type{
1610 BlockEntry,
1611 };
1612
1613 pub const BlockEntry = struct {
1614 pub const ops = [_]AbbrevOp{
1615 .{ .literal = 2 },
1616 ValueAbbrev,
1617 .{ .array_fixed = 8 },
1618 };
1619 value_id: u32,
1620 string: []const u8,
1621 };
1622};
1623
1624pub const Strtab = struct {
1625 pub const id = 23;
1626
1627 pub const abbrevs = [_]type{Blob};
1628
1629 pub const Blob = struct {
1630 pub const ops = [_]AbbrevOp{
1631 .{ .literal = 1 },
1632 .blob,
1633 };
1634 blob: []const u8,
1635 };
1636};
src/link.zig+1-2
...@@ -839,10 +839,9 @@ pub const File = struct {...@@ -839,10 +839,9 @@ pub const File = struct {
839 }839 }
840840
841 const llvm_bindings = @import("codegen/llvm/bindings.zig");841 const llvm_bindings = @import("codegen/llvm/bindings.zig");
842 const Builder = @import("codegen/llvm/Builder.zig");
843 const llvm = @import("codegen/llvm.zig");842 const llvm = @import("codegen/llvm.zig");
844 const target = comp.root_mod.resolved_target.result;843 const target = comp.root_mod.resolved_target.result;
845 Builder.initializeLLVMTarget(target.cpu.arch);844 llvm.initializeLLVMTarget(target.cpu.arch);
846 const os_tag = llvm.targetOs(target.os.tag);845 const os_tag = llvm.targetOs(target.os.tag);
847 const bad = llvm_bindings.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_tag);846 const bad = llvm_bindings.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_tag);
848 if (bad) return error.UnableToWriteArchive;847 if (bad) return error.UnableToWriteArchive;
src/zig_llvm.cpp-624
...@@ -24,9 +24,7 @@...@@ -24,9 +24,7 @@
24#include <llvm/Analysis/TargetLibraryInfo.h>24#include <llvm/Analysis/TargetLibraryInfo.h>
25#include <llvm/Analysis/TargetTransformInfo.h>25#include <llvm/Analysis/TargetTransformInfo.h>
26#include <llvm/Bitcode/BitcodeWriter.h>26#include <llvm/Bitcode/BitcodeWriter.h>
27#include <llvm/IR/DIBuilder.h>
28#include <llvm/IR/DiagnosticInfo.h>27#include <llvm/IR/DiagnosticInfo.h>
29#include <llvm/IR/IRBuilder.h>
30#include <llvm/IR/InlineAsm.h>28#include <llvm/IR/InlineAsm.h>
31#include <llvm/IR/Instructions.h>29#include <llvm/IR/Instructions.h>
32#include <llvm/IR/LegacyPassManager.h>30#include <llvm/IR/LegacyPassManager.h>
...@@ -382,566 +380,10 @@ void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {...@@ -382,566 +380,10 @@ void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
382 unwrap(context_ref)->setOptPassGate(opt_bisect);380 unwrap(context_ref)->setOptPassGate(opt_bisect);
383}381}
384382
385LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, LLVMTypeRef FunctionTy, unsigned AddressSpace) {
386 Function* func = Function::Create(unwrap<FunctionType>(FunctionTy), GlobalValue::ExternalLinkage, AddressSpace, Name, unwrap(M));
387 return wrap(func);
388}
389
390void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind) {
391 CallInst::TailCallKind TCK;
392 switch (TailCallKind) {
393 case ZigLLVMTailCallKindNone:
394 TCK = CallInst::TCK_None;
395 break;
396 case ZigLLVMTailCallKindTail:
397 TCK = CallInst::TCK_Tail;
398 break;
399 case ZigLLVMTailCallKindMustTail:
400 TCK = CallInst::TCK_MustTail;
401 break;
402 case ZigLLVMTailCallKindNoTail:
403 TCK = CallInst::TCK_NoTail;
404 break;
405 }
406 unwrap<CallInst>(Call)->setTailCallKind(TCK);
407}
408
409void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) {
410 assert( isa<Function>(unwrap(fn)) );
411 Function *unwrapped_function = reinterpret_cast<Function*>(unwrap(fn));
412 unwrapped_function->setSubprogram(reinterpret_cast<DISubprogram*>(subprogram));
413}
414
415
416ZigLLVMDIType *ZigLLVMCreateDebugPointerType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *pointee_type,
417 uint64_t size_in_bits, uint64_t align_in_bits, const char *name)
418{
419 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createPointerType(
420 reinterpret_cast<DIType*>(pointee_type), size_in_bits, align_in_bits, std::optional<unsigned>(), name);
421 return reinterpret_cast<ZigLLVMDIType*>(di_type);
422}
423
424ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const char *name,
425 uint64_t size_in_bits, unsigned encoding)
426{
427 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createBasicType(
428 name, size_in_bits, encoding);
429 return reinterpret_cast<ZigLLVMDIType*>(di_type);
430}
431
432struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
433 uint64_t SizeInBits, uint32_t AlignInBits, struct ZigLLVMDIType *Ty, uint32_t elem_count)
434{
435 SmallVector<Metadata *, 1> subrange;
436 subrange.push_back(reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateSubrange(0, elem_count));
437 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createVectorType(
438 SizeInBits,
439 AlignInBits,
440 reinterpret_cast<DIType*>(Ty),
441 reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(subrange));
442 return reinterpret_cast<ZigLLVMDIType*>(di_type);
443}
444
445ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits,
446 uint64_t align_in_bits, ZigLLVMDIType *elem_type, int64_t elem_count)
447{
448 SmallVector<Metadata *, 1> subrange;
449 subrange.push_back(reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateSubrange(0, elem_count));
450 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createArrayType(
451 size_in_bits, align_in_bits,
452 reinterpret_cast<DIType*>(elem_type),
453 reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(subrange));
454 return reinterpret_cast<ZigLLVMDIType*>(di_type);
455}
456
457ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(ZigLLVMDIBuilder *dibuilder, const char *name, uint64_t val, bool isUnsigned) {
458 DIEnumerator *di_enumerator = reinterpret_cast<DIBuilder*>(dibuilder)->createEnumerator(name, val, isUnsigned);
459 return reinterpret_cast<ZigLLVMDIEnumerator*>(di_enumerator);
460}
461
462ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision(ZigLLVMDIBuilder *dibuilder,
463 const char *name, unsigned NumWords, const uint64_t Words[], unsigned int bits, bool isUnsigned)
464{
465 DIEnumerator *di_enumerator = reinterpret_cast<DIBuilder*>(dibuilder)->createEnumerator(name,
466 APSInt(APInt(bits, ArrayRef(Words, NumWords)), isUnsigned));
467 return reinterpret_cast<ZigLLVMDIEnumerator*>(di_enumerator);
468}
469
470ZigLLVMDIType *ZigLLVMCreateDebugEnumerationType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
471 const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits,
472 uint64_t align_in_bits, ZigLLVMDIEnumerator **enumerator_array, int enumerator_array_len,
473 ZigLLVMDIType *underlying_type, const char *unique_id)
474{
475 SmallVector<Metadata *, 8> fields;
476 for (int i = 0; i < enumerator_array_len; i += 1) {
477 DIEnumerator *dienumerator = reinterpret_cast<DIEnumerator*>(enumerator_array[i]);
478 fields.push_back(dienumerator);
479 }
480 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createEnumerationType(
481 reinterpret_cast<DIScope*>(scope),
482 name,
483 reinterpret_cast<DIFile*>(file),
484 line_number, size_in_bits, align_in_bits,
485 reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(fields),
486 reinterpret_cast<DIType*>(underlying_type),
487 unique_id);
488 return reinterpret_cast<ZigLLVMDIType*>(di_type);
489}
490
491ZigLLVMDIType *ZigLLVMCreateDebugMemberType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
492 const char *name, ZigLLVMDIFile *file, unsigned line, uint64_t size_in_bits,
493 uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags, ZigLLVMDIType *type)
494{
495 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createMemberType(
496 reinterpret_cast<DIScope*>(scope),
497 name,
498 reinterpret_cast<DIFile*>(file),
499 line, size_in_bits, align_in_bits, offset_in_bits,
500 static_cast<DINode::DIFlags>(flags),
501 reinterpret_cast<DIType*>(type));
502 return reinterpret_cast<ZigLLVMDIType*>(di_type);
503}
504
505ZigLLVMDIType *ZigLLVMCreateDebugUnionType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
506 const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits,
507 uint64_t align_in_bits, unsigned flags, ZigLLVMDIType **types_array, int types_array_len,
508 unsigned run_time_lang, const char *unique_id)
509{
510 SmallVector<Metadata *, 8> fields;
511 for (int i = 0; i < types_array_len; i += 1) {
512 DIType *ditype = reinterpret_cast<DIType*>(types_array[i]);
513 fields.push_back(ditype);
514 }
515 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createUnionType(
516 reinterpret_cast<DIScope*>(scope),
517 name,
518 reinterpret_cast<DIFile*>(file),
519 line_number, size_in_bits, align_in_bits,
520 static_cast<DINode::DIFlags>(flags),
521 reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(fields),
522 run_time_lang, unique_id);
523 return reinterpret_cast<ZigLLVMDIType*>(di_type);
524}
525
526ZigLLVMDIType *ZigLLVMCreateDebugStructType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
527 const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits,
528 uint64_t align_in_bits, unsigned flags, ZigLLVMDIType *derived_from,
529 ZigLLVMDIType **types_array, int types_array_len, unsigned run_time_lang, ZigLLVMDIType *vtable_holder,
530 const char *unique_id)
531{
532 SmallVector<Metadata *, 8> fields;
533 for (int i = 0; i < types_array_len; i += 1) {
534 DIType *ditype = reinterpret_cast<DIType*>(types_array[i]);
535 fields.push_back(ditype);
536 }
537 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createStructType(
538 reinterpret_cast<DIScope*>(scope),
539 name,
540 reinterpret_cast<DIFile*>(file),
541 line_number, size_in_bits, align_in_bits,
542 static_cast<DINode::DIFlags>(flags),
543 reinterpret_cast<DIType*>(derived_from),
544 reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(fields),
545 run_time_lang,
546 reinterpret_cast<DIType*>(vtable_holder),
547 unique_id);
548 return reinterpret_cast<ZigLLVMDIType*>(di_type);
549}
550
551ZigLLVMDIType *ZigLLVMCreateReplaceableCompositeType(ZigLLVMDIBuilder *dibuilder, unsigned tag,
552 const char *name, ZigLLVMDIScope *scope, ZigLLVMDIFile *file, unsigned line)
553{
554 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createReplaceableCompositeType(
555 tag, name,
556 reinterpret_cast<DIScope*>(scope),
557 reinterpret_cast<DIFile*>(file),
558 line);
559 return reinterpret_cast<ZigLLVMDIType*>(di_type);
560}
561
562ZigLLVMDIType *ZigLLVMCreateDebugForwardDeclType(ZigLLVMDIBuilder *dibuilder, unsigned tag,
563 const char *name, ZigLLVMDIScope *scope, ZigLLVMDIFile *file, unsigned line)
564{
565 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createForwardDecl(
566 tag, name,
567 reinterpret_cast<DIScope*>(scope),
568 reinterpret_cast<DIFile*>(file),
569 line);
570 return reinterpret_cast<ZigLLVMDIType*>(di_type);
571}
572
573void ZigLLVMReplaceTemporary(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *type,
574 ZigLLVMDIType *replacement)
575{
576 reinterpret_cast<DIBuilder*>(dibuilder)->replaceTemporary(
577 TempDIType(reinterpret_cast<DIType*>(type)),
578 reinterpret_cast<DIType*>(replacement));
579}
580
581void ZigLLVMReplaceDebugArrays(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *type,
582 ZigLLVMDIType **types_array, int types_array_len)
583{
584 SmallVector<Metadata *, 8> fields;
585 for (int i = 0; i < types_array_len; i += 1) {
586 DIType *ditype = reinterpret_cast<DIType*>(types_array[i]);
587 fields.push_back(ditype);
588 }
589 DICompositeType *composite_type = (DICompositeType*)reinterpret_cast<DIType*>(type);
590 reinterpret_cast<DIBuilder*>(dibuilder)->replaceArrays(
591 composite_type,
592 reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(fields));
593}
594
595ZigLLVMDIType *ZigLLVMCreateSubroutineType(ZigLLVMDIBuilder *dibuilder_wrapped,
596 ZigLLVMDIType **types_array, int types_array_len, unsigned flags)
597{
598 SmallVector<Metadata *, 8> types;
599 for (int i = 0; i < types_array_len; i += 1) {
600 DIType *ditype = reinterpret_cast<DIType*>(types_array[i]);
601 types.push_back(ditype);
602 }
603 DIBuilder *dibuilder = reinterpret_cast<DIBuilder*>(dibuilder_wrapped);
604 DISubroutineType *subroutine_type = dibuilder->createSubroutineType(
605 dibuilder->getOrCreateTypeArray(types),
606 static_cast<DINode::DIFlags>(flags));
607 DIType *ditype = subroutine_type;
608 return reinterpret_cast<ZigLLVMDIType*>(ditype);
609}
610
611unsigned ZigLLVMEncoding_DW_ATE_unsigned(void) {
612 return dwarf::DW_ATE_unsigned;
613}
614
615unsigned ZigLLVMEncoding_DW_ATE_signed(void) {
616 return dwarf::DW_ATE_signed;
617}
618
619unsigned ZigLLVMEncoding_DW_ATE_float(void) {
620 return dwarf::DW_ATE_float;
621}
622
623unsigned ZigLLVMEncoding_DW_ATE_boolean(void) {
624 return dwarf::DW_ATE_boolean;
625}
626
627unsigned ZigLLVMEncoding_DW_ATE_unsigned_char(void) {
628 return dwarf::DW_ATE_unsigned_char;
629}
630
631unsigned ZigLLVMEncoding_DW_ATE_signed_char(void) {
632 return dwarf::DW_ATE_signed_char;
633}
634
635unsigned ZigLLVMLang_DW_LANG_C99(void) {
636 return dwarf::DW_LANG_C99;
637}
638
639unsigned ZigLLVMTag_DW_variable(void) {
640 return dwarf::DW_TAG_variable;
641}
642
643unsigned ZigLLVMTag_DW_structure_type(void) {
644 return dwarf::DW_TAG_structure_type;
645}
646
647unsigned ZigLLVMTag_DW_enumeration_type(void) {
648 return dwarf::DW_TAG_enumeration_type;
649}
650
651unsigned ZigLLVMTag_DW_union_type(void) {
652 return dwarf::DW_TAG_union_type;
653}
654
655ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) {
656 DIBuilder *di_builder = new(std::nothrow) DIBuilder(*unwrap(module), allow_unresolved);
657 if (di_builder == nullptr)
658 return nullptr;
659 return reinterpret_cast<ZigLLVMDIBuilder *>(di_builder);
660}
661
662void ZigLLVMDisposeDIBuilder(ZigLLVMDIBuilder *dbuilder) {
663 DIBuilder *di_builder = reinterpret_cast<DIBuilder *>(dbuilder);
664 delete di_builder;
665}
666
667void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder,
668 unsigned int line, unsigned int column, ZigLLVMDIScope *scope)
669{
670 DIScope* di_scope = reinterpret_cast<DIScope*>(scope);
671 DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, column, di_scope, nullptr, false);
672 unwrap(builder)->SetCurrentDebugLocation(debug_loc);
673}
674
675void ZigLLVMSetCurrentDebugLocation2(LLVMBuilderRef builder, unsigned int line,
676 unsigned int column, ZigLLVMDIScope *scope, ZigLLVMDILocation *inlined_at)
677{
678 DIScope* di_scope = reinterpret_cast<DIScope*>(scope);
679 DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, column, di_scope,
680 reinterpret_cast<DILocation *>(inlined_at), false);
681 unwrap(builder)->SetCurrentDebugLocation(debug_loc);
682}
683
684void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder) {
685 unwrap(builder)->SetCurrentDebugLocation(DebugLoc());
686}
687
688
689ZigLLVMDILexicalBlock *ZigLLVMCreateLexicalBlock(ZigLLVMDIBuilder *dbuilder, ZigLLVMDIScope *scope,
690 ZigLLVMDIFile *file, unsigned line, unsigned col)
691{
692 DILexicalBlock *result = reinterpret_cast<DIBuilder*>(dbuilder)->createLexicalBlock(
693 reinterpret_cast<DIScope*>(scope),
694 reinterpret_cast<DIFile*>(file),
695 line,
696 col);
697 return reinterpret_cast<ZigLLVMDILexicalBlock*>(result);
698}
699
700ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(ZigLLVMDIBuilder *dbuilder,
701 ZigLLVMDIScope *scope, const char *name, ZigLLVMDIFile *file, unsigned line_no,
702 ZigLLVMDIType *type, bool always_preserve, unsigned flags)
703{
704 DILocalVariable *result = reinterpret_cast<DIBuilder*>(dbuilder)->createAutoVariable(
705 reinterpret_cast<DIScope*>(scope),
706 name,
707 reinterpret_cast<DIFile*>(file),
708 line_no,
709 reinterpret_cast<DIType*>(type),
710 always_preserve,
711 static_cast<DINode::DIFlags>(flags));
712 return reinterpret_cast<ZigLLVMDILocalVariable*>(result);
713}
714
715ZigLLVMDIGlobalVariableExpression *ZigLLVMCreateGlobalVariableExpression(ZigLLVMDIBuilder *dbuilder,
716 ZigLLVMDIScope *scope, const char *name, const char *linkage_name, ZigLLVMDIFile *file,
717 unsigned line_no, ZigLLVMDIType *di_type, bool is_local_to_unit)
718{
719 return reinterpret_cast<ZigLLVMDIGlobalVariableExpression*>(reinterpret_cast<DIBuilder*>(dbuilder)->createGlobalVariableExpression(
720 reinterpret_cast<DIScope*>(scope),
721 name,
722 linkage_name,
723 reinterpret_cast<DIFile*>(file),
724 line_no,
725 reinterpret_cast<DIType*>(di_type),
726 is_local_to_unit));
727}
728
729ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder,
730 ZigLLVMDIScope *scope, const char *name, ZigLLVMDIFile *file, unsigned line_no,
731 ZigLLVMDIType *type, bool always_preserve, unsigned flags, unsigned arg_no)
732{
733 assert(arg_no != 0);
734 DILocalVariable *result = reinterpret_cast<DIBuilder*>(dbuilder)->createParameterVariable(
735 reinterpret_cast<DIScope*>(scope),
736 name,
737 arg_no,
738 reinterpret_cast<DIFile*>(file),
739 line_no,
740 reinterpret_cast<DIType*>(type),
741 always_preserve,
742 static_cast<DINode::DIFlags>(flags));
743 return reinterpret_cast<ZigLLVMDILocalVariable*>(result);
744}
745
746ZigLLVMDIScope *ZigLLVMLexicalBlockToScope(ZigLLVMDILexicalBlock *lexical_block) {
747 DIScope *scope = reinterpret_cast<DILexicalBlock*>(lexical_block);
748 return reinterpret_cast<ZigLLVMDIScope*>(scope);
749}
750
751ZigLLVMDIScope *ZigLLVMCompileUnitToScope(ZigLLVMDICompileUnit *compile_unit) {
752 DIScope *scope = reinterpret_cast<DICompileUnit*>(compile_unit);
753 return reinterpret_cast<ZigLLVMDIScope*>(scope);
754}
755
756ZigLLVMDIScope *ZigLLVMFileToScope(ZigLLVMDIFile *difile) {
757 DIScope *scope = reinterpret_cast<DIFile*>(difile);
758 return reinterpret_cast<ZigLLVMDIScope*>(scope);
759}
760
761ZigLLVMDIScope *ZigLLVMSubprogramToScope(ZigLLVMDISubprogram *subprogram) {
762 DIScope *scope = reinterpret_cast<DISubprogram*>(subprogram);
763 return reinterpret_cast<ZigLLVMDIScope*>(scope);
764}
765
766ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type) {
767 DIScope *scope = reinterpret_cast<DIType*>(type);
768 return reinterpret_cast<ZigLLVMDIScope*>(scope);
769}
770
771ZigLLVMDINode *ZigLLVMLexicalBlockToNode(ZigLLVMDILexicalBlock *lexical_block) {
772 DINode *node = reinterpret_cast<DILexicalBlock*>(lexical_block);
773 return reinterpret_cast<ZigLLVMDINode*>(node);
774}
775
776ZigLLVMDINode *ZigLLVMCompileUnitToNode(ZigLLVMDICompileUnit *compile_unit) {
777 DINode *node = reinterpret_cast<DICompileUnit*>(compile_unit);
778 return reinterpret_cast<ZigLLVMDINode*>(node);
779}
780
781ZigLLVMDINode *ZigLLVMFileToNode(ZigLLVMDIFile *difile) {
782 DINode *node = reinterpret_cast<DIFile*>(difile);
783 return reinterpret_cast<ZigLLVMDINode*>(node);
784}
785
786ZigLLVMDINode *ZigLLVMSubprogramToNode(ZigLLVMDISubprogram *subprogram) {
787 DINode *node = reinterpret_cast<DISubprogram*>(subprogram);
788 return reinterpret_cast<ZigLLVMDINode*>(node);
789}
790
791ZigLLVMDINode *ZigLLVMTypeToNode(ZigLLVMDIType *type) {
792 DINode *node = reinterpret_cast<DIType*>(type);
793 return reinterpret_cast<ZigLLVMDINode*>(node);
794}
795
796ZigLLVMDINode *ZigLLVMScopeToNode(ZigLLVMDIScope *scope) {
797 DINode *node = reinterpret_cast<DIScope*>(scope);
798 return reinterpret_cast<ZigLLVMDINode*>(node);
799}
800
801ZigLLVMDINode *ZigLLVMGlobalVariableToNode(ZigLLVMDIGlobalVariable *global_variable) {
802 DINode *node = reinterpret_cast<DIGlobalVariable*>(global_variable);
803 return reinterpret_cast<ZigLLVMDINode*>(node);
804}
805
806void ZigLLVMSubprogramReplaceLinkageName(ZigLLVMDISubprogram *subprogram,
807 ZigLLVMMDString *linkage_name)
808{
809 MDString *linkage_name_md = reinterpret_cast<MDString*>(linkage_name);
810 reinterpret_cast<DISubprogram*>(subprogram)->replaceLinkageName(linkage_name_md);
811}
812
813void ZigLLVMGlobalVariableReplaceLinkageName(ZigLLVMDIGlobalVariable *global_variable,
814 ZigLLVMMDString *linkage_name)
815{
816 Metadata *linkage_name_md = reinterpret_cast<MDString*>(linkage_name);
817 // NOTE: Operand index must match llvm::DIGlobalVariable
818 reinterpret_cast<DIGlobalVariable*>(global_variable)->replaceOperandWith(5, linkage_name_md);
819}
820
821ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder,
822 unsigned lang, ZigLLVMDIFile *difile, const char *producer,
823 bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,
824 uint64_t dwo_id, bool emit_debug_info)
825{
826 DICompileUnit *result = reinterpret_cast<DIBuilder*>(dibuilder)->createCompileUnit(
827 lang,
828 reinterpret_cast<DIFile*>(difile),
829 producer, is_optimized, flags, runtime_version, split_name,
830 (emit_debug_info ? DICompileUnit::DebugEmissionKind::FullDebug : DICompileUnit::DebugEmissionKind::NoDebug),
831 dwo_id);
832 return reinterpret_cast<ZigLLVMDICompileUnit*>(result);
833}
834
835
836ZigLLVMDIFile *ZigLLVMCreateFile(ZigLLVMDIBuilder *dibuilder, const char *filename, const char *directory) {
837 DIFile *result = reinterpret_cast<DIBuilder*>(dibuilder)->createFile(filename, directory);
838 return reinterpret_cast<ZigLLVMDIFile*>(result);
839}
840
841ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
842 const char *name, const char *linkage_name, ZigLLVMDIFile *file, unsigned lineno,
843 ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition, unsigned scope_line,
844 unsigned flags, bool is_optimized, ZigLLVMDISubprogram *decl_subprogram)
845{
846 DISubroutineType *di_sub_type = static_cast<DISubroutineType*>(reinterpret_cast<DIType*>(fn_di_type));
847 DISubprogram *result = reinterpret_cast<DIBuilder*>(dibuilder)->createFunction(
848 reinterpret_cast<DIScope*>(scope),
849 name, linkage_name,
850 reinterpret_cast<DIFile*>(file),
851 lineno,
852 di_sub_type,
853 scope_line,
854 static_cast<DINode::DIFlags>(flags),
855 DISubprogram::toSPFlags(is_local_to_unit, is_definition, is_optimized),
856 nullptr,
857 reinterpret_cast<DISubprogram *>(decl_subprogram),
858 nullptr);
859 return reinterpret_cast<ZigLLVMDISubprogram*>(result);
860}
861
862void ZigLLVMDIBuilderFinalize(ZigLLVMDIBuilder *dibuilder) {
863 reinterpret_cast<DIBuilder*>(dibuilder)->finalize();
864}
865
866LLVMValueRef ZigLLVMInsertDeclareAtEnd(ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
867 ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref)
868{
869 Instruction *result = reinterpret_cast<DIBuilder*>(dibuilder)->insertDeclare(
870 unwrap(storage),
871 reinterpret_cast<DILocalVariable *>(var_info),
872 reinterpret_cast<DIBuilder*>(dibuilder)->createExpression(),
873 reinterpret_cast<DILocation*>(debug_loc),
874 static_cast<BasicBlock*>(unwrap(basic_block_ref)));
875 return wrap(result);
876}
877
878LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(ZigLLVMDIBuilder *dib, LLVMValueRef val,
879 ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc,
880 LLVMBasicBlockRef basic_block_ref)
881{
882 Instruction *result = reinterpret_cast<DIBuilder*>(dib)->insertDbgValueIntrinsic(
883 unwrap(val),
884 reinterpret_cast<DILocalVariable *>(var_info),
885 reinterpret_cast<DIBuilder*>(dib)->createExpression(),
886 reinterpret_cast<DILocation*>(debug_loc),
887 static_cast<BasicBlock*>(unwrap(basic_block_ref)));
888 return wrap(result);
889}
890
891LLVMValueRef ZigLLVMInsertDeclare(ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
892 ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr)
893{
894 Instruction *result = reinterpret_cast<DIBuilder*>(dibuilder)->insertDeclare(
895 unwrap(storage),
896 reinterpret_cast<DILocalVariable *>(var_info),
897 reinterpret_cast<DIBuilder*>(dibuilder)->createExpression(),
898 reinterpret_cast<DILocation*>(debug_loc),
899 static_cast<Instruction*>(unwrap(insert_before_instr)));
900 return wrap(result);
901}
902
903ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, ZigLLVMDIScope *scope) {
904 DIScope* di_scope = reinterpret_cast<DIScope*>(scope);
905 DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, col, di_scope, nullptr, false);
906 return reinterpret_cast<ZigLLVMDILocation*>(debug_loc.get());
907}
908
909ZigLLVMDILocation *ZigLLVMGetDebugLoc2(unsigned line, unsigned col, ZigLLVMDIScope *scope,
910 ZigLLVMDILocation *inlined_at) {
911 DIScope* di_scope = reinterpret_cast<DIScope*>(scope);
912 DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, col, di_scope,
913 reinterpret_cast<DILocation *>(inlined_at), false);
914 return reinterpret_cast<ZigLLVMDILocation*>(debug_loc.get());
915}
916
917void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {
918 if (on_state) {
919 FastMathFlags fmf;
920 fmf.setFast();
921 unwrap(builder_wrapped)->setFastMathFlags(fmf);
922 } else {
923 unwrap(builder_wrapped)->clearFastMathFlags();
924 }
925}
926
927void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {383void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
928 cl::ParseCommandLineOptions(argc, argv);384 cl::ParseCommandLineOptions(argc, argv);
929}385}
930386
931void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) {
932 unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
933 unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4);
934
935 if (produce_dwarf64) {
936 unwrap(module)->addModuleFlag(Module::Warning, "DWARF64", 1);
937 }
938}
939
940void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) {
941 unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
942 unwrap(module)->addModuleFlag(Module::Warning, "CodeView", 1);
943}
944
945void ZigLLVMSetModulePICLevel(LLVMModuleRef module) {387void ZigLLVMSetModulePICLevel(LLVMModuleRef module) {
946 unwrap(module)->setPICLevel(PICLevel::Level::BigPIC);388 unwrap(module)->setPICLevel(PICLevel::Level::BigPIC);
947}389}
...@@ -956,35 +398,6 @@ void ZigLLVMSetModuleCodeModel(LLVMModuleRef module, LLVMCodeModel code_model) {...@@ -956,35 +398,6 @@ void ZigLLVMSetModuleCodeModel(LLVMModuleRef module, LLVMCodeModel code_model) {
956 assert(!JIT);398 assert(!JIT);
957}399}
958400
959LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
960 const char *name)
961{
962 return wrap(unwrap(builder)->CreateShl(unwrap(LHS), unwrap(RHS), name, false, true));
963}
964
965LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
966 const char *name)
967{
968 return wrap(unwrap(builder)->CreateShl(unwrap(LHS), unwrap(RHS), name, true, false));
969}
970
971LLVMValueRef ZigLLVMBuildLShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
972 const char *name)
973{
974 return wrap(unwrap(builder)->CreateLShr(unwrap(LHS), unwrap(RHS), name, true));
975}
976
977LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
978 const char *name)
979{
980 return wrap(unwrap(builder)->CreateAShr(unwrap(LHS), unwrap(RHS), name, true));
981}
982
983LLVMValueRef ZigLLVMBuildAllocaInAddressSpace(LLVMBuilderRef builder, LLVMTypeRef Ty,
984 unsigned AddressSpace, const char *Name) {
985 return wrap(unwrap(builder)->CreateAlloca(unwrap(Ty), AddressSpace, nullptr, Name));
986}
987
988bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch,401bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch,
989 const char *output_lib_path, bool kill_at)402 const char *output_lib_path, bool kill_at)
990{403{
...@@ -1134,43 +547,6 @@ bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disab...@@ -1134,43 +547,6 @@ bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disab
1134 return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);547 return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
1135}548}
1136549
1137void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {
1138 unwrap(new_owner)->takeName(unwrap(victim));
1139}
1140
1141void ZigLLVMRemoveGlobalValue(LLVMValueRef GlobalVal) {
1142 unwrap<GlobalValue>(GlobalVal)->removeFromParent();
1143}
1144
1145void ZigLLVMEraseGlobalValue(LLVMValueRef GlobalVal) {
1146 unwrap<GlobalValue>(GlobalVal)->eraseFromParent();
1147}
1148
1149void ZigLLVMDeleteGlobalValue(LLVMValueRef GlobalVal) {
1150 auto *GV = unwrap<GlobalValue>(GlobalVal);
1151 assert(GV->getParent() == nullptr);
1152 switch (GV->getValueID()) {
1153#define HANDLE_GLOBAL_VALUE(NAME) \
1154 case Value::NAME##Val: \
1155 delete static_cast<NAME *>(GV); \
1156 break;
1157#include <llvm/IR/Value.def>
1158 default: llvm_unreachable("Expected global value");
1159 }
1160}
1161
1162void ZigLLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal) {
1163 unwrap<GlobalVariable>(GlobalVar)->setInitializer(ConstantVal ? unwrap<Constant>(ConstantVal) : nullptr);
1164}
1165
1166ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1167 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
1168}
1169
1170void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1171 unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression));
1172}
1173
1174static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");550static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");
1175static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, "");551static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, "");
1176static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, "");552static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, "");
src/zig_llvm.h-193
...@@ -24,24 +24,6 @@...@@ -24,24 +24,6 @@
24// ATTENTION: If you modify this file, be sure to update the corresponding24// ATTENTION: If you modify this file, be sure to update the corresponding
25// extern function declarations in the self-hosted compiler.25// extern function declarations in the self-hosted compiler.
2626
27struct ZigLLVMDIType;
28struct ZigLLVMDIBuilder;
29struct ZigLLVMDICompileUnit;
30struct ZigLLVMDIScope;
31struct ZigLLVMDIFile;
32struct ZigLLVMDILexicalBlock;
33struct ZigLLVMDISubprogram;
34struct ZigLLVMDISubroutineType;
35struct ZigLLVMDILocalVariable;
36struct ZigLLVMDIGlobalVariableExpression;
37struct ZigLLVMDIGlobalVariable;
38struct ZigLLVMDIGlobalExpression;
39struct ZigLLVMDILocation;
40struct ZigLLVMDIEnumerator;
41struct ZigLLVMInsertionPoint;
42struct ZigLLVMDINode;
43struct ZigLLVMMDString;
44
45ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,27ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
46 char **error_message, bool is_debug,28 char **error_message, bool is_debug,
47 bool is_small, bool time_report, bool tsan, bool lto,29 bool is_small, bool time_report, bool tsan, bool lto,
...@@ -62,9 +44,6 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co...@@ -62,9 +44,6 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
6244
63ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit);45ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit);
6446
65ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
66 LLVMTypeRef FunctionTy, unsigned AddressSpace);
67
68enum ZigLLVMTailCallKind {47enum ZigLLVMTailCallKind {
69 ZigLLVMTailCallKindNone,48 ZigLLVMTailCallKindNone,
70 ZigLLVMTailCallKindTail,49 ZigLLVMTailCallKindTail,
...@@ -72,8 +51,6 @@ enum ZigLLVMTailCallKind {...@@ -72,8 +51,6 @@ enum ZigLLVMTailCallKind {
72 ZigLLVMTailCallKindNoTail,51 ZigLLVMTailCallKindNoTail,
73};52};
7453
75ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind);
76
77enum ZigLLVM_CallingConv {54enum ZigLLVM_CallingConv {
78 ZigLLVM_C = 0,55 ZigLLVM_C = 0,
79 ZigLLVM_Fast = 8,56 ZigLLVM_Fast = 8,
...@@ -122,176 +99,12 @@ enum ZigLLVM_CallingConv {...@@ -122,176 +99,12 @@ enum ZigLLVM_CallingConv {
122 ZigLLVM_MaxID = 1023,99 ZigLLVM_MaxID = 1023,
123};100};
124101
125ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
126 const char *name);
127ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
128 const char *name);
129ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
130 const char *name);
131ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
132 const char *name);
133
134ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAllocaInAddressSpace(LLVMBuilderRef builder, LLVMTypeRef Ty, unsigned AddressSpace,
135 const char *Name);
136
137ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugPointerType(struct ZigLLVMDIBuilder *dibuilder,
138 struct ZigLLVMDIType *pointee_type, uint64_t size_in_bits, uint64_t align_in_bits, const char *name);
139
140ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugBasicType(struct ZigLLVMDIBuilder *dibuilder, const char *name,
141 uint64_t size_in_bits, unsigned encoding);
142
143ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugArrayType(struct ZigLLVMDIBuilder *dibuilder,
144 uint64_t size_in_bits, uint64_t align_in_bits, struct ZigLLVMDIType *elem_type,
145 int64_t elem_count);
146
147ZIG_EXTERN_C struct ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(struct ZigLLVMDIBuilder *dibuilder,
148 const char *name, uint64_t val, bool isUnsigned);
149
150
151ZIG_EXTERN_C struct ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision(struct ZigLLVMDIBuilder *dibuilder,
152 const char *name, unsigned NumWords, const uint64_t Words[], unsigned int bits, bool isUnsigned);
153
154ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugEnumerationType(struct ZigLLVMDIBuilder *dibuilder,
155 struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number,
156 uint64_t size_in_bits, uint64_t align_in_bits, struct ZigLLVMDIEnumerator **enumerator_array,
157 int enumerator_array_len, struct ZigLLVMDIType *underlying_type, const char *unique_id);
158
159ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugStructType(struct ZigLLVMDIBuilder *dibuilder,
160 struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number,
161 uint64_t size_in_bits, uint64_t align_in_bits, unsigned flags, struct ZigLLVMDIType *derived_from,
162 struct ZigLLVMDIType **types_array, int types_array_len, unsigned run_time_lang,
163 struct ZigLLVMDIType *vtable_holder, const char *unique_id);
164
165ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugUnionType(struct ZigLLVMDIBuilder *dibuilder,
166 struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number,
167 uint64_t size_in_bits, uint64_t align_in_bits, unsigned flags, struct ZigLLVMDIType **types_array,
168 int types_array_len, unsigned run_time_lang, const char *unique_id);
169
170ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugMemberType(struct ZigLLVMDIBuilder *dibuilder,
171 struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line,
172 uint64_t size_in_bits, uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags,
173 struct ZigLLVMDIType *type);
174
175ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateReplaceableCompositeType(struct ZigLLVMDIBuilder *dibuilder,
176 unsigned tag, const char *name, struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line);
177
178ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugForwardDeclType(struct ZigLLVMDIBuilder *dibuilder, unsigned tag,
179 const char *name, struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line);
180
181ZIG_EXTERN_C void ZigLLVMReplaceTemporary(struct ZigLLVMDIBuilder *dibuilder, struct ZigLLVMDIType *type,
182 struct ZigLLVMDIType *replacement);
183
184ZIG_EXTERN_C void ZigLLVMReplaceDebugArrays(struct ZigLLVMDIBuilder *dibuilder, struct ZigLLVMDIType *type,
185 struct ZigLLVMDIType **types_array, int types_array_len);
186
187ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateSubroutineType(struct ZigLLVMDIBuilder *dibuilder_wrapped,
188 struct ZigLLVMDIType **types_array, int types_array_len, unsigned flags);
189
190ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_unsigned(void);
191ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed(void);
192ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_float(void);
193ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_boolean(void);
194ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_unsigned_char(void);
195ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed_char(void);
196ZIG_EXTERN_C unsigned ZigLLVMLang_DW_LANG_C99(void);
197ZIG_EXTERN_C unsigned ZigLLVMTag_DW_variable(void);
198ZIG_EXTERN_C unsigned ZigLLVMTag_DW_structure_type(void);
199ZIG_EXTERN_C unsigned ZigLLVMTag_DW_enumeration_type(void);
200ZIG_EXTERN_C unsigned ZigLLVMTag_DW_union_type(void);
201
202ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved);
203ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder);
204ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64);
205ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module);
206ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module);102ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module);
207ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module);103ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module);
208ZIG_EXTERN_C void ZigLLVMSetModuleCodeModel(LLVMModuleRef module, LLVMCodeModel code_model);104ZIG_EXTERN_C void ZigLLVMSetModuleCodeModel(LLVMModuleRef module, LLVMCodeModel code_model);
209105
210ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder,
211 unsigned int line, unsigned int column, struct ZigLLVMDIScope *scope);
212ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation2(LLVMBuilderRef builder, unsigned int line,
213 unsigned int column, struct ZigLLVMDIScope *scope, struct ZigLLVMDILocation *inlined_at);
214ZIG_EXTERN_C void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder);
215
216ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMLexicalBlockToScope(struct ZigLLVMDILexicalBlock *lexical_block);
217ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMCompileUnitToScope(struct ZigLLVMDICompileUnit *compile_unit);
218ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *difile);
219ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram);
220ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMTypeToScope(struct ZigLLVMDIType *type);
221
222ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMLexicalBlockToNode(struct ZigLLVMDILexicalBlock *lexical_block);
223ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMCompileUnitToNode(struct ZigLLVMDICompileUnit *compile_unit);
224ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMFileToNode(struct ZigLLVMDIFile *difile);
225ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMSubprogramToNode(struct ZigLLVMDISubprogram *subprogram);
226ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMTypeToNode(struct ZigLLVMDIType *type);
227ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMScopeToNode(struct ZigLLVMDIScope *scope);
228ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMGlobalVariableToNode(struct ZigLLVMDIGlobalVariable *global_variable);
229
230ZIG_EXTERN_C void ZigLLVMSubprogramReplaceLinkageName(struct ZigLLVMDISubprogram *subprogram,
231 struct ZigLLVMMDString *linkage_name);
232ZIG_EXTERN_C void ZigLLVMGlobalVariableReplaceLinkageName(struct ZigLLVMDIGlobalVariable *global_variable,
233 struct ZigLLVMMDString *linkage_name);
234
235ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(struct ZigLLVMDIBuilder *dbuilder,
236 struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no,
237 struct ZigLLVMDIType *type, bool always_preserve, unsigned flags);
238
239ZIG_EXTERN_C struct ZigLLVMDIGlobalVariableExpression *ZigLLVMCreateGlobalVariableExpression(struct ZigLLVMDIBuilder *dbuilder,
240 struct ZigLLVMDIScope *scope, const char *name, const char *linkage_name, struct ZigLLVMDIFile *file,
241 unsigned line_no, struct ZigLLVMDIType *di_type, bool is_local_to_unit);
242
243ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(struct ZigLLVMDIBuilder *dbuilder,
244 struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no,
245 struct ZigLLVMDIType *type, bool always_preserve, unsigned flags, unsigned arg_no);
246
247ZIG_EXTERN_C struct ZigLLVMDILexicalBlock *ZigLLVMCreateLexicalBlock(struct ZigLLVMDIBuilder *dbuilder,
248 struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line, unsigned col);
249
250ZIG_EXTERN_C struct ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(struct ZigLLVMDIBuilder *dibuilder,
251 unsigned lang, struct ZigLLVMDIFile *difile, const char *producer,
252 bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,
253 uint64_t dwo_id, bool emit_debug_info);
254
255ZIG_EXTERN_C struct ZigLLVMDIFile *ZigLLVMCreateFile(struct ZigLLVMDIBuilder *dibuilder, const char *filename,
256 const char *directory);
257
258ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIBuilder *dibuilder,
259 struct ZigLLVMDIScope *scope, const char *name, const char *linkage_name, struct ZigLLVMDIFile *file,
260 unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,
261 unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram);
262
263ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
264 uint64_t SizeInBits, uint32_t AlignInBits, struct ZigLLVMDIType *Ty, uint32_t elem_count);
265
266ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);
267
268ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder);
269
270ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col,
271 struct ZigLLVMDIScope *scope);
272ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc2(unsigned line, unsigned col,
273 struct ZigLLVMDIScope *scope, struct ZigLLVMDILocation *inlined_at);
274
275ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclareAtEnd(struct ZigLLVMDIBuilder *dib,
276 LLVMValueRef storage, struct ZigLLVMDILocalVariable *var_info,
277 struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);
278
279ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclare(struct ZigLLVMDIBuilder *dib,
280 LLVMValueRef storage, struct ZigLLVMDILocalVariable *var_info,
281 struct ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr);
282
283ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBuilder *dib,
284 LLVMValueRef val, struct ZigLLVMDILocalVariable *var_info,
285 struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);
286
287ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
288
289ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);106ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);
290107
291ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression);
292ZIG_EXTERN_C void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression);
293
294
295// synchronize with llvm/include/ADT/Triple.h::ArchType108// synchronize with llvm/include/ADT/Triple.h::ArchType
296// synchronize with std.Target.Cpu.Arch109// synchronize with std.Target.Cpu.Arch
297// synchronize with codegen/llvm/bindings.zig::ArchType110// synchronize with codegen/llvm/bindings.zig::ArchType
...@@ -494,12 +307,6 @@ enum ZigLLVM_ObjectFormatType {...@@ -494,12 +307,6 @@ enum ZigLLVM_ObjectFormatType {
494 ZigLLVM_XCOFF,307 ZigLLVM_XCOFF,
495};308};
496309
497ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim);
498ZIG_EXTERN_C void ZigLLVMRemoveGlobalValue(LLVMValueRef GlobalVal);
499ZIG_EXTERN_C void ZigLLVMEraseGlobalValue(LLVMValueRef GlobalVal);
500ZIG_EXTERN_C void ZigLLVMDeleteGlobalValue(LLVMValueRef GlobalVal);
501ZIG_EXTERN_C void ZigLLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal);
502
503#define ZigLLVM_DIFlags_Zero 0U310#define ZigLLVM_DIFlags_Zero 0U
504#define ZigLLVM_DIFlags_Private 1U311#define ZigLLVM_DIFlags_Private 1U
505#define ZigLLVM_DIFlags_Protected 2U312#define ZigLLVM_DIFlags_Protected 2U