authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-31 18:25:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-31 18:25:57-07:00
log2f9533f639311f680f3080747aa03b411ca63100
tree6ea7b61114cdbdfab7b87069810e624e834183a9
parent356a865b871db458149f70bc103a3971780d6962

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 files changed, 63 insertions(+), 7 deletions(-)

src/codegen/llvm.zig+63-7
......@@ -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;