authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-11 23:02:18-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-19 23:38:40-04:00
log8fde3a8f04e393b05879aff7afb9b09aadb4f2e1
tree2628676ca535e6d436b012419809fb5d36103475
parent1f8407c356b5cdc9eca0f2403a85d863744cf279

llvm: finish converting constants


2 files changed, 333 insertions(+), 255 deletions(-)

src/codegen/llvm.zig+159-200
......@@ -8,7 +8,10 @@ const native_endian = builtin.cpu.arch.endian();
88const DW = std.dwarf;
99
1010const Builder = @import("llvm/Builder.zig");
11const llvm = @import("llvm/bindings.zig");
11const llvm = if (build_options.have_llvm)
12 @import("llvm/bindings.zig")
13else
14 @compileError("LLVM unavailable");
1215const link = @import("../link.zig");
1316const Compilation = @import("../Compilation.zig");
1417const build_options = @import("build_options");
......@@ -577,7 +580,7 @@ pub const Object = struct {
577580 extern_collisions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void),
578581
579582 /// Memoizes a null `?usize` value.
580 null_opt_addr: ?*llvm.Value,
583 null_opt_usize: Builder.Constant,
581584
582585 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);
583586
......@@ -733,7 +736,7 @@ pub const Object = struct {
733736 .di_type_map = .{},
734737 .error_name_table = .none,
735738 .extern_collisions = .{},
736 .null_opt_addr = null,
739 .null_opt_usize = .no_init,
737740 };
738741 }
739742
......@@ -789,31 +792,31 @@ pub const Object = struct {
789792 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_nts));
790793 const str_init = try o.builder.stringNullConst(name);
791794 const str_ty = str_init.typeOf(&o.builder);
792 const str_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");
793 str_global.setInitializer(str_init.toLlvm(&o.builder));
794 str_global.setLinkage(.Private);
795 str_global.setGlobalConstant(.True);
796 str_global.setUnnamedAddr(.True);
797 str_global.setAlignment(1);
798
799 var global = Builder.Global{
795 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");
796 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));
797 str_llvm_global.setLinkage(.Private);
798 str_llvm_global.setGlobalConstant(.True);
799 str_llvm_global.setUnnamedAddr(.True);
800 str_llvm_global.setAlignment(1);
801
802 var str_global = Builder.Global{
800803 .linkage = .private,
801804 .unnamed_addr = .unnamed_addr,
802805 .type = str_ty,
803806 .alignment = comptime Builder.Alignment.fromByteUnits(1),
804807 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
805808 };
806 var variable = Builder.Variable{
809 var str_variable = Builder.Variable{
807810 .global = @enumFromInt(o.builder.globals.count()),
808811 .mutability = .constant,
809812 .init = str_init,
810813 };
811 try o.builder.llvm.globals.append(o.gpa, str_global);
812 const str_global_index = try o.builder.addGlobal(.empty, global);
813 try o.builder.variables.append(o.gpa, variable);
814 try o.builder.llvm.globals.append(o.gpa, str_llvm_global);
815 const global_index = try o.builder.addGlobal(.empty, str_global);
816 try o.builder.variables.append(o.gpa, str_variable);
814817
815818 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
816 str_global_index.toConst(),
819 global_index.toConst(),
817820 try o.builder.intConst(llvm_usize_ty, name.toSlice(&o.builder).?.len),
818821 });
819822 }
......@@ -2684,55 +2687,6 @@ pub const Object = struct {
26842687 return buffer.toOwnedSliceSentinel(0);
26852688 }
26862689
2687 fn getNullOptAddr(o: *Object) !*llvm.Value {
2688 if (o.null_opt_addr) |global| return global;
2689
2690 const mod = o.module;
2691 const target = mod.getTarget();
2692 const ty = try mod.intern(.{ .opt_type = .usize_type });
2693
2694 const llvm_init = try o.lowerValue(try mod.intern(.{ .opt = .{
2695 .ty = ty,
2696 .val = .none,
2697 } }));
2698 const llvm_ty = llvm_init.typeOf(&o.builder);
2699 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);
2700 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);
2701 const llvm_alignment = ty.toType().abiAlignment(mod);
2702 const llvm_global = o.llvm_module.addGlobalInAddressSpace(
2703 llvm_ty.toLlvm(&o.builder),
2704 "",
2705 @intFromEnum(llvm_actual_addrspace),
2706 );
2707 llvm_global.setLinkage(.Internal);
2708 llvm_global.setUnnamedAddr(.True);
2709 llvm_global.setAlignment(llvm_alignment);
2710 llvm_global.setInitializer(llvm_init.toLlvm(&o.builder));
2711
2712 var global = Builder.Global{
2713 .linkage = .internal,
2714 .unnamed_addr = .unnamed_addr,
2715 .type = llvm_ty,
2716 .alignment = Builder.Alignment.fromByteUnits(llvm_alignment),
2717 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
2718 };
2719 var variable = Builder.Variable{
2720 .global = @enumFromInt(o.builder.globals.count()),
2721 .init = llvm_init,
2722 };
2723 try o.builder.llvm.globals.append(o.gpa, llvm_global);
2724 _ = try o.builder.addGlobal(.empty, global);
2725 try o.builder.variables.append(o.gpa, variable);
2726
2727 const addrspace_casted_global = if (llvm_wanted_addrspace != llvm_actual_addrspace)
2728 llvm_global.constAddrSpaceCast((try o.builder.ptrType(llvm_wanted_addrspace)).toLlvm(&o.builder))
2729 else
2730 llvm_global;
2731
2732 o.null_opt_addr = addrspace_casted_global;
2733 return addrspace_casted_global;
2734 }
2735
27362690 /// If the llvm function does not exist, create it.
27372691 /// Note that this can be called before the function's semantic analysis has
27382692 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.
......@@ -3755,25 +3709,34 @@ pub const Object = struct {
37553709 },
37563710 },
37573711 .vector_type => |vector_type| {
3758 const ExpectedContents = [Builder.expected_fields_len]Builder.Constant;
3759 var stack align(@max(
3760 @alignOf(std.heap.StackFallbackAllocator(0)),
3761 @alignOf(ExpectedContents),
3762 )) = std.heap.stackFallback(@sizeOf(ExpectedContents), o.gpa);
3763 const allocator = stack.get();
3764 const vals = try allocator.alloc(Builder.Constant, vector_type.len);
3765 defer allocator.free(vals);
3766
3712 const vector_ty = try o.lowerType(ty);
37673713 switch (aggregate.storage) {
3768 .bytes => |bytes| for (vals, bytes) |*result_val, byte| {
3769 result_val.* = try o.builder.intConst(.i8, byte);
3770 },
3771 .elems => |elems| for (vals, elems) |*result_val, elem| {
3772 result_val.* = try o.lowerValue(elem);
3714 .bytes, .elems => {
3715 const ExpectedContents = [Builder.expected_fields_len]Builder.Constant;
3716 var stack align(@max(
3717 @alignOf(std.heap.StackFallbackAllocator(0)),
3718 @alignOf(ExpectedContents),
3719 )) = std.heap.stackFallback(@sizeOf(ExpectedContents), o.gpa);
3720 const allocator = stack.get();
3721 const vals = try allocator.alloc(Builder.Constant, vector_type.len);
3722 defer allocator.free(vals);
3723
3724 switch (aggregate.storage) {
3725 .bytes => |bytes| for (vals, bytes) |*result_val, byte| {
3726 result_val.* = try o.builder.intConst(.i8, byte);
3727 },
3728 .elems => |elems| for (vals, elems) |*result_val, elem| {
3729 result_val.* = try o.lowerValue(elem);
3730 },
3731 .repeated_elem => unreachable,
3732 }
3733 return o.builder.vectorConst(vector_ty, vals);
37733734 },
3774 .repeated_elem => |elem| @memset(vals, try o.lowerValue(elem)),
3735 .repeated_elem => |elem| return o.builder.splatConst(
3736 vector_ty,
3737 try o.lowerValue(elem),
3738 ),
37753739 }
3776 return o.builder.vectorConst(try o.lowerType(ty), vals);
37773740 },
37783741 .anon_struct_type => |tuple| {
37793742 const struct_ty = try o.lowerType(ty);
......@@ -4209,14 +4172,11 @@ pub const Object = struct {
42094172 else
42104173 (try o.resolveGlobalDecl(decl_index)).ptrConst(&o.builder).global;
42114174
4212 const target = mod.getTarget();
4213 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
4214 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
4215 const llvm_val = if (llvm_wanted_addrspace != llvm_actual_addrspace) try o.builder.castConst(
4216 .addrspacecast,
4175 const llvm_val = try o.builder.convConst(
4176 .unneeded,
42174177 llvm_global.toConst(),
4218 try o.builder.ptrType(llvm_wanted_addrspace),
4219 ) else llvm_global.toConst();
4178 try o.builder.ptrType(toLlvmAddressSpace(decl.@"addrspace", mod.getTarget())),
4179 );
42204180
42214181 return o.builder.convConst(if (ty.isAbiInt(mod)) switch (ty.intInfo(mod).signedness) {
42224182 .signed => .signed,
......@@ -4618,15 +4578,15 @@ pub const FuncGen = struct {
46184578 .ty = self.typeOf(inst),
46194579 .val = (try self.air.value(inst, mod)).?,
46204580 });
4621 gop.value_ptr.* = llvm_val;
4622 return llvm_val;
4581 gop.value_ptr.* = llvm_val.toLlvm(&o.builder);
4582 return gop.value_ptr.*;
46234583 }
46244584
4625 fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value {
4585 fn resolveValue(self: *FuncGen, tv: TypedValue) Error!Builder.Constant {
46264586 const o = self.dg.object;
46274587 const mod = o.module;
46284588 const llvm_val = try o.lowerValue(tv.val.toIntern());
4629 if (!isByRef(tv.ty, mod)) return llvm_val.toLlvm(&o.builder);
4589 if (!isByRef(tv.ty, mod)) return llvm_val;
46304590
46314591 // We have an LLVM value but we need to create a global constant and
46324592 // set the value as its initializer, and then return a pointer to the global.
......@@ -4645,6 +4605,7 @@ pub const FuncGen = struct {
46454605 var global = Builder.Global{
46464606 .linkage = .private,
46474607 .unnamed_addr = .unnamed_addr,
4608 .addr_space = llvm_actual_addrspace,
46484609 .type = llvm_ty,
46494610 .alignment = Builder.Alignment.fromByteUnits(llvm_alignment),
46504611 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
......@@ -4655,16 +4616,27 @@ pub const FuncGen = struct {
46554616 .init = llvm_val,
46564617 };
46574618 try o.builder.llvm.globals.append(o.gpa, llvm_global);
4658 _ = try o.builder.addGlobal(.empty, global);
4619 const global_index = try o.builder.addGlobal(.empty, global);
46594620 try o.builder.variables.append(o.gpa, variable);
46604621
4661 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)
4662 llvm_global.constAddrSpaceCast(
4663 (try o.builder.ptrType(llvm_wanted_addrspace)).toLlvm(&o.builder),
4664 )
4665 else
4666 llvm_global;
4667 return addrspace_casted_ptr;
4622 return try o.builder.convConst(
4623 .unneeded,
4624 global_index.toConst(),
4625 try o.builder.ptrType(llvm_wanted_addrspace),
4626 );
4627 }
4628
4629 fn resolveNullOptUsize(self: *FuncGen) Error!Builder.Constant {
4630 const o = self.dg.object;
4631 const mod = o.module;
4632 if (o.null_opt_usize == .no_init) {
4633 const ty = try mod.intern(.{ .opt_type = .usize_type });
4634 o.null_opt_usize = try self.resolveValue(.{
4635 .ty = ty.toType(),
4636 .val = (try mod.intern(.{ .opt = .{ .ty = ty, .val = .none } })).toValue(),
4637 });
4638 }
4639 return o.null_opt_usize;
46684640 }
46694641
46704642 fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void {
......@@ -5243,7 +5215,7 @@ pub const FuncGen = struct {
52435215 const msg_decl = mod.declPtr(msg_decl_index);
52445216 const msg_len = msg_decl.ty.childType(mod).arrayLen(mod);
52455217 const msg_ptr = try o.lowerValue(try msg_decl.internValue(mod));
5246 const null_opt_addr_global = try o.getNullOptAddr();
5218 const null_opt_addr_global = try fg.resolveNullOptUsize();
52475219 const target = mod.getTarget();
52485220 const llvm_usize = try o.lowerType(Type.usize);
52495221 // example:
......@@ -5257,7 +5229,7 @@ pub const FuncGen = struct {
52575229 msg_ptr.toLlvm(&o.builder),
52585230 (try o.builder.intConst(llvm_usize, msg_len)).toLlvm(&o.builder),
52595231 (try o.builder.nullConst(.ptr)).toLlvm(&o.builder),
5260 null_opt_addr_global,
5232 null_opt_addr_global.toLlvm(&o.builder),
52615233 };
52625234 const panic_func = mod.funcInfo(mod.panic_func_index);
52635235 const panic_decl = mod.declPtr(panic_func.owner_decl);
......@@ -6872,11 +6844,11 @@ pub const FuncGen = struct {
68726844 const operand = try self.resolveInst(un_op);
68736845 const operand_ty = self.typeOf(un_op);
68746846 const optional_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6875 const optional_llvm_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder);
6847 const optional_llvm_ty = try o.lowerType(optional_ty);
68766848 const payload_ty = optional_ty.optionalChild(mod);
68776849 if (optional_ty.optionalReprIsPayload(mod)) {
68786850 const loaded = if (operand_is_ptr)
6879 self.builder.buildLoad(optional_llvm_ty, operand, "")
6851 self.builder.buildLoad(optional_llvm_ty.toLlvm(&o.builder), operand, "")
68806852 else
68816853 operand;
68826854 if (payload_ty.isSlice(mod)) {
......@@ -6887,21 +6859,21 @@ pub const FuncGen = struct {
68876859 ));
68886860 return self.builder.buildICmp(pred, slice_ptr, (try o.builder.nullConst(ptr_ty)).toLlvm(&o.builder), "");
68896861 }
6890 return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), "");
6862 return self.builder.buildICmp(pred, loaded, (try o.builder.zeroInitConst(optional_llvm_ty)).toLlvm(&o.builder), "");
68916863 }
68926864
68936865 comptime assert(optional_layout_version == 3);
68946866
68956867 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
68966868 const loaded = if (operand_is_ptr)
6897 self.builder.buildLoad(optional_llvm_ty, operand, "")
6869 self.builder.buildLoad(optional_llvm_ty.toLlvm(&o.builder), operand, "")
68986870 else
68996871 operand;
69006872 return self.builder.buildICmp(pred, loaded, (try o.builder.intConst(.i8, 0)).toLlvm(&o.builder), "");
69016873 }
69026874
69036875 const is_by_ref = operand_is_ptr or isByRef(optional_ty, mod);
6904 const non_null_bit = try self.optIsNonNull(optional_llvm_ty, operand, is_by_ref);
6876 const non_null_bit = try self.optIsNonNull(optional_llvm_ty.toLlvm(&o.builder), operand, is_by_ref);
69056877 if (pred == .EQ) {
69066878 return self.builder.buildNot(non_null_bit, "");
69076879 } else {
......@@ -7549,24 +7521,18 @@ pub const FuncGen = struct {
75497521 }
75507522 if (scalar_ty.isSignedInt(mod)) {
75517523 const inst_llvm_ty = try o.lowerType(inst_ty);
7552 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
7553 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
7554 const vec_len = inst_ty.vectorLen(mod);
7555
7556 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
7557 defer self.gpa.free(shifts);
7558
7559 @memset(shifts, (try o.builder.intConst(try o.lowerType(scalar_ty), scalar_bit_size_minus_one)).toLlvm(&o.builder));
7560 break :const_vector llvm.constVector(shifts.ptr, vec_len);
7561 } else (try o.builder.intConst(inst_llvm_ty, scalar_bit_size_minus_one)).toLlvm(&o.builder);
7524 const bit_size_minus_one = try o.builder.splatConst(inst_llvm_ty, try o.builder.intConst(
7525 inst_llvm_ty.scalarType(&o.builder),
7526 inst_llvm_ty.scalarBits(&o.builder) - 1,
7527 ));
75627528
75637529 const div = self.builder.buildSDiv(lhs, rhs, "");
75647530 const rem = self.builder.buildSRem(lhs, rhs, "");
75657531 const div_sign = self.builder.buildXor(lhs, rhs, "");
7566 const div_sign_mask = self.builder.buildAShr(div_sign, bit_size_minus_one, "");
7567 const zero = inst_llvm_ty.toLlvm(&o.builder).constNull();
7568 const rem_nonzero = self.builder.buildICmp(.NE, rem, zero, "");
7569 const correction = self.builder.buildSelect(rem_nonzero, div_sign_mask, zero, "");
7532 const div_sign_mask = self.builder.buildAShr(div_sign, bit_size_minus_one.toLlvm(&o.builder), "");
7533 const zero = try o.builder.zeroInitConst(inst_llvm_ty);
7534 const rem_nonzero = self.builder.buildICmp(.NE, rem, zero.toLlvm(&o.builder), "");
7535 const correction = self.builder.buildSelect(rem_nonzero, div_sign_mask, zero.toLlvm(&o.builder), "");
75707536 return self.builder.buildNSWAdd(div, correction, "");
75717537 }
75727538 return self.builder.buildUDiv(lhs, rhs, "");
......@@ -7620,29 +7586,23 @@ pub const FuncGen = struct {
76207586 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });
76217587 const b = try self.buildFloatOp(.add, inst_ty, 2, .{ a, rhs });
76227588 const c = try self.buildFloatOp(.fmod, inst_ty, 2, .{ b, rhs });
7623 const zero = inst_llvm_ty.toLlvm(&o.builder).constNull();
7624 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });
7589 const zero = try o.builder.zeroInitConst(inst_llvm_ty);
7590 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero.toLlvm(&o.builder) });
76257591 return self.builder.buildSelect(ltz, c, a, "");
76267592 }
76277593 if (scalar_ty.isSignedInt(mod)) {
7628 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
7629 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
7630 const vec_len = inst_ty.vectorLen(mod);
7631
7632 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
7633 defer self.gpa.free(shifts);
7634
7635 @memset(shifts, (try o.builder.intConst(try o.lowerType(scalar_ty), scalar_bit_size_minus_one)).toLlvm(&o.builder));
7636 break :const_vector llvm.constVector(shifts.ptr, vec_len);
7637 } else (try o.builder.intConst(inst_llvm_ty, scalar_bit_size_minus_one)).toLlvm(&o.builder);
7594 const bit_size_minus_one = try o.builder.splatConst(inst_llvm_ty, try o.builder.intConst(
7595 inst_llvm_ty.scalarType(&o.builder),
7596 inst_llvm_ty.scalarBits(&o.builder) - 1,
7597 ));
76387598
76397599 const rem = self.builder.buildSRem(lhs, rhs, "");
76407600 const div_sign = self.builder.buildXor(lhs, rhs, "");
7641 const div_sign_mask = self.builder.buildAShr(div_sign, bit_size_minus_one, "");
7601 const div_sign_mask = self.builder.buildAShr(div_sign, bit_size_minus_one.toLlvm(&o.builder), "");
76427602 const rhs_masked = self.builder.buildAnd(rhs, div_sign_mask, "");
7643 const zero = inst_llvm_ty.toLlvm(&o.builder).constNull();
7644 const rem_nonzero = self.builder.buildICmp(.NE, rem, zero, "");
7645 const correction = self.builder.buildSelect(rem_nonzero, rhs_masked, zero, "");
7603 const zero = try o.builder.zeroInitConst(inst_llvm_ty);
7604 const rem_nonzero = self.builder.buildICmp(.NE, rem, zero.toLlvm(&o.builder), "");
7605 const correction = self.builder.buildSelect(rem_nonzero, rhs_masked, zero.toLlvm(&o.builder), "");
76467606 return self.builder.buildNSWAdd(rem, correction, "");
76477607 }
76487608 return self.builder.buildURem(lhs, rhs, "");
......@@ -7953,17 +7913,17 @@ pub const FuncGen = struct {
79537913 // In this case we can generate a softfloat negation by XORing the
79547914 // bits with a constant.
79557915 const int_ty = try o.builder.intType(@intCast(float_bits));
7956 const one = (try o.builder.intConst(int_ty, 1)).toLlvm(&o.builder);
7916 const one = try o.builder.intConst(int_ty, 1);
79577917 const shift_amt = try o.builder.intConst(int_ty, float_bits - 1);
7958 const sign_mask = one.constShl(shift_amt.toLlvm(&o.builder));
7918 const sign_mask = try o.builder.binConst(.shl, one, shift_amt);
79597919 const result = if (ty.zigTypeTag(mod) == .Vector) blk: {
7960 const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(mod), sign_mask, "");
7920 const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(mod), sign_mask.toLlvm(&o.builder), "");
79617921 const cast_ty = try o.builder.vectorType(.normal, ty.vectorLen(mod), int_ty);
79627922 const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty.toLlvm(&o.builder), "");
79637923 break :blk self.builder.buildXor(bitcasted_operand, splat_sign_mask, "");
79647924 } else blk: {
79657925 const bitcasted_operand = self.builder.buildBitCast(params[0], int_ty.toLlvm(&o.builder), "");
7966 break :blk self.builder.buildXor(bitcasted_operand, sign_mask, "");
7926 break :blk self.builder.buildXor(bitcasted_operand, sign_mask.toLlvm(&o.builder), "");
79677927 };
79687928 return self.builder.buildBitCast(result, llvm_ty.toLlvm(&o.builder), "");
79697929 },
......@@ -8886,9 +8846,9 @@ pub const FuncGen = struct {
88868846 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
88878847
88888848 if (intrinsic_len0_traps) {
8889 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile);
8849 try self.safeWasmMemset(dest_ptr, fill_byte.toLlvm(&o.builder), len, dest_ptr_align, is_volatile);
88908850 } else {
8891 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile);
8851 _ = self.builder.buildMemSet(dest_ptr, fill_byte.toLlvm(&o.builder), len, dest_ptr_align, is_volatile);
88928852 }
88938853 return null;
88948854 }
......@@ -8987,8 +8947,9 @@ pub const FuncGen = struct {
89878947 dest_ptr_align: u32,
89888948 is_volatile: bool,
89898949 ) !void {
8990 const llvm_usize_ty = self.context.intType(self.dg.object.target.ptrBitWidth());
8991 const cond = try self.cmp(len, llvm_usize_ty.constInt(0, .False), Type.usize, .neq);
8950 const o = self.dg.object;
8951 const llvm_usize_ty = try o.lowerType(Type.usize);
8952 const cond = try self.cmp(len, (try o.builder.intConst(llvm_usize_ty, 0)).toLlvm(&o.builder), Type.usize, .neq);
89928953 const memset_block = self.context.appendBasicBlock(self.llvm_func, "MemsetTrapSkip");
89938954 const end_block = self.context.appendBasicBlock(self.llvm_func, "MemsetTrapEnd");
89948955 _ = self.builder.buildCondBr(cond, memset_block, end_block);
......@@ -9020,8 +8981,8 @@ pub const FuncGen = struct {
90208981 std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and
90218982 dest_ptr_ty.isSlice(mod))
90228983 {
9023 const llvm_usize_ty = self.context.intType(self.dg.object.target.ptrBitWidth());
9024 const cond = try self.cmp(len, llvm_usize_ty.constInt(0, .False), Type.usize, .neq);
8984 const llvm_usize_ty = try o.lowerType(Type.usize);
8985 const cond = try self.cmp(len, (try o.builder.intConst(llvm_usize_ty, 0)).toLlvm(&o.builder), Type.usize, .neq);
90258986 const memcpy_block = self.context.appendBasicBlock(self.llvm_func, "MemcpyTrapSkip");
90268987 const end_block = self.context.appendBasicBlock(self.llvm_func, "MemcpyTrapEnd");
90278988 _ = self.builder.buildCondBr(cond, memcpy_block, end_block);
......@@ -9183,19 +9144,13 @@ pub const FuncGen = struct {
91839144 if (operand_ty.zigTypeTag(mod) == .Vector) {
91849145 const vec_len = operand_ty.vectorLen(mod);
91859146 operand_llvm_ty = try o.builder.vectorType(.normal, vec_len, scalar_ty);
9147 } else operand_llvm_ty = scalar_ty;
91869148
9187 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
9188 defer self.gpa.free(shifts);
9189 @memset(shifts, (try o.builder.intConst(scalar_ty, 8)).toLlvm(&o.builder));
9190 const shift_vec = llvm.constVector(shifts.ptr, vec_len);
9149 const shift_amt =
9150 try o.builder.splatConst(operand_llvm_ty, try o.builder.intConst(scalar_ty, 8));
9151 const extended = self.builder.buildZExt(operand, operand_llvm_ty.toLlvm(&o.builder), "");
9152 operand = self.builder.buildShl(extended, shift_amt.toLlvm(&o.builder), "");
91919153
9192 const extended = self.builder.buildZExt(operand, operand_llvm_ty.toLlvm(&o.builder), "");
9193 operand = self.builder.buildShl(extended, shift_vec, "");
9194 } else {
9195 const extended = self.builder.buildZExt(operand, scalar_ty.toLlvm(&o.builder), "");
9196 operand = self.builder.buildShl(extended, (try o.builder.intConst(scalar_ty, 8)).toLlvm(&o.builder), "");
9197 operand_llvm_ty = scalar_ty;
9198 }
91999154 bits = bits + 8;
92009155 }
92019156
......@@ -9358,11 +9313,8 @@ pub const FuncGen = struct {
93589313 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
93599314 const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)});
93609315
9361 const slice_ty = Type.slice_const_u8_sentinel_0;
9362 const ret_ty = try o.lowerType(slice_ty);
9363 const llvm_ret_ty = ret_ty.toLlvm(&o.builder);
9316 const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
93649317 const usize_ty = try o.lowerType(Type.usize);
9365 const slice_alignment = slice_ty.abiAlignment(mod);
93669318
93679319 const fn_type = try o.builder.fnType(ret_ty, &.{
93689320 try o.lowerType(enum_type.tag_ty.toType()),
......@@ -9399,33 +9351,38 @@ pub const FuncGen = struct {
93999351 const tag_int_value = fn_val.getParam(0);
94009352 const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block, @as(c_uint, @intCast(enum_type.names.len)));
94019353
9402 const array_ptr_indices: [2]*llvm.Value = .{
9403 (try o.builder.intConst(usize_ty, 0)).toLlvm(&o.builder),
9404 } ** 2;
9405
94069354 for (enum_type.names, 0..) |name_ip, field_index_usize| {
94079355 const field_index = @as(u32, @intCast(field_index_usize));
9408 const name = mod.intern_pool.stringToSlice(name_ip);
9409 const str_init = self.context.constString(name.ptr, @as(c_uint, @intCast(name.len)), .False);
9410 const str_init_llvm_ty = str_init.typeOf();
9411 const str_global = o.llvm_module.addGlobal(str_init_llvm_ty, "");
9412 str_global.setInitializer(str_init);
9413 str_global.setLinkage(.Private);
9414 str_global.setGlobalConstant(.True);
9415 str_global.setUnnamedAddr(.True);
9416 str_global.setAlignment(1);
9417
9418 const slice_fields = [_]*llvm.Value{
9419 str_init_llvm_ty.constInBoundsGEP(str_global, &array_ptr_indices, array_ptr_indices.len),
9420 (try o.builder.intConst(usize_ty, name.len)).toLlvm(&o.builder),
9356 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_ip));
9357 const str_init = try o.builder.stringNullConst(name);
9358 const str_ty = str_init.typeOf(&o.builder);
9359 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");
9360 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));
9361 str_llvm_global.setLinkage(.Private);
9362 str_llvm_global.setGlobalConstant(.True);
9363 str_llvm_global.setUnnamedAddr(.True);
9364 str_llvm_global.setAlignment(1);
9365
9366 var str_global = Builder.Global{
9367 .linkage = .private,
9368 .unnamed_addr = .unnamed_addr,
9369 .type = str_ty,
9370 .alignment = comptime Builder.Alignment.fromByteUnits(1),
9371 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
94219372 };
9422 const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len);
9423 const slice_global = o.llvm_module.addGlobal(slice_init.typeOf(), "");
9424 slice_global.setInitializer(slice_init);
9425 slice_global.setLinkage(.Private);
9426 slice_global.setGlobalConstant(.True);
9427 slice_global.setUnnamedAddr(.True);
9428 slice_global.setAlignment(slice_alignment);
9373 var str_variable = Builder.Variable{
9374 .global = @enumFromInt(o.builder.globals.count()),
9375 .mutability = .constant,
9376 .init = str_init,
9377 };
9378 try o.builder.llvm.globals.append(o.gpa, str_llvm_global);
9379 const global_index = try o.builder.addGlobal(.empty, str_global);
9380 try o.builder.variables.append(o.gpa, str_variable);
9381
9382 const slice_val = try o.builder.structConst(ret_ty, &.{
9383 global_index.toConst(),
9384 try o.builder.intConst(usize_ty, name.toSlice(&o.builder).?.len),
9385 });
94299386
94309387 const return_block = self.context.appendBasicBlock(fn_val, "Name");
94319388 const this_tag_int_value =
......@@ -9433,9 +9390,7 @@ pub const FuncGen = struct {
94339390 switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), return_block);
94349391
94359392 self.builder.positionBuilderAtEnd(return_block);
9436 const loaded = self.builder.buildLoad(llvm_ret_ty, slice_global, "");
9437 loaded.setAlignment(slice_alignment);
9438 _ = self.builder.buildRet(loaded);
9393 _ = self.builder.buildRet(slice_val.toLlvm(&o.builder));
94399394 }
94409395
94419396 self.builder.positionBuilderAtEnd(bad_value_block);
......@@ -9530,22 +9485,25 @@ pub const FuncGen = struct {
95309485 // when changing code, so Zig uses negative numbers to index the
95319486 // second vector. These start at -1 and go down, and are easiest to use
95329487 // with the ~ operator. Here we convert between the two formats.
9533 const values = try self.gpa.alloc(*llvm.Value, mask_len);
9488 const values = try self.gpa.alloc(Builder.Constant, mask_len);
95349489 defer self.gpa.free(values);
95359490
95369491 for (values, 0..) |*val, i| {
95379492 const elem = try mask.elemValue(mod, i);
95389493 if (elem.isUndef(mod)) {
9539 val.* = Builder.Type.i32.toLlvm(&o.builder).getUndef();
9494 val.* = try o.builder.undefConst(.i32);
95409495 } else {
95419496 const int = elem.toSignedInt(mod);
95429497 const unsigned = if (int >= 0) @as(u32, @intCast(int)) else @as(u32, @intCast(~int + a_len));
9543 val.* = (try o.builder.intConst(.i32, unsigned)).toLlvm(&o.builder);
9498 val.* = try o.builder.intConst(.i32, unsigned);
95449499 }
95459500 }
95469501
9547 const llvm_mask_value = llvm.constVector(values.ptr, mask_len);
9548 return self.builder.buildShuffleVector(a, b, llvm_mask_value, "");
9502 const llvm_mask_value = try o.builder.vectorConst(
9503 try o.builder.vectorType(.normal, mask_len, .i32),
9504 values,
9505 );
9506 return self.builder.buildShuffleVector(a, b, llvm_mask_value.toLlvm(&o.builder), "");
95499507 }
95509508
95519509 /// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result.
......@@ -9816,7 +9774,7 @@ pub const FuncGen = struct {
98169774 .val = sent_val,
98179775 });
98189776
9819 try self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic);
9777 try self.store(elem_ptr, elem_ptr_ty, llvm_elem.toLlvm(&o.builder), .NotAtomic);
98209778 }
98219779
98229780 return alloca_inst;
......@@ -10431,12 +10389,13 @@ pub const FuncGen = struct {
1043110389 else
1043210390 self.builder.buildBitCast(elem, value_bits_type.toLlvm(&o.builder), "");
1043310391
10434 var mask_val = (try o.builder.intConst(value_bits_type, -1)).toLlvm(&o.builder);
10435 mask_val = mask_val.constZExt(containing_int_ty.toLlvm(&o.builder));
10436 mask_val = mask_val.constShl(shift_amt.toLlvm(&o.builder));
10437 mask_val = mask_val.constNot();
10392 var mask_val = try o.builder.intConst(value_bits_type, -1);
10393 mask_val = try o.builder.castConst(.zext, mask_val, containing_int_ty);
10394 mask_val = try o.builder.binConst(.shl, mask_val, shift_amt);
10395 mask_val =
10396 try o.builder.binConst(.xor, mask_val, try o.builder.intConst(containing_int_ty, -1));
1043810397
10439 const anded_containing_int = self.builder.buildAnd(containing_int, mask_val, "");
10398 const anded_containing_int = self.builder.buildAnd(containing_int, mask_val.toLlvm(&o.builder), "");
1044010399 const extended_value = self.builder.buildZExt(value_bits, containing_int_ty.toLlvm(&o.builder), "");
1044110400 const shifted_value = self.builder.buildShl(extended_value, shift_amt.toLlvm(&o.builder), "");
1044210401 const ored_value = self.builder.buildOr(shifted_value, anded_containing_int, "");
src/codegen/llvm/Builder.zig+174-55
......@@ -251,14 +251,41 @@ pub const Type = enum(u32) {
251251 };
252252 }
253253
254 pub fn isFn(self: Type, builder: *const Builder) bool {
254 pub fn isFloatingPoint(self: Type) bool {
255 return switch (self) {
256 .half, .bfloat, .float, .double, .fp128, .x86_fp80, .ppc_fp128 => true,
257 else => false,
258 };
259 }
260
261 pub fn isInteger(self: Type, builder: *const Builder) bool {
262 return switch (self) {
263 .i1, .i8, .i16, .i29, .i32, .i64, .i80, .i128 => true,
264 else => switch (self.tag(builder)) {
265 .integer => true,
266 else => false,
267 },
268 };
269 }
270
271 pub fn isPointer(self: Type, builder: *const Builder) bool {
272 return switch (self) {
273 .ptr => true,
274 else => switch (self.tag(builder)) {
275 .pointer => true,
276 else => false,
277 },
278 };
279 }
280
281 pub fn isFunction(self: Type, builder: *const Builder) bool {
255282 return switch (self.tag(builder)) {
256283 .function, .vararg_function => true,
257284 else => false,
258285 };
259286 }
260287
261 pub fn fnKind(self: Type, builder: *const Builder) Type.Function.Kind {
288 pub fn functionKind(self: Type, builder: *const Builder) Type.Function.Kind {
262289 return switch (self.tag(builder)) {
263290 .function => .normal,
264291 .vararg_function => .vararg,
......@@ -345,6 +372,20 @@ pub const Type = enum(u32) {
345372 };
346373 }
347374
375 pub fn scalarType(self: Type, builder: *const Builder) Type {
376 if (self.isFloatingPoint()) return self;
377 const item = builder.type_items.items[@intFromEnum(self)];
378 return switch (item.tag) {
379 .integer,
380 .pointer,
381 => self,
382 .vector,
383 .scalable_vector,
384 => builder.typeExtraData(Type.Vector, item.data).child,
385 else => unreachable,
386 };
387 }
388
348389 pub fn vectorLen(self: Type, builder: *const Builder) u32 {
349390 const item = builder.type_items.items[@intFromEnum(self)];
350391 return switch (item.tag) {
......@@ -809,17 +850,17 @@ pub const Global = struct {
809850 }
810851
811852 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
812 try builder.ensureUnusedCapacityGlobal(new_name);
853 try builder.ensureUnusedGlobalCapacity(new_name);
813854 self.renameAssumeCapacity(new_name, builder);
814855 }
815856
816857 pub fn takeName(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
817 try builder.ensureUnusedCapacityGlobal(.empty);
858 try builder.ensureUnusedGlobalCapacity(.empty);
818859 self.takeNameAssumeCapacity(other, builder);
819860 }
820861
821862 pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
822 try builder.ensureUnusedCapacityGlobal(.empty);
863 try builder.ensureUnusedGlobalCapacity(.empty);
823864 self.replaceAssumeCapacity(other, builder);
824865 }
825866
......@@ -1047,6 +1088,7 @@ pub const Constant = enum(u32) {
10471088 string,
10481089 string_null,
10491090 vector,
1091 splat,
10501092 zeroinitializer,
10511093 undef,
10521094 poison,
......@@ -1126,6 +1168,11 @@ pub const Constant = enum(u32) {
11261168 type: Type,
11271169 };
11281170
1171 pub const Splat = extern struct {
1172 type: Type,
1173 value: Constant,
1174 };
1175
11291176 pub const BlockAddress = extern struct {
11301177 function: Function.Index,
11311178 block: Function.Block.Index,
......@@ -1217,6 +1264,7 @@ pub const Constant = enum(u32) {
12171264 .array,
12181265 .vector,
12191266 => builder.constantExtraData(Aggregate, item.data).type,
1267 .splat => builder.constantExtraData(Splat, item.data).type,
12201268 .string,
12211269 .string_null,
12221270 => builder.arrayTypeAssumeCapacity(
......@@ -1270,28 +1318,10 @@ pub const Constant = enum(u32) {
12701318 },
12711319 .icmp, .fcmp => {
12721320 const ty = builder.constantExtraData(Compare, item.data).lhs.typeOf(builder);
1273 return switch (ty) {
1274 .half,
1275 .bfloat,
1276 .float,
1277 .double,
1278 .fp128,
1279 .x86_fp80,
1280 .ppc_fp128,
1281 .i1,
1282 .i8,
1283 .i16,
1284 .i29,
1285 .i32,
1286 .i64,
1287 .i80,
1288 .i128,
1289 => ty,
1290 else => if (ty.isVector(builder)) switch (ty.vectorKind(builder)) {
1291 inline else => |kind| builder
1292 .vectorTypeAssumeCapacity(kind, ty.vectorLen(builder), .i1),
1293 } else ty,
1294 };
1321 return if (ty.isVector(builder)) switch (ty.vectorKind(builder)) {
1322 inline else => |kind| builder
1323 .vectorTypeAssumeCapacity(kind, ty.vectorLen(builder), .i1),
1324 } else ty;
12951325 },
12961326 .extractelement => builder.constantExtraData(ExtractElement, item.data)
12971327 .arg.typeOf(builder).childType(builder),
......@@ -1479,7 +1509,6 @@ pub const Constant = enum(u32) {
14791509 const len = extra.data.type.aggregateLen(data.builder);
14801510 const vals: []const Constant =
14811511 @ptrCast(data.builder.constant_extra.items[extra.end..][0..len]);
1482
14831512 try writer.writeAll(switch (tag) {
14841513 .structure => "{ ",
14851514 .packed_structure => "<{ ",
......@@ -1499,6 +1528,16 @@ pub const Constant = enum(u32) {
14991528 else => unreachable,
15001529 });
15011530 },
1531 .splat => {
1532 const extra = data.builder.constantExtraData(Splat, item.data);
1533 const len = extra.type.vectorLen(data.builder);
1534 try writer.writeByte('<');
1535 for (0..len) |index| {
1536 if (index > 0) try writer.writeAll(", ");
1537 try writer.print("{%}", .{extra.value.fmt(data.builder)});
1538 }
1539 try writer.writeByte('>');
1540 },
15021541 inline .string,
15031542 .string_null,
15041543 => |tag| try writer.print("c{\"" ++ switch (tag) {
......@@ -2093,7 +2132,7 @@ pub fn namedTypeSetBody(
20932132pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index {
20942133 assert(!name.isAnon());
20952134 try self.ensureUnusedTypeCapacity(1, null, 0);
2096 try self.ensureUnusedCapacityGlobal(name);
2135 try self.ensureUnusedGlobalCapacity(name);
20972136 return self.addGlobalAssumeCapacity(name, global);
20982137}
20992138
......@@ -2231,8 +2270,17 @@ pub fn vectorConst(self: *Builder, ty: Type, vals: []const Constant) Allocator.E
22312270 return self.vectorConstAssumeCapacity(ty, vals);
22322271}
22332272
2273pub fn splatConst(self: *Builder, ty: Type, val: Constant) Allocator.Error!Constant {
2274 try self.ensureUnusedConstantCapacity(1, Constant.Splat, 0);
2275 return self.splatConstAssumeCapacity(ty, val);
2276}
2277
22342278pub fn zeroInitConst(self: *Builder, ty: Type) Allocator.Error!Constant {
2235 try self.ensureUnusedConstantCapacity(1, null, 0);
2279 try self.ensureUnusedConstantCapacity(1, Constant.Fp128, 0);
2280 try self.constant_limbs.ensureUnusedCapacity(
2281 self.gpa,
2282 Constant.Integer.limbs + comptime std.math.big.int.calcLimbLen(0),
2283 );
22362284 return self.zeroInitConstAssumeCapacity(ty);
22372285}
22382286
......@@ -2477,7 +2525,7 @@ fn isValidIdentifier(id: []const u8) bool {
24772525 return true;
24782526}
24792527
2480fn ensureUnusedCapacityGlobal(self: *Builder, name: String) Allocator.Error!void {
2528fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void {
24812529 if (self.useLibLlvm()) try self.llvm.globals.ensureUnusedCapacity(self.gpa, 1);
24822530 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
24832531 if (name.toSlice(self)) |id| try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len +
......@@ -2571,6 +2619,7 @@ fn vectorTypeAssumeCapacity(
25712619 len: u32,
25722620 child: Type,
25732621) Type {
2622 assert(child.isFloatingPoint() or child.isInteger(self) or child.isPointer(self));
25742623 const tag: Type.Tag = switch (kind) {
25752624 .normal => .vector,
25762625 .scalable => .scalable_vector,
......@@ -3321,14 +3370,13 @@ fn vectorConstAssumeCapacity(
33213370 ty: Type,
33223371 vals: []const Constant,
33233372) if (build_options.have_llvm) Allocator.Error!Constant else Constant {
3324 if (std.debug.runtime_safety) {
3325 const type_item = self.type_items.items[@intFromEnum(ty)];
3326 assert(type_item.tag == .vector);
3327 const extra = self.typeExtraData(Type.Vector, type_item.data);
3328 assert(extra.len == vals.len);
3329 for (vals) |val| assert(extra.child == val.typeOf(self));
3330 }
3373 assert(ty.isVector(self));
3374 assert(ty.vectorLen(self) == vals.len);
3375 for (vals) |val| assert(ty.childType(self) == val.typeOf(self));
33313376
3377 for (vals[1..]) |val| {
3378 if (vals[0] != val) break;
3379 } else return self.splatConstAssumeCapacity(ty, vals[0]);
33323380 for (vals) |val| {
33333381 if (!val.isZeroInit(self)) break;
33343382 } else return self.zeroInitConstAssumeCapacity(ty);
......@@ -3351,23 +3399,91 @@ fn vectorConstAssumeCapacity(
33513399 return result.constant;
33523400}
33533401
3402fn splatConstAssumeCapacity(
3403 self: *Builder,
3404 ty: Type,
3405 val: Constant,
3406) if (build_options.have_llvm) Allocator.Error!Constant else Constant {
3407 assert(ty.scalarType(self) == val.typeOf(self));
3408
3409 if (!ty.isVector(self)) return val;
3410 if (val.isZeroInit(self)) return self.zeroInitConstAssumeCapacity(ty);
3411
3412 const Adapter = struct {
3413 builder: *const Builder,
3414 pub fn hash(_: @This(), key: Constant.Splat) u32 {
3415 return @truncate(std.hash.Wyhash.hash(
3416 comptime std.hash.uint32(@intFromEnum(Constant.Tag.splat)),
3417 std.mem.asBytes(&key),
3418 ));
3419 }
3420 pub fn eql(ctx: @This(), lhs_key: Constant.Splat, _: void, rhs_index: usize) bool {
3421 if (ctx.builder.constant_items.items(.tag)[rhs_index] != .splat) return false;
3422 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
3423 const rhs_extra = ctx.builder.constantExtraData(Constant.Splat, rhs_data);
3424 return std.meta.eql(lhs_key, rhs_extra);
3425 }
3426 };
3427 const data = Constant.Splat{ .type = ty, .value = val };
3428 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
3429 if (!gop.found_existing) {
3430 gop.key_ptr.* = {};
3431 gop.value_ptr.* = {};
3432 self.constant_items.appendAssumeCapacity(.{
3433 .tag = .splat,
3434 .data = self.addConstantExtraAssumeCapacity(data),
3435 });
3436 if (self.useLibLlvm()) {
3437 const ExpectedContents = [expected_fields_len]*llvm.Value;
3438 var stack align(@alignOf(ExpectedContents)) =
3439 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
3440 const allocator = stack.get();
3441
3442 const llvm_vals = try allocator.alloc(*llvm.Value, ty.vectorLen(self));
3443 defer allocator.free(llvm_vals);
3444 @memset(llvm_vals, val.toLlvm(self));
3445
3446 self.llvm.constants.appendAssumeCapacity(
3447 llvm.constVector(llvm_vals.ptr, @intCast(llvm_vals.len)),
3448 );
3449 }
3450 }
3451 return @enumFromInt(gop.index);
3452}
3453
33543454fn zeroInitConstAssumeCapacity(self: *Builder, ty: Type) Constant {
3355 switch (self.type_items.items[@intFromEnum(ty)].tag) {
3356 .simple,
3357 .function,
3358 .vararg_function,
3359 .integer,
3360 .pointer,
3361 => unreachable,
3362 .target,
3363 .vector,
3364 .scalable_vector,
3365 .small_array,
3366 .array,
3367 .structure,
3368 .packed_structure,
3369 .named_structure,
3370 => {},
3455 switch (ty) {
3456 inline .half,
3457 .bfloat,
3458 .float,
3459 .double,
3460 .fp128,
3461 .x86_fp80,
3462 => |tag| return @field(Builder, @tagName(tag) ++ "ConstAssumeCapacity")(self, 0.0),
3463 .ppc_fp128 => return self.ppc_fp128ConstAssumeCapacity(.{ 0.0, 0.0 }),
3464 .token => return .none,
3465 .i1 => return .false,
3466 else => switch (self.type_items.items[@intFromEnum(ty)].tag) {
3467 .simple,
3468 .function,
3469 .vararg_function,
3470 => unreachable,
3471 .integer => {
3472 var limbs: [std.math.big.int.calcLimbLen(0)]std.math.big.Limb = undefined;
3473 const bigint = std.math.big.int.Mutable.init(&limbs, 0);
3474 return self.bigIntConstAssumeCapacity(ty, bigint.toConst()) catch unreachable;
3475 },
3476 .pointer => return self.nullConstAssumeCapacity(ty),
3477 .target,
3478 .vector,
3479 .scalable_vector,
3480 .small_array,
3481 .array,
3482 .structure,
3483 .packed_structure,
3484 .named_structure,
3485 => {},
3486 },
33713487 }
33723488 const result = self.getOrPutConstantNoExtraAssumeCapacity(
33733489 .{ .tag = .zeroinitializer, .data = @intFromEnum(ty) },
......@@ -4034,7 +4150,10 @@ pub inline fn useLibLlvm(self: *const Builder) bool {
40344150const assert = std.debug.assert;
40354151const build_options = @import("build_options");
40364152const builtin = @import("builtin");
4037const llvm = @import("bindings.zig");
4153const llvm = if (build_options.have_llvm)
4154 @import("bindings.zig")
4155else
4156 @compileError("LLVM unavailable");
40384157const log = std.log.scoped(.llvm);
40394158const std = @import("std");
40404159