| ... | @@ -910,10 +910,11 @@ pub const Object = struct { | ... | @@ -910,10 +910,11 @@ pub const Object = struct { |
| 910 | while (it.next()) |lowering| switch (lowering) { | 910 | while (it.next()) |lowering| switch (lowering) { |
| 911 | .no_bits => continue, | 911 | .no_bits => continue, |
| 912 | .byval => { | 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 | const param = llvm_func.getParam(llvm_arg_i); | 916 | const param = llvm_func.getParam(llvm_arg_i); |
| 915 | try args.ensureUnusedCapacity(1); | 917 | try args.ensureUnusedCapacity(1); |
| 916 | assert(!it.byval_attr); | | |
| 917 | | 918 | |
| 918 | if (isByRef(param_ty)) { | 919 | if (isByRef(param_ty)) { |
| 919 | const alignment = param_ty.abiAlignment(target); | 920 | const alignment = param_ty.abiAlignment(target); |
| ... | @@ -926,32 +927,7 @@ pub const Object = struct { | ... | @@ -926,32 +927,7 @@ pub const Object = struct { |
| 926 | } else { | 927 | } else { |
| 927 | args.appendAssumeCapacity(param); | 928 | args.appendAssumeCapacity(param); |
| 928 | | 929 | |
| 929 | if (param_ty.isPtrAtRuntime()) { | 930 | dg.addByValParamAttrs(llvm_func, param_ty, param_index, fn_info, llvm_arg_i); |
| 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 | }; | | |
| 955 | } | 931 | } |
| 956 | llvm_arg_i += 1; | 932 | llvm_arg_i += 1; |
| 957 | }, | 933 | }, |
| ... | @@ -961,13 +937,7 @@ pub const Object = struct { | ... | @@ -961,13 +937,7 @@ pub const Object = struct { |
| 961 | const param = llvm_func.getParam(llvm_arg_i); | 937 | const param = llvm_func.getParam(llvm_arg_i); |
| 962 | const alignment = param_ty.abiAlignment(target); | 938 | const alignment = param_ty.abiAlignment(target); |
| 963 | | 939 | |
| 964 | dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); | 940 | dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); |
| 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 | | | |
| 971 | llvm_arg_i += 1; | 941 | llvm_arg_i += 1; |
| 972 | | 942 | |
| 973 | try args.ensureUnusedCapacity(1); | 943 | try args.ensureUnusedCapacity(1); |
| ... | @@ -2531,6 +2501,39 @@ pub const DeclGen = struct { | ... | @@ -2531,6 +2501,39 @@ pub const DeclGen = struct { |
| 2531 | dg.addFnAttr(llvm_fn, "noreturn"); | 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 | return llvm_fn; | 2537 | return llvm_fn; |
| 2535 | } | 2538 | } |
| 2536 | | 2539 | |
| ... | @@ -4141,6 +4144,59 @@ pub const DeclGen = struct { | ... | @@ -4141,6 +4144,59 @@ pub const DeclGen = struct { |
| 4141 | return null; | 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 | pub const FuncGen = struct { | 4202 | pub const FuncGen = struct { |