authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-31 15:30:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-31 15:32:15-07:00
logec919c3c9b915ea0795c24f07c3014915ca0038a
treee58d2c339375c44e7b12b3bc1b86dfd9ca7b7249
parent43311e19f440a1b6294653f9fdf97c64f3bdd0ae

LLVM: integrate param attrs with iterateParamTypes

This moves some logic from resolveLlvmFunction to updateFunc and takes advantage of the iteration we already do that takes into account C ABI lowering, making LLVM parameter attributes accurate for C ABI functions as well as our own unspecified calling convention. Related to #11498.

1 files changed, 22 insertions(+), 34 deletions(-)

src/codegen/llvm.zig+22-34
...@@ -712,7 +712,6 @@ pub const Object = struct {...@@ -712,7 +712,6 @@ pub const Object = struct {
712 .byval => {712 .byval => {
713 const param_ty = fn_info.param_types[it.zig_index - 1];713 const param_ty = fn_info.param_types[it.zig_index - 1];
714 const param = llvm_func.getParam(llvm_arg_i);714 const param = llvm_func.getParam(llvm_arg_i);
715 llvm_arg_i += 1;
716715
717 if (isByRef(param_ty)) {716 if (isByRef(param_ty)) {
718 const alignment = param_ty.abiAlignment(target);717 const alignment = param_ty.abiAlignment(target);
...@@ -724,11 +723,33 @@ pub const Object = struct {...@@ -724,11 +723,33 @@ pub const Object = struct {
724 try args.append(arg_ptr);723 try args.append(arg_ptr);
725 } else {724 } else {
726 try args.append(param);725 try args.append(param);
726
727 if (param_ty.isPtrAtRuntime()) {
728 // TODO noalias attribute
729 const ptr_info = param_ty.ptrInfo().data;
730 if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") {
731 dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
732 }
733 if (!ptr_info.mutable) {
734 dg.addArgAttr(llvm_func, llvm_arg_i, "readonly");
735 }
736 if (ptr_info.@"align" != 0) {
737 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align");
738 } else {
739 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.pointee_type.abiAlignment(target));
740 }
741 }
727 }742 }
743 llvm_arg_i += 1;
728 },744 },
729 .byref => {745 .byref => {
730 const param_ty = fn_info.param_types[it.zig_index - 1];746 const param_ty = fn_info.param_types[it.zig_index - 1];
731 const param = llvm_func.getParam(llvm_arg_i);747 const param = llvm_func.getParam(llvm_arg_i);
748
749 dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
750 dg.addArgAttr(llvm_func, llvm_arg_i, "readonly");
751 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", param_ty.abiAlignment(target));
752
732 llvm_arg_i += 1;753 llvm_arg_i += 1;
733754
734 if (isByRef(param_ty)) {755 if (isByRef(param_ty)) {
...@@ -2213,35 +2234,8 @@ pub const DeclGen = struct {...@@ -2213,35 +2234,8 @@ pub const DeclGen = struct {
2213 dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull");2234 dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull");
2214 }2235 }
22152236
2216 // Set parameter attributes.
2217 switch (fn_info.cc) {2237 switch (fn_info.cc) {
2218 .Unspecified, .Inline => {2238 .Unspecified, .Inline => {
2219 var llvm_param_i: c_uint = @as(c_uint, @boolToInt(sret)) + @boolToInt(err_return_tracing);
2220 for (fn_info.param_types) |param_ty| {
2221 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
2222
2223 // TODO: noalias attribute
2224
2225 if (isByRef(param_ty)) {
2226 dg.addArgAttr(llvm_fn, llvm_param_i, "nonnull");
2227 dg.addArgAttr(llvm_fn, llvm_param_i, "readonly");
2228 dg.addArgAttrInt(llvm_fn, llvm_param_i, "align", param_ty.abiAlignment(target));
2229 } else if (param_ty.isPtrAtRuntime()) {
2230 const ptr_info = param_ty.ptrInfo().data;
2231 if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") {
2232 dg.addArgAttr(llvm_fn, llvm_param_i, "nonnull");
2233 }
2234 if (!ptr_info.mutable) {
2235 dg.addArgAttr(llvm_fn, llvm_param_i, "readonly");
2236 }
2237 if (ptr_info.@"align" != 0) {
2238 dg.addArgAttrInt(llvm_fn, llvm_param_i, "align", ptr_info.@"align");
2239 } else {
2240 dg.addArgAttrInt(llvm_fn, llvm_param_i, "align", ptr_info.pointee_type.abiAlignment(target));
2241 }
2242 }
2243 llvm_param_i += 1;
2244 }
2245 llvm_fn.setFunctionCallConv(.Fast);2239 llvm_fn.setFunctionCallConv(.Fast);
2246 },2240 },
2247 .Naked => {2241 .Naked => {
...@@ -2252,12 +2246,6 @@ pub const DeclGen = struct {...@@ -2252,12 +2246,6 @@ pub const DeclGen = struct {
2252 @panic("TODO: LLVM backend lower async function");2246 @panic("TODO: LLVM backend lower async function");
2253 },2247 },
2254 else => {2248 else => {
2255 // TODO set attributes such as noalias, nonnull, readonly, and align
2256 // Note that there is not a one to one correspondence between fn_info.param_types
2257 // and llvm parameters due to C ABI lowering. This will need to involve
2258 // iterateParamTypes which is currently happening over in updateFunc.
2259 // Probably this whole "set parameter attributes" section of code should
2260 // move there and integrate with this abstraction.
2261 llvm_fn.setFunctionCallConv(toLlvmCallConv(fn_info.cc, target));2249 llvm_fn.setFunctionCallConv(toLlvmCallConv(fn_info.cc, target));
2262 },2250 },
2263 }2251 }