| ... | @@ -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; | | |
| 716 | | 715 | |
| 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; |
| 733 | | 754 | |
| 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 | } |
| 2215 | | 2236 | |
| 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 | } |