authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-08 04:38:31-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-19 23:38:40-04:00
logd167bd4b568e2d5808fc37a8c683e4c06317a434
treec099f307438d8eeba89a7831a148fa1a3281047e
parent3314fd83af5a6a269926a6f8ad3fcb62b04242c9

llvm: finish converting `lowerType`


3 files changed, 1308 insertions(+), 950 deletions(-)

src/codegen/llvm.zig+722-858
......@@ -374,12 +374,11 @@ const DataLayoutBuilder = struct {
374374 .pref = 64,
375375 .idx = 64,
376376 };
377 const address_space_info = llvmAddressSpaceInfo(self.target);
378 assert(address_space_info[0].llvm == llvm.address_space.default);
379 for (address_space_info) |info| {
380 const is_default = info.llvm == llvm.address_space.default;
377 const addr_space_info = llvmAddrSpaceInfo(self.target);
378 for (addr_space_info, 0..) |info, i| {
379 assert((info.llvm == .default) == (i == 0));
381380 if (info.non_integral) {
382 assert(!is_default);
381 assert(info.llvm != .default);
383382 any_non_integral = true;
384383 }
385384 const size = info.size orelse ptr_bit_width;
......@@ -391,7 +390,7 @@ const DataLayoutBuilder = struct {
391390 abi == default_info.abi and
392391 pref == default_info.pref and
393392 idx == default_info.idx;
394 if (is_default) default_info = .{
393 if (info.llvm == .default) default_info = .{
395394 .size = size,
396395 .abi = abi,
397396 .pref = pref,
......@@ -400,7 +399,7 @@ const DataLayoutBuilder = struct {
400399 if (!info.force_in_data_layout and matches_default and
401400 self.target.cpu.arch != .riscv64 and !is_aarch64_windows) continue;
402401 try writer.writeAll("-p");
403 if (!is_default) try writer.print("{d}", .{info.llvm});
402 if (info.llvm != .default) try writer.print("{d}", .{@intFromEnum(info.llvm)});
404403 try writer.print(":{d}:{d}", .{ size, abi });
405404 if (pref != abi or idx != size) {
406405 try writer.print(":{d}", .{pref});
......@@ -459,8 +458,8 @@ const DataLayoutBuilder = struct {
459458 try self.typeAlignment(.vector, 512, 128, 128, true, writer);
460459 if (any_non_integral) {
461460 try writer.writeAll("-ni");
462 for (address_space_info) |info| if (info.non_integral)
463 try writer.print(":{d}", .{info.llvm});
461 for (addr_space_info) |info| if (info.non_integral)
462 try writer.print(":{d}", .{@intFromEnum(info.llvm)});
464463 }
465464 }
466465
......@@ -589,7 +588,7 @@ pub const Object = struct {
589588 /// Memoizes a null `?usize` value.
590589 null_opt_addr: ?*llvm.Value,
591590
592 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, *llvm.Type);
591 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);
593592
594593 /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we
595594 /// want to iterate over it while adding entries to it.
......@@ -809,15 +808,10 @@ pub const Object = struct {
809808 const error_name_table_ptr_global = o.error_name_table orelse return;
810809
811810 const mod = o.module;
812 const target = mod.getTarget();
813811
814 const llvm_ptr_ty = o.context.pointerType(0); // TODO: Address space
815 const llvm_usize_ty = o.context.intType(target.ptrBitWidth());
816 const type_fields = [_]*llvm.Type{
817 llvm_ptr_ty,
818 llvm_usize_ty,
819 };
820 const llvm_slice_ty = o.context.structType(&type_fields, type_fields.len, .False);
812 // TODO: Address space
813 const llvm_usize_ty = try o.lowerType(Type.usize);
814 const llvm_slice_ty = (try o.builder.structType(.normal, &.{ .ptr, llvm_usize_ty })).toLlvm(&o.builder);
821815 const slice_ty = Type.slice_const_u8_sentinel_0;
822816 const slice_alignment = slice_ty.abiAlignment(mod);
823817
......@@ -838,7 +832,7 @@ pub const Object = struct {
838832
839833 const slice_fields = [_]*llvm.Value{
840834 str_global,
841 llvm_usize_ty.constInt(name.len, .False),
835 llvm_usize_ty.toLlvm(&o.builder).constInt(name.len, .False),
842836 };
843837 llvm_error.* = llvm_slice_ty.constNamedStruct(&slice_fields, slice_fields.len);
844838 }
......@@ -1204,7 +1198,7 @@ pub const Object = struct {
12041198 {
12051199 var llvm_arg_i = @as(c_uint, @intFromBool(ret_ptr != null)) + @intFromBool(err_return_tracing);
12061200 var it = iterateParamTypes(o, fn_info);
1207 while (it.next()) |lowering| switch (lowering) {
1201 while (try it.next()) |lowering| switch (lowering) {
12081202 .no_bits => continue,
12091203 .byval => {
12101204 assert(!it.byval_attr);
......@@ -1229,7 +1223,7 @@ pub const Object = struct {
12291223 },
12301224 .byref => {
12311225 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1232 const param_llvm_ty = try o.lowerLlvmType(param_ty);
1226 const param_llvm_ty = try o.lowerType(param_ty);
12331227 const param = llvm_func.getParam(llvm_arg_i);
12341228 const alignment = param_ty.abiAlignment(mod);
12351229
......@@ -1241,14 +1235,14 @@ pub const Object = struct {
12411235 if (isByRef(param_ty, mod)) {
12421236 args.appendAssumeCapacity(param);
12431237 } else {
1244 const load_inst = builder.buildLoad(param_llvm_ty, param, "");
1238 const load_inst = builder.buildLoad(param_llvm_ty.toLlvm(&o.builder), param, "");
12451239 load_inst.setAlignment(alignment);
12461240 args.appendAssumeCapacity(load_inst);
12471241 }
12481242 },
12491243 .byref_mut => {
12501244 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1251 const param_llvm_ty = try o.lowerLlvmType(param_ty);
1245 const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
12521246 const param = llvm_func.getParam(llvm_arg_i);
12531247 const alignment = param_ty.abiAlignment(mod);
12541248
......@@ -1271,7 +1265,7 @@ pub const Object = struct {
12711265 const param = llvm_func.getParam(llvm_arg_i);
12721266 llvm_arg_i += 1;
12731267
1274 const param_llvm_ty = try o.lowerLlvmType(param_ty);
1268 const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
12751269 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
12761270 const int_llvm_ty = o.context.intType(abi_size * 8);
12771271 const alignment = @max(
......@@ -1316,16 +1310,16 @@ pub const Object = struct {
13161310 const len_param = llvm_func.getParam(llvm_arg_i);
13171311 llvm_arg_i += 1;
13181312
1319 const slice_llvm_ty = try o.lowerLlvmType(param_ty);
1313 const slice_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
13201314 const partial = builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr_param, 0, "");
13211315 const aggregate = builder.buildInsertValue(partial, len_param, 1, "");
13221316 try args.append(aggregate);
13231317 },
13241318 .multiple_llvm_types => {
13251319 assert(!it.byval_attr);
1326 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];
1320 const field_types = it.llvm_types_buffer[0..it.types_len];
13271321 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1328 const param_llvm_ty = try o.lowerLlvmType(param_ty);
1322 const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
13291323 const param_alignment = param_ty.abiAlignment(mod);
13301324 const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
13311325 const llvm_ty = o.context.structType(field_types.ptr, @as(c_uint, @intCast(field_types.len)), .False);
......@@ -1356,7 +1350,7 @@ pub const Object = struct {
13561350 },
13571351 .float_array => {
13581352 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1359 const param_llvm_ty = try o.lowerLlvmType(param_ty);
1353 const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
13601354 const param = llvm_func.getParam(llvm_arg_i);
13611355 llvm_arg_i += 1;
13621356
......@@ -1374,7 +1368,7 @@ pub const Object = struct {
13741368 },
13751369 .i32_array, .i64_array => {
13761370 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1377 const param_llvm_ty = try o.lowerLlvmType(param_ty);
1371 const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
13781372 const param = llvm_func.getParam(llvm_arg_i);
13791373 llvm_arg_i += 1;
13801374
......@@ -2678,7 +2672,7 @@ pub const Object = struct {
26782672 const global = o.llvm_module.addGlobalInAddressSpace(
26792673 llvm_init.typeOf(),
26802674 "",
2681 llvm_actual_addrspace,
2675 @intFromEnum(llvm_actual_addrspace),
26822676 );
26832677 global.setLinkage(.Internal);
26842678 global.setUnnamedAddr(.True);
......@@ -2686,7 +2680,7 @@ pub const Object = struct {
26862680 global.setInitializer(llvm_init);
26872681
26882682 const addrspace_casted_global = if (llvm_wanted_addrspace != llvm_actual_addrspace)
2689 global.constAddrSpaceCast(o.context.pointerType(llvm_wanted_addrspace))
2683 global.constAddrSpaceCast(o.context.pointerType(@intFromEnum(llvm_wanted_addrspace)))
26902684 else
26912685 global;
26922686
......@@ -2710,16 +2704,16 @@ pub const Object = struct {
27102704 const target = mod.getTarget();
27112705 const sret = firstParamSRet(fn_info, mod);
27122706
2713 const fn_type = try o.lowerLlvmType(zig_fn_type);
2707 const fn_type = try o.lowerType(zig_fn_type);
27142708
27152709 const ip = &mod.intern_pool;
27162710 const fqn = try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod)));
27172711
27182712 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
2719 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(fqn.toSlice(&o.builder).?, fn_type, llvm_addrspace);
2713 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(fqn.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder), @intFromEnum(llvm_addrspace));
27202714
27212715 var global = Builder.Global{
2722 .type = .void,
2716 .type = fn_type,
27232717 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
27242718 };
27252719 var function = Builder.Function{
......@@ -2745,7 +2739,7 @@ pub const Object = struct {
27452739 o.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0
27462740 o.addArgAttr(llvm_fn, 0, "noalias");
27472741
2748 const raw_llvm_ret_ty = try o.lowerLlvmType(fn_info.return_type.toType());
2742 const raw_llvm_ret_ty = (try o.lowerType(fn_info.return_type.toType())).toLlvm(&o.builder);
27492743 llvm_fn.addSretAttr(raw_llvm_ret_ty);
27502744 }
27512745
......@@ -2789,7 +2783,7 @@ pub const Object = struct {
27892783 var it = iterateParamTypes(o, fn_info);
27902784 it.llvm_index += @intFromBool(sret);
27912785 it.llvm_index += @intFromBool(err_return_tracing);
2792 while (it.next()) |lowering| switch (lowering) {
2786 while (try it.next()) |lowering| switch (lowering) {
27932787 .byval => {
27942788 const param_index = it.zig_index - 1;
27952789 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
......@@ -2799,7 +2793,7 @@ pub const Object = struct {
27992793 },
28002794 .byref => {
28012795 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1];
2802 const param_llvm_ty = try o.lowerLlvmType(param_ty.toType());
2796 const param_llvm_ty = try o.lowerType(param_ty.toType());
28032797 const alignment = param_ty.toType().abiAlignment(mod);
28042798 o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
28052799 },
......@@ -2883,15 +2877,9 @@ pub const Object = struct {
28832877
28842878 const target = mod.getTarget();
28852879
2886 const ty = try o.lowerType(decl.ty);
2887 const llvm_type = if (ty != .none)
2888 o.builder.llvm_types.items[@intFromEnum(ty)]
2889 else
2890 try o.lowerLlvmType(decl.ty);
2891 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
2892
28932880 var global = Builder.Global{
2894 .type = if (ty != .none) ty else .void,
2881 .addr_space = toLlvmGlobalAddressSpace(decl.@"addrspace", target),
2882 .type = try o.lowerType(decl.ty),
28952883 .kind = .{ .object = @enumFromInt(o.builder.objects.items.len) },
28962884 };
28972885 var object = Builder.Object{
......@@ -2904,9 +2892,9 @@ pub const Object = struct {
29042892 else
29052893 fqn;
29062894 const llvm_global = o.llvm_module.addGlobalInAddressSpace(
2907 llvm_type,
2895 global.type.toLlvm(&o.builder),
29082896 fqn.toSlice(&o.builder).?,
2909 llvm_actual_addrspace,
2897 @intFromEnum(global.addr_space),
29102898 );
29112899
29122900 // This is needed for declarations created by `@extern`.
......@@ -2943,22 +2931,19 @@ pub const Object = struct {
29432931 }
29442932
29452933 fn isUnnamedType(o: *Object, ty: Type, val: *llvm.Value) bool {
2946 // Once `lowerLlvmType` succeeds, successive calls to it with the same Zig type
2947 // are guaranteed to succeed. So if a call to `lowerLlvmType` fails here it means
2934 // Once `lowerType` succeeds, successive calls to it with the same Zig type
2935 // are guaranteed to succeed. So if a call to `lowerType` fails here it means
29482936 // it is the first time lowering the type, which means the value can't possible
29492937 // have that type.
2950 const llvm_ty = o.lowerLlvmType(ty) catch return true;
2938 const llvm_ty = (o.lowerType(ty) catch return true).toLlvm(&o.builder);
29512939 return val.typeOf() != llvm_ty;
29522940 }
29532941
2954 fn lowerLlvmType(o: *Object, t: Type) Allocator.Error!*llvm.Type {
2955 const ty = try o.lowerType(t);
2956 const llvm_ty = if (ty != .none)
2957 o.builder.llvm_types.items[@intFromEnum(ty)]
2958 else
2959 try o.lowerLlvmTypeInner(t);
2942 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
2943 const ty = try o.lowerTypeInner(t);
29602944 const mod = o.module;
29612945 if (std.debug.runtime_safety and false) check: {
2946 const llvm_ty = ty.toLlvm(&o.builder);
29622947 if (t.zigTypeTag(mod) == .Opaque) break :check;
29632948 if (!t.hasRuntimeBits(mod)) break :check;
29642949 if (!llvm_ty.isSized().toBool()) break :check;
......@@ -2971,445 +2956,10 @@ pub const Object = struct {
29712956 });
29722957 }
29732958 }
2974 return llvm_ty;
2975 }
2976
2977 fn lowerLlvmTypeInner(o: *Object, t: Type) Allocator.Error!*llvm.Type {
2978 const gpa = o.gpa;
2979 const mod = o.module;
2980 const target = mod.getTarget();
2981 switch (t.zigTypeTag(mod)) {
2982 .Void, .NoReturn => return o.context.voidType(),
2983 .Int => {
2984 const info = t.intInfo(mod);
2985 assert(info.bits != 0);
2986 return o.context.intType(info.bits);
2987 },
2988 .Enum => {
2989 const int_ty = t.intTagType(mod);
2990 const bit_count = int_ty.intInfo(mod).bits;
2991 assert(bit_count != 0);
2992 return o.context.intType(bit_count);
2993 },
2994 .Float => switch (t.floatBits(target)) {
2995 16 => return if (backendSupportsF16(target)) o.context.halfType() else o.context.intType(16),
2996 32 => return o.context.floatType(),
2997 64 => return o.context.doubleType(),
2998 80 => return if (backendSupportsF80(target)) o.context.x86_fp80Type() else o.context.intType(80),
2999 128 => return o.context.fp128Type(),
3000 else => unreachable,
3001 },
3002 .Bool => return o.context.intType(1),
3003 .Pointer => {
3004 if (t.isSlice(mod)) {
3005 const ptr_type = t.slicePtrFieldType(mod);
3006
3007 const fields: [2]*llvm.Type = .{
3008 try o.lowerLlvmType(ptr_type),
3009 try o.lowerLlvmType(Type.usize),
3010 };
3011 return o.context.structType(&fields, fields.len, .False);
3012 }
3013 const ptr_info = t.ptrInfo(mod);
3014 const llvm_addrspace = toLlvmAddressSpace(ptr_info.flags.address_space, target);
3015 return o.context.pointerType(llvm_addrspace);
3016 },
3017 .Opaque => {
3018 if (t.toIntern() == .anyopaque_type) return o.context.intType(8);
3019
3020 const gop = try o.type_map.getOrPut(gpa, t.toIntern());
3021 if (gop.found_existing) return gop.value_ptr.*;
3022
3023 const opaque_type = mod.intern_pool.indexToKey(t.toIntern()).opaque_type;
3024 const name = mod.intern_pool.stringToSlice(try mod.opaqueFullyQualifiedName(opaque_type));
3025
3026 const llvm_struct_ty = o.context.structCreateNamed(name);
3027 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
3028 return llvm_struct_ty;
3029 },
3030 .Array => {
3031 const elem_ty = t.childType(mod);
3032 if (std.debug.runtime_safety) assert((try elem_ty.onePossibleValue(mod)) == null);
3033 const elem_llvm_ty = try o.lowerLlvmType(elem_ty);
3034 const total_len = t.arrayLen(mod) + @intFromBool(t.sentinel(mod) != null);
3035 return elem_llvm_ty.arrayType(@as(c_uint, @intCast(total_len)));
3036 },
3037 .Vector => {
3038 const elem_type = try o.lowerLlvmType(t.childType(mod));
3039 return elem_type.vectorType(t.vectorLen(mod));
3040 },
3041 .Optional => {
3042 const child_ty = t.optionalChild(mod);
3043 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3044 return o.context.intType(8);
3045 }
3046 const payload_llvm_ty = try o.lowerLlvmType(child_ty);
3047 if (t.optionalReprIsPayload(mod)) {
3048 return payload_llvm_ty;
3049 }
3050
3051 comptime assert(optional_layout_version == 3);
3052 var fields_buf: [3]*llvm.Type = .{
3053 payload_llvm_ty, o.context.intType(8), undefined,
3054 };
3055 const offset = child_ty.abiSize(mod) + 1;
3056 const abi_size = t.abiSize(mod);
3057 const padding = @as(c_uint, @intCast(abi_size - offset));
3058 if (padding == 0) {
3059 return o.context.structType(&fields_buf, 2, .False);
3060 }
3061 fields_buf[2] = o.context.intType(8).arrayType(padding);
3062 return o.context.structType(&fields_buf, 3, .False);
3063 },
3064 .ErrorUnion => {
3065 const payload_ty = t.errorUnionPayload(mod);
3066 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3067 return try o.lowerLlvmType(Type.anyerror);
3068 }
3069 const llvm_error_type = try o.lowerLlvmType(Type.anyerror);
3070 const llvm_payload_type = try o.lowerLlvmType(payload_ty);
3071
3072 const payload_align = payload_ty.abiAlignment(mod);
3073 const error_align = Type.anyerror.abiAlignment(mod);
3074
3075 const payload_size = payload_ty.abiSize(mod);
3076 const error_size = Type.anyerror.abiSize(mod);
3077
3078 var fields_buf: [3]*llvm.Type = undefined;
3079 if (error_align > payload_align) {
3080 fields_buf[0] = llvm_error_type;
3081 fields_buf[1] = llvm_payload_type;
3082 const payload_end =
3083 std.mem.alignForward(u64, error_size, payload_align) +
3084 payload_size;
3085 const abi_size = std.mem.alignForward(u64, payload_end, error_align);
3086 const padding = @as(c_uint, @intCast(abi_size - payload_end));
3087 if (padding == 0) {
3088 return o.context.structType(&fields_buf, 2, .False);
3089 }
3090 fields_buf[2] = o.context.intType(8).arrayType(padding);
3091 return o.context.structType(&fields_buf, 3, .False);
3092 } else {
3093 fields_buf[0] = llvm_payload_type;
3094 fields_buf[1] = llvm_error_type;
3095 const error_end =
3096 std.mem.alignForward(u64, payload_size, error_align) +
3097 error_size;
3098 const abi_size = std.mem.alignForward(u64, error_end, payload_align);
3099 const padding = @as(c_uint, @intCast(abi_size - error_end));
3100 if (padding == 0) {
3101 return o.context.structType(&fields_buf, 2, .False);
3102 }
3103 fields_buf[2] = o.context.intType(8).arrayType(padding);
3104 return o.context.structType(&fields_buf, 3, .False);
3105 }
3106 },
3107 .ErrorSet => return o.context.intType(16),
3108 .Struct => {
3109 const gop = try o.type_map.getOrPut(gpa, t.toIntern());
3110 if (gop.found_existing) return gop.value_ptr.*;
3111
3112 const struct_type = switch (mod.intern_pool.indexToKey(t.toIntern())) {
3113 .anon_struct_type => |tuple| {
3114 const llvm_struct_ty = o.context.structCreateNamed("");
3115 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
3116
3117 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};
3118 defer llvm_field_types.deinit(gpa);
3119
3120 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);
3121
3122 comptime assert(struct_layout_version == 2);
3123 var offset: u64 = 0;
3124 var big_align: u32 = 0;
3125
3126 for (tuple.types, tuple.values) |field_ty, field_val| {
3127 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
3128
3129 const field_align = field_ty.toType().abiAlignment(mod);
3130 big_align = @max(big_align, field_align);
3131 const prev_offset = offset;
3132 offset = std.mem.alignForward(u64, offset, field_align);
3133
3134 const padding_len = offset - prev_offset;
3135 if (padding_len > 0) {
3136 const llvm_array_ty = o.context.intType(8).arrayType(@as(c_uint, @intCast(padding_len)));
3137 try llvm_field_types.append(gpa, llvm_array_ty);
3138 }
3139 const field_llvm_ty = try o.lowerLlvmType(field_ty.toType());
3140 try llvm_field_types.append(gpa, field_llvm_ty);
3141
3142 offset += field_ty.toType().abiSize(mod);
3143 }
3144 {
3145 const prev_offset = offset;
3146 offset = std.mem.alignForward(u64, offset, big_align);
3147 const padding_len = offset - prev_offset;
3148 if (padding_len > 0) {
3149 const llvm_array_ty = o.context.intType(8).arrayType(@as(c_uint, @intCast(padding_len)));
3150 try llvm_field_types.append(gpa, llvm_array_ty);
3151 }
3152 }
3153
3154 llvm_struct_ty.structSetBody(
3155 llvm_field_types.items.ptr,
3156 @as(c_uint, @intCast(llvm_field_types.items.len)),
3157 .False,
3158 );
3159
3160 return llvm_struct_ty;
3161 },
3162 .struct_type => |struct_type| struct_type,
3163 else => unreachable,
3164 };
3165
3166 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3167
3168 if (struct_obj.layout == .Packed) {
3169 assert(struct_obj.haveLayout());
3170 const int_llvm_ty = try o.lowerLlvmType(struct_obj.backing_int_ty);
3171 gop.value_ptr.* = int_llvm_ty;
3172 return int_llvm_ty;
3173 }
3174
3175 const name = try o.builder.string(mod.intern_pool.stringToSlice(
3176 try struct_obj.getFullyQualifiedName(mod),
3177 ));
3178 const ty = try o.builder.opaqueType(name);
3179
3180 const llvm_struct_ty = o.builder.llvm_types.items[@intFromEnum(ty)];
3181 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
3182
3183 assert(struct_obj.haveFieldTypes());
3184
3185 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};
3186 defer llvm_field_types.deinit(gpa);
3187
3188 try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count());
3189
3190 comptime assert(struct_layout_version == 2);
3191 var offset: u64 = 0;
3192 var big_align: u32 = 1;
3193 var any_underaligned_fields = false;
3194
3195 var it = struct_obj.runtimeFieldIterator(mod);
3196 while (it.next()) |field_and_index| {
3197 const field = field_and_index.field;
3198 const field_align = field.alignment(mod, struct_obj.layout);
3199 const field_ty_align = field.ty.abiAlignment(mod);
3200 any_underaligned_fields = any_underaligned_fields or
3201 field_align < field_ty_align;
3202 big_align = @max(big_align, field_align);
3203 const prev_offset = offset;
3204 offset = std.mem.alignForward(u64, offset, field_align);
3205
3206 const padding_len = offset - prev_offset;
3207 if (padding_len > 0) {
3208 const llvm_array_ty = o.context.intType(8).arrayType(@as(c_uint, @intCast(padding_len)));
3209 try llvm_field_types.append(gpa, llvm_array_ty);
3210 }
3211 const field_llvm_ty = try o.lowerLlvmType(field.ty);
3212 try llvm_field_types.append(gpa, field_llvm_ty);
3213
3214 offset += field.ty.abiSize(mod);
3215 }
3216 {
3217 const prev_offset = offset;
3218 offset = std.mem.alignForward(u64, offset, big_align);
3219 const padding_len = offset - prev_offset;
3220 if (padding_len > 0) {
3221 const llvm_array_ty = o.context.intType(8).arrayType(@as(c_uint, @intCast(padding_len)));
3222 try llvm_field_types.append(gpa, llvm_array_ty);
3223 }
3224 }
3225
3226 llvm_struct_ty.structSetBody(
3227 llvm_field_types.items.ptr,
3228 @as(c_uint, @intCast(llvm_field_types.items.len)),
3229 llvm.Bool.fromBool(any_underaligned_fields),
3230 );
3231
3232 return llvm_struct_ty;
3233 },
3234 .Union => {
3235 const gop = try o.type_map.getOrPut(gpa, t.toIntern());
3236 if (gop.found_existing) return gop.value_ptr.*;
3237
3238 const layout = t.unionGetLayout(mod);
3239 const union_obj = mod.typeToUnion(t).?;
3240
3241 if (union_obj.layout == .Packed) {
3242 const bitsize = @as(c_uint, @intCast(t.bitSize(mod)));
3243 const int_llvm_ty = o.context.intType(bitsize);
3244 gop.value_ptr.* = int_llvm_ty;
3245 return int_llvm_ty;
3246 }
3247
3248 if (layout.payload_size == 0) {
3249 const enum_tag_llvm_ty = try o.lowerLlvmType(union_obj.tag_ty);
3250 gop.value_ptr.* = enum_tag_llvm_ty;
3251 return enum_tag_llvm_ty;
3252 }
3253
3254 const name = mod.intern_pool.stringToSlice(try union_obj.getFullyQualifiedName(mod));
3255
3256 const llvm_union_ty = o.context.structCreateNamed(name);
3257 gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls
3258
3259 const aligned_field = union_obj.fields.values()[layout.most_aligned_field];
3260 const llvm_aligned_field_ty = try o.lowerLlvmType(aligned_field.ty);
3261
3262 const llvm_payload_ty = t: {
3263 if (layout.most_aligned_field_size == layout.payload_size) {
3264 break :t llvm_aligned_field_ty;
3265 }
3266 const padding_len = if (layout.tag_size == 0)
3267 @as(c_uint, @intCast(layout.abi_size - layout.most_aligned_field_size))
3268 else
3269 @as(c_uint, @intCast(layout.payload_size - layout.most_aligned_field_size));
3270 const fields: [2]*llvm.Type = .{
3271 llvm_aligned_field_ty,
3272 o.context.intType(8).arrayType(padding_len),
3273 };
3274 break :t o.context.structType(&fields, fields.len, .True);
3275 };
3276
3277 if (layout.tag_size == 0) {
3278 var llvm_fields: [1]*llvm.Type = .{llvm_payload_ty};
3279 llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False);
3280 return llvm_union_ty;
3281 }
3282 const enum_tag_llvm_ty = try o.lowerLlvmType(union_obj.tag_ty);
3283
3284 // Put the tag before or after the payload depending on which one's
3285 // alignment is greater.
3286 var llvm_fields: [3]*llvm.Type = undefined;
3287 var llvm_fields_len: c_uint = 2;
3288
3289 if (layout.tag_align >= layout.payload_align) {
3290 llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined };
3291 } else {
3292 llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined };
3293 }
3294
3295 // Insert padding to make the LLVM struct ABI size match the Zig union ABI size.
3296 if (layout.padding != 0) {
3297 llvm_fields[2] = o.context.intType(8).arrayType(layout.padding);
3298 llvm_fields_len = 3;
3299 }
3300
3301 llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);
3302 return llvm_union_ty;
3303 },
3304 .Fn => return lowerLlvmTypeFn(o, t),
3305 .ComptimeInt => unreachable,
3306 .ComptimeFloat => unreachable,
3307 .Type => unreachable,
3308 .Undefined => unreachable,
3309 .Null => unreachable,
3310 .EnumLiteral => unreachable,
3311
3312 .Frame => @panic("TODO implement llvmType for Frame types"),
3313 .AnyFrame => @panic("TODO implement llvmType for AnyFrame types"),
3314 }
3315 }
3316
3317 fn lowerLlvmTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {
3318 const mod = o.module;
3319 const ip = &mod.intern_pool;
3320 const fn_info = mod.typeToFunc(fn_ty).?;
3321 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
3322
3323 var llvm_params = std.ArrayList(*llvm.Type).init(o.gpa);
3324 defer llvm_params.deinit();
3325
3326 if (firstParamSRet(fn_info, mod)) {
3327 try llvm_params.append(o.context.pointerType(0));
3328 }
3329
3330 if (fn_info.return_type.toType().isError(mod) and
3331 mod.comp.bin_file.options.error_return_tracing)
3332 {
3333 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());
3334 try llvm_params.append(try o.lowerLlvmType(ptr_ty));
3335 }
3336
3337 var it = iterateParamTypes(o, fn_info);
3338 while (it.next()) |lowering| switch (lowering) {
3339 .no_bits => continue,
3340 .byval => {
3341 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3342 try llvm_params.append(try o.lowerLlvmType(param_ty));
3343 },
3344 .byref, .byref_mut => {
3345 try llvm_params.append(o.context.pointerType(0));
3346 },
3347 .abi_sized_int => {
3348 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3349 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
3350 try llvm_params.append(o.context.intType(abi_size * 8));
3351 },
3352 .slice => {
3353 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3354 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
3355 param_ty.optionalChild(mod).slicePtrFieldType(mod)
3356 else
3357 param_ty.slicePtrFieldType(mod);
3358 const ptr_llvm_ty = try o.lowerLlvmType(ptr_ty);
3359 const len_llvm_ty = try o.lowerLlvmType(Type.usize);
3360
3361 try llvm_params.ensureUnusedCapacity(2);
3362 llvm_params.appendAssumeCapacity(ptr_llvm_ty);
3363 llvm_params.appendAssumeCapacity(len_llvm_ty);
3364 },
3365 .multiple_llvm_types => {
3366 try llvm_params.appendSlice(it.llvm_types_buffer[0..it.llvm_types_len]);
3367 },
3368 .as_u16 => {
3369 try llvm_params.append(o.context.intType(16));
3370 },
3371 .float_array => |count| {
3372 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3373 const float_ty = try o.lowerLlvmType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
3374 const field_count = @as(c_uint, @intCast(count));
3375 const arr_ty = float_ty.arrayType(field_count);
3376 try llvm_params.append(arr_ty);
3377 },
3378 .i32_array, .i64_array => |arr_len| {
3379 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;
3380 const arr_ty = o.context.intType(elem_size).arrayType(arr_len);
3381 try llvm_params.append(arr_ty);
3382 },
3383 };
3384
3385 return llvm.functionType(
3386 llvm_ret_ty,
3387 llvm_params.items.ptr,
3388 @as(c_uint, @intCast(llvm_params.items.len)),
3389 llvm.Bool.fromBool(fn_info.is_var_args),
3390 );
2959 return ty;
33912960 }
33922961
3393 /// Use this instead of lowerLlvmType when you want to handle correctly the case of elem_ty
3394 /// being a zero bit type, but it should still be lowered as an i8 in such case.
3395 /// There are other similar cases handled here as well.
3396 fn lowerPtrElemTy(o: *Object, elem_ty: Type) Allocator.Error!*llvm.Type {
3397 const mod = o.module;
3398 const lower_elem_ty = switch (elem_ty.zigTypeTag(mod)) {
3399 .Opaque => true,
3400 .Fn => !mod.typeToFunc(elem_ty).?.is_generic,
3401 .Array => elem_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod),
3402 else => elem_ty.hasRuntimeBitsIgnoreComptime(mod),
3403 };
3404 const llvm_elem_ty = if (lower_elem_ty)
3405 try o.lowerLlvmType(elem_ty)
3406 else
3407 o.context.intType(8);
3408
3409 return llvm_elem_ty;
3410 }
3411
3412 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
2962 fn lowerTypeInner(o: *Object, t: Type) Allocator.Error!Builder.Type {
34132963 const mod = o.module;
34142964 const target = mod.getTarget();
34152965 return switch (t.toIntern()) {
......@@ -3459,8 +3009,11 @@ pub const Object = struct {
34593009 .bool_type => .i1,
34603010 .void_type => .void,
34613011 .type_type => unreachable,
3462 .anyerror_type => .i16,
3463 .comptime_int_type, .comptime_float_type, .noreturn_type => unreachable,
3012 .anyerror_type => Builder.Type.err_int,
3013 .comptime_int_type,
3014 .comptime_float_type,
3015 .noreturn_type,
3016 => unreachable,
34643017 .anyframe_type => @panic("TODO implement lowerType for AnyFrame types"),
34653018 .null_type,
34663019 .undefined_type,
......@@ -3482,10 +3035,16 @@ pub const Object = struct {
34823035 .manyptr_const_u8_sentinel_0_type,
34833036 .single_const_pointer_to_comptime_int_type,
34843037 => .ptr,
3485 .slice_const_u8_type, .slice_const_u8_sentinel_0_type => .none,
3038 .slice_const_u8_type,
3039 .slice_const_u8_sentinel_0_type,
3040 => try o.builder.structType(.normal, &.{ .ptr, try o.lowerType(Type.usize) }),
34863041 .optional_noreturn_type => unreachable,
3487 .anyerror_void_error_union_type => .i16,
3488 .generic_poison_type, .empty_struct_type => unreachable,
3042 .anyerror_void_error_union_type,
3043 .adhoc_inferred_error_set_type,
3044 => Builder.Type.err_int,
3045 .generic_poison_type,
3046 .empty_struct_type,
3047 => unreachable,
34893048 // values, not types
34903049 .undef,
34913050 .zero,
......@@ -3511,22 +3070,265 @@ pub const Object = struct {
35113070 else => switch (mod.intern_pool.indexToKey(t.toIntern())) {
35123071 .int_type => |int_type| try o.builder.intType(int_type.bits),
35133072 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
3514 .One, .Many, .C => try o.builder.pointerType(@enumFromInt(
3073 .One, .Many, .C => try o.builder.ptrType(
35153074 toLlvmAddressSpace(ptr_type.flags.address_space, target),
3516 )),
3517 .Slice => .none,
3075 ),
3076 .Slice => try o.builder.structType(.normal, &.{
3077 .ptr,
3078 try o.lowerType(Type.usize),
3079 }),
3080 },
3081 .array_type => |array_type| o.builder.arrayType(
3082 array_type.len + @intFromBool(array_type.sentinel != .none),
3083 try o.lowerType(array_type.child.toType()),
3084 ),
3085 .vector_type => |vector_type| o.builder.vectorType(
3086 .normal,
3087 vector_type.len,
3088 try o.lowerType(vector_type.child.toType()),
3089 ),
3090 .opt_type => |child_ty| {
3091 if (!child_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) return .i8;
3092
3093 const payload_ty = try o.lowerType(child_ty.toType());
3094 if (t.optionalReprIsPayload(mod)) return payload_ty;
3095
3096 comptime assert(optional_layout_version == 3);
3097 var fields_buf: [3]Builder.Type = .{ payload_ty, .i8, .none };
3098 const offset = child_ty.toType().abiSize(mod) + 1;
3099 const abi_size = t.abiSize(mod);
3100 const padding = abi_size - offset;
3101 if (padding == 0) return o.builder.structType(.normal, fields_buf[0..2]);
3102 fields_buf[2] = try o.builder.arrayType(padding, .i8);
3103 return o.builder.structType(.normal, fields_buf[0..3]);
35183104 },
3519 .array_type, .vector_type, .opt_type => .none,
35203105 .anyframe_type => @panic("TODO implement lowerType for AnyFrame types"),
3521 .error_union_type => .none,
3106 .error_union_type => |error_union_type| {
3107 const error_type = Builder.Type.err_int;
3108 if (!error_union_type.payload_type.toType().hasRuntimeBitsIgnoreComptime(mod))
3109 return error_type;
3110 const payload_type = try o.lowerType(error_union_type.payload_type.toType());
3111
3112 const payload_align = error_union_type.payload_type.toType().abiAlignment(mod);
3113 const error_align = Type.err_int.abiAlignment(mod);
3114
3115 const payload_size = error_union_type.payload_type.toType().abiSize(mod);
3116 const error_size = Type.err_int.abiSize(mod);
3117
3118 var fields_buf: [3]Builder.Type = undefined;
3119 if (error_align > payload_align) {
3120 fields_buf[0] = error_type;
3121 fields_buf[1] = payload_type;
3122 const payload_end =
3123 std.mem.alignForward(u64, error_size, payload_align) +
3124 payload_size;
3125 const abi_size = std.mem.alignForward(u64, payload_end, error_align);
3126 const padding = abi_size - payload_end;
3127 if (padding == 0) return o.builder.structType(.normal, fields_buf[0..2]);
3128 fields_buf[2] = try o.builder.arrayType(padding, .i8);
3129 return o.builder.structType(.normal, fields_buf[0..3]);
3130 } else {
3131 fields_buf[0] = payload_type;
3132 fields_buf[1] = error_type;
3133 const error_end =
3134 std.mem.alignForward(u64, payload_size, error_align) +
3135 error_size;
3136 const abi_size = std.mem.alignForward(u64, error_end, payload_align);
3137 const padding = abi_size - error_end;
3138 if (padding == 0) return o.builder.structType(.normal, fields_buf[0..2]);
3139 fields_buf[2] = try o.builder.arrayType(padding, .i8);
3140 return o.builder.structType(.normal, fields_buf[0..3]);
3141 }
3142 },
35223143 .simple_type => unreachable,
3523 .struct_type,
3524 .anon_struct_type,
3525 .union_type,
3526 .opaque_type,
3527 => .none,
3144 .struct_type => |struct_type| {
3145 const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
3146 if (gop.found_existing) return gop.value_ptr.*;
3147
3148 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3149 if (struct_obj.layout == .Packed) {
3150 assert(struct_obj.haveLayout());
3151 const int_ty = try o.lowerType(struct_obj.backing_int_ty);
3152 gop.value_ptr.* = int_ty;
3153 return int_ty;
3154 }
3155
3156 const name = try o.builder.string(mod.intern_pool.stringToSlice(
3157 try struct_obj.getFullyQualifiedName(mod),
3158 ));
3159 const ty = try o.builder.opaqueType(name);
3160 gop.value_ptr.* = ty; // must be done before any recursive calls
3161
3162 assert(struct_obj.haveFieldTypes());
3163
3164 var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};
3165 defer llvm_field_types.deinit(o.gpa);
3166 try llvm_field_types.ensureUnusedCapacity(o.gpa, struct_obj.fields.count());
3167
3168 comptime assert(struct_layout_version == 2);
3169 var offset: u64 = 0;
3170 var big_align: u32 = 1;
3171 var struct_kind: Builder.Type.Structure.Kind = .normal;
3172
3173 var it = struct_obj.runtimeFieldIterator(mod);
3174 while (it.next()) |field_and_index| {
3175 const field = field_and_index.field;
3176 const field_align = field.alignment(mod, struct_obj.layout);
3177 const field_ty_align = field.ty.abiAlignment(mod);
3178 if (field_align < field_ty_align) struct_kind = .@"packed";
3179 big_align = @max(big_align, field_align);
3180 const prev_offset = offset;
3181 offset = std.mem.alignForward(u64, offset, field_align);
3182
3183 const padding_len = offset - prev_offset;
3184 if (padding_len > 0) try llvm_field_types.append(
3185 o.gpa,
3186 try o.builder.arrayType(padding_len, .i8),
3187 );
3188 try llvm_field_types.append(o.gpa, try o.lowerType(field.ty));
3189
3190 offset += field.ty.abiSize(mod);
3191 }
3192 {
3193 const prev_offset = offset;
3194 offset = std.mem.alignForward(u64, offset, big_align);
3195 const padding_len = offset - prev_offset;
3196 if (padding_len > 0) try llvm_field_types.append(
3197 o.gpa,
3198 try o.builder.arrayType(padding_len, .i8),
3199 );
3200 }
3201
3202 try o.builder.namedTypeSetBody(
3203 ty,
3204 try o.builder.structType(struct_kind, llvm_field_types.items),
3205 );
3206 return ty;
3207 },
3208 .anon_struct_type => |anon_struct_type| {
3209 var llvm_field_types: std.ArrayListUnmanaged(Builder.Type) = .{};
3210 defer llvm_field_types.deinit(o.gpa);
3211 try llvm_field_types.ensureUnusedCapacity(o.gpa, anon_struct_type.types.len);
3212
3213 comptime assert(struct_layout_version == 2);
3214 var offset: u64 = 0;
3215 var big_align: u32 = 0;
3216
3217 for (anon_struct_type.types, anon_struct_type.values) |field_ty, field_val| {
3218 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
3219
3220 const field_align = field_ty.toType().abiAlignment(mod);
3221 big_align = @max(big_align, field_align);
3222 const prev_offset = offset;
3223 offset = std.mem.alignForward(u64, offset, field_align);
3224
3225 const padding_len = offset - prev_offset;
3226 if (padding_len > 0) try llvm_field_types.append(
3227 o.gpa,
3228 try o.builder.arrayType(padding_len, .i8),
3229 );
3230 try llvm_field_types.append(o.gpa, try o.lowerType(field_ty.toType()));
3231
3232 offset += field_ty.toType().abiSize(mod);
3233 }
3234 {
3235 const prev_offset = offset;
3236 offset = std.mem.alignForward(u64, offset, big_align);
3237 const padding_len = offset - prev_offset;
3238 if (padding_len > 0) try llvm_field_types.append(
3239 o.gpa,
3240 try o.builder.arrayType(padding_len, .i8),
3241 );
3242 }
3243 return o.builder.structType(.normal, llvm_field_types.items);
3244 },
3245 .union_type => |union_type| {
3246 const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
3247 if (gop.found_existing) return gop.value_ptr.*;
3248
3249 const union_obj = mod.unionPtr(union_type.index);
3250 const layout = union_obj.getLayout(mod, union_type.hasTag());
3251
3252 if (union_obj.layout == .Packed) {
3253 const int_ty = try o.builder.intType(@intCast(t.bitSize(mod)));
3254 gop.value_ptr.* = int_ty;
3255 return int_ty;
3256 }
3257
3258 if (layout.payload_size == 0) {
3259 const enum_tag_ty = try o.lowerType(union_obj.tag_ty);
3260 gop.value_ptr.* = enum_tag_ty;
3261 return enum_tag_ty;
3262 }
3263
3264 const name = try o.builder.string(mod.intern_pool.stringToSlice(
3265 try union_obj.getFullyQualifiedName(mod),
3266 ));
3267 const ty = try o.builder.opaqueType(name);
3268 gop.value_ptr.* = ty; // must be done before any recursive calls
3269
3270 const aligned_field = union_obj.fields.values()[layout.most_aligned_field];
3271 const aligned_field_ty = try o.lowerType(aligned_field.ty);
3272
3273 const payload_ty = ty: {
3274 if (layout.most_aligned_field_size == layout.payload_size) {
3275 break :ty aligned_field_ty;
3276 }
3277 const padding_len = if (layout.tag_size == 0)
3278 layout.abi_size - layout.most_aligned_field_size
3279 else
3280 layout.payload_size - layout.most_aligned_field_size;
3281 break :ty try o.builder.structType(.@"packed", &.{
3282 aligned_field_ty,
3283 try o.builder.arrayType(padding_len, .i8),
3284 });
3285 };
3286
3287 if (layout.tag_size == 0) {
3288 try o.builder.namedTypeSetBody(
3289 ty,
3290 try o.builder.structType(.normal, &.{payload_ty}),
3291 );
3292 return ty;
3293 }
3294 const enum_tag_ty = try o.lowerType(union_obj.tag_ty);
3295
3296 // Put the tag before or after the payload depending on which one's
3297 // alignment is greater.
3298 var llvm_fields: [3]Builder.Type = undefined;
3299 var llvm_fields_len: usize = 2;
3300
3301 if (layout.tag_align >= layout.payload_align) {
3302 llvm_fields = .{ enum_tag_ty, payload_ty, .none };
3303 } else {
3304 llvm_fields = .{ payload_ty, enum_tag_ty, .none };
3305 }
3306
3307 // Insert padding to make the LLVM struct ABI size match the Zig union ABI size.
3308 if (layout.padding != 0) {
3309 llvm_fields[llvm_fields_len] = try o.builder.arrayType(layout.padding, .i8);
3310 llvm_fields_len += 1;
3311 }
3312
3313 try o.builder.namedTypeSetBody(
3314 ty,
3315 try o.builder.structType(.normal, llvm_fields[0..llvm_fields_len]),
3316 );
3317 return ty;
3318 },
3319 .opaque_type => |opaque_type| {
3320 const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
3321 if (!gop.found_existing) {
3322 const name = try o.builder.string(mod.intern_pool.stringToSlice(
3323 try mod.opaqueFullyQualifiedName(opaque_type),
3324 ));
3325 gop.value_ptr.* = try o.builder.opaqueType(name);
3326 }
3327 return gop.value_ptr.*;
3328 },
35283329 .enum_type => |enum_type| try o.lowerType(enum_type.tag_ty.toType()),
3529 .func_type, .error_set_type, .inferred_error_set_type => .none,
3330 .func_type => |func_type| try o.lowerTypeFn(func_type),
3331 .error_set_type, .inferred_error_set_type => Builder.Type.err_int,
35303332 // values, not types
35313333 .undef,
35323334 .runtime_value,
......@@ -3552,6 +3354,85 @@ pub const Object = struct {
35523354 };
35533355 }
35543356
3357 /// Use this instead of lowerType when you want to handle correctly the case of elem_ty
3358 /// being a zero bit type, but it should still be lowered as an i8 in such case.
3359 /// There are other similar cases handled here as well.
3360 fn lowerPtrElemTy(o: *Object, elem_ty: Type) Allocator.Error!Builder.Type {
3361 const mod = o.module;
3362 const lower_elem_ty = switch (elem_ty.zigTypeTag(mod)) {
3363 .Opaque => true,
3364 .Fn => !mod.typeToFunc(elem_ty).?.is_generic,
3365 .Array => elem_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod),
3366 else => elem_ty.hasRuntimeBitsIgnoreComptime(mod),
3367 };
3368 return if (lower_elem_ty) try o.lowerType(elem_ty) else .i8;
3369 }
3370
3371 fn lowerTypeFn(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
3372 const mod = o.module;
3373 const ip = &mod.intern_pool;
3374 const ret_ty = try lowerFnRetTy(o, fn_info);
3375
3376 var llvm_params = std.ArrayListUnmanaged(Builder.Type){};
3377 defer llvm_params.deinit(o.gpa);
3378
3379 if (firstParamSRet(fn_info, mod)) {
3380 try llvm_params.append(o.gpa, .ptr);
3381 }
3382
3383 if (fn_info.return_type.toType().isError(mod) and
3384 mod.comp.bin_file.options.error_return_tracing)
3385 {
3386 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());
3387 try llvm_params.append(o.gpa, try o.lowerType(ptr_ty));
3388 }
3389
3390 var it = iterateParamTypes(o, fn_info);
3391 while (try it.next()) |lowering| switch (lowering) {
3392 .no_bits => continue,
3393 .byval => {
3394 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3395 try llvm_params.append(o.gpa, try o.lowerType(param_ty));
3396 },
3397 .byref, .byref_mut => {
3398 try llvm_params.append(o.gpa, .ptr);
3399 },
3400 .abi_sized_int => {
3401 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3402 try llvm_params.append(o.gpa, try o.builder.intType(
3403 @intCast(param_ty.abiSize(mod) * 8),
3404 ));
3405 },
3406 .slice => {
3407 try llvm_params.appendSlice(o.gpa, &.{ .ptr, try o.lowerType(Type.usize) });
3408 },
3409 .multiple_llvm_types => {
3410 try llvm_params.appendSlice(o.gpa, it.types_buffer[0..it.types_len]);
3411 },
3412 .as_u16 => {
3413 try llvm_params.append(o.gpa, .i16);
3414 },
3415 .float_array => |count| {
3416 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3417 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
3418 try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty));
3419 },
3420 .i32_array, .i64_array => |arr_len| {
3421 try llvm_params.append(o.gpa, try o.builder.arrayType(arr_len, switch (lowering) {
3422 .i32_array => .i32,
3423 .i64_array => .i64,
3424 else => unreachable,
3425 }));
3426 },
3427 };
3428
3429 return o.builder.fnType(
3430 ret_ty,
3431 llvm_params.items,
3432 if (fn_info.is_var_args) .vararg else .normal,
3433 );
3434 }
3435
35553436 fn lowerValue(o: *Object, arg_tv: TypedValue) Error!*llvm.Value {
35563437 const mod = o.module;
35573438 const gpa = o.gpa;
......@@ -3562,8 +3443,7 @@ pub const Object = struct {
35623443 else => {},
35633444 }
35643445 if (tv.val.isUndefDeep(mod)) {
3565 const llvm_type = try o.lowerLlvmType(tv.ty);
3566 return llvm_type.getUndef();
3446 return (try o.lowerType(tv.ty)).toLlvm(&o.builder).getUndef();
35673447 }
35683448
35693449 switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
......@@ -3595,7 +3475,7 @@ pub const Object = struct {
35953475 .generic_poison,
35963476 => unreachable, // non-runtime values
35973477 .false, .true => {
3598 const llvm_type = try o.lowerLlvmType(tv.ty);
3478 const llvm_type = (try o.lowerType(tv.ty)).toLlvm(&o.builder);
35993479 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();
36003480 },
36013481 },
......@@ -3623,7 +3503,7 @@ pub const Object = struct {
36233503 return lowerBigInt(o, tv.ty, bigint);
36243504 },
36253505 .err => |err| {
3626 const llvm_ty = try o.lowerLlvmType(Type.anyerror);
3506 const llvm_ty = Builder.Type.err_int.toLlvm(&o.builder);
36273507 const int = try mod.getErrorValue(err.name);
36283508 return llvm_ty.constInt(int, .False);
36293509 },
......@@ -3659,7 +3539,7 @@ pub const Object = struct {
36593539 });
36603540 var fields_buf: [3]*llvm.Value = undefined;
36613541
3662 const llvm_ty = try o.lowerLlvmType(tv.ty);
3542 const llvm_ty = (try o.lowerType(tv.ty)).toLlvm(&o.builder);
36633543 const llvm_field_count = llvm_ty.countStructElementTypes();
36643544 if (llvm_field_count > 2) {
36653545 assert(llvm_field_count == 3);
......@@ -3703,7 +3583,7 @@ pub const Object = struct {
37033583 return unsigned_val;
37043584 },
37053585 .float => {
3706 const llvm_ty = try o.lowerLlvmType(tv.ty);
3586 const llvm_ty = (try o.lowerType(tv.ty)).toLlvm(&o.builder);
37073587 switch (tv.ty.floatBits(target)) {
37083588 16 => {
37093589 const repr = @as(u16, @bitCast(tv.val.toFloat(f16, mod)));
......@@ -3788,7 +3668,7 @@ pub const Object = struct {
37883668 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
37893669 return non_null_bit;
37903670 }
3791 const llvm_ty = try o.lowerLlvmType(tv.ty);
3671 const llvm_ty = (try o.lowerType(tv.ty)).toLlvm(&o.builder);
37923672 if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) {
37933673 .none => llvm_ty.constNull(),
37943674 else => |payload| o.lowerValue(.{ .ty = payload_ty, .val = payload.toValue() }),
......@@ -3834,7 +3714,7 @@ pub const Object = struct {
38343714 .True,
38353715 );
38363716 } else {
3837 const llvm_elem_ty = try o.lowerLlvmType(elem_ty);
3717 const llvm_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
38383718 return llvm_elem_ty.constArray(
38393719 llvm_elems.ptr,
38403720 @as(c_uint, @intCast(llvm_elems.len)),
......@@ -3869,7 +3749,7 @@ pub const Object = struct {
38693749 .True,
38703750 );
38713751 } else {
3872 const llvm_elem_ty = try o.lowerLlvmType(elem_ty);
3752 const llvm_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
38733753 return llvm_elem_ty.constArray(
38743754 llvm_elems.ptr,
38753755 @as(c_uint, @intCast(llvm_elems.len)),
......@@ -3956,7 +3836,7 @@ pub const Object = struct {
39563836 .False,
39573837 );
39583838 } else {
3959 const llvm_struct_ty = try o.lowerLlvmType(tv.ty);
3839 const llvm_struct_ty = (try o.lowerType(tv.ty)).toLlvm(&o.builder);
39603840 return llvm_struct_ty.constNamedStruct(
39613841 llvm_fields.items.ptr,
39623842 @as(c_uint, @intCast(llvm_fields.items.len)),
......@@ -3965,7 +3845,7 @@ pub const Object = struct {
39653845 },
39663846 .struct_type => |struct_type| {
39673847 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3968 const llvm_struct_ty = try o.lowerLlvmType(tv.ty);
3848 const llvm_struct_ty = (try o.lowerType(tv.ty)).toLlvm(&o.builder);
39693849
39703850 if (struct_obj.layout == .Packed) {
39713851 assert(struct_obj.haveLayout());
......@@ -4062,7 +3942,7 @@ pub const Object = struct {
40623942 else => unreachable,
40633943 },
40643944 .un => {
4065 const llvm_union_ty = try o.lowerLlvmType(tv.ty);
3945 const llvm_union_ty = (try o.lowerType(tv.ty)).toLlvm(&o.builder);
40663946 const tag_and_val: Value.Payload.Union.Data = switch (tv.val.toIntern()) {
40673947 .none => tv.val.castTag(.@"union").?.data,
40683948 else => switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
......@@ -4232,7 +4112,7 @@ pub const Object = struct {
42324112 llvm_u32.constInt(0, .False),
42334113 llvm_u32.constInt(payload_offset, .False),
42344114 };
4235 const eu_llvm_ty = try o.lowerLlvmType(eu_ty);
4115 const eu_llvm_ty = (try o.lowerType(eu_ty)).toLlvm(&o.builder);
42364116 return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
42374117 },
42384118 .opt_payload => |opt_ptr| {
......@@ -4253,19 +4133,19 @@ pub const Object = struct {
42534133 llvm_u32.constInt(0, .False),
42544134 llvm_u32.constInt(0, .False),
42554135 };
4256 const opt_llvm_ty = try o.lowerLlvmType(opt_ty);
4136 const opt_llvm_ty = (try o.lowerType(opt_ty)).toLlvm(&o.builder);
42574137 return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
42584138 },
42594139 .comptime_field => unreachable,
42604140 .elem => |elem_ptr| {
42614141 const parent_llvm_ptr = try o.lowerParentPtr(elem_ptr.base.toValue(), true);
42624142
4263 const llvm_usize = try o.lowerLlvmType(Type.usize);
4143 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
42644144 const indices: [1]*llvm.Value = .{
42654145 llvm_usize.constInt(elem_ptr.index, .False),
42664146 };
42674147 const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod);
4268 const elem_llvm_ty = try o.lowerLlvmType(elem_ty);
4148 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
42694149 return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
42704150 },
42714151 .field => |field_ptr| {
......@@ -4294,7 +4174,7 @@ pub const Object = struct {
42944174 llvm_u32.constInt(0, .False),
42954175 llvm_u32.constInt(llvm_pl_index, .False),
42964176 };
4297 const parent_llvm_ty = try o.lowerLlvmType(parent_ty);
4177 const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder);
42984178 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
42994179 },
43004180 .Struct => {
......@@ -4317,7 +4197,7 @@ pub const Object = struct {
43174197 return field_addr.constIntToPtr(final_llvm_ty);
43184198 }
43194199
4320 const parent_llvm_ty = try o.lowerLlvmType(parent_ty);
4200 const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder);
43214201 if (llvmField(parent_ty, field_index, mod)) |llvm_field| {
43224202 const indices: [2]*llvm.Value = .{
43234203 llvm_u32.constInt(0, .False),
......@@ -4336,7 +4216,7 @@ pub const Object = struct {
43364216 llvm_u32.constInt(0, .False),
43374217 llvm_u32.constInt(field_index, .False),
43384218 };
4339 const parent_llvm_ty = try o.lowerLlvmType(parent_ty);
4219 const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder);
43404220 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
43414221 },
43424222 else => unreachable,
......@@ -4386,11 +4266,11 @@ pub const Object = struct {
43864266 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
43874267 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
43884268 const llvm_val = if (llvm_wanted_addrspace != llvm_actual_addrspace) blk: {
4389 const llvm_decl_wanted_ptr_ty = o.context.pointerType(llvm_wanted_addrspace);
4269 const llvm_decl_wanted_ptr_ty = o.context.pointerType(@intFromEnum(llvm_wanted_addrspace));
43904270 break :blk llvm_decl_val.constAddrSpaceCast(llvm_decl_wanted_ptr_ty);
43914271 } else llvm_decl_val;
43924272
4393 const llvm_type = try o.lowerLlvmType(tv.ty);
4273 const llvm_type = (try o.lowerType(tv.ty)).toLlvm(&o.builder);
43944274 if (tv.ty.zigTypeTag(mod) == .Int) {
43954275 return llvm_val.constPtrToInt(llvm_type);
43964276 } else {
......@@ -4405,8 +4285,8 @@ pub const Object = struct {
44054285 // The value cannot be undefined, because we use the `nonnull` annotation
44064286 // for non-optional pointers. We also need to respect the alignment, even though
44074287 // the address will never be dereferenced.
4408 const llvm_usize = try o.lowerLlvmType(Type.usize);
4409 const llvm_ptr_ty = try o.lowerLlvmType(ptr_ty);
4288 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
4289 const llvm_ptr_ty = (try o.lowerType(ptr_ty)).toLlvm(&o.builder);
44104290 if (ptr_ty.ptrInfo(mod).flags.alignment.toByteUnitsOptional()) |alignment| {
44114291 return llvm_usize.constInt(alignment, .False).constIntToPtr(llvm_ptr_ty);
44124292 }
......@@ -4492,23 +4372,23 @@ pub const Object = struct {
44924372 /// widen it before using it and then truncate the result.
44934373 /// RMW exchange of floating-point values is bitcasted to same-sized integer
44944374 /// types to work around a LLVM deficiency when targeting ARM/AArch64.
4495 fn getAtomicAbiType(o: *Object, ty: Type, is_rmw_xchg: bool) ?*llvm.Type {
4375 fn getAtomicAbiType(o: *Object, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type {
44964376 const mod = o.module;
44974377 const int_ty = switch (ty.zigTypeTag(mod)) {
44984378 .Int => ty,
44994379 .Enum => ty.intTagType(mod),
45004380 .Float => {
4501 if (!is_rmw_xchg) return null;
4502 return o.context.intType(@as(c_uint, @intCast(ty.abiSize(mod) * 8)));
4381 if (!is_rmw_xchg) return .none;
4382 return o.builder.intType(@intCast(ty.abiSize(mod) * 8));
45034383 },
4504 .Bool => return o.context.intType(8),
4505 else => return null,
4384 .Bool => return .i8,
4385 else => return .none,
45064386 };
45074387 const bit_count = int_ty.intInfo(mod).bits;
45084388 if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) {
4509 return o.context.intType(@as(c_uint, @intCast(int_ty.abiSize(mod) * 8)));
4389 return o.builder.intType(@intCast(int_ty.abiSize(mod) * 8));
45104390 } else {
4511 return null;
4391 return .none;
45124392 }
45134393 }
45144394
......@@ -4549,13 +4429,13 @@ pub const Object = struct {
45494429 llvm_arg_i: u32,
45504430 alignment: u32,
45514431 byval_attr: bool,
4552 param_llvm_ty: *llvm.Type,
4432 param_llvm_ty: Builder.Type,
45534433 ) void {
45544434 o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
45554435 o.addArgAttr(llvm_fn, llvm_arg_i, "readonly");
45564436 o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment);
45574437 if (byval_attr) {
4558 llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty);
4438 llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder));
45594439 }
45604440 }
45614441};
......@@ -4626,7 +4506,7 @@ pub const DeclGen = struct {
46264506 const new_global = o.llvm_module.addGlobalInAddressSpace(
46274507 llvm_init.typeOf(),
46284508 "",
4629 llvm_global_addrspace,
4509 @intFromEnum(llvm_global_addrspace),
46304510 );
46314511 new_global.setLinkage(llvm_global.getLinkage());
46324512 new_global.setUnnamedAddr(llvm_global.getUnnamedAddress());
......@@ -4761,14 +4641,14 @@ pub const FuncGen = struct {
47614641 const target = mod.getTarget();
47624642 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);
47634643 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);
4764 const global = o.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_actual_addrspace);
4644 const global = o.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", @intFromEnum(llvm_actual_addrspace));
47654645 global.setInitializer(llvm_val);
47664646 global.setLinkage(.Private);
47674647 global.setGlobalConstant(.True);
47684648 global.setUnnamedAddr(.True);
47694649 global.setAlignment(tv.ty.abiAlignment(mod));
47704650 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)
4771 global.constAddrSpaceCast(self.context.pointerType(llvm_wanted_addrspace))
4651 global.constAddrSpaceCast(self.context.pointerType(@intFromEnum(llvm_wanted_addrspace)))
47724652 else
47734653 global;
47744654 return addrspace_casted_ptr;
......@@ -5053,7 +4933,7 @@ pub const FuncGen = struct {
50534933 defer llvm_args.deinit();
50544934
50554935 const ret_ptr = if (!sret) null else blk: {
5056 const llvm_ret_ty = try o.lowerLlvmType(return_type);
4936 const llvm_ret_ty = (try o.lowerType(return_type)).toLlvm(&o.builder);
50574937 const ret_ptr = self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(mod));
50584938 try llvm_args.append(ret_ptr);
50594939 break :blk ret_ptr;
......@@ -5066,13 +4946,13 @@ pub const FuncGen = struct {
50664946 }
50674947
50684948 var it = iterateParamTypes(o, fn_info);
5069 while (it.nextCall(self, args)) |lowering| switch (lowering) {
4949 while (try it.nextCall(self, args)) |lowering| switch (lowering) {
50704950 .no_bits => continue,
50714951 .byval => {
50724952 const arg = args[it.zig_index - 1];
50734953 const param_ty = self.typeOf(arg);
50744954 const llvm_arg = try self.resolveInst(arg);
5075 const llvm_param_ty = try o.lowerLlvmType(param_ty);
4955 const llvm_param_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
50764956 if (isByRef(param_ty, mod)) {
50774957 const alignment = param_ty.abiAlignment(mod);
50784958 const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, "");
......@@ -5103,7 +4983,7 @@ pub const FuncGen = struct {
51034983 const llvm_arg = try self.resolveInst(arg);
51044984
51054985 const alignment = param_ty.abiAlignment(mod);
5106 const param_llvm_ty = try o.lowerLlvmType(param_ty);
4986 const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
51074987 const arg_ptr = self.buildAlloca(param_llvm_ty, alignment);
51084988 if (isByRef(param_ty, mod)) {
51094989 const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, "");
......@@ -5157,7 +5037,7 @@ pub const FuncGen = struct {
51575037 .multiple_llvm_types => {
51585038 const arg = args[it.zig_index - 1];
51595039 const param_ty = self.typeOf(arg);
5160 const llvm_types = it.llvm_types_buffer[0..it.llvm_types_len];
5040 const llvm_types = it.llvm_types_buffer[0..it.types_len];
51615041 const llvm_arg = try self.resolveInst(arg);
51625042 const is_by_ref = isByRef(param_ty, mod);
51635043 const arg_ptr = if (is_by_ref) llvm_arg else p: {
......@@ -5168,7 +5048,7 @@ pub const FuncGen = struct {
51685048 };
51695049
51705050 const llvm_ty = self.context.structType(llvm_types.ptr, @as(c_uint, @intCast(llvm_types.len)), .False);
5171 try llvm_args.ensureUnusedCapacity(it.llvm_types_len);
5051 try llvm_args.ensureUnusedCapacity(it.types_len);
51725052 for (llvm_types, 0..) |field_ty, i_usize| {
51735053 const i = @as(c_uint, @intCast(i_usize));
51745054 const field_ptr = self.builder.buildStructGEP(llvm_ty, arg_ptr, i, "");
......@@ -5194,7 +5074,7 @@ pub const FuncGen = struct {
51945074 llvm_arg = store_inst;
51955075 }
51965076
5197 const float_ty = try o.lowerLlvmType(aarch64_c_abi.getFloatArrayType(arg_ty, mod).?);
5077 const float_ty = (try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, mod).?)).toLlvm(&o.builder);
51985078 const array_llvm_ty = float_ty.arrayType(count);
51995079
52005080 const alignment = arg_ty.abiAlignment(mod);
......@@ -5223,7 +5103,7 @@ pub const FuncGen = struct {
52235103 };
52245104
52255105 const call = self.builder.buildCall(
5226 try o.lowerLlvmType(zig_fn_ty),
5106 (try o.lowerType(zig_fn_ty)).toLlvm(&o.builder),
52275107 llvm_fn,
52285108 llvm_args.items.ptr,
52295109 @as(c_uint, @intCast(llvm_args.items.len)),
......@@ -5237,7 +5117,7 @@ pub const FuncGen = struct {
52375117 it = iterateParamTypes(o, fn_info);
52385118 it.llvm_index += @intFromBool(sret);
52395119 it.llvm_index += @intFromBool(err_return_tracing);
5240 while (it.next()) |lowering| switch (lowering) {
5120 while (try it.next()) |lowering| switch (lowering) {
52415121 .byval => {
52425122 const param_index = it.zig_index - 1;
52435123 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
......@@ -5248,7 +5128,7 @@ pub const FuncGen = struct {
52485128 .byref => {
52495129 const param_index = it.zig_index - 1;
52505130 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
5251 const param_llvm_ty = try o.lowerLlvmType(param_ty);
5131 const param_llvm_ty = try o.lowerType(param_ty);
52525132 const alignment = param_ty.abiAlignment(mod);
52535133 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
52545134 },
......@@ -5297,7 +5177,7 @@ pub const FuncGen = struct {
52975177 return null;
52985178 }
52995179
5300 const llvm_ret_ty = try o.lowerLlvmType(return_type);
5180 const llvm_ret_ty = (try o.lowerType(return_type)).toLlvm(&o.builder);
53015181
53025182 if (ret_ptr) |rp| {
53035183 call.setCallSret(llvm_ret_ty);
......@@ -5311,7 +5191,7 @@ pub const FuncGen = struct {
53115191 }
53125192 }
53135193
5314 const abi_ret_ty = try lowerFnRetTy(o, fn_info);
5194 const abi_ret_ty = (try lowerFnRetTy(o, fn_info)).toLlvm(&o.builder);
53155195
53165196 if (abi_ret_ty != llvm_ret_ty) {
53175197 // In this case the function return type is honoring the calling convention by having
......@@ -5374,7 +5254,7 @@ pub const FuncGen = struct {
53745254 const fn_info = mod.typeToFunc(panic_decl.ty).?;
53755255 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);
53765256 _ = fg.builder.buildCall(
5377 try o.lowerLlvmType(panic_decl.ty),
5257 (try o.lowerType(panic_decl.ty)).toLlvm(&o.builder),
53785258 panic_global.toLlvm(&o.builder),
53795259 &args,
53805260 args.len,
......@@ -5403,7 +5283,7 @@ pub const FuncGen = struct {
54035283 // Functions with an empty error set are emitted with an error code
54045284 // return type and return zero so they can be function pointers coerced
54055285 // to functions that return anyerror.
5406 const err_int = try o.lowerLlvmType(Type.anyerror);
5286 const err_int = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder);
54075287 _ = self.builder.buildRet(err_int.constInt(0, .False));
54085288 } else {
54095289 _ = self.builder.buildRetVoid();
......@@ -5411,7 +5291,7 @@ pub const FuncGen = struct {
54115291 return null;
54125292 }
54135293
5414 const abi_ret_ty = try lowerFnRetTy(o, fn_info);
5294 const abi_ret_ty = (try lowerFnRetTy(o, fn_info)).toLlvm(&o.builder);
54155295 const operand = try self.resolveInst(un_op);
54165296 const alignment = ret_ty.abiAlignment(mod);
54175297
......@@ -5451,7 +5331,7 @@ pub const FuncGen = struct {
54515331 // Functions with an empty error set are emitted with an error code
54525332 // return type and return zero so they can be function pointers coerced
54535333 // to functions that return anyerror.
5454 const err_int = try o.lowerLlvmType(Type.anyerror);
5334 const err_int = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder);
54555335 _ = self.builder.buildRet(err_int.constInt(0, .False));
54565336 } else {
54575337 _ = self.builder.buildRetVoid();
......@@ -5463,7 +5343,7 @@ pub const FuncGen = struct {
54635343 return null;
54645344 }
54655345 const ptr = try self.resolveInst(un_op);
5466 const abi_ret_ty = try lowerFnRetTy(o, fn_info);
5346 const abi_ret_ty = (try lowerFnRetTy(o, fn_info)).toLlvm(&o.builder);
54675347 const loaded = self.builder.buildLoad(abi_ret_ty, ptr, "");
54685348 loaded.setAlignment(ret_ty.abiAlignment(mod));
54695349 _ = self.builder.buildRet(loaded);
......@@ -5475,7 +5355,7 @@ pub const FuncGen = struct {
54755355 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
54765356 const list = try self.resolveInst(ty_op.operand);
54775357 const arg_ty = self.air.getRefType(ty_op.ty);
5478 const llvm_arg_ty = try o.lowerLlvmType(arg_ty);
5358 const llvm_arg_ty = (try o.lowerType(arg_ty)).toLlvm(&o.builder);
54795359
54805360 return self.builder.buildVAArg(list, llvm_arg_ty, "");
54815361 }
......@@ -5485,7 +5365,7 @@ pub const FuncGen = struct {
54855365 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
54865366 const src_list = try self.resolveInst(ty_op.operand);
54875367 const va_list_ty = self.air.getRefType(ty_op.ty);
5488 const llvm_va_list_ty = try o.lowerLlvmType(va_list_ty);
5368 const llvm_va_list_ty = (try o.lowerType(va_list_ty)).toLlvm(&o.builder);
54895369 const mod = o.module;
54905370
54915371 const result_alignment = va_list_ty.abiAlignment(mod);
......@@ -5533,7 +5413,7 @@ pub const FuncGen = struct {
55335413 const o = self.dg.object;
55345414 const mod = o.module;
55355415 const va_list_ty = self.typeOfIndex(inst);
5536 const llvm_va_list_ty = try o.lowerLlvmType(va_list_ty);
5416 const llvm_va_list_ty = (try o.lowerType(va_list_ty)).toLlvm(&o.builder);
55375417
55385418 const result_alignment = va_list_ty.abiAlignment(mod);
55395419 const list = self.buildAlloca(llvm_va_list_ty, result_alignment);
......@@ -5612,7 +5492,7 @@ pub const FuncGen = struct {
56125492 // We need to emit instructions to check for equality/inequality
56135493 // of optionals that are not pointers.
56145494 const is_by_ref = isByRef(scalar_ty, mod);
5615 const opt_llvm_ty = try o.lowerLlvmType(scalar_ty);
5495 const opt_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
56165496 const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref);
56175497 const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref);
56185498 const llvm_i2 = self.context.intType(2);
......@@ -5722,7 +5602,7 @@ pub const FuncGen = struct {
57225602 const is_body = inst_ty.zigTypeTag(mod) == .Fn;
57235603 if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
57245604
5725 const raw_llvm_ty = try o.lowerLlvmType(inst_ty);
5605 const raw_llvm_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder);
57265606
57275607 const llvm_ty = ty: {
57285608 // If the zig tag type is a function, this represents an actual function body; not
......@@ -5827,11 +5707,11 @@ pub const FuncGen = struct {
58275707 const mod = o.module;
58285708 const payload_ty = err_union_ty.errorUnionPayload(mod);
58295709 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5830 const err_union_llvm_ty = try o.lowerLlvmType(err_union_ty);
5710 const err_union_llvm_ty = (try o.lowerType(err_union_ty)).toLlvm(&o.builder);
58315711
58325712 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
58335713 const is_err = err: {
5834 const err_set_ty = try o.lowerLlvmType(Type.anyerror);
5714 const err_set_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder);
58355715 const zero = err_set_ty.constNull();
58365716 if (!payload_has_bits) {
58375717 // TODO add alignment to this load
......@@ -5966,9 +5846,9 @@ pub const FuncGen = struct {
59665846 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
59675847 const operand_ty = self.typeOf(ty_op.operand);
59685848 const array_ty = operand_ty.childType(mod);
5969 const llvm_usize = try o.lowerLlvmType(Type.usize);
5849 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
59705850 const len = llvm_usize.constInt(array_ty.arrayLen(mod), .False);
5971 const slice_llvm_ty = try o.lowerLlvmType(self.typeOfIndex(inst));
5851 const slice_llvm_ty = (try o.lowerType(self.typeOfIndex(inst))).toLlvm(&o.builder);
59725852 const operand = try self.resolveInst(ty_op.operand);
59735853 if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
59745854 const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, "");
......@@ -5977,7 +5857,7 @@ pub const FuncGen = struct {
59775857 const indices: [2]*llvm.Value = .{
59785858 llvm_usize.constNull(), llvm_usize.constNull(),
59795859 };
5980 const array_llvm_ty = try o.lowerLlvmType(array_ty);
5860 const array_llvm_ty = (try o.lowerType(array_ty)).toLlvm(&o.builder);
59815861 const ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indices, indices.len, "");
59825862 const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, "");
59835863 return self.builder.buildInsertValue(partial, len, 1, "");
......@@ -5994,7 +5874,7 @@ pub const FuncGen = struct {
59945874
59955875 const dest_ty = self.typeOfIndex(inst);
59965876 const dest_scalar_ty = dest_ty.scalarType(mod);
5997 const dest_llvm_ty = try o.lowerLlvmType(dest_ty);
5877 const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
59985878 const target = mod.getTarget();
59995879
60005880 if (intrinsicsAllowed(dest_scalar_ty, target)) {
......@@ -6055,7 +5935,7 @@ pub const FuncGen = struct {
60555935
60565936 const dest_ty = self.typeOfIndex(inst);
60575937 const dest_scalar_ty = dest_ty.scalarType(mod);
6058 const dest_llvm_ty = try o.lowerLlvmType(dest_ty);
5938 const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
60595939
60605940 if (intrinsicsAllowed(operand_scalar_ty, target)) {
60615941 // TODO set fast math flag
......@@ -6087,7 +5967,7 @@ pub const FuncGen = struct {
60875967 compiler_rt_dest_abbrev,
60885968 }) catch unreachable;
60895969
6090 const operand_llvm_ty = try o.lowerLlvmType(operand_ty);
5970 const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
60915971 const param_types = [1]*llvm.Type{operand_llvm_ty};
60925972 const libc_fn = try self.getLibcFunction(fn_name, &param_types, libc_ret_ty);
60935973 const params = [1]*llvm.Value{operand};
......@@ -6145,7 +6025,7 @@ pub const FuncGen = struct {
61456025 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
61466026 const slice_ptr = try self.resolveInst(ty_op.operand);
61476027 const slice_ptr_ty = self.typeOf(ty_op.operand);
6148 const slice_llvm_ty = try o.lowerPtrElemTy(slice_ptr_ty.childType(mod));
6028 const slice_llvm_ty = (try o.lowerPtrElemTy(slice_ptr_ty.childType(mod))).toLlvm(&o.builder);
61496029
61506030 return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, "");
61516031 }
......@@ -6159,7 +6039,7 @@ pub const FuncGen = struct {
61596039 const slice = try self.resolveInst(bin_op.lhs);
61606040 const index = try self.resolveInst(bin_op.rhs);
61616041 const elem_ty = slice_ty.childType(mod);
6162 const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty);
6042 const llvm_elem_ty = (try o.lowerPtrElemTy(elem_ty)).toLlvm(&o.builder);
61636043 const base_ptr = self.builder.buildExtractValue(slice, 0, "");
61646044 const indices: [1]*llvm.Value = .{index};
61656045 const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
......@@ -6182,7 +6062,7 @@ pub const FuncGen = struct {
61826062
61836063 const slice = try self.resolveInst(bin_op.lhs);
61846064 const index = try self.resolveInst(bin_op.rhs);
6185 const llvm_elem_ty = try o.lowerPtrElemTy(slice_ty.childType(mod));
6065 const llvm_elem_ty = (try o.lowerPtrElemTy(slice_ty.childType(mod))).toLlvm(&o.builder);
61866066 const base_ptr = self.builder.buildExtractValue(slice, 0, "");
61876067 const indices: [1]*llvm.Value = .{index};
61886068 return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
......@@ -6197,7 +6077,7 @@ pub const FuncGen = struct {
61976077 const array_ty = self.typeOf(bin_op.lhs);
61986078 const array_llvm_val = try self.resolveInst(bin_op.lhs);
61996079 const rhs = try self.resolveInst(bin_op.rhs);
6200 const array_llvm_ty = try o.lowerLlvmType(array_ty);
6080 const array_llvm_ty = (try o.lowerType(array_ty)).toLlvm(&o.builder);
62016081 const elem_ty = array_ty.childType(mod);
62026082 if (isByRef(array_ty, mod)) {
62036083 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
......@@ -6208,7 +6088,7 @@ pub const FuncGen = struct {
62086088
62096089 return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false);
62106090 } else {
6211 const elem_llvm_ty = try o.lowerLlvmType(elem_ty);
6091 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
62126092 if (Air.refToIndex(bin_op.lhs)) |lhs_index| {
62136093 if (self.air.instructions.items(.tag)[lhs_index] == .load) {
62146094 const load_data = self.air.instructions.items(.data)[lhs_index];
......@@ -6242,7 +6122,7 @@ pub const FuncGen = struct {
62426122 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
62436123 const ptr_ty = self.typeOf(bin_op.lhs);
62446124 const elem_ty = ptr_ty.childType(mod);
6245 const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty);
6125 const llvm_elem_ty = (try o.lowerPtrElemTy(elem_ty)).toLlvm(&o.builder);
62466126 const base_ptr = try self.resolveInst(bin_op.lhs);
62476127 const rhs = try self.resolveInst(bin_op.rhs);
62486128 // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch
......@@ -6279,7 +6159,7 @@ pub const FuncGen = struct {
62796159 const elem_ptr = self.air.getRefType(ty_pl.ty);
62806160 if (elem_ptr.ptrInfo(mod).flags.vector_index != .none) return base_ptr;
62816161
6282 const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty);
6162 const llvm_elem_ty = (try o.lowerPtrElemTy(elem_ty)).toLlvm(&o.builder);
62836163 if (ptr_ty.isSinglePointer(mod)) {
62846164 // If this is a single-item pointer to an array, we need another index in the GEP.
62856165 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
......@@ -6333,7 +6213,7 @@ pub const FuncGen = struct {
63336213 const containing_int = struct_llvm_val;
63346214 const shift_amt = containing_int.typeOf().constInt(bit_offset, .False);
63356215 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");
6336 const elem_llvm_ty = try o.lowerLlvmType(field_ty);
6216 const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder);
63376217 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
63386218 const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod)));
63396219 const same_size_int = self.context.intType(elem_bits);
......@@ -6355,7 +6235,7 @@ pub const FuncGen = struct {
63556235 .Union => {
63566236 assert(struct_ty.containerLayout(mod) == .Packed);
63576237 const containing_int = struct_llvm_val;
6358 const elem_llvm_ty = try o.lowerLlvmType(field_ty);
6238 const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder);
63596239 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
63606240 const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod)));
63616241 const same_size_int = self.context.intType(elem_bits);
......@@ -6377,7 +6257,7 @@ pub const FuncGen = struct {
63776257 .Struct => {
63786258 assert(struct_ty.containerLayout(mod) != .Packed);
63796259 const llvm_field = llvmField(struct_ty, field_index, mod).?;
6380 const struct_llvm_ty = try o.lowerLlvmType(struct_ty);
6260 const struct_llvm_ty = (try o.lowerType(struct_ty)).toLlvm(&o.builder);
63816261 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field.index, "");
63826262 const field_ptr_ty = try mod.ptrType(.{
63836263 .child = llvm_field.ty.toIntern(),
......@@ -6396,11 +6276,11 @@ pub const FuncGen = struct {
63966276 }
63976277 },
63986278 .Union => {
6399 const union_llvm_ty = try o.lowerLlvmType(struct_ty);
6279 const union_llvm_ty = (try o.lowerType(struct_ty)).toLlvm(&o.builder);
64006280 const layout = struct_ty.unionGetLayout(mod);
64016281 const payload_index = @intFromBool(layout.tag_align >= layout.payload_align);
64026282 const field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, "");
6403 const llvm_field_ty = try o.lowerLlvmType(field_ty);
6283 const llvm_field_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder);
64046284 if (isByRef(field_ty, mod)) {
64056285 if (canElideLoad(self, body_tail))
64066286 return field_ptr;
......@@ -6426,7 +6306,7 @@ pub const FuncGen = struct {
64266306 const parent_ty = self.air.getRefType(ty_pl.ty).childType(mod);
64276307 const field_offset = parent_ty.structFieldOffset(extra.field_index, mod);
64286308
6429 const res_ty = try o.lowerLlvmType(self.air.getRefType(ty_pl.ty));
6309 const res_ty = (try o.lowerType(self.air.getRefType(ty_pl.ty))).toLlvm(&o.builder);
64306310 if (field_offset == 0) {
64316311 return field_ptr;
64326312 }
......@@ -6691,7 +6571,7 @@ pub const FuncGen = struct {
66916571 const output_inst = try self.resolveInst(output);
66926572 const output_ty = self.typeOf(output);
66936573 assert(output_ty.zigTypeTag(mod) == .Pointer);
6694 const elem_llvm_ty = try o.lowerPtrElemTy(output_ty.childType(mod));
6574 const elem_llvm_ty = (try o.lowerPtrElemTy(output_ty.childType(mod))).toLlvm(&o.builder);
66956575
66966576 if (llvm_ret_indirect[i]) {
66976577 // Pass the result by reference as an indirect output (e.g. "=*m")
......@@ -6708,7 +6588,7 @@ pub const FuncGen = struct {
67086588 }
67096589 } else {
67106590 const ret_ty = self.typeOfIndex(inst);
6711 llvm_ret_types[llvm_ret_i] = try o.lowerLlvmType(ret_ty);
6591 llvm_ret_types[llvm_ret_i] = (try o.lowerType(ret_ty)).toLlvm(&o.builder);
67126592 llvm_ret_i += 1;
67136593 }
67146594
......@@ -6745,13 +6625,13 @@ pub const FuncGen = struct {
67456625 const arg_ty = self.typeOf(input);
67466626 var llvm_elem_ty: ?*llvm.Type = null;
67476627 if (isByRef(arg_ty, mod)) {
6748 llvm_elem_ty = try o.lowerPtrElemTy(arg_ty);
6628 llvm_elem_ty = (try o.lowerPtrElemTy(arg_ty)).toLlvm(&o.builder);
67496629 if (constraintAllowsMemory(constraint)) {
67506630 llvm_param_values[llvm_param_i] = arg_llvm_value;
67516631 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();
67526632 } else {
67536633 const alignment = arg_ty.abiAlignment(mod);
6754 const arg_llvm_ty = try o.lowerLlvmType(arg_ty);
6634 const arg_llvm_ty = (try o.lowerType(arg_ty)).toLlvm(&o.builder);
67556635 const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, "");
67566636 load_inst.setAlignment(alignment);
67576637 llvm_param_values[llvm_param_i] = load_inst;
......@@ -6792,7 +6672,7 @@ pub const FuncGen = struct {
67926672 // an elementtype(<ty>) attribute.
67936673 if (constraint[0] == '*') {
67946674 llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse
6795 try o.lowerPtrElemTy(arg_ty.childType(mod));
6675 (try o.lowerPtrElemTy(arg_ty.childType(mod))).toLlvm(&o.builder);
67966676 } else {
67976677 llvm_param_attrs[llvm_param_i] = null;
67986678 }
......@@ -6989,7 +6869,7 @@ pub const FuncGen = struct {
69896869 const operand = try self.resolveInst(un_op);
69906870 const operand_ty = self.typeOf(un_op);
69916871 const optional_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6992 const optional_llvm_ty = try o.lowerLlvmType(optional_ty);
6872 const optional_llvm_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder);
69936873 const payload_ty = optional_ty.optionalChild(mod);
69946874 if (optional_ty.optionalReprIsPayload(mod)) {
69956875 const loaded = if (operand_is_ptr)
......@@ -6998,7 +6878,7 @@ pub const FuncGen = struct {
69986878 operand;
69996879 if (payload_ty.isSlice(mod)) {
70006880 const slice_ptr = self.builder.buildExtractValue(loaded, 0, "");
7001 const ptr_ty = try o.lowerLlvmType(payload_ty.slicePtrFieldType(mod));
6881 const ptr_ty = (try o.lowerType(payload_ty.slicePtrFieldType(mod))).toLlvm(&o.builder);
70026882 return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), "");
70036883 }
70046884 return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), "");
......@@ -7037,7 +6917,7 @@ pub const FuncGen = struct {
70376917 const operand_ty = self.typeOf(un_op);
70386918 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
70396919 const payload_ty = err_union_ty.errorUnionPayload(mod);
7040 const err_set_ty = try o.lowerLlvmType(Type.anyerror);
6920 const err_set_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder);
70416921 const zero = err_set_ty.constNull();
70426922
70436923 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
......@@ -7051,7 +6931,7 @@ pub const FuncGen = struct {
70516931
70526932 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
70536933 const loaded = if (operand_is_ptr)
7054 self.builder.buildLoad(try o.lowerLlvmType(err_union_ty), operand, "")
6934 self.builder.buildLoad((try o.lowerType(err_union_ty)).toLlvm(&o.builder), operand, "")
70556935 else
70566936 operand;
70576937 return self.builder.buildICmp(op, loaded, zero, "");
......@@ -7060,7 +6940,7 @@ pub const FuncGen = struct {
70606940 const err_field_index = errUnionErrorOffset(payload_ty, mod);
70616941
70626942 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
7063 const err_union_llvm_ty = try o.lowerLlvmType(err_union_ty);
6943 const err_union_llvm_ty = (try o.lowerType(err_union_ty)).toLlvm(&o.builder);
70646944 const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, "");
70656945 const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, "");
70666946 return self.builder.buildICmp(op, loaded, zero, "");
......@@ -7086,7 +6966,7 @@ pub const FuncGen = struct {
70866966 // The payload and the optional are the same value.
70876967 return operand;
70886968 }
7089 const optional_llvm_ty = try o.lowerLlvmType(optional_ty);
6969 const optional_llvm_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder);
70906970 return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, "");
70916971 }
70926972
......@@ -7112,7 +6992,7 @@ pub const FuncGen = struct {
71126992 }
71136993
71146994 // First set the non-null bit.
7115 const optional_llvm_ty = try o.lowerLlvmType(optional_ty);
6995 const optional_llvm_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder);
71166996 const non_null_ptr = self.builder.buildStructGEP(optional_llvm_ty, operand, 1, "");
71176997 // TODO set alignment on this store
71186998 _ = self.builder.buildStore(non_null_bit, non_null_ptr);
......@@ -7139,7 +7019,7 @@ pub const FuncGen = struct {
71397019 return operand;
71407020 }
71417021
7142 const opt_llvm_ty = try o.lowerLlvmType(optional_ty);
7022 const opt_llvm_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder);
71437023 const can_elide_load = if (isByRef(payload_ty, mod)) self.canElideLoad(body_tail) else false;
71447024 return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty, can_elide_load);
71457025 }
......@@ -7163,7 +7043,7 @@ pub const FuncGen = struct {
71637043 return if (operand_is_ptr) operand else null;
71647044 }
71657045 const offset = errUnionPayloadOffset(payload_ty, mod);
7166 const err_union_llvm_ty = try o.lowerLlvmType(err_union_ty);
7046 const err_union_llvm_ty = (try o.lowerType(err_union_ty)).toLlvm(&o.builder);
71677047 if (operand_is_ptr) {
71687048 return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");
71697049 } else if (isByRef(err_union_ty, mod)) {
......@@ -7193,7 +7073,7 @@ pub const FuncGen = struct {
71937073 const operand_ty = self.typeOf(ty_op.operand);
71947074 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
71957075 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
7196 const err_llvm_ty = try o.lowerLlvmType(Type.anyerror);
7076 const err_llvm_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder);
71977077 if (operand_is_ptr) {
71987078 return operand;
71997079 } else {
......@@ -7201,7 +7081,7 @@ pub const FuncGen = struct {
72017081 }
72027082 }
72037083
7204 const err_set_llvm_ty = try o.lowerLlvmType(Type.anyerror);
7084 const err_set_llvm_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder);
72057085
72067086 const payload_ty = err_union_ty.errorUnionPayload(mod);
72077087 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
......@@ -7212,7 +7092,7 @@ pub const FuncGen = struct {
72127092 const offset = errUnionErrorOffset(payload_ty, mod);
72137093
72147094 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
7215 const err_union_llvm_ty = try o.lowerLlvmType(err_union_ty);
7095 const err_union_llvm_ty = (try o.lowerType(err_union_ty)).toLlvm(&o.builder);
72167096 const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");
72177097 return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, "");
72187098 }
......@@ -7233,7 +7113,7 @@ pub const FuncGen = struct {
72337113 _ = self.builder.buildStore(non_error_val, operand);
72347114 return operand;
72357115 }
7236 const err_union_llvm_ty = try o.lowerLlvmType(err_union_ty);
7116 const err_union_llvm_ty = (try o.lowerType(err_union_ty)).toLlvm(&o.builder);
72377117 {
72387118 const error_offset = errUnionErrorOffset(payload_ty, mod);
72397119 // First set the non-error value.
......@@ -7269,7 +7149,7 @@ pub const FuncGen = struct {
72697149
72707150 const mod = o.module;
72717151 const llvm_field = llvmField(struct_ty, field_index, mod).?;
7272 const struct_llvm_ty = try o.lowerLlvmType(struct_ty);
7152 const struct_llvm_ty = (try o.lowerType(struct_ty)).toLlvm(&o.builder);
72737153 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field.index, "");
72747154 const field_ptr_ty = try mod.ptrType(.{
72757155 .child = llvm_field.ty.toIntern(),
......@@ -7293,7 +7173,7 @@ pub const FuncGen = struct {
72937173 if (optional_ty.optionalReprIsPayload(mod)) {
72947174 return operand;
72957175 }
7296 const llvm_optional_ty = try o.lowerLlvmType(optional_ty);
7176 const llvm_optional_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder);
72977177 if (isByRef(optional_ty, mod)) {
72987178 const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(mod));
72997179 const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, "");
......@@ -7317,8 +7197,8 @@ pub const FuncGen = struct {
73177197 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
73187198 return operand;
73197199 }
7320 const ok_err_code = (try o.lowerLlvmType(Type.anyerror)).constNull();
7321 const err_un_llvm_ty = try o.lowerLlvmType(err_un_ty);
7200 const ok_err_code = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder).constNull();
7201 const err_un_llvm_ty = (try o.lowerType(err_un_ty)).toLlvm(&o.builder);
73227202
73237203 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
73247204 const error_offset = errUnionErrorOffset(payload_ty, mod);
......@@ -7347,7 +7227,7 @@ pub const FuncGen = struct {
73477227 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
73487228 return operand;
73497229 }
7350 const err_un_llvm_ty = try o.lowerLlvmType(err_un_ty);
7230 const err_un_llvm_ty = (try o.lowerType(err_un_ty)).toLlvm(&o.builder);
73517231
73527232 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
73537233 const error_offset = errUnionErrorOffset(payload_ty, mod);
......@@ -7403,7 +7283,7 @@ pub const FuncGen = struct {
74037283 const operand = try self.resolveInst(extra.rhs);
74047284
74057285 const loaded_vector = blk: {
7406 const elem_llvm_ty = try o.lowerLlvmType(vector_ptr_ty.childType(mod));
7286 const elem_llvm_ty = (try o.lowerType(vector_ptr_ty.childType(mod))).toLlvm(&o.builder);
74077287 const load_inst = self.builder.buildLoad(elem_llvm_ty, vector_ptr, "");
74087288 load_inst.setAlignment(vector_ptr_ty.ptrAlignment(mod));
74097289 load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr(mod)));
......@@ -7447,7 +7327,7 @@ pub const FuncGen = struct {
74477327 const ptr = try self.resolveInst(bin_op.lhs);
74487328 const len = try self.resolveInst(bin_op.rhs);
74497329 const inst_ty = self.typeOfIndex(inst);
7450 const llvm_slice_ty = try o.lowerLlvmType(inst_ty);
7330 const llvm_slice_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder);
74517331
74527332 // In case of slicing a global, the result type looks something like `{ i8*, i64 }`
74537333 // but `ptr` is pointing to the global directly.
......@@ -7491,7 +7371,7 @@ pub const FuncGen = struct {
74917371 true => signed_intrinsic,
74927372 false => unsigned_intrinsic,
74937373 };
7494 const llvm_inst_ty = try o.lowerLlvmType(inst_ty);
7374 const llvm_inst_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder);
74957375 const llvm_fn = fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty});
74967376 const result_struct = fg.builder.buildCall(
74977377 llvm_fn.globalGetValueType(),
......@@ -7664,11 +7544,11 @@ pub const FuncGen = struct {
76647544 return self.buildFloatOp(.floor, inst_ty, 1, .{result});
76657545 }
76667546 if (scalar_ty.isSignedInt(mod)) {
7667 const inst_llvm_ty = try o.lowerLlvmType(inst_ty);
7547 const inst_llvm_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder);
76687548 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
76697549 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
76707550 const vec_len = inst_ty.vectorLen(mod);
7671 const scalar_llvm_ty = try o.lowerLlvmType(scalar_ty);
7551 const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
76727552
76737553 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
76747554 defer self.gpa.free(shifts);
......@@ -7730,7 +7610,7 @@ pub const FuncGen = struct {
77307610 const lhs = try self.resolveInst(bin_op.lhs);
77317611 const rhs = try self.resolveInst(bin_op.rhs);
77327612 const inst_ty = self.typeOfIndex(inst);
7733 const inst_llvm_ty = try o.lowerLlvmType(inst_ty);
7613 const inst_llvm_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder);
77347614 const scalar_ty = inst_ty.scalarType(mod);
77357615
77367616 if (scalar_ty.isRuntimeFloat()) {
......@@ -7745,7 +7625,7 @@ pub const FuncGen = struct {
77457625 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
77467626 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
77477627 const vec_len = inst_ty.vectorLen(mod);
7748 const scalar_llvm_ty = try o.lowerLlvmType(scalar_ty);
7628 const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
77497629
77507630 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
77517631 defer self.gpa.free(shifts);
......@@ -7774,7 +7654,7 @@ pub const FuncGen = struct {
77747654 const ptr = try self.resolveInst(bin_op.lhs);
77757655 const offset = try self.resolveInst(bin_op.rhs);
77767656 const ptr_ty = self.typeOf(bin_op.lhs);
7777 const llvm_elem_ty = try o.lowerPtrElemTy(ptr_ty.childType(mod));
7657 const llvm_elem_ty = (try o.lowerPtrElemTy(ptr_ty.childType(mod))).toLlvm(&o.builder);
77787658 switch (ptr_ty.ptrSize(mod)) {
77797659 .One => {
77807660 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
......@@ -7802,7 +7682,7 @@ pub const FuncGen = struct {
78027682 const offset = try self.resolveInst(bin_op.rhs);
78037683 const negative_offset = self.builder.buildNeg(offset, "");
78047684 const ptr_ty = self.typeOf(bin_op.lhs);
7805 const llvm_elem_ty = try o.lowerPtrElemTy(ptr_ty.childType(mod));
7685 const llvm_elem_ty = (try o.lowerPtrElemTy(ptr_ty.childType(mod))).toLlvm(&o.builder);
78067686 switch (ptr_ty.ptrSize(mod)) {
78077687 .One => {
78087688 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
......@@ -7843,8 +7723,8 @@ pub const FuncGen = struct {
78437723
78447724 const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
78457725
7846 const llvm_lhs_ty = try o.lowerLlvmType(lhs_ty);
7847 const llvm_dest_ty = try o.lowerLlvmType(dest_ty);
7726 const llvm_lhs_ty = (try o.lowerType(lhs_ty)).toLlvm(&o.builder);
7727 const llvm_dest_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
78487728
78497729 const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty});
78507730 const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, "");
......@@ -7920,7 +7800,7 @@ pub const FuncGen = struct {
79207800 const f = o.llvm_module.addFunction(name.toSlice(&o.builder).?, fn_type);
79217801
79227802 var global = Builder.Global{
7923 .type = .void,
7803 .type = try o.builder.fnType(.void, &.{}, .normal),
79247804 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
79257805 };
79267806 var function = Builder.Function{
......@@ -7947,7 +7827,7 @@ pub const FuncGen = struct {
79477827 const mod = o.module;
79487828 const target = o.module.getTarget();
79497829 const scalar_ty = ty.scalarType(mod);
7950 const scalar_llvm_ty = try o.lowerLlvmType(scalar_ty);
7830 const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
79517831
79527832 if (intrinsicsAllowed(scalar_ty, target)) {
79537833 const llvm_predicate: llvm.RealPredicate = switch (pred) {
......@@ -8050,8 +7930,8 @@ pub const FuncGen = struct {
80507930 const mod = o.module;
80517931 const target = mod.getTarget();
80527932 const scalar_ty = ty.scalarType(mod);
8053 const llvm_ty = try o.lowerLlvmType(ty);
8054 const scalar_llvm_ty = try o.lowerLlvmType(scalar_ty);
7933 const llvm_ty = (try o.lowerType(ty)).toLlvm(&o.builder);
7934 const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
80557935
80567936 const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target);
80577937 var fn_name_buf: [64]u8 = undefined;
......@@ -8161,10 +8041,10 @@ pub const FuncGen = struct {
81618041 const rhs_scalar_ty = rhs_ty.scalarType(mod);
81628042
81638043 const dest_ty = self.typeOfIndex(inst);
8164 const llvm_dest_ty = try o.lowerLlvmType(dest_ty);
8044 const llvm_dest_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
81658045
81668046 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
8167 self.builder.buildZExt(rhs, try o.lowerLlvmType(lhs_ty), "")
8047 self.builder.buildZExt(rhs, (try o.lowerType(lhs_ty)).toLlvm(&o.builder), "")
81688048 else
81698049 rhs;
81708050
......@@ -8235,7 +8115,7 @@ pub const FuncGen = struct {
82358115 const rhs_scalar_ty = rhs_ty.scalarType(mod);
82368116
82378117 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
8238 self.builder.buildZExt(rhs, try o.lowerLlvmType(lhs_ty), "")
8118 self.builder.buildZExt(rhs, (try o.lowerType(lhs_ty)).toLlvm(&o.builder), "")
82398119 else
82408120 rhs;
82418121 if (lhs_scalar_ty.isSignedInt(mod)) return self.builder.buildNSWShl(lhs, casted_rhs, "");
......@@ -8256,7 +8136,7 @@ pub const FuncGen = struct {
82568136 const rhs_scalar_ty = rhs_type.scalarType(mod);
82578137
82588138 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
8259 self.builder.buildZExt(rhs, try o.lowerLlvmType(lhs_type), "")
8139 self.builder.buildZExt(rhs, (try o.lowerType(lhs_type)).toLlvm(&o.builder), "")
82608140 else
82618141 rhs;
82628142 return self.builder.buildShl(lhs, casted_rhs, "");
......@@ -8291,7 +8171,7 @@ pub const FuncGen = struct {
82918171 // poison value."
82928172 // However Zig semantics says that saturating shift left can never produce
82938173 // undefined; instead it saturates.
8294 const lhs_scalar_llvm_ty = try o.lowerLlvmType(lhs_scalar_ty);
8174 const lhs_scalar_llvm_ty = (try o.lowerType(lhs_scalar_ty)).toLlvm(&o.builder);
82958175 const bits = lhs_scalar_llvm_ty.constInt(lhs_bits, .False);
82968176 const lhs_max = lhs_scalar_llvm_ty.constAllOnes();
82978177 if (rhs_ty.zigTypeTag(mod) == .Vector) {
......@@ -8320,7 +8200,7 @@ pub const FuncGen = struct {
83208200 const rhs_scalar_ty = rhs_ty.scalarType(mod);
83218201
83228202 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
8323 self.builder.buildZExt(rhs, try o.lowerLlvmType(lhs_ty), "")
8203 self.builder.buildZExt(rhs, (try o.lowerType(lhs_ty)).toLlvm(&o.builder), "")
83248204 else
83258205 rhs;
83268206 const is_signed_int = lhs_scalar_ty.isSignedInt(mod);
......@@ -8346,7 +8226,7 @@ pub const FuncGen = struct {
83468226 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
83478227 const dest_ty = self.typeOfIndex(inst);
83488228 const dest_info = dest_ty.intInfo(mod);
8349 const dest_llvm_ty = try o.lowerLlvmType(dest_ty);
8229 const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
83508230 const operand = try self.resolveInst(ty_op.operand);
83518231 const operand_ty = self.typeOf(ty_op.operand);
83528232 const operand_info = operand_ty.intInfo(mod);
......@@ -8367,7 +8247,7 @@ pub const FuncGen = struct {
83678247 const o = self.dg.object;
83688248 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
83698249 const operand = try self.resolveInst(ty_op.operand);
8370 const dest_llvm_ty = try o.lowerLlvmType(self.typeOfIndex(inst));
8250 const dest_llvm_ty = (try o.lowerType(self.typeOfIndex(inst))).toLlvm(&o.builder);
83718251 return self.builder.buildTrunc(operand, dest_llvm_ty, "");
83728252 }
83738253
......@@ -8383,11 +8263,11 @@ pub const FuncGen = struct {
83838263 const src_bits = operand_ty.floatBits(target);
83848264
83858265 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
8386 const dest_llvm_ty = try o.lowerLlvmType(dest_ty);
8266 const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
83878267 return self.builder.buildFPTrunc(operand, dest_llvm_ty, "");
83888268 } else {
8389 const operand_llvm_ty = try o.lowerLlvmType(operand_ty);
8390 const dest_llvm_ty = try o.lowerLlvmType(dest_ty);
8269 const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
8270 const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
83918271
83928272 var fn_name_buf: [64]u8 = undefined;
83938273 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__trunc{s}f{s}f2", .{
......@@ -8414,11 +8294,11 @@ pub const FuncGen = struct {
84148294 const src_bits = operand_ty.floatBits(target);
84158295
84168296 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
8417 const dest_llvm_ty = try o.lowerLlvmType(dest_ty);
8297 const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
84188298 return self.builder.buildFPExt(operand, dest_llvm_ty, "");
84198299 } else {
8420 const operand_llvm_ty = try o.lowerLlvmType(operand_ty);
8421 const dest_llvm_ty = try o.lowerLlvmType(dest_ty);
8300 const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
8301 const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder);
84228302
84238303 var fn_name_buf: [64]u8 = undefined;
84248304 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__extend{s}f{s}f2", .{
......@@ -8439,7 +8319,7 @@ pub const FuncGen = struct {
84398319 const operand = try self.resolveInst(un_op);
84408320 const ptr_ty = self.typeOf(un_op);
84418321 const operand_ptr = self.sliceOrArrayPtr(operand, ptr_ty);
8442 const dest_llvm_ty = try o.lowerLlvmType(self.typeOfIndex(inst));
8322 const dest_llvm_ty = (try o.lowerType(self.typeOfIndex(inst))).toLlvm(&o.builder);
84438323 return self.builder.buildPtrToInt(operand_ptr, dest_llvm_ty, "");
84448324 }
84458325
......@@ -8456,7 +8336,7 @@ pub const FuncGen = struct {
84568336 const mod = o.module;
84578337 const operand_is_ref = isByRef(operand_ty, mod);
84588338 const result_is_ref = isByRef(inst_ty, mod);
8459 const llvm_dest_ty = try o.lowerLlvmType(inst_ty);
8339 const llvm_dest_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder);
84608340
84618341 if (operand_is_ref and result_is_ref) {
84628342 // They are both pointers, so just return the same opaque pointer :)
......@@ -8486,7 +8366,7 @@ pub const FuncGen = struct {
84868366 } else {
84878367 // If the ABI size of the element type is not evenly divisible by size in bits;
84888368 // a simple bitcast will not work, and we fall back to extractelement.
8489 const llvm_usize = try o.lowerLlvmType(Type.usize);
8369 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
84908370 const llvm_u32 = self.context.intType(32);
84918371 const zero = llvm_usize.constNull();
84928372 const vector_len = operand_ty.arrayLen(mod);
......@@ -8503,7 +8383,7 @@ pub const FuncGen = struct {
85038383 return array_ptr;
85048384 } else if (operand_ty.zigTypeTag(mod) == .Array and inst_ty.zigTypeTag(mod) == .Vector) {
85058385 const elem_ty = operand_ty.childType(mod);
8506 const llvm_vector_ty = try o.lowerLlvmType(inst_ty);
8386 const llvm_vector_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder);
85078387 if (!operand_is_ref) {
85088388 return self.dg.todo("implement bitcast non-ref array to vector", .{});
85098389 }
......@@ -8518,9 +8398,9 @@ pub const FuncGen = struct {
85188398 } else {
85198399 // If the ABI size of the element type is not evenly divisible by size in bits;
85208400 // a simple bitcast will not work, and we fall back to extractelement.
8521 const array_llvm_ty = try o.lowerLlvmType(operand_ty);
8522 const elem_llvm_ty = try o.lowerLlvmType(elem_ty);
8523 const llvm_usize = try o.lowerLlvmType(Type.usize);
8401 const array_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
8402 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
8403 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
85248404 const llvm_u32 = self.context.intType(32);
85258405 const zero = llvm_usize.constNull();
85268406 const vector_len = operand_ty.arrayLen(mod);
......@@ -8629,7 +8509,7 @@ pub const FuncGen = struct {
86298509 if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime(mod))
86308510 return o.lowerPtrToVoid(ptr_ty);
86318511
8632 const pointee_llvm_ty = try o.lowerLlvmType(pointee_type);
8512 const pointee_llvm_ty = (try o.lowerType(pointee_type)).toLlvm(&o.builder);
86338513 const alignment = ptr_ty.ptrAlignment(mod);
86348514 return self.buildAlloca(pointee_llvm_ty, alignment);
86358515 }
......@@ -8641,7 +8521,7 @@ pub const FuncGen = struct {
86418521 const ret_ty = ptr_ty.childType(mod);
86428522 if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return o.lowerPtrToVoid(ptr_ty);
86438523 if (self.ret_ptr) |ret_ptr| return ret_ptr;
8644 const ret_llvm_ty = try o.lowerLlvmType(ret_ty);
8524 const ret_llvm_ty = (try o.lowerType(ret_ty)).toLlvm(&o.builder);
86458525 return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(mod));
86468526 }
86478527
......@@ -8673,7 +8553,7 @@ pub const FuncGen = struct {
86738553 else
86748554 u8_llvm_ty.getUndef();
86758555 const operand_size = operand_ty.abiSize(mod);
8676 const usize_llvm_ty = try o.lowerLlvmType(Type.usize);
8556 const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
86778557 const len = usize_llvm_ty.constInt(operand_size, .False);
86788558 const dest_ptr_align = ptr_ty.ptrAlignment(mod);
86798559 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod));
......@@ -8746,7 +8626,7 @@ pub const FuncGen = struct {
87468626 _ = inst;
87478627 const o = self.dg.object;
87488628 const mod = o.module;
8749 const llvm_usize = try o.lowerLlvmType(Type.usize);
8629 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
87508630 const target = mod.getTarget();
87518631 if (!target_util.supportsReturnAddress(target)) {
87528632 // https://github.com/ziglang/zig/issues/11946
......@@ -8774,7 +8654,7 @@ pub const FuncGen = struct {
87748654
87758655 const params = [_]*llvm.Value{llvm_i32.constNull()};
87768656 const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .Fast, .Auto, "");
8777 const llvm_usize = try o.lowerLlvmType(Type.usize);
8657 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
87788658 return self.builder.buildPtrToInt(ptr_val, llvm_usize, "");
87798659 }
87808660
......@@ -8795,15 +8675,16 @@ pub const FuncGen = struct {
87958675 var expected_value = try self.resolveInst(extra.expected_value);
87968676 var new_value = try self.resolveInst(extra.new_value);
87978677 const operand_ty = self.typeOf(extra.ptr).childType(mod);
8798 const opt_abi_ty = o.getAtomicAbiType(operand_ty, false);
8799 if (opt_abi_ty) |abi_ty| {
8678 const abi_ty = try o.getAtomicAbiType(operand_ty, false);
8679 if (abi_ty != .none) {
8680 const llvm_abi_ty = abi_ty.toLlvm(&o.builder);
88008681 // operand needs widening and truncating
88018682 if (operand_ty.isSignedInt(mod)) {
8802 expected_value = self.builder.buildSExt(expected_value, abi_ty, "");
8803 new_value = self.builder.buildSExt(new_value, abi_ty, "");
8683 expected_value = self.builder.buildSExt(expected_value, llvm_abi_ty, "");
8684 new_value = self.builder.buildSExt(new_value, llvm_abi_ty, "");
88048685 } else {
8805 expected_value = self.builder.buildZExt(expected_value, abi_ty, "");
8806 new_value = self.builder.buildZExt(new_value, abi_ty, "");
8686 expected_value = self.builder.buildZExt(expected_value, llvm_abi_ty, "");
8687 new_value = self.builder.buildZExt(new_value, llvm_abi_ty, "");
88078688 }
88088689 }
88098690 const result = self.builder.buildAtomicCmpXchg(
......@@ -8819,8 +8700,8 @@ pub const FuncGen = struct {
88198700 const optional_ty = self.typeOfIndex(inst);
88208701
88218702 var payload = self.builder.buildExtractValue(result, 0, "");
8822 if (opt_abi_ty != null) {
8823 payload = self.builder.buildTrunc(payload, try o.lowerLlvmType(operand_ty), "");
8703 if (abi_ty != .none) {
8704 payload = self.builder.buildTrunc(payload, (try o.lowerType(operand_ty)).toLlvm(&o.builder), "");
88248705 }
88258706 const success_bit = self.builder.buildExtractValue(result, 1, "");
88268707
......@@ -8848,15 +8729,16 @@ pub const FuncGen = struct {
88488729 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
88498730 const ordering = toLlvmAtomicOrdering(extra.ordering());
88508731 const single_threaded = llvm.Bool.fromBool(self.single_threaded);
8851 const opt_abi_ty = o.getAtomicAbiType(operand_ty, op == .Xchg);
8852 if (opt_abi_ty) |abi_ty| {
8732 const abi_ty = try o.getAtomicAbiType(operand_ty, op == .Xchg);
8733 if (abi_ty != .none) {
8734 const llvm_abi_ty = abi_ty.toLlvm(&o.builder);
88538735 // operand needs widening and truncating or bitcasting.
88548736 const casted_operand = if (is_float)
8855 self.builder.buildBitCast(operand, abi_ty, "")
8737 self.builder.buildBitCast(operand, llvm_abi_ty, "")
88568738 else if (is_signed_int)
8857 self.builder.buildSExt(operand, abi_ty, "")
8739 self.builder.buildSExt(operand, llvm_abi_ty, "")
88588740 else
8859 self.builder.buildZExt(operand, abi_ty, "");
8741 self.builder.buildZExt(operand, llvm_abi_ty, "");
88608742
88618743 const uncasted_result = self.builder.buildAtomicRmw(
88628744 op,
......@@ -8865,7 +8747,7 @@ pub const FuncGen = struct {
88658747 ordering,
88668748 single_threaded,
88678749 );
8868 const operand_llvm_ty = try o.lowerLlvmType(operand_ty);
8750 const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
88698751 if (is_float) {
88708752 return self.builder.buildBitCast(uncasted_result, operand_llvm_ty, "");
88718753 } else {
......@@ -8878,7 +8760,7 @@ pub const FuncGen = struct {
88788760 }
88798761
88808762 // It's a pointer but we need to treat it as an int.
8881 const usize_llvm_ty = try o.lowerLlvmType(Type.usize);
8763 const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
88828764 const casted_operand = self.builder.buildPtrToInt(operand, usize_llvm_ty, "");
88838765 const uncasted_result = self.builder.buildAtomicRmw(
88848766 op,
......@@ -8887,7 +8769,7 @@ pub const FuncGen = struct {
88878769 ordering,
88888770 single_threaded,
88898771 );
8890 const operand_llvm_ty = try o.lowerLlvmType(operand_ty);
8772 const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
88918773 return self.builder.buildIntToPtr(uncasted_result, operand_llvm_ty, "");
88928774 }
88938775
......@@ -8902,15 +8784,16 @@ pub const FuncGen = struct {
89028784 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod))
89038785 return null;
89048786 const ordering = toLlvmAtomicOrdering(atomic_load.order);
8905 const opt_abi_llvm_ty = o.getAtomicAbiType(elem_ty, false);
8787 const abi_ty = try o.getAtomicAbiType(elem_ty, false);
89068788 const ptr_alignment = @as(u32, @intCast(ptr_info.flags.alignment.toByteUnitsOptional() orelse
89078789 ptr_info.child.toType().abiAlignment(mod)));
89088790 const ptr_volatile = llvm.Bool.fromBool(ptr_info.flags.is_volatile);
8909 const elem_llvm_ty = try o.lowerLlvmType(elem_ty);
8791 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
89108792
8911 if (opt_abi_llvm_ty) |abi_llvm_ty| {
8793 if (abi_ty != .none) {
8794 const llvm_abi_ty = abi_ty.toLlvm(&o.builder);
89128795 // operand needs widening and truncating
8913 const load_inst = self.builder.buildLoad(abi_llvm_ty, ptr, "");
8796 const load_inst = self.builder.buildLoad(llvm_abi_ty, ptr, "");
89148797 load_inst.setAlignment(ptr_alignment);
89158798 load_inst.setVolatile(ptr_volatile);
89168799 load_inst.setOrdering(ordering);
......@@ -8936,14 +8819,15 @@ pub const FuncGen = struct {
89368819 if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return null;
89378820 const ptr = try self.resolveInst(bin_op.lhs);
89388821 var element = try self.resolveInst(bin_op.rhs);
8939 const opt_abi_ty = o.getAtomicAbiType(operand_ty, false);
8822 const abi_ty = try o.getAtomicAbiType(operand_ty, false);
89408823
8941 if (opt_abi_ty) |abi_ty| {
8824 if (abi_ty != .none) {
8825 const llvm_abi_ty = abi_ty.toLlvm(&o.builder);
89428826 // operand needs widening
89438827 if (operand_ty.isSignedInt(mod)) {
8944 element = self.builder.buildSExt(element, abi_ty, "");
8828 element = self.builder.buildSExt(element, llvm_abi_ty, "");
89458829 } else {
8946 element = self.builder.buildZExt(element, abi_ty, "");
8830 element = self.builder.buildZExt(element, llvm_abi_ty, "");
89478831 }
89488832 }
89498833 try self.store(ptr, ptr_ty, element, ordering);
......@@ -9056,7 +8940,7 @@ pub const FuncGen = struct {
90568940 .One => llvm_usize_ty.constInt(ptr_ty.childType(mod).arrayLen(mod), .False),
90578941 .Many, .C => unreachable,
90588942 };
9059 const elem_llvm_ty = try o.lowerLlvmType(elem_ty);
8943 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
90608944 const len_gep = [_]*llvm.Value{len};
90618945 const end_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, dest_ptr, &len_gep, len_gep.len, "");
90628946 _ = self.builder.buildBr(loop_block);
......@@ -9181,7 +9065,7 @@ pub const FuncGen = struct {
91819065 _ = self.builder.buildStore(new_tag, union_ptr);
91829066 return null;
91839067 }
9184 const un_llvm_ty = try o.lowerLlvmType(un_ty);
9068 const un_llvm_ty = (try o.lowerType(un_ty)).toLlvm(&o.builder);
91859069 const tag_index = @intFromBool(layout.tag_align < layout.payload_align);
91869070 const tag_field_ptr = self.builder.buildStructGEP(un_llvm_ty, union_ptr, tag_index, "");
91879071 // TODO alignment on this store
......@@ -9198,7 +9082,7 @@ pub const FuncGen = struct {
91989082 if (layout.tag_size == 0) return null;
91999083 const union_handle = try self.resolveInst(ty_op.operand);
92009084 if (isByRef(un_ty, mod)) {
9201 const llvm_un_ty = try o.lowerLlvmType(un_ty);
9085 const llvm_un_ty = (try o.lowerType(un_ty)).toLlvm(&o.builder);
92029086 if (layout.payload_size == 0) {
92039087 return self.builder.buildLoad(llvm_un_ty, union_handle, "");
92049088 }
......@@ -9240,13 +9124,13 @@ pub const FuncGen = struct {
92409124 const operand = try self.resolveInst(ty_op.operand);
92419125
92429126 const llvm_i1 = self.context.intType(1);
9243 const operand_llvm_ty = try o.lowerLlvmType(operand_ty);
9127 const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
92449128 const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});
92459129
92469130 const params = [_]*llvm.Value{ operand, llvm_i1.constNull() };
92479131 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");
92489132 const result_ty = self.typeOfIndex(inst);
9249 const result_llvm_ty = try o.lowerLlvmType(result_ty);
9133 const result_llvm_ty = (try o.lowerType(result_ty)).toLlvm(&o.builder);
92509134
92519135 const bits = operand_ty.intInfo(mod).bits;
92529136 const result_bits = result_ty.intInfo(mod).bits;
......@@ -9267,12 +9151,12 @@ pub const FuncGen = struct {
92679151 const operand = try self.resolveInst(ty_op.operand);
92689152
92699153 const params = [_]*llvm.Value{operand};
9270 const operand_llvm_ty = try o.lowerLlvmType(operand_ty);
9154 const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
92719155 const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});
92729156
92739157 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");
92749158 const result_ty = self.typeOfIndex(inst);
9275 const result_llvm_ty = try o.lowerLlvmType(result_ty);
9159 const result_llvm_ty = (try o.lowerType(result_ty)).toLlvm(&o.builder);
92769160
92779161 const bits = operand_ty.intInfo(mod).bits;
92789162 const result_bits = result_ty.intInfo(mod).bits;
......@@ -9294,7 +9178,7 @@ pub const FuncGen = struct {
92949178 assert(bits % 8 == 0);
92959179
92969180 var operand = try self.resolveInst(ty_op.operand);
9297 var operand_llvm_ty = try o.lowerLlvmType(operand_ty);
9181 var operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
92989182
92999183 if (bits % 16 == 8) {
93009184 // If not an even byte-multiple, we need zero-extend + shift-left 1 byte
......@@ -9328,7 +9212,7 @@ pub const FuncGen = struct {
93289212 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");
93299213
93309214 const result_ty = self.typeOfIndex(inst);
9331 const result_llvm_ty = try o.lowerLlvmType(result_ty);
9215 const result_llvm_ty = (try o.lowerType(result_ty)).toLlvm(&o.builder);
93329216 const result_bits = result_ty.intInfo(mod).bits;
93339217 if (bits > result_bits) {
93349218 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
......@@ -9407,9 +9291,9 @@ pub const FuncGen = struct {
94079291 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
94089292 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)});
94099293
9410 const param_types = [_]*llvm.Type{try o.lowerLlvmType(enum_type.tag_ty.toType())};
9294 const param_types = [_]*llvm.Type{(try o.lowerType(enum_type.tag_ty.toType())).toLlvm(&o.builder)};
94119295
9412 const llvm_ret_ty = try o.lowerLlvmType(Type.bool);
9296 const llvm_ret_ty = (try o.lowerType(Type.bool)).toLlvm(&o.builder);
94139297 const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False);
94149298 const fn_val = o.llvm_module.addFunction(llvm_fn_name, fn_type);
94159299 fn_val.setLinkage(.Internal);
......@@ -9477,11 +9361,11 @@ pub const FuncGen = struct {
94779361 const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)});
94789362
94799363 const slice_ty = Type.slice_const_u8_sentinel_0;
9480 const llvm_ret_ty = try o.lowerLlvmType(slice_ty);
9481 const usize_llvm_ty = try o.lowerLlvmType(Type.usize);
9364 const llvm_ret_ty = (try o.lowerType(slice_ty)).toLlvm(&o.builder);
9365 const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
94829366 const slice_alignment = slice_ty.abiAlignment(mod);
94839367
9484 const param_types = [_]*llvm.Type{try o.lowerLlvmType(enum_type.tag_ty.toType())};
9368 const param_types = [_]*llvm.Type{(try o.lowerType(enum_type.tag_ty.toType())).toLlvm(&o.builder)};
94859369
94869370 const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False);
94879371 const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type);
......@@ -9490,7 +9374,7 @@ pub const FuncGen = struct {
94909374 o.addCommonFnAttributes(fn_val);
94919375
94929376 var global = Builder.Global{
9493 .type = .void,
9377 .type = try o.builder.fnType(.void, &.{}, .normal),
94949378 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
94959379 };
94969380 var function = Builder.Function{
......@@ -9573,8 +9457,8 @@ pub const FuncGen = struct {
95739457
95749458 // Function signature: fn (anyerror) bool
95759459
9576 const ret_llvm_ty = try o.lowerLlvmType(Type.bool);
9577 const anyerror_llvm_ty = try o.lowerLlvmType(Type.anyerror);
9460 const ret_llvm_ty = (try o.lowerType(Type.bool)).toLlvm(&o.builder);
9461 const anyerror_llvm_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder);
95789462 const param_types = [_]*llvm.Type{anyerror_llvm_ty};
95799463
95809464 const fn_type = llvm.functionType(ret_llvm_ty, &param_types, param_types.len, .False);
......@@ -9590,7 +9474,7 @@ pub const FuncGen = struct {
95909474 const un_op = self.air.instructions.items(.data)[inst].un_op;
95919475 const operand = try self.resolveInst(un_op);
95929476 const slice_ty = self.typeOfIndex(inst);
9593 const slice_llvm_ty = try o.lowerLlvmType(slice_ty);
9477 const slice_llvm_ty = (try o.lowerType(slice_ty)).toLlvm(&o.builder);
95949478
95959479 const error_name_table_ptr = try self.getErrorNameTable();
95969480 const ptr_slice_llvm_ty = self.context.pointerType(0);
......@@ -9676,7 +9560,7 @@ pub const FuncGen = struct {
96769560 accum_init: *llvm.Value,
96779561 ) !*llvm.Value {
96789562 const o = self.dg.object;
9679 const llvm_usize_ty = try o.lowerLlvmType(Type.usize);
9563 const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
96809564 const llvm_vector_len = llvm_usize_ty.constInt(vector_len, .False);
96819565 const llvm_result_ty = accum_init.typeOf();
96829566
......@@ -9753,7 +9637,7 @@ pub const FuncGen = struct {
97539637 .Add => switch (scalar_ty.zigTypeTag(mod)) {
97549638 .Int => return self.builder.buildAddReduce(operand),
97559639 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
9756 const scalar_llvm_ty = try o.lowerLlvmType(scalar_ty);
9640 const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
97579641 const neutral_value = scalar_llvm_ty.constReal(-0.0);
97589642 return self.builder.buildFPAddReduce(neutral_value, operand);
97599643 },
......@@ -9762,7 +9646,7 @@ pub const FuncGen = struct {
97629646 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
97639647 .Int => return self.builder.buildMulReduce(operand),
97649648 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
9765 const scalar_llvm_ty = try o.lowerLlvmType(scalar_ty);
9649 const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
97669650 const neutral_value = scalar_llvm_ty.constReal(1.0);
97679651 return self.builder.buildFPMulReduce(neutral_value, operand);
97689652 },
......@@ -9790,7 +9674,7 @@ pub const FuncGen = struct {
97909674 else => unreachable,
97919675 };
97929676
9793 const param_llvm_ty = try o.lowerLlvmType(scalar_ty);
9677 const param_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
97949678 const param_types = [2]*llvm.Type{ param_llvm_ty, param_llvm_ty };
97959679 const libc_fn = try self.getLibcFunction(fn_name, &param_types, param_llvm_ty);
97969680 const init_value = try o.lowerValue(.{
......@@ -9813,7 +9697,7 @@ pub const FuncGen = struct {
98139697 const result_ty = self.typeOfIndex(inst);
98149698 const len = @as(usize, @intCast(result_ty.arrayLen(mod)));
98159699 const elements = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[ty_pl.payload..][0..len]));
9816 const llvm_result_ty = try o.lowerLlvmType(result_ty);
9700 const llvm_result_ty = (try o.lowerType(result_ty)).toLlvm(&o.builder);
98179701
98189702 switch (result_ty.zigTypeTag(mod)) {
98199703 .Vector => {
......@@ -9901,7 +9785,7 @@ pub const FuncGen = struct {
99019785 .Array => {
99029786 assert(isByRef(result_ty, mod));
99039787
9904 const llvm_usize = try o.lowerLlvmType(Type.usize);
9788 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
99059789 const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod));
99069790
99079791 const array_info = result_ty.arrayInfo(mod);
......@@ -9944,7 +9828,7 @@ pub const FuncGen = struct {
99449828 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
99459829 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
99469830 const union_ty = self.typeOfIndex(inst);
9947 const union_llvm_ty = try o.lowerLlvmType(union_ty);
9831 const union_llvm_ty = (try o.lowerType(union_ty)).toLlvm(&o.builder);
99489832 const layout = union_ty.unionGetLayout(mod);
99499833 const union_obj = mod.typeToUnion(union_ty).?;
99509834
......@@ -9986,7 +9870,7 @@ pub const FuncGen = struct {
99869870 const llvm_payload = try self.resolveInst(extra.init);
99879871 assert(union_obj.haveFieldTypes());
99889872 const field = union_obj.fields.values()[extra.field_index];
9989 const field_llvm_ty = try o.lowerLlvmType(field.ty);
9873 const field_llvm_ty = (try o.lowerType(field.ty)).toLlvm(&o.builder);
99909874 const field_size = field.ty.abiSize(mod);
99919875 const field_align = field.normalAlignment(mod);
99929876
......@@ -10009,7 +9893,7 @@ pub const FuncGen = struct {
100099893 const fields: [1]*llvm.Type = .{payload};
100109894 break :t self.context.structType(&fields, fields.len, .False);
100119895 }
10012 const tag_llvm_ty = try o.lowerLlvmType(union_obj.tag_ty);
9896 const tag_llvm_ty = (try o.lowerType(union_obj.tag_ty)).toLlvm(&o.builder);
100139897 var fields: [3]*llvm.Type = undefined;
100149898 var fields_len: c_uint = 2;
100159899 if (layout.tag_align >= layout.payload_align) {
......@@ -10062,7 +9946,7 @@ pub const FuncGen = struct {
100629946 index_type.constInt(@intFromBool(layout.tag_align < layout.payload_align), .False),
100639947 };
100649948 const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, result_ptr, &indices, indices.len, "");
10065 const tag_llvm_ty = try o.lowerLlvmType(union_obj.tag_ty);
9949 const tag_llvm_ty = (try o.lowerType(union_obj.tag_ty)).toLlvm(&o.builder);
100669950 const llvm_tag = tag_llvm_ty.constInt(tag_int, .False);
100679951 const store_inst = self.builder.buildStore(llvm_tag, field_ptr);
100689952 store_inst.setAlignment(union_obj.tag_ty.abiAlignment(mod));
......@@ -10144,7 +10028,7 @@ pub const FuncGen = struct {
1014410028 const inst_ty = self.typeOfIndex(inst);
1014510029 const operand = try self.resolveInst(ty_op.operand);
1014610030
10147 const llvm_dest_ty = try o.lowerLlvmType(inst_ty);
10031 const llvm_dest_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder);
1014810032 return self.builder.buildAddrSpaceCast(operand, llvm_dest_ty, "");
1014910033 }
1015010034
......@@ -10278,7 +10162,7 @@ pub const FuncGen = struct {
1027810162
1027910163 return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, false);
1028010164 }
10281 const payload_llvm_ty = try o.lowerLlvmType(payload_ty);
10165 const payload_llvm_ty = (try o.lowerType(payload_ty)).toLlvm(&o.builder);
1028210166 const load_inst = fg.builder.buildLoad(payload_llvm_ty, payload_ptr, "");
1028310167 load_inst.setAlignment(payload_alignment);
1028410168 return load_inst;
......@@ -10295,7 +10179,7 @@ pub const FuncGen = struct {
1029510179 non_null_bit: *llvm.Value,
1029610180 ) !?*llvm.Value {
1029710181 const o = self.dg.object;
10298 const optional_llvm_ty = try o.lowerLlvmType(optional_ty);
10182 const optional_llvm_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder);
1029910183 const non_null_field = self.builder.buildZExt(non_null_bit, self.context.intType(8), "");
1030010184 const mod = o.module;
1030110185
......@@ -10350,13 +10234,13 @@ pub const FuncGen = struct {
1035010234 const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod);
1035110235 if (byte_offset == 0) return struct_ptr;
1035210236 const byte_llvm_ty = self.context.intType(8);
10353 const llvm_usize = try o.lowerLlvmType(Type.usize);
10237 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
1035410238 const llvm_index = llvm_usize.constInt(byte_offset, .False);
1035510239 const indices: [1]*llvm.Value = .{llvm_index};
1035610240 return self.builder.buildInBoundsGEP(byte_llvm_ty, struct_ptr, &indices, indices.len, "");
1035710241 },
1035810242 else => {
10359 const struct_llvm_ty = try o.lowerPtrElemTy(struct_ty);
10243 const struct_llvm_ty = (try o.lowerPtrElemTy(struct_ty)).toLlvm(&o.builder);
1036010244
1036110245 if (llvmField(struct_ty, field_index, mod)) |llvm_field| {
1036210246 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field.index, "");
......@@ -10376,7 +10260,7 @@ pub const FuncGen = struct {
1037610260 const layout = struct_ty.unionGetLayout(mod);
1037710261 if (layout.payload_size == 0 or struct_ty.containerLayout(mod) == .Packed) return struct_ptr;
1037810262 const payload_index = @intFromBool(layout.tag_align >= layout.payload_align);
10379 const union_llvm_ty = try o.lowerLlvmType(struct_ty);
10263 const union_llvm_ty = (try o.lowerType(struct_ty)).toLlvm(&o.builder);
1038010264 const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, "");
1038110265 return union_field_ptr;
1038210266 },
......@@ -10401,7 +10285,7 @@ pub const FuncGen = struct {
1040110285 ) !*llvm.Value {
1040210286 const o = fg.dg.object;
1040310287 const mod = o.module;
10404 const pointee_llvm_ty = try o.lowerLlvmType(pointee_type);
10288 const pointee_llvm_ty = (try o.lowerType(pointee_type)).toLlvm(&o.builder);
1040510289 const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod));
1040610290 const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align);
1040710291 const llvm_usize = fg.context.intType(Type.usize.intInfo(mod).bits);
......@@ -10434,7 +10318,7 @@ pub const FuncGen = struct {
1043410318 assert(info.flags.vector_index != .runtime);
1043510319 if (info.flags.vector_index != .none) {
1043610320 const index_u32 = self.context.intType(32).constInt(@intFromEnum(info.flags.vector_index), .False);
10437 const vec_elem_ty = try o.lowerLlvmType(elem_ty);
10321 const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
1043810322 const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size);
1043910323
1044010324 const loaded_vector = self.builder.buildLoad(vec_ty, ptr, "");
......@@ -10448,7 +10332,7 @@ pub const FuncGen = struct {
1044810332 if (isByRef(elem_ty, mod)) {
1044910333 return self.loadByRef(ptr, elem_ty, ptr_alignment, info.flags.is_volatile);
1045010334 }
10451 const elem_llvm_ty = try o.lowerLlvmType(elem_ty);
10335 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
1045210336 const llvm_inst = self.builder.buildLoad(elem_llvm_ty, ptr, "");
1045310337 llvm_inst.setAlignment(ptr_alignment);
1045410338 llvm_inst.setVolatile(ptr_volatile);
......@@ -10463,7 +10347,7 @@ pub const FuncGen = struct {
1046310347 const elem_bits = @as(c_uint, @intCast(ptr_ty.childType(mod).bitSize(mod)));
1046410348 const shift_amt = containing_int.typeOf().constInt(info.packed_offset.bit_offset, .False);
1046510349 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");
10466 const elem_llvm_ty = try o.lowerLlvmType(elem_ty);
10350 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
1046710351
1046810352 if (isByRef(elem_ty, mod)) {
1046910353 const result_align = elem_ty.abiAlignment(mod);
......@@ -10511,7 +10395,7 @@ pub const FuncGen = struct {
1051110395 assert(info.flags.vector_index != .runtime);
1051210396 if (info.flags.vector_index != .none) {
1051310397 const index_u32 = self.context.intType(32).constInt(@intFromEnum(info.flags.vector_index), .False);
10514 const vec_elem_ty = try o.lowerLlvmType(elem_ty);
10398 const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
1051510399 const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size);
1051610400
1051710401 const loaded_vector = self.builder.buildLoad(vec_ty, ptr, "");
......@@ -10951,14 +10835,14 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca
1095110835}
1095210836
1095310837/// Convert a zig-address space to an llvm address space.
10954fn toLlvmAddressSpace(address_space: std.builtin.AddressSpace, target: std.Target) c_uint {
10955 for (llvmAddressSpaceInfo(target)) |info| if (info.zig == address_space) return info.llvm;
10838fn toLlvmAddressSpace(address_space: std.builtin.AddressSpace, target: std.Target) Builder.AddrSpace {
10839 for (llvmAddrSpaceInfo(target)) |info| if (info.zig == address_space) return info.llvm;
1095610840 unreachable;
1095710841}
1095810842
10959const AddressSpaceInfo = struct {
10843const AddrSpaceInfo = struct {
1096010844 zig: ?std.builtin.AddressSpace,
10961 llvm: c_uint,
10845 llvm: Builder.AddrSpace,
1096210846 non_integral: bool = false,
1096310847 size: ?u16 = null,
1096410848 abi: ?u16 = null,
......@@ -10966,49 +10850,49 @@ const AddressSpaceInfo = struct {
1096610850 idx: ?u16 = null,
1096710851 force_in_data_layout: bool = false,
1096810852};
10969fn llvmAddressSpaceInfo(target: std.Target) []const AddressSpaceInfo {
10853fn llvmAddrSpaceInfo(target: std.Target) []const AddrSpaceInfo {
1097010854 return switch (target.cpu.arch) {
1097110855 .x86, .x86_64 => &.{
10972 .{ .zig = .generic, .llvm = llvm.address_space.default },
10973 .{ .zig = .gs, .llvm = llvm.address_space.x86.gs },
10974 .{ .zig = .fs, .llvm = llvm.address_space.x86.fs },
10975 .{ .zig = .ss, .llvm = llvm.address_space.x86.ss },
10976 .{ .zig = null, .llvm = llvm.address_space.x86.ptr32_sptr, .size = 32, .abi = 32, .force_in_data_layout = true },
10977 .{ .zig = null, .llvm = llvm.address_space.x86.ptr32_uptr, .size = 32, .abi = 32, .force_in_data_layout = true },
10978 .{ .zig = null, .llvm = llvm.address_space.x86.ptr64, .size = 64, .abi = 64, .force_in_data_layout = true },
10856 .{ .zig = .generic, .llvm = .default },
10857 .{ .zig = .gs, .llvm = Builder.AddrSpace.x86.gs },
10858 .{ .zig = .fs, .llvm = Builder.AddrSpace.x86.fs },
10859 .{ .zig = .ss, .llvm = Builder.AddrSpace.x86.ss },
10860 .{ .zig = null, .llvm = Builder.AddrSpace.x86.ptr32_sptr, .size = 32, .abi = 32, .force_in_data_layout = true },
10861 .{ .zig = null, .llvm = Builder.AddrSpace.x86.ptr32_uptr, .size = 32, .abi = 32, .force_in_data_layout = true },
10862 .{ .zig = null, .llvm = Builder.AddrSpace.x86.ptr64, .size = 64, .abi = 64, .force_in_data_layout = true },
1097910863 },
1098010864 .nvptx, .nvptx64 => &.{
10981 .{ .zig = .generic, .llvm = llvm.address_space.default },
10982 .{ .zig = .global, .llvm = llvm.address_space.nvptx.global },
10983 .{ .zig = .constant, .llvm = llvm.address_space.nvptx.constant },
10984 .{ .zig = .param, .llvm = llvm.address_space.nvptx.param },
10985 .{ .zig = .shared, .llvm = llvm.address_space.nvptx.shared },
10986 .{ .zig = .local, .llvm = llvm.address_space.nvptx.local },
10865 .{ .zig = .generic, .llvm = .default },
10866 .{ .zig = .global, .llvm = Builder.AddrSpace.nvptx.global },
10867 .{ .zig = .constant, .llvm = Builder.AddrSpace.nvptx.constant },
10868 .{ .zig = .param, .llvm = Builder.AddrSpace.nvptx.param },
10869 .{ .zig = .shared, .llvm = Builder.AddrSpace.nvptx.shared },
10870 .{ .zig = .local, .llvm = Builder.AddrSpace.nvptx.local },
1098710871 },
1098810872 .amdgcn => &.{
10989 .{ .zig = .generic, .llvm = llvm.address_space.amdgpu.flat },
10990 .{ .zig = .global, .llvm = llvm.address_space.amdgpu.global },
10991 .{ .zig = .constant, .llvm = llvm.address_space.amdgpu.constant },
10992 .{ .zig = .shared, .llvm = llvm.address_space.amdgpu.local },
10993 .{ .zig = .local, .llvm = llvm.address_space.amdgpu.private },
10873 .{ .zig = .generic, .llvm = Builder.AddrSpace.amdgpu.flat },
10874 .{ .zig = .global, .llvm = Builder.AddrSpace.amdgpu.global },
10875 .{ .zig = .constant, .llvm = Builder.AddrSpace.amdgpu.constant },
10876 .{ .zig = .shared, .llvm = Builder.AddrSpace.amdgpu.local },
10877 .{ .zig = .local, .llvm = Builder.AddrSpace.amdgpu.private },
1099410878 },
1099510879 .avr => &.{
10996 .{ .zig = .generic, .llvm = llvm.address_space.default },
10997 .{ .zig = .flash, .llvm = llvm.address_space.avr.flash },
10998 .{ .zig = .flash1, .llvm = llvm.address_space.avr.flash1 },
10999 .{ .zig = .flash2, .llvm = llvm.address_space.avr.flash2 },
11000 .{ .zig = .flash3, .llvm = llvm.address_space.avr.flash3 },
11001 .{ .zig = .flash4, .llvm = llvm.address_space.avr.flash4 },
11002 .{ .zig = .flash5, .llvm = llvm.address_space.avr.flash5 },
10880 .{ .zig = .generic, .llvm = .default },
10881 .{ .zig = .flash, .llvm = Builder.AddrSpace.avr.flash },
10882 .{ .zig = .flash1, .llvm = Builder.AddrSpace.avr.flash1 },
10883 .{ .zig = .flash2, .llvm = Builder.AddrSpace.avr.flash2 },
10884 .{ .zig = .flash3, .llvm = Builder.AddrSpace.avr.flash3 },
10885 .{ .zig = .flash4, .llvm = Builder.AddrSpace.avr.flash4 },
10886 .{ .zig = .flash5, .llvm = Builder.AddrSpace.avr.flash5 },
1100310887 },
1100410888 .wasm32, .wasm64 => &.{
11005 .{ .zig = .generic, .llvm = llvm.address_space.default },
11006 .{ .zig = null, .llvm = llvm.address_space.wasm.variable, .non_integral = true },
11007 .{ .zig = null, .llvm = llvm.address_space.wasm.externref, .non_integral = true, .size = 8, .abi = 8 },
11008 .{ .zig = null, .llvm = llvm.address_space.wasm.funcref, .non_integral = true, .size = 8, .abi = 8 },
10889 .{ .zig = .generic, .llvm = .default },
10890 .{ .zig = null, .llvm = Builder.AddrSpace.wasm.variable, .non_integral = true },
10891 .{ .zig = null, .llvm = Builder.AddrSpace.wasm.externref, .non_integral = true, .size = 8, .abi = 8 },
10892 .{ .zig = null, .llvm = Builder.AddrSpace.wasm.funcref, .non_integral = true, .size = 8, .abi = 8 },
1100910893 },
1101010894 else => &.{
11011 .{ .zig = .generic, .llvm = llvm.address_space.default },
10895 .{ .zig = .generic, .llvm = .default },
1101210896 },
1101310897 };
1101410898}
......@@ -11017,30 +10901,30 @@ fn llvmAddressSpaceInfo(target: std.Target) []const AddressSpaceInfo {
1101710901/// different address, space and then cast back to the generic address space.
1101810902/// For example, on GPUs local variable declarations must be generated into the local address space.
1101910903/// This function returns the address space local values should be generated into.
11020fn llvmAllocaAddressSpace(target: std.Target) c_uint {
10904fn llvmAllocaAddressSpace(target: std.Target) Builder.AddrSpace {
1102110905 return switch (target.cpu.arch) {
1102210906 // On amdgcn, locals should be generated into the private address space.
1102310907 // To make Zig not impossible to use, these are then converted to addresses in the
1102410908 // generic address space and treates as regular pointers. This is the way that HIP also does it.
11025 .amdgcn => llvm.address_space.amdgpu.private,
11026 else => llvm.address_space.default,
10909 .amdgcn => Builder.AddrSpace.amdgpu.private,
10910 else => .default,
1102710911 };
1102810912}
1102910913
1103010914/// On some targets, global values that are in the generic address space must be generated into a
1103110915/// different address space, and then cast back to the generic address space.
11032fn llvmDefaultGlobalAddressSpace(target: std.Target) c_uint {
10916fn llvmDefaultGlobalAddressSpace(target: std.Target) Builder.AddrSpace {
1103310917 return switch (target.cpu.arch) {
1103410918 // On amdgcn, globals must be explicitly allocated and uploaded so that the program can access
1103510919 // them.
11036 .amdgcn => llvm.address_space.amdgpu.global,
11037 else => llvm.address_space.default,
10920 .amdgcn => Builder.AddrSpace.amdgpu.global,
10921 else => .default,
1103810922 };
1103910923}
1104010924
1104110925/// Return the actual address space that a value should be stored in if its a global address space.
1104210926/// When a value is placed in the resulting address space, it needs to be cast back into wanted_address_space.
11043fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, target: std.Target) c_uint {
10927fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, target: std.Target) Builder.AddrSpace {
1104410928 return switch (wanted_address_space) {
1104510929 .generic => llvmDefaultGlobalAddressSpace(target),
1104610930 else => |as| toLlvmAddressSpace(as, target),
......@@ -11170,161 +11054,129 @@ fn firstParamSRetSystemV(ty: Type, mod: *Module) bool {
1117011054/// In order to support the C calling convention, some return types need to be lowered
1117111055/// completely differently in the function prototype to honor the C ABI, and then
1117211056/// be effectively bitcasted to the actual return type.
11173fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) !*llvm.Type {
11057fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
1117411058 const mod = o.module;
1117511059 const return_type = fn_info.return_type.toType();
1117611060 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
1117711061 // If the return type is an error set or an error union, then we make this
1117811062 // anyerror return type instead, so that it can be coerced into a function
1117911063 // pointer type which has anyerror as the return type.
11180 if (return_type.isError(mod)) {
11181 return o.lowerLlvmType(Type.anyerror);
11182 } else {
11183 return o.context.voidType();
11184 }
11064 return if (return_type.isError(mod)) Builder.Type.err_int else .void;
1118511065 }
1118611066 const target = mod.getTarget();
1118711067 switch (fn_info.cc) {
11188 .Unspecified, .Inline => {
11189 if (isByRef(return_type, mod)) {
11190 return o.context.voidType();
11191 } else {
11192 return o.lowerLlvmType(return_type);
11193 }
11194 },
11068 .Unspecified,
11069 .Inline,
11070 => return if (isByRef(return_type, mod)) .void else o.lowerType(return_type),
1119511071 .C => {
1119611072 switch (target.cpu.arch) {
11197 .mips, .mipsel => return o.lowerLlvmType(return_type),
11073 .mips, .mipsel => return o.lowerType(return_type),
1119811074 .x86_64 => switch (target.os.tag) {
1119911075 .windows => return lowerWin64FnRetTy(o, fn_info),
1120011076 else => return lowerSystemVFnRetTy(o, fn_info),
1120111077 },
1120211078 .wasm32 => {
1120311079 if (isScalar(mod, return_type)) {
11204 return o.lowerLlvmType(return_type);
11080 return o.lowerType(return_type);
1120511081 }
1120611082 const classes = wasm_c_abi.classifyType(return_type, mod);
1120711083 if (classes[0] == .indirect or classes[0] == .none) {
11208 return o.context.voidType();
11084 return .void;
1120911085 }
1121011086
1121111087 assert(classes[0] == .direct and classes[1] == .none);
1121211088 const scalar_type = wasm_c_abi.scalarType(return_type, mod);
11213 const abi_size = scalar_type.abiSize(mod);
11214 return o.context.intType(@as(c_uint, @intCast(abi_size * 8)));
11089 return o.builder.intType(@intCast(scalar_type.abiSize(mod) * 8));
1121511090 },
1121611091 .aarch64, .aarch64_be => {
1121711092 switch (aarch64_c_abi.classifyType(return_type, mod)) {
11218 .memory => return o.context.voidType(),
11219 .float_array => return o.lowerLlvmType(return_type),
11220 .byval => return o.lowerLlvmType(return_type),
11221 .integer => {
11222 const bit_size = return_type.bitSize(mod);
11223 return o.context.intType(@as(c_uint, @intCast(bit_size)));
11224 },
11225 .double_integer => return o.context.intType(64).arrayType(2),
11093 .memory => return .void,
11094 .float_array => return o.lowerType(return_type),
11095 .byval => return o.lowerType(return_type),
11096 .integer => return o.builder.intType(@intCast(return_type.bitSize(mod))),
11097 .double_integer => return o.builder.arrayType(2, .i64),
1122611098 }
1122711099 },
1122811100 .arm, .armeb => {
1122911101 switch (arm_c_abi.classifyType(return_type, mod, .ret)) {
11230 .memory, .i64_array => return o.context.voidType(),
11231 .i32_array => |len| if (len == 1) {
11232 return o.context.intType(32);
11233 } else {
11234 return o.context.voidType();
11235 },
11236 .byval => return o.lowerLlvmType(return_type),
11102 .memory, .i64_array => return .void,
11103 .i32_array => |len| return if (len == 1) .i32 else .void,
11104 .byval => return o.lowerType(return_type),
1123711105 }
1123811106 },
1123911107 .riscv32, .riscv64 => {
1124011108 switch (riscv_c_abi.classifyType(return_type, mod)) {
11241 .memory => return o.context.voidType(),
11109 .memory => return .void,
1124211110 .integer => {
11243 const bit_size = return_type.bitSize(mod);
11244 return o.context.intType(@as(c_uint, @intCast(bit_size)));
11111 return o.builder.intType(@intCast(return_type.bitSize(mod)));
1124511112 },
1124611113 .double_integer => {
11247 var llvm_types_buffer: [2]*llvm.Type = .{
11248 o.context.intType(64),
11249 o.context.intType(64),
11250 };
11251 return o.context.structType(&llvm_types_buffer, 2, .False);
11114 return o.builder.structType(.normal, &.{ .i64, .i64 });
1125211115 },
11253 .byval => return o.lowerLlvmType(return_type),
11116 .byval => return o.lowerType(return_type),
1125411117 }
1125511118 },
1125611119 // TODO investigate C ABI for other architectures
11257 else => return o.lowerLlvmType(return_type),
11120 else => return o.lowerType(return_type),
1125811121 }
1125911122 },
1126011123 .Win64 => return lowerWin64FnRetTy(o, fn_info),
1126111124 .SysV => return lowerSystemVFnRetTy(o, fn_info),
11262 .Stdcall => {
11263 if (isScalar(mod, return_type)) {
11264 return o.lowerLlvmType(return_type);
11265 } else {
11266 return o.context.voidType();
11267 }
11268 },
11269 else => return o.lowerLlvmType(return_type),
11125 .Stdcall => return if (isScalar(mod, return_type)) o.lowerType(return_type) else .void,
11126 else => return o.lowerType(return_type),
1127011127 }
1127111128}
1127211129
11273fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) !*llvm.Type {
11130fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
1127411131 const mod = o.module;
1127511132 const return_type = fn_info.return_type.toType();
1127611133 switch (x86_64_abi.classifyWindows(return_type, mod)) {
1127711134 .integer => {
1127811135 if (isScalar(mod, return_type)) {
11279 return o.lowerLlvmType(return_type);
11136 return o.lowerType(return_type);
1128011137 } else {
11281 const abi_size = return_type.abiSize(mod);
11282 return o.context.intType(@as(c_uint, @intCast(abi_size * 8)));
11138 return o.builder.intType(@intCast(return_type.abiSize(mod) * 8));
1128311139 }
1128411140 },
11285 .win_i128 => return o.context.intType(64).vectorType(2),
11286 .memory => return o.context.voidType(),
11287 .sse => return o.lowerLlvmType(return_type),
11141 .win_i128 => return o.builder.vectorType(.normal, 2, .i64),
11142 .memory => return .void,
11143 .sse => return o.lowerType(return_type),
1128811144 else => unreachable,
1128911145 }
1129011146}
1129111147
11292fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) !*llvm.Type {
11148fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
1129311149 const mod = o.module;
1129411150 const return_type = fn_info.return_type.toType();
1129511151 if (isScalar(mod, return_type)) {
11296 return o.lowerLlvmType(return_type);
11152 return o.lowerType(return_type);
1129711153 }
1129811154 const classes = x86_64_abi.classifySystemV(return_type, mod, .ret);
11299 if (classes[0] == .memory) {
11300 return o.context.voidType();
11301 }
11302 var llvm_types_buffer: [8]*llvm.Type = undefined;
11303 var llvm_types_index: u32 = 0;
11155 if (classes[0] == .memory) return .void;
11156 var types_index: u32 = 0;
11157 var types_buffer: [8]Builder.Type = undefined;
1130411158 for (classes) |class| {
1130511159 switch (class) {
1130611160 .integer => {
11307 llvm_types_buffer[llvm_types_index] = o.context.intType(64);
11308 llvm_types_index += 1;
11161 types_buffer[types_index] = .i64;
11162 types_index += 1;
1130911163 },
1131011164 .sse, .sseup => {
11311 llvm_types_buffer[llvm_types_index] = o.context.doubleType();
11312 llvm_types_index += 1;
11165 types_buffer[types_index] = .double;
11166 types_index += 1;
1131311167 },
1131411168 .float => {
11315 llvm_types_buffer[llvm_types_index] = o.context.floatType();
11316 llvm_types_index += 1;
11169 types_buffer[types_index] = .float;
11170 types_index += 1;
1131711171 },
1131811172 .float_combine => {
11319 llvm_types_buffer[llvm_types_index] = o.context.floatType().vectorType(2);
11320 llvm_types_index += 1;
11173 types_buffer[types_index] = try o.builder.vectorType(.normal, 2, .float);
11174 types_index += 1;
1132111175 },
1132211176 .x87 => {
11323 if (llvm_types_index != 0 or classes[2] != .none) {
11324 return o.context.voidType();
11325 }
11326 llvm_types_buffer[llvm_types_index] = o.context.x86_fp80Type();
11327 llvm_types_index += 1;
11177 if (types_index != 0 or classes[2] != .none) return .void;
11178 types_buffer[types_index] = .x86_fp80;
11179 types_index += 1;
1132811180 },
1132911181 .x87up => continue,
1133011182 .complex_x87 => {
......@@ -11336,10 +11188,9 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) !*llvm.Type
1133611188 }
1133711189 }
1133811190 if (classes[0] == .integer and classes[1] == .none) {
11339 const abi_size = return_type.abiSize(mod);
11340 return o.context.intType(@as(c_uint, @intCast(abi_size * 8)));
11191 return o.builder.intType(@intCast(return_type.abiSize(mod) * 8));
1134111192 }
11342 return o.context.structType(&llvm_types_buffer, llvm_types_index, .False);
11193 return o.builder.structType(.normal, types_buffer[0..types_index]);
1134311194}
1134411195
1134511196const ParamTypeIterator = struct {
......@@ -11347,7 +11198,8 @@ const ParamTypeIterator = struct {
1134711198 fn_info: InternPool.Key.FuncType,
1134811199 zig_index: u32,
1134911200 llvm_index: u32,
11350 llvm_types_len: u32,
11201 types_len: u32,
11202 types_buffer: [8]Builder.Type,
1135111203 llvm_types_buffer: [8]*llvm.Type,
1135211204 byval_attr: bool,
1135311205
......@@ -11365,7 +11217,7 @@ const ParamTypeIterator = struct {
1136511217 i64_array: u8,
1136611218 };
1136711219
11368 pub fn next(it: *ParamTypeIterator) ?Lowering {
11220 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {
1136911221 if (it.zig_index >= it.fn_info.param_types.len) return null;
1137011222 const mod = it.object.module;
1137111223 const ip = &mod.intern_pool;
......@@ -11375,7 +11227,7 @@ const ParamTypeIterator = struct {
1137511227 }
1137611228
1137711229 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
11378 pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering {
11230 pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering {
1137911231 const mod = it.object.module;
1138011232 const ip = &mod.intern_pool;
1138111233 if (it.zig_index >= it.fn_info.param_types.len) {
......@@ -11389,7 +11241,7 @@ const ParamTypeIterator = struct {
1138911241 }
1139011242 }
1139111243
11392 fn nextInner(it: *ParamTypeIterator, ty: Type) ?Lowering {
11244 fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
1139311245 const mod = it.object.module;
1139411246 const target = mod.getTarget();
1139511247
......@@ -11444,8 +11296,9 @@ const ParamTypeIterator = struct {
1144411296 .float_array => |len| return Lowering{ .float_array = len },
1144511297 .byval => return .byval,
1144611298 .integer => {
11447 it.llvm_types_len = 1;
11448 it.llvm_types_buffer[0] = it.object.context.intType(64);
11299 it.types_len = 1;
11300 it.types_buffer[0] = .i64;
11301 it.llvm_types_buffer[0] = it.types_buffer[0].toLlvm(&it.object.builder);
1144911302 return .multiple_llvm_types;
1145011303 },
1145111304 .double_integer => return Lowering{ .i64_array = 2 },
......@@ -11539,7 +11392,7 @@ const ParamTypeIterator = struct {
1153911392 }
1154011393 }
1154111394
11542 fn nextSystemV(it: *ParamTypeIterator, ty: Type) ?Lowering {
11395 fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
1154311396 const mod = it.object.module;
1154411397 const classes = x86_64_abi.classifySystemV(ty, mod, .arg);
1154511398 if (classes[0] == .memory) {
......@@ -11553,25 +11406,34 @@ const ParamTypeIterator = struct {
1155311406 it.llvm_index += 1;
1155411407 return .byval;
1155511408 }
11409 var types_index: u32 = 0;
11410 var types_buffer: [8]Builder.Type = undefined;
1155611411 var llvm_types_buffer: [8]*llvm.Type = undefined;
11557 var llvm_types_index: u32 = 0;
1155811412 for (classes) |class| {
1155911413 switch (class) {
1156011414 .integer => {
11561 llvm_types_buffer[llvm_types_index] = it.object.context.intType(64);
11562 llvm_types_index += 1;
11415 types_buffer[types_index] = .i64;
11416 llvm_types_buffer[types_index] =
11417 types_buffer[types_index].toLlvm(&it.object.builder);
11418 types_index += 1;
1156311419 },
1156411420 .sse, .sseup => {
11565 llvm_types_buffer[llvm_types_index] = it.object.context.doubleType();
11566 llvm_types_index += 1;
11421 types_buffer[types_index] = .double;
11422 llvm_types_buffer[types_index] =
11423 types_buffer[types_index].toLlvm(&it.object.builder);
11424 types_index += 1;
1156711425 },
1156811426 .float => {
11569 llvm_types_buffer[llvm_types_index] = it.object.context.floatType();
11570 llvm_types_index += 1;
11427 types_buffer[types_index] = .float;
11428 llvm_types_buffer[types_index] =
11429 types_buffer[types_index].toLlvm(&it.object.builder);
11430 types_index += 1;
1157111431 },
1157211432 .float_combine => {
11573 llvm_types_buffer[llvm_types_index] = it.object.context.floatType().vectorType(2);
11574 llvm_types_index += 1;
11433 types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float);
11434 llvm_types_buffer[types_index] =
11435 types_buffer[types_index].toLlvm(&it.object.builder);
11436 types_index += 1;
1157511437 },
1157611438 .x87 => {
1157711439 it.zig_index += 1;
......@@ -11593,9 +11455,10 @@ const ParamTypeIterator = struct {
1159311455 it.llvm_index += 1;
1159411456 return .abi_sized_int;
1159511457 }
11458 it.types_len = types_index;
11459 it.types_buffer = types_buffer;
1159611460 it.llvm_types_buffer = llvm_types_buffer;
11597 it.llvm_types_len = llvm_types_index;
11598 it.llvm_index += llvm_types_index;
11461 it.llvm_index += types_index;
1159911462 it.zig_index += 1;
1160011463 return .multiple_llvm_types;
1160111464 }
......@@ -11607,8 +11470,9 @@ fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTyp
1160711470 .fn_info = fn_info,
1160811471 .zig_index = 0,
1160911472 .llvm_index = 0,
11473 .types_len = 0,
11474 .types_buffer = undefined,
1161011475 .llvm_types_buffer = undefined,
11611 .llvm_types_len = 0,
1161211476 .byval_attr = false,
1161311477 };
1161411478}
......@@ -11905,7 +11769,7 @@ fn buildAllocaInner(
1190511769 }
1190611770 builder.clearCurrentDebugLocation();
1190711771
11908 break :blk builder.buildAllocaInAddressSpace(llvm_ty, address_space, "");
11772 break :blk builder.buildAllocaInAddressSpace(llvm_ty, @intFromEnum(address_space), "");
1190911773 };
1191011774
1191111775 if (maybe_alignment) |alignment| {
......@@ -11914,7 +11778,7 @@ fn buildAllocaInner(
1191411778
1191511779 // The pointer returned from this function should have the generic address space,
1191611780 // if this isn't the case then cast it to the generic address space.
11917 if (address_space != llvm.address_space.default) {
11781 if (address_space != .default) {
1191811782 return builder.buildAddrSpaceCast(alloca, context.pointerType(llvm.address_space.default), "");
1191911783 }
1192011784
src/codegen/llvm/Builder.zig+580-89
......@@ -19,7 +19,7 @@ types: std.AutoArrayHashMapUnmanaged(String, Type) = .{},
1919next_unnamed_type: String = @enumFromInt(0),
2020next_unique_type_id: std.AutoHashMapUnmanaged(String, u32) = .{},
2121type_map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
22type_data: std.ArrayListUnmanaged(Type.Data) = .{},
22type_items: std.ArrayListUnmanaged(Type.Item) = .{},
2323type_extra: std.ArrayListUnmanaged(u32) = .{},
2424
2525globals: std.AutoArrayHashMapUnmanaged(String, Global) = .{},
......@@ -62,10 +62,10 @@ pub const String = enum(u32) {
6262 else
6363 @compileError("invalid format string: '" ++ fmt_str ++ "'");
6464 if (need_quotes) try writer.writeByte('\"');
65 for (slice) |c| switch (c) {
65 for (slice) |character| switch (character) {
6666 '\\' => try writer.writeAll("\\\\"),
67 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(c),
68 else => try writer.print("\\{X:0>2}", .{c}),
67 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(character),
68 else => try writer.print("\\{X:0>2}", .{character}),
6969 };
7070 if (need_quotes) try writer.writeByte('\"');
7171 }
......@@ -120,21 +120,25 @@ pub const Type = enum(u32) {
120120 none = std.math.maxInt(u32),
121121 _,
122122
123 const Tag = enum(u4) {
123 pub const err_int = Type.i16;
124
125 pub const Tag = enum(u4) {
124126 simple,
125127 function,
128 vararg_function,
126129 integer,
127130 pointer,
128131 target,
129132 vector,
130 vscale_vector,
133 scalable_vector,
134 small_array,
131135 array,
132136 structure,
133137 packed_structure,
134138 named_structure,
135139 };
136140
137 const Simple = enum {
141 pub const Simple = enum {
138142 void,
139143 half,
140144 bfloat,
......@@ -150,19 +154,55 @@ pub const Type = enum(u32) {
150154 metadata,
151155 };
152156
153 const NamedStructure = struct {
154 id: String,
157 pub const Function = struct {
158 ret: Type,
159 params_len: u32,
160
161 pub const Kind = enum { normal, vararg };
162 };
163
164 pub const Target = extern struct {
165 name: String,
166 types_len: u32,
167 ints_len: u32,
168 };
169
170 pub const Vector = extern struct {
171 len: u32,
172 child: Type,
173
174 pub const Kind = enum { normal, scalable };
175 };
176
177 pub const Array = extern struct {
178 len_lo: u32,
179 len_hi: u32,
155180 child: Type,
181
182 fn len(self: Array) u64 {
183 return @as(u64, self.len_hi) << 32 | self.len_lo;
184 }
185 };
186
187 pub const Structure = struct {
188 fields_len: u32,
189
190 pub const Kind = enum { normal, @"packed" };
156191 };
157192
158 const Data = packed struct(u32) {
193 pub const NamedStructure = struct {
194 id: String,
195 body: Type,
196 };
197
198 pub const Item = packed struct(u32) {
159199 tag: Tag,
160200 data: ExtraIndex,
161201 };
162202
163 const ExtraIndex = u28;
203 pub const ExtraIndex = u28;
164204
165 const FormatData = struct {
205 pub const FormatData = struct {
166206 type: Type,
167207 builder: *const Builder,
168208 };
......@@ -174,27 +214,106 @@ pub const Type = enum(u32) {
174214 ) @TypeOf(writer).Error!void {
175215 assert(data.type != .none);
176216 if (std.enums.tagName(Type, data.type)) |name| return writer.writeAll(name);
177 const type_data = data.builder.type_data.items[@intFromEnum(data.type)];
178 switch (type_data.tag) {
179 .integer => try writer.print("i{d}", .{type_data.data}),
217 const type_item = data.builder.type_items.items[@intFromEnum(data.type)];
218 switch (type_item.tag) {
219 .simple => unreachable,
220 .function, .vararg_function => {
221 const extra = data.builder.typeExtraDataTrail(Type.Function, type_item.data);
222 const params: []const Type =
223 @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.params_len]);
224 if (!comptime std.mem.eql(u8, fmt_str, ">"))
225 try writer.print("{%} ", .{extra.data.ret.fmt(data.builder)});
226 if (!comptime std.mem.eql(u8, fmt_str, "<")) {
227 try writer.writeByte('(');
228 for (params, 0..) |param, index| {
229 if (index > 0) try writer.writeAll(", ");
230 try writer.print("{%}", .{param.fmt(data.builder)});
231 }
232 switch (type_item.tag) {
233 .function => {},
234 .vararg_function => {
235 if (params.len > 0) try writer.writeAll(", ");
236 try writer.writeAll("...");
237 },
238 else => unreachable,
239 }
240 try writer.writeByte(')');
241 }
242 },
243 .integer => try writer.print("i{d}", .{type_item.data}),
244 .pointer => try writer.print("ptr{}", .{@as(AddrSpace, @enumFromInt(type_item.data))}),
245 .target => {
246 const extra = data.builder.typeExtraDataTrail(Type.Target, type_item.data);
247 const types: []const Type =
248 @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.types_len]);
249 const ints: []const u32 = @ptrCast(data.builder.type_extra.items[extra.end +
250 extra.data.types_len ..][0..extra.data.ints_len]);
251 try writer.print(
252 \\target({"}
253 , .{extra.data.name.fmt(data.builder)});
254 for (types) |ty| try writer.print(", {%}", .{ty.fmt(data.builder)});
255 for (ints) |int| try writer.print(", {d}", .{int});
256 try writer.writeByte(')');
257 },
258 .vector => {
259 const extra = data.builder.typeExtraData(Type.Vector, type_item.data);
260 try writer.print("<{d} x {%}>", .{ extra.len, extra.child.fmt(data.builder) });
261 },
262 .scalable_vector => {
263 const extra = data.builder.typeExtraData(Type.Vector, type_item.data);
264 try writer.print("<vscale x {d} x {%}>", .{ extra.len, extra.child.fmt(data.builder) });
265 },
266 .small_array => {
267 const extra = data.builder.typeExtraData(Type.Vector, type_item.data);
268 try writer.print("[{d} x {%}]", .{ extra.len, extra.child.fmt(data.builder) });
269 },
270 .array => {
271 const extra = data.builder.typeExtraData(Type.Array, type_item.data);
272 try writer.print("[{d} x {%}]", .{ extra.len(), extra.child.fmt(data.builder) });
273 },
274 .structure, .packed_structure => {
275 const extra = data.builder.typeExtraDataTrail(Type.Structure, type_item.data);
276 const fields: []const Type =
277 @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.fields_len]);
278 switch (type_item.tag) {
279 .structure => {},
280 .packed_structure => try writer.writeByte('<'),
281 else => unreachable,
282 }
283 try writer.writeAll("{ ");
284 for (fields, 0..) |field, index| {
285 if (index > 0) try writer.writeAll(", ");
286 try writer.print("{%}", .{field.fmt(data.builder)});
287 }
288 try writer.writeAll(" }");
289 switch (type_item.tag) {
290 .structure => {},
291 .packed_structure => try writer.writeByte('>'),
292 else => unreachable,
293 }
294 },
180295 .named_structure => {
181 const extra = data.builder.typeExtraData(NamedStructure, type_data.data);
182 if (comptime std.mem.eql(u8, fmt_str, "")) switch (extra.child) {
296 const extra = data.builder.typeExtraData(Type.NamedStructure, type_item.data);
297 if (comptime std.mem.eql(u8, fmt_str, "%")) try writer.print("%{}", .{
298 extra.id.fmt(data.builder),
299 }) else switch (extra.body) {
183300 .none => try writer.writeAll("opaque"),
184301 else => try format(.{
185 .type = extra.child,
302 .type = extra.body,
186303 .builder = data.builder,
187304 }, fmt_str, fmt_opts, writer),
188 } else if (comptime std.mem.eql(u8, fmt_str, "%")) try writer.print("%{}", .{
189 extra.id.fmt(data.builder),
190 }) else @compileError("invalid format string: '" ++ fmt_str ++ "'");
305 }
191306 },
192 else => try writer.print("<type 0x{X}>", .{@intFromEnum(data.type)}),
193307 }
194308 }
195309 pub fn fmt(self: Type, builder: *const Builder) std.fmt.Formatter(format) {
196310 return .{ .data = .{ .type = self, .builder = builder } };
197311 }
312
313 pub fn toLlvm(self: Type, builder: *const Builder) *llvm.Type {
314 assert(builder.useLibLlvm());
315 return builder.llvm_types.items[@intFromEnum(self)];
316 }
198317};
199318
200319pub const Linkage = enum {
......@@ -217,9 +336,7 @@ pub const Linkage = enum {
217336 _: std.fmt.FormatOptions,
218337 writer: anytype,
219338 ) @TypeOf(writer).Error!void {
220 if (self == .default) return;
221 try writer.writeAll(@tagName(self));
222 try writer.writeByte(' ');
339 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
223340 }
224341};
225342
......@@ -234,9 +351,7 @@ pub const Preemption = enum {
234351 _: std.fmt.FormatOptions,
235352 writer: anytype,
236353 ) @TypeOf(writer).Error!void {
237 if (self == .default) return;
238 try writer.writeAll(@tagName(self));
239 try writer.writeByte(' ');
354 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
240355 }
241356};
242357
......@@ -251,9 +366,7 @@ pub const Visibility = enum {
251366 _: std.fmt.FormatOptions,
252367 writer: anytype,
253368 ) @TypeOf(writer).Error!void {
254 if (self == .default) return;
255 try writer.writeAll(@tagName(self));
256 try writer.writeByte(' ');
369 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
257370 }
258371};
259372
......@@ -268,9 +381,7 @@ pub const DllStorageClass = enum {
268381 _: std.fmt.FormatOptions,
269382 writer: anytype,
270383 ) @TypeOf(writer).Error!void {
271 if (self == .default) return;
272 try writer.writeAll(@tagName(self));
273 try writer.writeByte(' ');
384 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
274385 }
275386};
276387
......@@ -288,13 +399,12 @@ pub const ThreadLocal = enum {
288399 writer: anytype,
289400 ) @TypeOf(writer).Error!void {
290401 if (self == .default) return;
291 try writer.writeAll("thread_local");
402 try writer.writeAll(" thread_local");
292403 if (self != .generaldynamic) {
293404 try writer.writeByte('(');
294405 try writer.writeAll(@tagName(self));
295406 try writer.writeByte(')');
296407 }
297 try writer.writeByte(' ');
298408 }
299409};
300410
......@@ -309,9 +419,7 @@ pub const UnnamedAddr = enum {
309419 _: std.fmt.FormatOptions,
310420 writer: anytype,
311421 ) @TypeOf(writer).Error!void {
312 if (self == .default) return;
313 try writer.writeAll(@tagName(self));
314 try writer.writeByte(' ');
422 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
315423 }
316424};
317425
......@@ -319,14 +427,82 @@ pub const AddrSpace = enum(u24) {
319427 default,
320428 _,
321429
430 // See llvm/lib/Target/X86/X86.h
431 pub const x86 = struct {
432 pub const gs: AddrSpace = @enumFromInt(256);
433 pub const fs: AddrSpace = @enumFromInt(257);
434 pub const ss: AddrSpace = @enumFromInt(258);
435
436 pub const ptr32_sptr: AddrSpace = @enumFromInt(270);
437 pub const ptr32_uptr: AddrSpace = @enumFromInt(271);
438 pub const ptr64: AddrSpace = @enumFromInt(272);
439 };
440 pub const x86_64 = x86;
441
442 // See llvm/lib/Target/AVR/AVR.h
443 pub const avr = struct {
444 pub const flash: AddrSpace = @enumFromInt(1);
445 pub const flash1: AddrSpace = @enumFromInt(2);
446 pub const flash2: AddrSpace = @enumFromInt(3);
447 pub const flash3: AddrSpace = @enumFromInt(4);
448 pub const flash4: AddrSpace = @enumFromInt(5);
449 pub const flash5: AddrSpace = @enumFromInt(6);
450 };
451
452 // See llvm/lib/Target/NVPTX/NVPTX.h
453 pub const nvptx = struct {
454 pub const generic: AddrSpace = @enumFromInt(0);
455 pub const global: AddrSpace = @enumFromInt(1);
456 pub const constant: AddrSpace = @enumFromInt(2);
457 pub const shared: AddrSpace = @enumFromInt(3);
458 pub const param: AddrSpace = @enumFromInt(4);
459 pub const local: AddrSpace = @enumFromInt(5);
460 };
461
462 // See llvm/lib/Target/AMDGPU/AMDGPU.h
463 pub const amdgpu = struct {
464 pub const flat: AddrSpace = @enumFromInt(0);
465 pub const global: AddrSpace = @enumFromInt(1);
466 pub const region: AddrSpace = @enumFromInt(2);
467 pub const local: AddrSpace = @enumFromInt(3);
468 pub const constant: AddrSpace = @enumFromInt(4);
469 pub const private: AddrSpace = @enumFromInt(5);
470 pub const constant_32bit: AddrSpace = @enumFromInt(6);
471 pub const buffer_fat_pointer: AddrSpace = @enumFromInt(7);
472 pub const param_d: AddrSpace = @enumFromInt(6);
473 pub const param_i: AddrSpace = @enumFromInt(7);
474 pub const constant_buffer_0: AddrSpace = @enumFromInt(8);
475 pub const constant_buffer_1: AddrSpace = @enumFromInt(9);
476 pub const constant_buffer_2: AddrSpace = @enumFromInt(10);
477 pub const constant_buffer_3: AddrSpace = @enumFromInt(11);
478 pub const constant_buffer_4: AddrSpace = @enumFromInt(12);
479 pub const constant_buffer_5: AddrSpace = @enumFromInt(13);
480 pub const constant_buffer_6: AddrSpace = @enumFromInt(14);
481 pub const constant_buffer_7: AddrSpace = @enumFromInt(15);
482 pub const constant_buffer_8: AddrSpace = @enumFromInt(16);
483 pub const constant_buffer_9: AddrSpace = @enumFromInt(17);
484 pub const constant_buffer_10: AddrSpace = @enumFromInt(18);
485 pub const constant_buffer_11: AddrSpace = @enumFromInt(19);
486 pub const constant_buffer_12: AddrSpace = @enumFromInt(20);
487 pub const constant_buffer_13: AddrSpace = @enumFromInt(21);
488 pub const constant_buffer_14: AddrSpace = @enumFromInt(22);
489 pub const constant_buffer_15: AddrSpace = @enumFromInt(23);
490 };
491
492 // See llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
493 pub const wasm = struct {
494 pub const variable: AddrSpace = @enumFromInt(1);
495 pub const externref: AddrSpace = @enumFromInt(10);
496 pub const funcref: AddrSpace = @enumFromInt(20);
497 };
498
322499 pub fn format(
323500 self: AddrSpace,
324501 comptime _: []const u8,
325502 _: std.fmt.FormatOptions,
326503 writer: anytype,
327504 ) @TypeOf(writer).Error!void {
328 if (self == .default) return;
329 try writer.print("addrspace({d}) ", .{@intFromEnum(self)});
505 if (self != .default) try writer.print(" addrspace({d})", .{@intFromEnum(self)});
330506 }
331507};
332508
......@@ -341,8 +517,8 @@ pub const ExternallyInitialized = enum {
341517 writer: anytype,
342518 ) @TypeOf(writer).Error!void {
343519 if (self == .default) return;
344 try writer.writeAll(@tagName(self));
345520 try writer.writeByte(' ');
521 try writer.writeAll(@tagName(self));
346522 }
347523};
348524
......@@ -399,6 +575,7 @@ pub const Global = struct {
399575 }
400576
401577 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
578 assert(builder.useLibLlvm());
402579 return builder.llvm_globals.items[@intFromEnum(self)];
403580 }
404581
......@@ -517,7 +694,7 @@ pub fn init(self: *Builder) Allocator.Error!void {
517694 {
518695 const static_len = @typeInfo(Type).Enum.fields.len - 1;
519696 try self.type_map.ensureTotalCapacity(self.gpa, static_len);
520 try self.type_data.ensureTotalCapacity(self.gpa, static_len);
697 try self.type_items.ensureTotalCapacity(self.gpa, static_len);
521698 if (self.useLibLlvm()) try self.llvm_types.ensureTotalCapacity(self.gpa, static_len);
522699 inline for (@typeInfo(Type.Simple).Enum.fields) |simple_field| {
523700 const result = self.typeNoExtraAssumeCapacity(.{
......@@ -532,7 +709,7 @@ pub fn init(self: *Builder) Allocator.Error!void {
532709 inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits| assert(self.intTypeAssumeCapacity(bits) ==
533710 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
534711 inline for (.{0}) |addr_space|
535 assert(self.pointerTypeAssumeCapacity(@enumFromInt(addr_space)) == .ptr);
712 assert(self.ptrTypeAssumeCapacity(@enumFromInt(addr_space)) == .ptr);
536713 }
537714}
538715
......@@ -547,7 +724,7 @@ pub fn deinit(self: *Builder) void {
547724 self.types.deinit(self.gpa);
548725 self.next_unique_type_id.deinit(self.gpa);
549726 self.type_map.deinit(self.gpa);
550 self.type_data.deinit(self.gpa);
727 self.type_items.deinit(self.gpa);
551728 self.type_extra.deinit(self.gpa);
552729
553730 self.globals.deinit(self.gpa);
......@@ -600,25 +777,95 @@ pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args:
600777 return String.fromIndex(gop.index);
601778}
602779
780pub fn fnType(
781 self: *Builder,
782 ret: Type,
783 params: []const Type,
784 kind: Type.Function.Kind,
785) Allocator.Error!Type {
786 try self.ensureUnusedCapacityTypes(1, Type.Function, params.len);
787 return switch (kind) {
788 inline else => |comptime_kind| self.fnTypeAssumeCapacity(ret, params, comptime_kind),
789 };
790}
791
792pub fn intType(self: *Builder, bits: u24) Allocator.Error!Type {
793 try self.ensureUnusedCapacityTypes(1, null, 0);
794 return self.intTypeAssumeCapacity(bits);
795}
796
797pub fn ptrType(self: *Builder, addr_space: AddrSpace) Allocator.Error!Type {
798 try self.ensureUnusedCapacityTypes(1, null, 0);
799 return self.ptrTypeAssumeCapacity(addr_space);
800}
801
802pub fn vectorType(
803 self: *Builder,
804 kind: Type.Vector.Kind,
805 len: u32,
806 child: Type,
807) Allocator.Error!Type {
808 try self.ensureUnusedCapacityTypes(1, Type.Vector, 0);
809 return switch (kind) {
810 inline else => |comptime_kind| self.vectorTypeAssumeCapacity(comptime_kind, len, child),
811 };
812}
813
814pub fn arrayType(self: *Builder, len: u64, child: Type) Allocator.Error!Type {
815 comptime assert(@sizeOf(Type.Array) >= @sizeOf(Type.Vector));
816 try self.ensureUnusedCapacityTypes(1, Type.Array, 0);
817 return self.arrayTypeAssumeCapacity(len, child);
818}
819
820pub fn structType(
821 self: *Builder,
822 kind: Type.Structure.Kind,
823 fields: []const Type,
824) Allocator.Error!Type {
825 try self.ensureUnusedCapacityTypes(1, Type.Structure, fields.len);
826 return switch (kind) {
827 inline else => |comptime_kind| self.structTypeAssumeCapacity(comptime_kind, fields),
828 };
829}
830
603831pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type {
604832 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
605 try self.string_bytes.ensureUnusedCapacity(self.gpa, name.toSlice(self).?.len +
833 if (name.toSlice(self)) |id| try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len +
606834 comptime std.fmt.count("{d}" ++ .{0}, .{std.math.maxInt(u32)}));
607835 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
608836 try self.types.ensureUnusedCapacity(self.gpa, 1);
609837 try self.next_unique_type_id.ensureUnusedCapacity(self.gpa, 1);
610 try self.ensureUnusedCapacityTypes(1, Type.NamedStructure);
838 try self.ensureUnusedCapacityTypes(1, Type.NamedStructure, 0);
611839 return self.opaqueTypeAssumeCapacity(name);
612840}
613841
614pub fn intType(self: *Builder, bits: u24) Allocator.Error!Type {
615 try self.ensureUnusedCapacityTypes(1, null);
616 return self.intTypeAssumeCapacity(bits);
617}
618
619pub fn pointerType(self: *Builder, addr_space: AddrSpace) Allocator.Error!Type {
620 try self.ensureUnusedCapacityTypes(1, null);
621 return self.pointerTypeAssumeCapacity(addr_space);
842pub fn namedTypeSetBody(
843 self: *Builder,
844 named_type: Type,
845 body_type: Type,
846) if (build_options.have_llvm) Allocator.Error!void else void {
847 const named_item = self.type_items.items[@intFromEnum(named_type)];
848 self.type_extra.items[named_item.data + std.meta.fieldIndex(Type.NamedStructure, "body").?] =
849 @intFromEnum(body_type);
850 if (self.useLibLlvm()) {
851 const body_item = self.type_items.items[@intFromEnum(body_type)];
852 const body_extra = self.typeExtraDataTrail(Type.Structure, body_item.data);
853 const body_fields: []const Type =
854 @ptrCast(self.type_extra.items[body_extra.end..][0..body_extra.data.fields_len]);
855 const llvm_fields = try self.gpa.alloc(*llvm.Type, body_fields.len);
856 defer self.gpa.free(llvm_fields);
857 for (llvm_fields, body_fields) |*llvm_field, body_field|
858 llvm_field.* = self.llvm_types.items[@intFromEnum(body_field)];
859 self.llvm_types.items[@intFromEnum(named_type)].structSetBody(
860 llvm_fields.ptr,
861 @intCast(llvm_fields.len),
862 switch (body_item.tag) {
863 .structure => .False,
864 .packed_structure => .True,
865 else => unreachable,
866 },
867 );
868 }
622869}
623870
624871pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index {
......@@ -667,6 +914,7 @@ fn addTypeExtraAssumeCapacity(self: *Builder, extra: anytype) Type.ExtraIndex {
667914 inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| {
668915 const value = @field(extra, field.name);
669916 self.type_extra.appendAssumeCapacity(switch (field.type) {
917 u32 => value,
670918 String, Type => @intFromEnum(value),
671919 else => @compileError("bad field type: " ++ @typeName(field.type)),
672920 });
......@@ -683,6 +931,7 @@ fn typeExtraDataTrail(
683931 const fields = @typeInfo(T).Struct.fields;
684932 inline for (fields, self.type_extra.items[index..][0..fields.len]) |field, data|
685933 @field(result, field.name) = switch (field.type) {
934 u32 => data,
686935 String, Type => @enumFromInt(data),
687936 else => @compileError("bad field type: " ++ @typeName(field.type)),
688937 };
......@@ -693,14 +942,254 @@ fn typeExtraData(self: *const Builder, comptime T: type, index: Type.ExtraIndex)
693942 return self.typeExtraDataTrail(T, index).data;
694943}
695944
945fn fnTypeAssumeCapacity(
946 self: *Builder,
947 ret: Type,
948 params: []const Type,
949 comptime kind: Type.Function.Kind,
950) if (build_options.have_llvm) Allocator.Error!Type else Type {
951 const tag: Type.Tag = switch (kind) {
952 .normal => .function,
953 .vararg => .vararg_function,
954 };
955 const Key = struct { ret: Type, params: []const Type };
956 const Adapter = struct {
957 builder: *const Builder,
958 pub fn hash(_: @This(), key: Key) u32 {
959 var hasher = std.hash.Wyhash.init(comptime std.hash.uint32(@intFromEnum(tag)));
960 hasher.update(std.mem.asBytes(&key.ret));
961 hasher.update(std.mem.sliceAsBytes(key.params));
962 return @truncate(hasher.final());
963 }
964 pub fn eql(ctx: @This(), lhs: Key, _: void, rhs_index: usize) bool {
965 const rhs_data = ctx.builder.type_items.items[rhs_index];
966 const rhs_extra = ctx.builder.typeExtraDataTrail(Type.Function, rhs_data.data);
967 const rhs_params: []const Type =
968 @ptrCast(ctx.builder.type_extra.items[rhs_extra.end..][0..rhs_extra.data.params_len]);
969 return rhs_data.tag == tag and lhs.ret == rhs_extra.data.ret and
970 std.mem.eql(Type, lhs.params, rhs_params);
971 }
972 };
973 const data = Key{ .ret = ret, .params = params };
974 const gop = self.type_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
975 if (!gop.found_existing) {
976 gop.key_ptr.* = {};
977 gop.value_ptr.* = {};
978 self.type_items.appendAssumeCapacity(.{
979 .tag = .function,
980 .data = self.addTypeExtraAssumeCapacity(Type.Function{
981 .ret = ret,
982 .params_len = @intCast(params.len),
983 }),
984 });
985 self.type_extra.appendSliceAssumeCapacity(@ptrCast(params));
986 if (self.useLibLlvm()) {
987 const llvm_params = try self.gpa.alloc(*llvm.Type, params.len);
988 defer self.gpa.free(llvm_params);
989 for (llvm_params, params) |*llvm_param, param| llvm_param.* = param.toLlvm(self);
990 self.llvm_types.appendAssumeCapacity(llvm.functionType(
991 ret.toLlvm(self),
992 llvm_params.ptr,
993 @intCast(llvm_params.len),
994 switch (kind) {
995 .normal => .False,
996 .vararg => .True,
997 },
998 ));
999 }
1000 }
1001 return @enumFromInt(gop.index);
1002}
1003
1004fn intTypeAssumeCapacity(self: *Builder, bits: u24) Type {
1005 const result = self.typeNoExtraAssumeCapacity(.{ .tag = .integer, .data = bits });
1006 if (self.useLibLlvm() and result.new)
1007 self.llvm_types.appendAssumeCapacity(self.llvm_context.intType(bits));
1008 return result.type;
1009}
1010
1011fn ptrTypeAssumeCapacity(self: *Builder, addr_space: AddrSpace) Type {
1012 const result = self.typeNoExtraAssumeCapacity(.{
1013 .tag = .pointer,
1014 .data = @intFromEnum(addr_space),
1015 });
1016 if (self.useLibLlvm() and result.new)
1017 self.llvm_types.appendAssumeCapacity(self.llvm_context.pointerType(@intFromEnum(addr_space)));
1018 return result.type;
1019}
1020
1021fn vectorTypeAssumeCapacity(
1022 self: *Builder,
1023 comptime kind: Type.Vector.Kind,
1024 len: u32,
1025 child: Type,
1026) Type {
1027 const tag: Type.Tag = switch (kind) {
1028 .normal => .vector,
1029 .scalable => .scalable_vector,
1030 };
1031 const Adapter = struct {
1032 builder: *const Builder,
1033 pub fn hash(_: @This(), key: Type.Vector) u32 {
1034 return @truncate(std.hash.Wyhash.hash(
1035 comptime std.hash.uint32(@intFromEnum(tag)),
1036 std.mem.asBytes(&key),
1037 ));
1038 }
1039 pub fn eql(ctx: @This(), lhs: Type.Vector, _: void, rhs_index: usize) bool {
1040 const rhs_data = ctx.builder.type_items.items[rhs_index];
1041 return rhs_data.tag == tag and
1042 std.meta.eql(lhs, ctx.builder.typeExtraData(Type.Vector, rhs_data.data));
1043 }
1044 };
1045 const data = Type.Vector{ .len = len, .child = child };
1046 const gop = self.type_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1047 if (!gop.found_existing) {
1048 gop.key_ptr.* = {};
1049 gop.value_ptr.* = {};
1050 self.type_items.appendAssumeCapacity(.{
1051 .tag = tag,
1052 .data = self.addTypeExtraAssumeCapacity(data),
1053 });
1054 if (self.useLibLlvm()) self.llvm_types.appendAssumeCapacity(switch (kind) {
1055 .normal => &llvm.Type.vectorType,
1056 .scalable => &llvm.Type.scalableVectorType,
1057 }(child.toLlvm(self), @intCast(len)));
1058 }
1059 return @enumFromInt(gop.index);
1060}
1061
1062fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type {
1063 if (std.math.cast(u32, len)) |small_len| {
1064 const Adapter = struct {
1065 builder: *const Builder,
1066 pub fn hash(_: @This(), key: Type.Vector) u32 {
1067 return @truncate(std.hash.Wyhash.hash(
1068 comptime std.hash.uint32(@intFromEnum(Type.Tag.small_array)),
1069 std.mem.asBytes(&key),
1070 ));
1071 }
1072 pub fn eql(ctx: @This(), lhs: Type.Vector, _: void, rhs_index: usize) bool {
1073 const rhs_data = ctx.builder.type_items.items[rhs_index];
1074 return rhs_data.tag == .small_array and
1075 std.meta.eql(lhs, ctx.builder.typeExtraData(Type.Vector, rhs_data.data));
1076 }
1077 };
1078 const data = Type.Vector{ .len = small_len, .child = child };
1079 const gop = self.type_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1080 if (!gop.found_existing) {
1081 gop.key_ptr.* = {};
1082 gop.value_ptr.* = {};
1083 self.type_items.appendAssumeCapacity(.{
1084 .tag = .small_array,
1085 .data = self.addTypeExtraAssumeCapacity(data),
1086 });
1087 if (self.useLibLlvm()) self.llvm_types.appendAssumeCapacity(
1088 child.toLlvm(self).arrayType(@intCast(len)),
1089 );
1090 }
1091 return @enumFromInt(gop.index);
1092 } else {
1093 const Adapter = struct {
1094 builder: *const Builder,
1095 pub fn hash(_: @This(), key: Type.Array) u32 {
1096 return @truncate(std.hash.Wyhash.hash(
1097 comptime std.hash.uint32(@intFromEnum(Type.Tag.array)),
1098 std.mem.asBytes(&key),
1099 ));
1100 }
1101 pub fn eql(ctx: @This(), lhs: Type.Array, _: void, rhs_index: usize) bool {
1102 const rhs_data = ctx.builder.type_items.items[rhs_index];
1103 return rhs_data.tag == .array and
1104 std.meta.eql(lhs, ctx.builder.typeExtraData(Type.Array, rhs_data.data));
1105 }
1106 };
1107 const data = Type.Array{
1108 .len_lo = @truncate(len),
1109 .len_hi = @intCast(len >> 32),
1110 .child = child,
1111 };
1112 const gop = self.type_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1113 if (!gop.found_existing) {
1114 gop.key_ptr.* = {};
1115 gop.value_ptr.* = {};
1116 self.type_items.appendAssumeCapacity(.{
1117 .tag = .array,
1118 .data = self.addTypeExtraAssumeCapacity(data),
1119 });
1120 if (self.useLibLlvm()) self.llvm_types.appendAssumeCapacity(
1121 child.toLlvm(self).arrayType(@intCast(len)),
1122 );
1123 }
1124 return @enumFromInt(gop.index);
1125 }
1126}
1127
1128fn structTypeAssumeCapacity(
1129 self: *Builder,
1130 comptime kind: Type.Structure.Kind,
1131 fields: []const Type,
1132) if (build_options.have_llvm) Allocator.Error!Type else Type {
1133 const tag: Type.Tag = switch (kind) {
1134 .normal => .structure,
1135 .@"packed" => .packed_structure,
1136 };
1137 const Adapter = struct {
1138 builder: *const Builder,
1139 pub fn hash(_: @This(), key: []const Type) u32 {
1140 return @truncate(std.hash.Wyhash.hash(
1141 comptime std.hash.uint32(@intFromEnum(tag)),
1142 std.mem.sliceAsBytes(key),
1143 ));
1144 }
1145 pub fn eql(ctx: @This(), lhs: []const Type, _: void, rhs_index: usize) bool {
1146 const rhs_data = ctx.builder.type_items.items[rhs_index];
1147 const rhs_extra = ctx.builder.typeExtraDataTrail(Type.Structure, rhs_data.data);
1148 const rhs_fields: []const Type =
1149 @ptrCast(ctx.builder.type_extra.items[rhs_extra.end..][0..rhs_extra.data.fields_len]);
1150 return rhs_data.tag == tag and std.mem.eql(Type, lhs, rhs_fields);
1151 }
1152 };
1153 const gop = self.type_map.getOrPutAssumeCapacityAdapted(fields, Adapter{ .builder = self });
1154 if (!gop.found_existing) {
1155 gop.key_ptr.* = {};
1156 gop.value_ptr.* = {};
1157 self.type_items.appendAssumeCapacity(.{
1158 .tag = tag,
1159 .data = self.addTypeExtraAssumeCapacity(Type.Structure{
1160 .fields_len = @intCast(fields.len),
1161 }),
1162 });
1163 self.type_extra.appendSliceAssumeCapacity(@ptrCast(fields));
1164 if (self.useLibLlvm()) {
1165 const llvm_fields = try self.gpa.alloc(*llvm.Type, fields.len);
1166 defer self.gpa.free(llvm_fields);
1167 for (llvm_fields, fields) |*llvm_field, field|
1168 llvm_field.* = self.llvm_types.items[@intFromEnum(field)];
1169 self.llvm_types.appendAssumeCapacity(self.llvm_context.structType(
1170 llvm_fields.ptr,
1171 @intCast(llvm_fields.len),
1172 switch (kind) {
1173 .normal => .False,
1174 .@"packed" => .True,
1175 },
1176 ));
1177 }
1178 }
1179 return @enumFromInt(gop.index);
1180}
1181
6961182fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {
6971183 const Adapter = struct {
6981184 builder: *const Builder,
6991185 pub fn hash(_: @This(), key: String) u32 {
700 return std.hash.uint32(@intFromEnum(key));
1186 return @truncate(std.hash.Wyhash.hash(
1187 comptime std.hash.uint32(@intFromEnum(Type.Tag.named_structure)),
1188 std.mem.asBytes(&key),
1189 ));
7011190 }
7021191 pub fn eql(ctx: @This(), lhs: String, _: void, rhs_index: usize) bool {
703 const rhs_data = ctx.builder.type_data.items[rhs_index];
1192 const rhs_data = ctx.builder.type_items.items[rhs_index];
7041193 return rhs_data.tag == .named_structure and
7051194 lhs == ctx.builder.typeExtraData(Type.NamedStructure, rhs_data.data).id;
7061195 }
......@@ -718,11 +1207,11 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {
7181207 assert(!gop.found_existing);
7191208 gop.key_ptr.* = {};
7201209 gop.value_ptr.* = {};
721 self.type_data.appendAssumeCapacity(.{
1210 self.type_items.appendAssumeCapacity(.{
7221211 .tag = .named_structure,
7231212 .data = self.addTypeExtraAssumeCapacity(Type.NamedStructure{
7241213 .id = id,
725 .child = .none,
1214 .body = .none,
7261215 }),
7271216 });
7281217 const result: Type = @enumFromInt(gop.index);
......@@ -740,53 +1229,49 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {
7401229 }
7411230}
7421231
743fn intTypeAssumeCapacity(self: *Builder, bits: u24) Type {
744 const result = self.typeNoExtraAssumeCapacity(.{ .tag = .integer, .data = bits });
745 if (self.useLibLlvm() and result.new)
746 self.llvm_types.appendAssumeCapacity(self.llvm_context.intType(bits));
747 return result.type;
748}
749
750fn pointerTypeAssumeCapacity(self: *Builder, addr_space: AddrSpace) Type {
751 const result = self.typeNoExtraAssumeCapacity(.{ .tag = .pointer, .data = @intFromEnum(addr_space) });
752 if (self.useLibLlvm() and result.new)
753 self.llvm_types.appendAssumeCapacity(self.llvm_context.pointerType(@intFromEnum(addr_space)));
754 return result.type;
755}
756
757fn ensureUnusedCapacityTypes(self: *Builder, count: usize, comptime Extra: ?type) Allocator.Error!void {
1232fn ensureUnusedCapacityTypes(
1233 self: *Builder,
1234 count: usize,
1235 comptime Extra: ?type,
1236 trail_len: usize,
1237) Allocator.Error!void {
7581238 try self.type_map.ensureUnusedCapacity(self.gpa, count);
759 try self.type_data.ensureUnusedCapacity(self.gpa, count);
760 if (Extra) |E|
761 try self.type_extra.ensureUnusedCapacity(self.gpa, count * @typeInfo(E).Struct.fields.len);
1239 try self.type_items.ensureUnusedCapacity(self.gpa, count);
1240 if (Extra) |E| try self.type_extra.ensureUnusedCapacity(
1241 self.gpa,
1242 count * (@typeInfo(E).Struct.fields.len + trail_len),
1243 );
7621244 if (self.useLibLlvm()) try self.llvm_types.ensureUnusedCapacity(self.gpa, count);
7631245}
7641246
765fn typeNoExtraAssumeCapacity(self: *Builder, data: Type.Data) struct { new: bool, type: Type } {
1247fn typeNoExtraAssumeCapacity(self: *Builder, item: Type.Item) struct { new: bool, type: Type } {
7661248 const Adapter = struct {
7671249 builder: *const Builder,
768 pub fn hash(_: @This(), key: Type.Data) u32 {
769 return std.hash.uint32(@bitCast(key));
1250 pub fn hash(_: @This(), key: Type.Item) u32 {
1251 return @truncate(std.hash.Wyhash.hash(
1252 comptime std.hash.uint32(@intFromEnum(Type.Tag.simple)),
1253 std.mem.asBytes(&key),
1254 ));
7701255 }
771 pub fn eql(ctx: @This(), lhs: Type.Data, _: void, rhs_index: usize) bool {
1256 pub fn eql(ctx: @This(), lhs: Type.Item, _: void, rhs_index: usize) bool {
7721257 const lhs_bits: u32 = @bitCast(lhs);
773 const rhs_bits: u32 = @bitCast(ctx.builder.type_data.items[rhs_index]);
1258 const rhs_bits: u32 = @bitCast(ctx.builder.type_items.items[rhs_index]);
7741259 return lhs_bits == rhs_bits;
7751260 }
7761261 };
777 const gop = self.type_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1262 const gop = self.type_map.getOrPutAssumeCapacityAdapted(item, Adapter{ .builder = self });
7781263 if (!gop.found_existing) {
7791264 gop.key_ptr.* = {};
7801265 gop.value_ptr.* = {};
781 self.type_data.appendAssumeCapacity(data);
1266 self.type_items.appendAssumeCapacity(item);
7821267 }
7831268 return .{ .new = !gop.found_existing, .type = @enumFromInt(gop.index) };
7841269}
7851270
7861271fn isValidIdentifier(id: []const u8) bool {
787 for (id, 0..) |c, i| switch (c) {
1272 for (id, 0..) |character, index| switch (character) {
7881273 '$', '-', '.', 'A'...'Z', '_', 'a'...'z' => {},
789 '0'...'9' => if (i == 0) return false,
1274 '0'...'9' => if (index == 0) return false,
7901275 else => return false,
7911276 };
7921277 return true;
......@@ -815,7 +1300,7 @@ pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
8151300 for (self.objects.items) |object| {
8161301 const global = self.globals.entries.get(@intFromEnum(object.global));
8171302 try writer.print(
818 \\@{} = {}{}{}{}{}{}{}{}{s} {}{,}
1303 \\@{} ={}{}{}{}{}{}{}{} {s} {%}{,}
8191304 \\
8201305 , .{
8211306 global.key.fmt(self),
......@@ -836,8 +1321,8 @@ pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
8361321 for (self.functions.items) |function| {
8371322 const global = self.globals.entries.get(@intFromEnum(function.global));
8381323 try writer.print(
839 \\{s} {}{}{}{}void @{}() {}{}{{
840 \\ ret void
1324 \\{s} {}{}{}{}{<}@{}{>} {}{}{{
1325 \\ ret {%}
8411326 \\}}
8421327 \\
8431328 , .{
......@@ -846,9 +1331,15 @@ pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
8461331 global.value.preemption,
8471332 global.value.visibility,
8481333 global.value.dll_storage_class,
1334 global.value.type.fmt(self),
8491335 global.key.fmt(self),
1336 global.value.type.fmt(self),
8501337 global.value.unnamed_addr,
8511338 global.value.alignment,
1339 self.typeExtraData(
1340 Type.Function,
1341 self.type_items.items[@intFromEnum(global.value.type)].data,
1342 ).ret.fmt(self),
8521343 });
8531344 }
8541345 try writer.writeByte('\n');
src/codegen/llvm/bindings.zig+6-3
......@@ -317,6 +317,9 @@ pub const Type = opaque {
317317 pub const vectorType = LLVMVectorType;
318318 extern fn LLVMVectorType(ElementType: *Type, ElementCount: c_uint) *Type;
319319
320 pub const scalableVectorType = LLVMScalableVectorType;
321 extern fn LLVMScalableVectorType(ElementType: *Type, ElementCount: c_uint) *Type;
322
320323 pub const structSetBody = LLVMStructSetBody;
321324 extern fn LLVMStructSetBody(
322325 StructTy: *Type,
......@@ -1615,9 +1618,9 @@ pub const address_space = struct {
16151618
16161619 // See llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
16171620 pub const wasm = struct {
1618 pub const variable = 1;
1619 pub const externref = 10;
1620 pub const funcref = 20;
1621 pub const variable: c_uint = 1;
1622 pub const externref: c_uint = 10;
1623 pub const funcref: c_uint = 20;
16211624 };
16221625};
16231626