Skip to content

Commit 2f9533f

Browse files
committed
LLVM: pass slices as ptr/len combo
LLVM optimization passes handle this better, and it allows Zig to specify pointer parameter attributes such as readonly, nonnull, noalias, and alignment. closes #561
1 parent 356a865 commit 2f9533f

File tree

1 file changed

+63
-7
lines changed

1 file changed

+63
-7
lines changed

src/codegen/llvm.zig

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ pub const Object = struct {
712712
.byval => {
713713
const param_ty = fn_info.param_types[it.zig_index - 1];
714714
const param = llvm_func.getParam(llvm_arg_i);
715+
try args.ensureUnusedCapacity(1);
715716

716717
if (isByRef(param_ty)) {
717718
const alignment = param_ty.abiAlignment(target);
@@ -720,9 +721,9 @@ pub const Object = struct {
720721
arg_ptr.setAlignment(alignment);
721722
const store_inst = builder.buildStore(param, arg_ptr);
722723
store_inst.setAlignment(alignment);
723-
try args.append(arg_ptr);
724+
args.appendAssumeCapacity(arg_ptr);
724725
} else {
725-
try args.append(param);
726+
args.appendAssumeCapacity(param);
726727

727728
if (param_ty.isPtrAtRuntime()) {
728729
const ptr_info = param_ty.ptrInfo().data;
@@ -756,13 +757,15 @@ pub const Object = struct {
756757

757758
llvm_arg_i += 1;
758759

760+
try args.ensureUnusedCapacity(1);
761+
759762
if (isByRef(param_ty)) {
760-
try args.append(param);
763+
args.appendAssumeCapacity(param);
761764
} else {
762765
const alignment = param_ty.abiAlignment(target);
763766
const load_inst = builder.buildLoad(param, "");
764767
load_inst.setAlignment(alignment);
765-
try args.append(load_inst);
768+
args.appendAssumeCapacity(load_inst);
766769
}
767770
},
768771
.abi_sized_int => {
@@ -784,14 +787,44 @@ pub const Object = struct {
784787
const store_inst = builder.buildStore(param, casted_ptr);
785788
store_inst.setAlignment(alignment);
786789

790+
try args.ensureUnusedCapacity(1);
791+
787792
if (isByRef(param_ty)) {
788-
try args.append(arg_ptr);
793+
args.appendAssumeCapacity(arg_ptr);
789794
} else {
790795
const load_inst = builder.buildLoad(arg_ptr, "");
791796
load_inst.setAlignment(alignment);
792-
try args.append(load_inst);
797+
args.appendAssumeCapacity(load_inst);
793798
}
794799
},
800+
.slice => {
801+
const param_ty = fn_info.param_types[it.zig_index - 1];
802+
const ptr_info = param_ty.ptrInfo().data;
803+
804+
if (math.cast(u5, it.zig_index - 1)) |i| {
805+
if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {
806+
dg.addArgAttr(llvm_func, llvm_arg_i, "noalias");
807+
}
808+
}
809+
dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
810+
if (!ptr_info.mutable) {
811+
dg.addArgAttr(llvm_func, llvm_arg_i, "readonly");
812+
}
813+
if (ptr_info.@"align" != 0) {
814+
dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align");
815+
} else {
816+
dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.pointee_type.abiAlignment(target));
817+
}
818+
const ptr_param = llvm_func.getParam(llvm_arg_i);
819+
llvm_arg_i += 1;
820+
const len_param = llvm_func.getParam(llvm_arg_i);
821+
llvm_arg_i += 1;
822+
823+
const slice_llvm_ty = try dg.lowerType(param_ty);
824+
const partial = builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr_param, 0, "");
825+
const aggregate = builder.buildInsertValue(partial, len_param, 1, "");
826+
try args.append(aggregate);
827+
},
795828
.multiple_llvm_ints => {
796829
const param_ty = fn_info.param_types[it.zig_index - 1];
797830
const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];
@@ -2743,6 +2776,17 @@ pub const DeclGen = struct {
27432776
const abi_size = @intCast(c_uint, param_ty.abiSize(target));
27442777
try llvm_params.append(dg.context.intType(abi_size * 8));
27452778
},
2779+
.slice => {
2780+
const param_ty = fn_info.param_types[it.zig_index - 1];
2781+
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2782+
const ptr_ty = param_ty.slicePtrFieldType(&buf);
2783+
const ptr_llvm_ty = try dg.lowerType(ptr_ty);
2784+
const len_llvm_ty = try dg.lowerType(Type.usize);
2785+
2786+
try llvm_params.ensureUnusedCapacity(2);
2787+
llvm_params.appendAssumeCapacity(ptr_llvm_ty);
2788+
llvm_params.appendAssumeCapacity(len_llvm_ty);
2789+
},
27462790
.multiple_llvm_ints => {
27472791
const param_ty = fn_info.param_types[it.zig_index - 1];
27482792
const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];
@@ -4205,6 +4249,15 @@ pub const FuncGen = struct {
42054249
try llvm_args.append(load_inst);
42064250
}
42074251
},
4252+
.slice => {
4253+
const arg = args[it.zig_index - 1];
4254+
const llvm_arg = try self.resolveInst(arg);
4255+
const ptr = self.builder.buildExtractValue(llvm_arg, 0, "");
4256+
const len = self.builder.buildExtractValue(llvm_arg, 1, "");
4257+
try llvm_args.ensureUnusedCapacity(2);
4258+
llvm_args.appendAssumeCapacity(ptr);
4259+
llvm_args.appendAssumeCapacity(len);
4260+
},
42084261
.multiple_llvm_ints => {
42094262
const arg = args[it.zig_index - 1];
42104263
const param_ty = self.air.typeOf(arg);
@@ -8811,6 +8864,7 @@ const ParamTypeIterator = struct {
88118864
byref,
88128865
abi_sized_int,
88138866
multiple_llvm_ints,
8867+
slice,
88148868
};
88158869

88168870
fn next(it: *ParamTypeIterator) ?Lowering {
@@ -8826,7 +8880,9 @@ const ParamTypeIterator = struct {
88268880
.Unspecified, .Inline => {
88278881
it.zig_index += 1;
88288882
it.llvm_index += 1;
8829-
if (isByRef(ty)) {
8883+
if (ty.isSlice()) {
8884+
return .slice;
8885+
} else if (isByRef(ty)) {
88308886
return .byref;
88318887
} else {
88328888
return .byval;

0 commit comments

Comments
 (0)