From d968d9d10329234afc1d7743bb9981245695ca2b Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 20 Nov 2022 20:14:03 +0200 Subject: llvm: add attributes to the arguments of function pointer calls Closes #13605 --- src/codegen/llvm.zig | 67 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 3 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a629624c58..8459920d61 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4700,9 +4700,9 @@ pub const FuncGen = struct { break :blk ret_ptr; }; - if (fn_info.return_type.isError() and - self.dg.module.comp.bin_file.options.error_return_tracing) - { + const err_return_tracing = fn_info.return_type.isError() and + self.dg.module.comp.bin_file.options.error_return_tracing; + if (err_return_tracing) { try llvm_args.append(self.err_ret_trace.?); } @@ -4890,6 +4890,66 @@ pub const FuncGen = struct { "", ); + if (callee_ty.zigTypeTag() == .Pointer) { + // Add argument attributes for function pointer calls. + it = iterateParamTypes(self.dg, fn_info); + it.llvm_index += @boolToInt(sret); + it.llvm_index += @boolToInt(err_return_tracing); + while (it.next()) |lowering| switch (lowering) { + .byval => { + const param_index = it.zig_index - 1; + const param_ty = fn_info.param_types[param_index]; + if (!isByRef(param_ty)) { + self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1); + } + }, + .byref => { + const param_index = it.zig_index - 1; + const param_ty = fn_info.param_types[param_index]; + const param_llvm_ty = try self.dg.lowerType(param_ty); + const alignment = param_ty.abiAlignment(target); + self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); + }, + .byref_mut => { + self.dg.addArgAttr(call, it.llvm_index - 1, "noundef"); + }, + // No attributes needed for these. + .no_bits, + .abi_sized_int, + .multiple_llvm_types, + .as_u16, + .float_array, + .i32_array, + .i64_array, + => continue, + + .slice => { + assert(!it.byval_attr); + const param_ty = fn_info.param_types[it.zig_index - 1]; + const ptr_info = param_ty.ptrInfo().data; + const llvm_arg_i = it.llvm_index - 2; + + if (math.cast(u5, it.zig_index - 1)) |i| { + if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { + self.dg.addArgAttr(call, llvm_arg_i, "noalias"); + } + } + if (param_ty.zigTypeTag() != .Optional) { + self.dg.addArgAttr(call, llvm_arg_i, "nonnull"); + } + if (!ptr_info.mutable) { + self.dg.addArgAttr(call, llvm_arg_i, "readonly"); + } + if (ptr_info.@"align" != 0) { + self.dg.addArgAttrInt(call, llvm_arg_i, "align", ptr_info.@"align"); + } else { + const elem_align = @max(ptr_info.pointee_type.abiAlignment(target), 1); + self.dg.addArgAttrInt(call, llvm_arg_i, "align", elem_align); + } + }, + }; + } + if (return_type.isNoReturn() and attr != .AlwaysTail) { _ = self.builder.buildUnreachable(); return null; @@ -10469,6 +10529,7 @@ const ParamTypeIterator = struct { it.llvm_index += 1; var buf: Type.Payload.ElemType = undefined; if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) { + it.llvm_index += 1; return .slice; } else if (isByRef(ty)) { return .byref; -- cgit v1.2.3