authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2024-02-29 19:59:55+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-25 22:58:47-07:00
logc231d94960ec2cecbea0de877f645ba5d439fd13
tree1773cde624c119ea7c476b76c2eaa830b137fd0c
parent3648d7df19642b6902b3f75538a826a322211673

LLVM: Remove deprecated or soon to be deprecated constant expressions


2 files changed, 182 insertions(+), 534 deletions(-)

src/codegen/llvm.zig+153-50
...@@ -3665,6 +3665,124 @@ pub const Object = struct {...@@ -3665,6 +3665,124 @@ pub const Object = struct {
3665 );3665 );
3666 }3666 }
36673667
3668 fn lowerValueToInt(o: *Object, llvm_int_ty: Builder.Type, arg_val: InternPool.Index) Error!Builder.Constant {
3669 const mod = o.module;
3670 const ip = &mod.intern_pool;
3671 const target = mod.getTarget();
3672
3673 const val = Value.fromInterned(arg_val);
3674 const val_key = ip.indexToKey(val.toIntern());
3675
3676 if (val.isUndefDeep(mod)) return o.builder.undefConst(llvm_int_ty);
3677
3678 const ty = Type.fromInterned(val_key.typeOf());
3679 switch (val_key) {
3680 .extern_func => |extern_func| {
3681 const fn_decl_index = extern_func.decl;
3682 const function_index = try o.resolveLlvmFunction(fn_decl_index);
3683 const ptr = function_index.ptrConst(&o.builder).global.toConst();
3684 return o.builder.convConst(ptr, llvm_int_ty);
3685 },
3686 .func => |func| {
3687 const fn_decl_index = func.owner_decl;
3688 const function_index = try o.resolveLlvmFunction(fn_decl_index);
3689 const ptr = function_index.ptrConst(&o.builder).global.toConst();
3690 return o.builder.convConst(ptr, llvm_int_ty);
3691 },
3692 .ptr => return o.builder.convConst(try o.lowerPtr(arg_val, 0), llvm_int_ty),
3693 .aggregate => switch (ip.indexToKey(ty.toIntern())) {
3694 .struct_type => {
3695 const struct_type = ip.loadStructType(ty.toIntern());
3696 assert(struct_type.haveLayout(ip));
3697 assert(struct_type.layout == .@"packed");
3698 comptime assert(Type.packed_struct_layout_version == 2);
3699 var running_int = try o.builder.intConst(llvm_int_ty, 0);
3700 var running_bits: u16 = 0;
3701 for (struct_type.field_types.get(ip), 0..) |field_ty, field_index| {
3702 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;
3703
3704 const shift_rhs = try o.builder.intConst(llvm_int_ty, running_bits);
3705 const field_val = try o.lowerValueToInt(llvm_int_ty, (try val.fieldValue(mod, field_index)).toIntern());
3706 const shifted = try o.builder.binConst(.shl, field_val, shift_rhs);
3707
3708 running_int = try o.builder.binConst(.xor, running_int, shifted);
3709
3710 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(mod));
3711 running_bits += ty_bit_size;
3712 }
3713 return running_int;
3714 },
3715 .vector_type => {},
3716 else => unreachable,
3717 },
3718 .un => |un| {
3719 const layout = ty.unionGetLayout(mod);
3720 if (layout.payload_size == 0) return o.lowerValue(un.tag);
3721
3722 const union_obj = mod.typeToUnion(ty).?;
3723 const container_layout = union_obj.getLayout(ip);
3724
3725 assert(container_layout == .@"packed");
3726
3727 var need_unnamed = false;
3728 if (un.tag == .none) {
3729 assert(layout.tag_size == 0);
3730 const union_val = try o.lowerValueToInt(llvm_int_ty, un.val);
3731
3732 need_unnamed = true;
3733 return union_val;
3734 }
3735 const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
3736 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
3737 if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(llvm_int_ty, 0);
3738 return o.lowerValueToInt(llvm_int_ty, un.val);
3739 },
3740 .simple_value => |simple_value| switch (simple_value) {
3741 .false, .true => {},
3742 else => unreachable,
3743 },
3744 .int,
3745 .float,
3746 .enum_tag,
3747 => {},
3748 else => unreachable,
3749 }
3750 const bits = ty.bitSize(mod);
3751 const bytes: usize = @intCast(std.mem.alignForward(u64, bits, 8) / 8);
3752
3753 var stack = std.heap.stackFallback(32, o.gpa);
3754 const allocator = stack.get();
3755
3756 const limbs = try allocator.alloc(
3757 std.math.big.Limb,
3758 std.mem.alignForward(usize, bytes, @sizeOf(std.math.big.Limb)) /
3759 @sizeOf(std.math.big.Limb),
3760 );
3761 defer allocator.free(limbs);
3762 @memset(limbs, 0);
3763
3764 val.writeToPackedMemory(
3765 ty,
3766 mod,
3767 std.mem.sliceAsBytes(limbs)[0..bytes],
3768 0,
3769 ) catch unreachable;
3770
3771 if (builtin.target.cpu.arch.endian() == .little) {
3772 if (target.cpu.arch.endian() == .big)
3773 std.mem.reverse(u8, std.mem.sliceAsBytes(limbs)[0..bytes]);
3774 } else if (target.cpu.arch.endian() == .little) {
3775 for (limbs) |*limb| {
3776 limb.* = std.mem.nativeToLittle(usize, limb.*);
3777 }
3778 }
3779
3780 return o.builder.bigIntConst(llvm_int_ty, .{
3781 .limbs = limbs,
3782 .positive = true,
3783 });
3784 }
3785
3668 fn lowerValue(o: *Object, arg_val: InternPool.Index) Error!Builder.Constant {3786 fn lowerValue(o: *Object, arg_val: InternPool.Index) Error!Builder.Constant {
3669 const mod = o.module;3787 const mod = o.module;
3670 const ip = &mod.intern_pool;3788 const ip = &mod.intern_pool;
...@@ -4022,28 +4140,11 @@ pub const Object = struct {...@@ -4022,28 +4140,11 @@ pub const Object = struct {
4022 const struct_ty = try o.lowerType(ty);4140 const struct_ty = try o.lowerType(ty);
4023 if (struct_type.layout == .@"packed") {4141 if (struct_type.layout == .@"packed") {
4024 comptime assert(Type.packed_struct_layout_version == 2);4142 comptime assert(Type.packed_struct_layout_version == 2);
4025 var running_int = try o.builder.intConst(struct_ty, 0);4143
4026 var running_bits: u16 = 0;4144 const bits = ty.bitSize(mod);
4027 for (struct_type.field_types.get(ip), 0..) |field_ty, field_index| {4145 const llvm_int_ty = try o.builder.intType(@intCast(bits));
4028 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;4146
40294147 return o.lowerValueToInt(llvm_int_ty, arg_val);
4030 const non_int_val =
4031 try o.lowerValue((try val.fieldValue(mod, field_index)).toIntern());
4032 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(mod));
4033 const small_int_ty = try o.builder.intType(ty_bit_size);
4034 const small_int_val = try o.builder.castConst(
4035 if (Type.fromInterned(field_ty).isPtrAtRuntime(mod)) .ptrtoint else .bitcast,
4036 non_int_val,
4037 small_int_ty,
4038 );
4039 const shift_rhs = try o.builder.intConst(struct_ty, running_bits);
4040 const extended_int_val =
4041 try o.builder.convConst(.unsigned, small_int_val, struct_ty);
4042 const shifted = try o.builder.binConst(.shl, extended_int_val, shift_rhs);
4043 running_int = try o.builder.binConst(.@"or", running_int, shifted);
4044 running_bits += ty_bit_size;
4045 }
4046 return running_int;
4047 }4148 }
4048 const llvm_len = struct_ty.aggregateLen(&o.builder);4149 const llvm_len = struct_ty.aggregateLen(&o.builder);
40494150
...@@ -4138,12 +4239,10 @@ pub const Object = struct {...@@ -4138,12 +4239,10 @@ pub const Object = struct {
4138 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);4239 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
4139 if (container_layout == .@"packed") {4240 if (container_layout == .@"packed") {
4140 if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(union_ty, 0);4241 if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(union_ty, 0);
4141 const small_int_val = try o.builder.castConst(4242 const bits = ty.bitSize(mod);
4142 if (field_ty.isPtrAtRuntime(mod)) .ptrtoint else .bitcast,4243 const llvm_int_ty = try o.builder.intType(@intCast(bits));
4143 try o.lowerValue(un.val),4244
4144 try o.builder.intType(@intCast(field_ty.bitSize(mod))),4245 return o.lowerValueToInt(llvm_int_ty, arg_val);
4145 );
4146 return o.builder.convConst(.unsigned, small_int_val, union_ty);
4147 }4246 }
41484247
4149 // Sometimes we must make an unnamed struct because LLVM does4248 // Sometimes we must make an unnamed struct because LLVM does
...@@ -4171,16 +4270,14 @@ pub const Object = struct {...@@ -4171,16 +4270,14 @@ pub const Object = struct {
4171 );4270 );
4172 } else p: {4271 } else p: {
4173 assert(layout.tag_size == 0);4272 assert(layout.tag_size == 0);
4174 const union_val = try o.lowerValue(un.val);
4175 if (container_layout == .@"packed") {4273 if (container_layout == .@"packed") {
4176 const bitcast_val = try o.builder.castConst(4274 const bits = ty.bitSize(mod);
4177 .bitcast,4275 const llvm_int_ty = try o.builder.intType(@intCast(bits));
4178 union_val,4276
4179 try o.builder.intType(@intCast(ty.bitSize(mod))),4277 return o.lowerValueToInt(llvm_int_ty, arg_val);
4180 );
4181 return o.builder.convConst(.unsigned, bitcast_val, union_ty);
4182 }4278 }
41834279
4280 const union_val = try o.lowerValue(un.val);
4184 need_unnamed = true;4281 need_unnamed = true;
4185 break :p union_val;4282 break :p union_val;
4186 };4283 };
...@@ -4316,12 +4413,11 @@ pub const Object = struct {...@@ -4316,12 +4413,11 @@ pub const Object = struct {
4316 const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global;4413 const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global;
43174414
4318 const llvm_val = try o.builder.convConst(4415 const llvm_val = try o.builder.convConst(
4319 .unneeded,
4320 llvm_global.toConst(),4416 llvm_global.toConst(),
4321 try o.builder.ptrType(llvm_addr_space),4417 try o.builder.ptrType(llvm_addr_space),
4322 );4418 );
43234419
4324 return o.builder.convConst(.unneeded, llvm_val, try o.lowerType(ptr_ty));4420 return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));
4325 }4421 }
43264422
4327 fn lowerDeclRefValue(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant {4423 fn lowerDeclRefValue(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant {
...@@ -4359,12 +4455,11 @@ pub const Object = struct {...@@ -4359,12 +4455,11 @@ pub const Object = struct {
4359 (try o.resolveGlobalDecl(decl_index)).ptrConst(&o.builder).global;4455 (try o.resolveGlobalDecl(decl_index)).ptrConst(&o.builder).global;
43604456
4361 const llvm_val = try o.builder.convConst(4457 const llvm_val = try o.builder.convConst(
4362 .unneeded,
4363 llvm_global.toConst(),4458 llvm_global.toConst(),
4364 try o.builder.ptrType(toLlvmAddressSpace(decl.@"addrspace", mod.getTarget())),4459 try o.builder.ptrType(toLlvmAddressSpace(decl.@"addrspace", mod.getTarget())),
4365 );4460 );
43664461
4367 return o.builder.convConst(.unneeded, llvm_val, try o.lowerType(ptr_ty));4462 return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));
4368 }4463 }
43694464
4370 fn lowerPtrToVoid(o: *Object, ptr_ty: Type) Allocator.Error!Builder.Constant {4465 fn lowerPtrToVoid(o: *Object, ptr_ty: Type) Allocator.Error!Builder.Constant {
...@@ -4750,7 +4845,6 @@ pub const FuncGen = struct {...@@ -4750,7 +4845,6 @@ pub const FuncGen = struct {
4750 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);4845 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4751 variable_index.setAlignment(ty.abiAlignment(mod).toLlvm(), &o.builder);4846 variable_index.setAlignment(ty.abiAlignment(mod).toLlvm(), &o.builder);
4752 return o.builder.convConst(4847 return o.builder.convConst(
4753 .unneeded,
4754 variable_index.toConst(&o.builder),4848 variable_index.toConst(&o.builder),
4755 try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),4849 try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),
4756 );4850 );
...@@ -10413,9 +10507,9 @@ pub const FuncGen = struct {...@@ -10413,9 +10507,9 @@ pub const FuncGen = struct {
1041310507
10414 const anded = if (workaround_explicit_mask and payload_llvm_ty != load_llvm_ty) blk: {10508 const anded = if (workaround_explicit_mask and payload_llvm_ty != load_llvm_ty) blk: {
10415 // this is rendundant with llvm.trunc. But without it, llvm17 emits invalid code for powerpc.10509 // this is rendundant with llvm.trunc. But without it, llvm17 emits invalid code for powerpc.
10416 var mask_val = try o.builder.intConst(payload_llvm_ty, -1);10510 const mask_val = try o.builder.intValue(payload_llvm_ty, -1);
10417 mask_val = try o.builder.castConst(.zext, mask_val, load_llvm_ty);10511 const zext_mask_val = try fg.wip.cast(.zext, mask_val, load_llvm_ty, "");
10418 break :blk try fg.wip.bin(.@"and", shifted, mask_val.toValue(), "");10512 break :blk try fg.wip.bin(.@"and", shifted, zext_mask_val, "");
10419 } else shifted;10513 } else shifted;
1042010514
10421 return fg.wip.conv(.unneeded, anded, payload_llvm_ty, "");10515 return fg.wip.conv(.unneeded, anded, payload_llvm_ty, "");
...@@ -10563,14 +10657,23 @@ pub const FuncGen = struct {...@@ -10563,14 +10657,23 @@ pub const FuncGen = struct {
10563 else10657 else
10564 try self.wip.cast(.bitcast, elem, value_bits_type, "");10658 try self.wip.cast(.bitcast, elem, value_bits_type, "");
1056510659
10566 var mask_val = try o.builder.intConst(value_bits_type, -1);10660 const mask_val = blk: {
10567 mask_val = try o.builder.castConst(.zext, mask_val, containing_int_ty);10661 const zext = try self.wip.cast(
10568 mask_val = try o.builder.binConst(.shl, mask_val, shift_amt);10662 .zext,
10569 mask_val =10663 try o.builder.intValue(value_bits_type, -1),
10570 try o.builder.binConst(.xor, mask_val, try o.builder.intConst(containing_int_ty, -1));10664 containing_int_ty,
10665 "",
10666 );
10667 const shl = try self.wip.bin(.shl, zext, shift_amt.toValue(), "");
10668 break :blk try self.wip.bin(
10669 .xor,
10670 shl,
10671 try o.builder.intValue(containing_int_ty, -1),
10672 "",
10673 );
10674 };
1057110675
10572 const anded_containing_int =10676 const anded_containing_int = try self.wip.bin(.@"and", containing_int, mask_val, "");
10573 try self.wip.bin(.@"and", containing_int, mask_val.toValue(), "");
10574 const extended_value = try self.wip.cast(.zext, value_bits, containing_int_ty, "");10677 const extended_value = try self.wip.cast(.zext, value_bits, containing_int_ty, "");
10575 const shifted_value = try self.wip.bin(.shl, extended_value, shift_amt.toValue(), "");10678 const shifted_value = try self.wip.bin(.shl, extended_value, shift_amt.toValue(), "");
10576 const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");10679 const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");
src/codegen/llvm/Builder.zig+29-484
...@@ -5694,7 +5694,7 @@ pub const WipFunction = struct {...@@ -5694,7 +5694,7 @@ pub const WipFunction = struct {
5694 ) Allocator.Error!Value {5694 ) Allocator.Error!Value {
5695 const val_ty = val.typeOfWip(self);5695 const val_ty = val.typeOfWip(self);
5696 if (val_ty == ty) return val;5696 if (val_ty == ty) return val;
5697 return self.cast(self.builder.convTag(Instruction.Tag, signedness, val_ty, ty), val, ty, name);5697 return self.cast(self.builder.convTag(signedness, val_ty, ty), val, ty, name);
5698 }5698 }
56995699
5700 pub fn cast(5700 pub fn cast(
...@@ -6891,39 +6891,19 @@ pub const Constant = enum(u32) {...@@ -6891,39 +6891,19 @@ pub const Constant = enum(u32) {
6891 dso_local_equivalent,6891 dso_local_equivalent,
6892 no_cfi,6892 no_cfi,
6893 trunc,6893 trunc,
6894 zext,
6895 sext,
6896 fptrunc,
6897 fpext,
6898 fptoui,
6899 fptosi,
6900 uitofp,
6901 sitofp,
6902 ptrtoint,6894 ptrtoint,
6903 inttoptr,6895 inttoptr,
6904 bitcast,6896 bitcast,
6905 addrspacecast,6897 addrspacecast,
6906 getelementptr,6898 getelementptr,
6907 @"getelementptr inbounds",6899 @"getelementptr inbounds",
6908 icmp,
6909 fcmp,
6910 extractelement,
6911 insertelement,
6912 shufflevector,
6913 add,6900 add,
6914 @"add nsw",6901 @"add nsw",
6915 @"add nuw",6902 @"add nuw",
6916 sub,6903 sub,
6917 @"sub nsw",6904 @"sub nsw",
6918 @"sub nuw",6905 @"sub nuw",
6919 mul,
6920 @"mul nsw",
6921 @"mul nuw",
6922 shl,6906 shl,
6923 lshr,
6924 ashr,
6925 @"and",
6926 @"or",
6927 xor,6907 xor,
6928 @"asm",6908 @"asm",
6929 @"asm sideeffect",6909 @"asm sideeffect",
...@@ -6952,15 +6932,7 @@ pub const Constant = enum(u32) {...@@ -6952,15 +6932,7 @@ pub const Constant = enum(u32) {
6952 .@"sub nsw",6932 .@"sub nsw",
6953 .@"sub nuw",6933 .@"sub nuw",
6954 => .sub,6934 => .sub,
6955 .mul,
6956 .@"mul nsw",
6957 .@"mul nuw",
6958 => .mul,
6959 .shl => .shl,6935 .shl => .shl,
6960 .lshr => .lshr,
6961 .ashr => .ashr,
6962 .@"and" => .@"and",
6963 .@"or" => .@"or",
6964 .xor => .xor,6936 .xor => .xor,
6965 else => unreachable,6937 else => unreachable,
6966 };6938 };
...@@ -6969,14 +6941,6 @@ pub const Constant = enum(u32) {...@@ -6969,14 +6941,6 @@ pub const Constant = enum(u32) {
6969 pub fn toCastOpcode(self: Tag) CastOpcode {6941 pub fn toCastOpcode(self: Tag) CastOpcode {
6970 return switch (self) {6942 return switch (self) {
6971 .trunc => .trunc,6943 .trunc => .trunc,
6972 .zext => .zext,
6973 .sext => .sext,
6974 .fptoui => .fptoui,
6975 .fptosi => .fptosi,
6976 .uitofp => .uitofp,
6977 .sitofp => .sitofp,
6978 .fptrunc => .fptrunc,
6979 .fpext => .fpext,
6980 .ptrtoint => .ptrtoint,6944 .ptrtoint => .ptrtoint,
6981 .inttoptr => .inttoptr,6945 .inttoptr => .inttoptr,
6982 .bitcast => .bitcast,6946 .bitcast => .bitcast,
...@@ -7051,29 +7015,6 @@ pub const Constant = enum(u32) {...@@ -7051,29 +7015,6 @@ pub const Constant = enum(u32) {
7051 pub const Info = packed struct(u32) { indices_len: u16, inrange: InRangeIndex };7015 pub const Info = packed struct(u32) { indices_len: u16, inrange: InRangeIndex };
7052 };7016 };
70537017
7054 pub const Compare = extern struct {
7055 cond: u32,
7056 lhs: Constant,
7057 rhs: Constant,
7058 };
7059
7060 pub const ExtractElement = extern struct {
7061 val: Constant,
7062 index: Constant,
7063 };
7064
7065 pub const InsertElement = extern struct {
7066 val: Constant,
7067 elem: Constant,
7068 index: Constant,
7069 };
7070
7071 pub const ShuffleVector = extern struct {
7072 lhs: Constant,
7073 rhs: Constant,
7074 mask: Constant,
7075 };
7076
7077 pub const Binary = extern struct {7018 pub const Binary = extern struct {
7078 lhs: Constant,7019 lhs: Constant,
7079 rhs: Constant,7020 rhs: Constant,
...@@ -7149,14 +7090,6 @@ pub const Constant = enum(u32) {...@@ -7149,14 +7090,6 @@ pub const Constant = enum(u32) {
7149 => builder.ptrTypeAssumeCapacity(@as(Function.Index, @enumFromInt(item.data))7090 => builder.ptrTypeAssumeCapacity(@as(Function.Index, @enumFromInt(item.data))
7150 .ptrConst(builder).global.ptrConst(builder).addr_space),7091 .ptrConst(builder).global.ptrConst(builder).addr_space),
7151 .trunc,7092 .trunc,
7152 .zext,
7153 .sext,
7154 .fptrunc,
7155 .fpext,
7156 .fptoui,
7157 .fptosi,
7158 .uitofp,
7159 .sitofp,
7160 .ptrtoint,7093 .ptrtoint,
7161 .inttoptr,7094 .inttoptr,
7162 .bitcast,7095 .bitcast,
...@@ -7176,35 +7109,13 @@ pub const Constant = enum(u32) {...@@ -7176,35 +7109,13 @@ pub const Constant = enum(u32) {
7176 };7109 };
7177 return base_ty;7110 return base_ty;
7178 },7111 },
7179 .icmp,
7180 .fcmp,
7181 => builder.constantExtraData(Compare, item.data).lhs.typeOf(builder)
7182 .changeScalarAssumeCapacity(.i1, builder),
7183 .extractelement => builder.constantExtraData(ExtractElement, item.data)
7184 .val.typeOf(builder).childType(builder),
7185 .insertelement => builder.constantExtraData(InsertElement, item.data)
7186 .val.typeOf(builder),
7187 .shufflevector => {
7188 const extra = builder.constantExtraData(ShuffleVector, item.data);
7189 return extra.lhs.typeOf(builder).changeLengthAssumeCapacity(
7190 extra.mask.typeOf(builder).vectorLen(builder),
7191 builder,
7192 );
7193 },
7194 .add,7112 .add,
7195 .@"add nsw",7113 .@"add nsw",
7196 .@"add nuw",7114 .@"add nuw",
7197 .sub,7115 .sub,
7198 .@"sub nsw",7116 .@"sub nsw",
7199 .@"sub nuw",7117 .@"sub nuw",
7200 .mul,
7201 .@"mul nsw",
7202 .@"mul nuw",
7203 .shl,7118 .shl,
7204 .lshr,
7205 .ashr,
7206 .@"and",
7207 .@"or",
7208 .xor,7119 .xor,
7209 => builder.constantExtraData(Binary, item.data).lhs.typeOf(builder),7120 => builder.constantExtraData(Binary, item.data).lhs.typeOf(builder),
7210 .@"asm",7121 .@"asm",
...@@ -7516,14 +7427,6 @@ pub const Constant = enum(u32) {...@@ -7516,14 +7427,6 @@ pub const Constant = enum(u32) {
7516 });7427 });
7517 },7428 },
7518 .trunc,7429 .trunc,
7519 .zext,
7520 .sext,
7521 .fptrunc,
7522 .fpext,
7523 .fptoui,
7524 .fptosi,
7525 .uitofp,
7526 .sitofp,
7527 .ptrtoint,7430 .ptrtoint,
7528 .inttoptr,7431 .inttoptr,
7529 .bitcast,7432 .bitcast,
...@@ -7550,61 +7453,13 @@ pub const Constant = enum(u32) {...@@ -7550,61 +7453,13 @@ pub const Constant = enum(u32) {
7550 for (indices) |index| try writer.print(", {%}", .{index.fmt(data.builder)});7453 for (indices) |index| try writer.print(", {%}", .{index.fmt(data.builder)});
7551 try writer.writeByte(')');7454 try writer.writeByte(')');
7552 },7455 },
7553 inline .icmp,
7554 .fcmp,
7555 => |tag| {
7556 const extra = data.builder.constantExtraData(Compare, item.data);
7557 try writer.print("{s} {s} ({%}, {%})", .{
7558 @tagName(tag),
7559 @tagName(@as(switch (tag) {
7560 .icmp => IntegerCondition,
7561 .fcmp => FloatCondition,
7562 else => unreachable,
7563 }, @enumFromInt(extra.cond))),
7564 extra.lhs.fmt(data.builder),
7565 extra.rhs.fmt(data.builder),
7566 });
7567 },
7568 .extractelement => |tag| {
7569 const extra = data.builder.constantExtraData(ExtractElement, item.data);
7570 try writer.print("{s} ({%}, {%})", .{
7571 @tagName(tag),
7572 extra.val.fmt(data.builder),
7573 extra.index.fmt(data.builder),
7574 });
7575 },
7576 .insertelement => |tag| {
7577 const extra = data.builder.constantExtraData(InsertElement, item.data);
7578 try writer.print("{s} ({%}, {%}, {%})", .{
7579 @tagName(tag),
7580 extra.val.fmt(data.builder),
7581 extra.elem.fmt(data.builder),
7582 extra.index.fmt(data.builder),
7583 });
7584 },
7585 .shufflevector => |tag| {
7586 const extra = data.builder.constantExtraData(ShuffleVector, item.data);
7587 try writer.print("{s} ({%}, {%}, {%})", .{
7588 @tagName(tag),
7589 extra.lhs.fmt(data.builder),
7590 extra.rhs.fmt(data.builder),
7591 extra.mask.fmt(data.builder),
7592 });
7593 },
7594 .add,7456 .add,
7595 .@"add nsw",7457 .@"add nsw",
7596 .@"add nuw",7458 .@"add nuw",
7597 .sub,7459 .sub,
7598 .@"sub nsw",7460 .@"sub nsw",
7599 .@"sub nuw",7461 .@"sub nuw",
7600 .mul,
7601 .@"mul nsw",
7602 .@"mul nuw",
7603 .shl,7462 .shl,
7604 .lshr,
7605 .ashr,
7606 .@"and",
7607 .@"or",
7608 .xor,7463 .xor,
7609 => |tag| {7464 => |tag| {
7610 const extra = data.builder.constantExtraData(Binary, item.data);7465 const extra = data.builder.constantExtraData(Binary, item.data);
...@@ -9278,21 +9133,19 @@ pub fn noCfiValue(self: *Builder, function: Function.Index) Allocator.Error!Valu...@@ -9278,21 +9133,19 @@ pub fn noCfiValue(self: *Builder, function: Function.Index) Allocator.Error!Valu
92789133
9279pub fn convConst(9134pub fn convConst(
9280 self: *Builder,9135 self: *Builder,
9281 signedness: Constant.Cast.Signedness,
9282 val: Constant,9136 val: Constant,
9283 ty: Type,9137 ty: Type,
9284) Allocator.Error!Constant {9138) Allocator.Error!Constant {
9285 try self.ensureUnusedConstantCapacity(1, Constant.Cast, 0);9139 try self.ensureUnusedConstantCapacity(1, Constant.Cast, 0);
9286 return self.convConstAssumeCapacity(signedness, val, ty);9140 return self.convConstAssumeCapacity(val, ty);
9287}9141}
92889142
9289pub fn convValue(9143pub fn convValue(
9290 self: *Builder,9144 self: *Builder,
9291 signedness: Constant.Cast.Signedness,
9292 val: Constant,9145 val: Constant,
9293 ty: Type,9146 ty: Type,
9294) Allocator.Error!Value {9147) Allocator.Error!Value {
9295 return (try self.convConst(signedness, val, ty)).toValue();9148 return (try self.convConst(val, ty)).toValue();
9296}9149}
92979150
9298pub fn castConst(self: *Builder, tag: Constant.Tag, val: Constant, ty: Type) Allocator.Error!Constant {9151pub fn castConst(self: *Builder, tag: Constant.Tag, val: Constant, ty: Type) Allocator.Error!Constant {
...@@ -9328,92 +9181,6 @@ pub fn gepValue(...@@ -9328,92 +9181,6 @@ pub fn gepValue(
9328 return (try self.gepConst(kind, ty, base, inrange, indices)).toValue();9181 return (try self.gepConst(kind, ty, base, inrange, indices)).toValue();
9329}9182}
93309183
9331pub fn icmpConst(
9332 self: *Builder,
9333 cond: IntegerCondition,
9334 lhs: Constant,
9335 rhs: Constant,
9336) Allocator.Error!Constant {
9337 try self.ensureUnusedConstantCapacity(1, Constant.Compare, 0);
9338 return self.icmpConstAssumeCapacity(cond, lhs, rhs);
9339}
9340
9341pub fn icmpValue(
9342 self: *Builder,
9343 cond: IntegerCondition,
9344 lhs: Constant,
9345 rhs: Constant,
9346) Allocator.Error!Value {
9347 return (try self.icmpConst(cond, lhs, rhs)).toValue();
9348}
9349
9350pub fn fcmpConst(
9351 self: *Builder,
9352 cond: FloatCondition,
9353 lhs: Constant,
9354 rhs: Constant,
9355) Allocator.Error!Constant {
9356 try self.ensureUnusedConstantCapacity(1, Constant.Compare, 0);
9357 return self.icmpConstAssumeCapacity(cond, lhs, rhs);
9358}
9359
9360pub fn fcmpValue(
9361 self: *Builder,
9362 cond: FloatCondition,
9363 lhs: Constant,
9364 rhs: Constant,
9365) Allocator.Error!Value {
9366 return (try self.fcmpConst(cond, lhs, rhs)).toValue();
9367}
9368
9369pub fn extractElementConst(self: *Builder, val: Constant, index: Constant) Allocator.Error!Constant {
9370 try self.ensureUnusedConstantCapacity(1, Constant.ExtractElement, 0);
9371 return self.extractElementConstAssumeCapacity(val, index);
9372}
9373
9374pub fn extractElementValue(self: *Builder, val: Constant, index: Constant) Allocator.Error!Value {
9375 return (try self.extractElementConst(val, index)).toValue();
9376}
9377
9378pub fn insertElementConst(
9379 self: *Builder,
9380 val: Constant,
9381 elem: Constant,
9382 index: Constant,
9383) Allocator.Error!Constant {
9384 try self.ensureUnusedConstantCapacity(1, Constant.InsertElement, 0);
9385 return self.insertElementConstAssumeCapacity(val, elem, index);
9386}
9387
9388pub fn insertElementValue(
9389 self: *Builder,
9390 val: Constant,
9391 elem: Constant,
9392 index: Constant,
9393) Allocator.Error!Value {
9394 return (try self.insertElementConst(val, elem, index)).toValue();
9395}
9396
9397pub fn shuffleVectorConst(
9398 self: *Builder,
9399 lhs: Constant,
9400 rhs: Constant,
9401 mask: Constant,
9402) Allocator.Error!Constant {
9403 try self.ensureUnusedTypeCapacity(1, Type.Array, 0);
9404 try self.ensureUnusedConstantCapacity(1, Constant.ShuffleVector, 0);
9405 return self.shuffleVectorConstAssumeCapacity(lhs, rhs, mask);
9406}
9407
9408pub fn shuffleVectorValue(
9409 self: *Builder,
9410 lhs: Constant,
9411 rhs: Constant,
9412 mask: Constant,
9413) Allocator.Error!Value {
9414 return (try self.shuffleVectorConst(lhs, rhs, mask)).toValue();
9415}
9416
9417pub fn binConst(9184pub fn binConst(
9418 self: *Builder,9185 self: *Builder,
9419 tag: Constant.Tag,9186 tag: Constant.Tag,
...@@ -11390,11 +11157,10 @@ fn noCfiConstAssumeCapacity(self: *Builder, function: Function.Index) Constant {...@@ -11390,11 +11157,10 @@ fn noCfiConstAssumeCapacity(self: *Builder, function: Function.Index) Constant {
1139011157
11391fn convTag(11158fn convTag(
11392 self: *Builder,11159 self: *Builder,
11393 comptime Tag: type,
11394 signedness: Constant.Cast.Signedness,11160 signedness: Constant.Cast.Signedness,
11395 val_ty: Type,11161 val_ty: Type,
11396 ty: Type,11162 ty: Type,
11397) Tag {11163) Function.Instruction.Tag {
11398 assert(val_ty != ty);11164 assert(val_ty != ty);
11399 return switch (val_ty.scalarTag(self)) {11165 return switch (val_ty.scalarTag(self)) {
11400 .simple => switch (ty.scalarTag(self)) {11166 .simple => switch (ty.scalarTag(self)) {
...@@ -11437,15 +11203,38 @@ fn convTag(...@@ -11437,15 +11203,38 @@ fn convTag(
11437 };11203 };
11438}11204}
1143911205
11206fn convConstTag(
11207 self: *Builder,
11208 val_ty: Type,
11209 ty: Type,
11210) Constant.Tag {
11211 assert(val_ty != ty);
11212 return switch (val_ty.scalarTag(self)) {
11213 .integer => switch (ty.scalarTag(self)) {
11214 .integer => switch (std.math.order(val_ty.scalarBits(self), ty.scalarBits(self))) {
11215 .gt => .trunc,
11216 else => unreachable,
11217 },
11218 .pointer => .inttoptr,
11219 else => unreachable,
11220 },
11221 .pointer => switch (ty.scalarTag(self)) {
11222 .integer => .ptrtoint,
11223 .pointer => .addrspacecast,
11224 else => unreachable,
11225 },
11226 else => unreachable,
11227 };
11228}
11229
11440fn convConstAssumeCapacity(11230fn convConstAssumeCapacity(
11441 self: *Builder,11231 self: *Builder,
11442 signedness: Constant.Cast.Signedness,
11443 val: Constant,11232 val: Constant,
11444 ty: Type,11233 ty: Type,
11445) Constant {11234) Constant {
11446 const val_ty = val.typeOf(self);11235 const val_ty = val.typeOf(self);
11447 if (val_ty == ty) return val;11236 if (val_ty == ty) return val;
11448 return self.castConstAssumeCapacity(self.convTag(Constant.Tag, signedness, val_ty, ty), val, ty);11237 return self.castConstAssumeCapacity(self.convConstTag(val_ty, ty), val, ty);
11449}11238}
1145011239
11451fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: Type) Constant {11240fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: Type) Constant {
...@@ -11570,179 +11359,6 @@ fn gepConstAssumeCapacity(...@@ -11570,179 +11359,6 @@ fn gepConstAssumeCapacity(
11570 return @enumFromInt(gop.index);11359 return @enumFromInt(gop.index);
11571}11360}
1157211361
11573fn icmpConstAssumeCapacity(
11574 self: *Builder,
11575 cond: IntegerCondition,
11576 lhs: Constant,
11577 rhs: Constant,
11578) Constant {
11579 const Adapter = struct {
11580 builder: *const Builder,
11581 pub fn hash(_: @This(), key: Constant.Compare) u32 {
11582 return @truncate(std.hash.Wyhash.hash(
11583 std.hash.uint32(@intFromEnum(Constant.tag.icmp)),
11584 std.mem.asBytes(&key),
11585 ));
11586 }
11587 pub fn eql(ctx: @This(), lhs_key: Constant.Compare, _: void, rhs_index: usize) bool {
11588 if (ctx.builder.constant_items.items(.tag)[rhs_index] != .icmp) return false;
11589 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
11590 const rhs_extra = ctx.builder.constantExtraData(Constant.Compare, rhs_data);
11591 return std.meta.eql(lhs_key, rhs_extra);
11592 }
11593 };
11594 const data = Constant.Compare{ .cond = @intFromEnum(cond), .lhs = lhs, .rhs = rhs };
11595 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
11596 if (!gop.found_existing) {
11597 gop.key_ptr.* = {};
11598 gop.value_ptr.* = {};
11599 self.constant_items.appendAssumeCapacity(.{
11600 .tag = .icmp,
11601 .data = self.addConstantExtraAssumeCapacity(data),
11602 });
11603 }
11604 return @enumFromInt(gop.index);
11605}
11606
11607fn fcmpConstAssumeCapacity(
11608 self: *Builder,
11609 cond: FloatCondition,
11610 lhs: Constant,
11611 rhs: Constant,
11612) Constant {
11613 const Adapter = struct {
11614 builder: *const Builder,
11615 pub fn hash(_: @This(), key: Constant.Compare) u32 {
11616 return @truncate(std.hash.Wyhash.hash(
11617 std.hash.uint32(@intFromEnum(Constant.tag.fcmp)),
11618 std.mem.asBytes(&key),
11619 ));
11620 }
11621 pub fn eql(ctx: @This(), lhs_key: Constant.Compare, _: void, rhs_index: usize) bool {
11622 if (ctx.builder.constant_items.items(.tag)[rhs_index] != .fcmp) return false;
11623 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
11624 const rhs_extra = ctx.builder.constantExtraData(Constant.Compare, rhs_data);
11625 return std.meta.eql(lhs_key, rhs_extra);
11626 }
11627 };
11628 const data = Constant.Compare{ .cond = @intFromEnum(cond), .lhs = lhs, .rhs = rhs };
11629 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
11630 if (!gop.found_existing) {
11631 gop.key_ptr.* = {};
11632 gop.value_ptr.* = {};
11633 self.constant_items.appendAssumeCapacity(.{
11634 .tag = .fcmp,
11635 .data = self.addConstantExtraAssumeCapacity(data),
11636 });
11637 }
11638 return @enumFromInt(gop.index);
11639}
11640
11641fn extractElementConstAssumeCapacity(
11642 self: *Builder,
11643 val: Constant,
11644 index: Constant,
11645) Constant {
11646 const Adapter = struct {
11647 builder: *const Builder,
11648 pub fn hash(_: @This(), key: Constant.ExtractElement) u32 {
11649 return @truncate(std.hash.Wyhash.hash(
11650 comptime std.hash.uint32(@intFromEnum(Constant.Tag.extractelement)),
11651 std.mem.asBytes(&key),
11652 ));
11653 }
11654 pub fn eql(ctx: @This(), lhs_key: Constant.ExtractElement, _: void, rhs_index: usize) bool {
11655 if (ctx.builder.constant_items.items(.tag)[rhs_index] != .extractelement) return false;
11656 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
11657 const rhs_extra = ctx.builder.constantExtraData(Constant.ExtractElement, rhs_data);
11658 return std.meta.eql(lhs_key, rhs_extra);
11659 }
11660 };
11661 const data = Constant.ExtractElement{ .val = val, .index = index };
11662 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
11663 if (!gop.found_existing) {
11664 gop.key_ptr.* = {};
11665 gop.value_ptr.* = {};
11666 self.constant_items.appendAssumeCapacity(.{
11667 .tag = .extractelement,
11668 .data = self.addConstantExtraAssumeCapacity(data),
11669 });
11670 }
11671 return @enumFromInt(gop.index);
11672}
11673
11674fn insertElementConstAssumeCapacity(
11675 self: *Builder,
11676 val: Constant,
11677 elem: Constant,
11678 index: Constant,
11679) Constant {
11680 const Adapter = struct {
11681 builder: *const Builder,
11682 pub fn hash(_: @This(), key: Constant.InsertElement) u32 {
11683 return @truncate(std.hash.Wyhash.hash(
11684 comptime std.hash.uint32(@intFromEnum(Constant.Tag.insertelement)),
11685 std.mem.asBytes(&key),
11686 ));
11687 }
11688 pub fn eql(ctx: @This(), lhs_key: Constant.InsertElement, _: void, rhs_index: usize) bool {
11689 if (ctx.builder.constant_items.items(.tag)[rhs_index] != .insertelement) return false;
11690 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
11691 const rhs_extra = ctx.builder.constantExtraData(Constant.InsertElement, rhs_data);
11692 return std.meta.eql(lhs_key, rhs_extra);
11693 }
11694 };
11695 const data = Constant.InsertElement{ .val = val, .elem = elem, .index = index };
11696 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
11697 if (!gop.found_existing) {
11698 gop.key_ptr.* = {};
11699 gop.value_ptr.* = {};
11700 self.constant_items.appendAssumeCapacity(.{
11701 .tag = .insertelement,
11702 .data = self.addConstantExtraAssumeCapacity(data),
11703 });
11704 }
11705 return @enumFromInt(gop.index);
11706}
11707
11708fn shuffleVectorConstAssumeCapacity(
11709 self: *Builder,
11710 lhs: Constant,
11711 rhs: Constant,
11712 mask: Constant,
11713) Constant {
11714 assert(lhs.typeOf(self).isVector(self.builder));
11715 assert(lhs.typeOf(self) == rhs.typeOf(self));
11716 assert(mask.typeOf(self).scalarType(self).isInteger(self));
11717 _ = lhs.typeOf(self).changeLengthAssumeCapacity(mask.typeOf(self).vectorLen(self), self);
11718 const Adapter = struct {
11719 builder: *const Builder,
11720 pub fn hash(_: @This(), key: Constant.ShuffleVector) u32 {
11721 return @truncate(std.hash.Wyhash.hash(
11722 comptime std.hash.uint32(@intFromEnum(Constant.Tag.shufflevector)),
11723 std.mem.asBytes(&key),
11724 ));
11725 }
11726 pub fn eql(ctx: @This(), lhs_key: Constant.ShuffleVector, _: void, rhs_index: usize) bool {
11727 if (ctx.builder.constant_items.items(.tag)[rhs_index] != .shufflevector) return false;
11728 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
11729 const rhs_extra = ctx.builder.constantExtraData(Constant.ShuffleVector, rhs_data);
11730 return std.meta.eql(lhs_key, rhs_extra);
11731 }
11732 };
11733 const data = Constant.ShuffleVector{ .lhs = lhs, .rhs = rhs, .mask = mask };
11734 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
11735 if (!gop.found_existing) {
11736 gop.key_ptr.* = {};
11737 gop.value_ptr.* = {};
11738 self.constant_items.appendAssumeCapacity(.{
11739 .tag = .shufflevector,
11740 .data = self.addConstantExtraAssumeCapacity(data),
11741 });
11742 }
11743 return @enumFromInt(gop.index);
11744}
11745
11746fn binConstAssumeCapacity(11362fn binConstAssumeCapacity(
11747 self: *Builder,11363 self: *Builder,
11748 tag: Constant.Tag,11364 tag: Constant.Tag,
...@@ -11756,14 +11372,7 @@ fn binConstAssumeCapacity(...@@ -11756,14 +11372,7 @@ fn binConstAssumeCapacity(
11756 .sub,11372 .sub,
11757 .@"sub nsw",11373 .@"sub nsw",
11758 .@"sub nuw",11374 .@"sub nuw",
11759 .mul,
11760 .@"mul nsw",
11761 .@"mul nuw",
11762 .shl,11375 .shl,
11763 .lshr,
11764 .ashr,
11765 .@"and",
11766 .@"or",
11767 .xor,11376 .xor,
11768 => {},11377 => {},
11769 else => unreachable,11378 else => unreachable,
...@@ -13938,16 +13547,8 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co...@@ -13938,16 +13547,8 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
13938 .bitcast,13547 .bitcast,
13939 .inttoptr,13548 .inttoptr,
13940 .ptrtoint,13549 .ptrtoint,
13941 .fptosi,
13942 .fptoui,
13943 .sitofp,
13944 .uitofp,
13945 .addrspacecast,13550 .addrspacecast,
13946 .fptrunc,
13947 .trunc,13551 .trunc,
13948 .fpext,
13949 .sext,
13950 .zext,
13951 => |tag| {13552 => |tag| {
13952 const extra = self.constantExtraData(Constant.Cast, data);13553 const extra = self.constantExtraData(Constant.Cast, data);
13953 try constants_block.writeAbbrevAdapted(Constants.Cast{13554 try constants_block.writeAbbrevAdapted(Constants.Cast{
...@@ -13962,14 +13563,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co...@@ -13962,14 +13563,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
13962 .sub,13563 .sub,
13963 .@"sub nsw",13564 .@"sub nsw",
13964 .@"sub nuw",13565 .@"sub nuw",
13965 .mul,
13966 .@"mul nsw",
13967 .@"mul nuw",
13968 .shl,13566 .shl,
13969 .lshr,
13970 .ashr,
13971 .@"and",
13972 .@"or",
13973 .xor,13567 .xor,
13974 => |tag| {13568 => |tag| {
13975 const extra = self.constantExtraData(Constant.Binary, data);13569 const extra = self.constantExtraData(Constant.Binary, data);
...@@ -13979,55 +13573,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co...@@ -13979,55 +13573,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
13979 .rhs = extra.rhs,13573 .rhs = extra.rhs,
13980 }, constant_adapter);13574 }, constant_adapter);
13981 },13575 },
13982 .icmp,
13983 .fcmp,
13984 => {
13985 const extra = self.constantExtraData(Constant.Compare, data);
13986 try constants_block.writeAbbrevAdapted(Constants.Cmp{
13987 .ty = extra.lhs.typeOf(self),
13988 .lhs = extra.lhs,
13989 .rhs = extra.rhs,
13990 .pred = extra.cond,
13991 }, constant_adapter);
13992 },
13993 .extractelement => {
13994 const extra = self.constantExtraData(Constant.ExtractElement, data);
13995 try constants_block.writeAbbrevAdapted(Constants.ExtractElement{
13996 .val_type = extra.val.typeOf(self),
13997 .val = extra.val,
13998 .index_type = extra.index.typeOf(self),
13999 .index = extra.index,
14000 }, constant_adapter);
14001 },
14002 .insertelement => {
14003 const extra = self.constantExtraData(Constant.InsertElement, data);
14004 try constants_block.writeAbbrevAdapted(Constants.InsertElement{
14005 .val = extra.val,
14006 .elem = extra.elem,
14007 .index_type = extra.index.typeOf(self),
14008 .index = extra.index,
14009 }, constant_adapter);
14010 },
14011 .shufflevector => {
14012 const extra = self.constantExtraData(Constant.ShuffleVector, data);
14013 const ty = constant.typeOf(self);
14014 const lhs_type = extra.lhs.typeOf(self);
14015 // Check if instruction is widening, truncating or not
14016 if (ty == lhs_type) {
14017 try constants_block.writeAbbrevAdapted(Constants.ShuffleVector{
14018 .lhs = extra.lhs,
14019 .rhs = extra.rhs,
14020 .mask = extra.mask,
14021 }, constant_adapter);
14022 } else {
14023 try constants_block.writeAbbrevAdapted(Constants.ShuffleVectorEx{
14024 .ty = ty,
14025 .lhs = extra.lhs,
14026 .rhs = extra.rhs,
14027 .mask = extra.mask,
14028 }, constant_adapter);
14029 }
14030 },
14031 .getelementptr,13576 .getelementptr,
14032 .@"getelementptr inbounds",13577 .@"getelementptr inbounds",
14033 => |tag| {13578 => |tag| {