| ... | ... | @@ -910,10 +910,11 @@ pub const Object = struct { |
| 910 | 910 | while (it.next()) |lowering| switch (lowering) { |
| 911 | 911 | .no_bits => continue, |
| 912 | 912 | .byval => { |
| 913 | | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 913 | assert(!it.byval_attr); |
| 914 | const param_index = it.zig_index - 1; |
| 915 | const param_ty = fn_info.param_types[param_index]; |
| 914 | 916 | const param = llvm_func.getParam(llvm_arg_i); |
| 915 | 917 | try args.ensureUnusedCapacity(1); |
| 916 | | assert(!it.byval_attr); |
| 917 | 918 | |
| 918 | 919 | if (isByRef(param_ty)) { |
| 919 | 920 | const alignment = param_ty.abiAlignment(target); |
| ... | ... | @@ -926,32 +927,7 @@ pub const Object = struct { |
| 926 | 927 | } else { |
| 927 | 928 | args.appendAssumeCapacity(param); |
| 928 | 929 | |
| 929 | | if (param_ty.isPtrAtRuntime()) { |
| 930 | | const ptr_info = param_ty.ptrInfo().data; |
| 931 | | if (math.cast(u5, it.zig_index - 1)) |i| { |
| 932 | | if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { |
| 933 | | dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); |
| 934 | | } |
| 935 | | } |
| 936 | | if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { |
| 937 | | dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); |
| 938 | | } |
| 939 | | if (!ptr_info.mutable) { |
| 940 | | dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); |
| 941 | | } |
| 942 | | if (ptr_info.@"align" != 0) { |
| 943 | | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align"); |
| 944 | | } else { |
| 945 | | const elem_align = @maximum( |
| 946 | | ptr_info.pointee_type.abiAlignment(target), |
| 947 | | 1, |
| 948 | | ); |
| 949 | | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); |
| 950 | | } |
| 951 | | } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { |
| 952 | | .signed => dg.addArgAttr(llvm_func, llvm_arg_i, "signext"), |
| 953 | | .unsigned => dg.addArgAttr(llvm_func, llvm_arg_i, "zeroext"), |
| 954 | | }; |
| 930 | dg.addByValParamAttrs(llvm_func, param_ty, param_index, fn_info, llvm_arg_i); |
| 955 | 931 | } |
| 956 | 932 | llvm_arg_i += 1; |
| 957 | 933 | }, |
| ... | ... | @@ -961,13 +937,7 @@ pub const Object = struct { |
| 961 | 937 | const param = llvm_func.getParam(llvm_arg_i); |
| 962 | 938 | const alignment = param_ty.abiAlignment(target); |
| 963 | 939 | |
| 964 | | dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); |
| 965 | | dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); |
| 966 | | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", alignment); |
| 967 | | if (it.byval_attr) { |
| 968 | | llvm_func.addByValAttr(llvm_arg_i, param_llvm_ty); |
| 969 | | } |
| 970 | | |
| 940 | dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); |
| 971 | 941 | llvm_arg_i += 1; |
| 972 | 942 | |
| 973 | 943 | try args.ensureUnusedCapacity(1); |
| ... | ... | @@ -2531,6 +2501,39 @@ pub const DeclGen = struct { |
| 2531 | 2501 | dg.addFnAttr(llvm_fn, "noreturn"); |
| 2532 | 2502 | } |
| 2533 | 2503 | |
| 2504 | // Add parameter attributes. We handle only the case of extern functions (no body) |
| 2505 | // because functions with bodies are handled in `updateFunc`. |
| 2506 | if (is_extern) { |
| 2507 | var it = iterateParamTypes(dg, fn_info); |
| 2508 | it.llvm_index += @boolToInt(sret); |
| 2509 | it.llvm_index += @boolToInt(err_return_tracing); |
| 2510 | while (it.next()) |lowering| switch (lowering) { |
| 2511 | .byval => { |
| 2512 | const param_index = it.zig_index - 1; |
| 2513 | const param_ty = fn_info.param_types[param_index]; |
| 2514 | if (!isByRef(param_ty)) { |
| 2515 | dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 2516 | } |
| 2517 | }, |
| 2518 | .byref => { |
| 2519 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 2520 | const param_llvm_ty = try dg.lowerType(param_ty); |
| 2521 | const alignment = param_ty.abiAlignment(target); |
| 2522 | dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| 2523 | }, |
| 2524 | // No attributes needed for these. |
| 2525 | .no_bits, |
| 2526 | .abi_sized_int, |
| 2527 | .multiple_llvm_ints, |
| 2528 | .multiple_llvm_float, |
| 2529 | .as_u16, |
| 2530 | => continue, |
| 2531 | |
| 2532 | .slice => unreachable, // extern functions do not support slice types. |
| 2533 | |
| 2534 | }; |
| 2535 | } |
| 2536 | |
| 2534 | 2537 | return llvm_fn; |
| 2535 | 2538 | } |
| 2536 | 2539 | |
| ... | ... | @@ -4141,6 +4144,59 @@ pub const DeclGen = struct { |
| 4141 | 4144 | return null; |
| 4142 | 4145 | } |
| 4143 | 4146 | } |
| 4147 | |
| 4148 | fn addByValParamAttrs( |
| 4149 | dg: DeclGen, |
| 4150 | llvm_fn: *const llvm.Value, |
| 4151 | param_ty: Type, |
| 4152 | param_index: u32, |
| 4153 | fn_info: Type.Payload.Function.Data, |
| 4154 | llvm_arg_i: u32, |
| 4155 | ) void { |
| 4156 | const target = dg.module.getTarget(); |
| 4157 | if (param_ty.isPtrAtRuntime()) { |
| 4158 | const ptr_info = param_ty.ptrInfo().data; |
| 4159 | if (math.cast(u5, param_index)) |i| { |
| 4160 | if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { |
| 4161 | dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); |
| 4162 | } |
| 4163 | } |
| 4164 | if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { |
| 4165 | dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| 4166 | } |
| 4167 | if (!ptr_info.mutable) { |
| 4168 | dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); |
| 4169 | } |
| 4170 | if (ptr_info.@"align" != 0) { |
| 4171 | dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align"); |
| 4172 | } else { |
| 4173 | const elem_align = @maximum( |
| 4174 | ptr_info.pointee_type.abiAlignment(target), |
| 4175 | 1, |
| 4176 | ); |
| 4177 | dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); |
| 4178 | } |
| 4179 | } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { |
| 4180 | .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"), |
| 4181 | .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), |
| 4182 | }; |
| 4183 | } |
| 4184 | |
| 4185 | fn addByRefParamAttrs( |
| 4186 | dg: DeclGen, |
| 4187 | llvm_fn: *const llvm.Value, |
| 4188 | llvm_arg_i: u32, |
| 4189 | alignment: u32, |
| 4190 | byval_attr: bool, |
| 4191 | param_llvm_ty: *const llvm.Type, |
| 4192 | ) void { |
| 4193 | dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| 4194 | dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); |
| 4195 | dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment); |
| 4196 | if (byval_attr) { |
| 4197 | llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty); |
| 4198 | } |
| 4199 | } |
| 4144 | 4200 | }; |
| 4145 | 4201 | |
| 4146 | 4202 | pub const FuncGen = struct { |