| ... | ... | @@ -1314,28 +1314,21 @@ pub const Object = struct { |
| 1314 | 1314 | |
| 1315 | 1315 | if (func.analysis(ip).is_noinline) { |
| 1316 | 1316 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| 1317 | | o.addFnAttr(llvm_func, "noinline"); |
| 1318 | 1317 | } else { |
| 1319 | 1318 | _ = try attributes.removeFnAttr(.@"noinline"); |
| 1320 | | Object.removeFnAttr(llvm_func, "noinline"); |
| 1321 | 1319 | } |
| 1322 | 1320 | |
| 1323 | 1321 | if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| { |
| 1324 | 1322 | try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder); |
| 1325 | 1323 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| 1326 | | o.addFnAttrInt(llvm_func, "alignstack", alignment); |
| 1327 | | o.addFnAttr(llvm_func, "noinline"); |
| 1328 | 1324 | } else { |
| 1329 | 1325 | _ = try attributes.removeFnAttr(.alignstack); |
| 1330 | | Object.removeFnAttr(llvm_func, "alignstack"); |
| 1331 | 1326 | } |
| 1332 | 1327 | |
| 1333 | 1328 | if (func.analysis(ip).is_cold) { |
| 1334 | 1329 | try attributes.addFnAttr(.cold, &o.builder); |
| 1335 | | o.addFnAttr(llvm_func, "cold"); |
| 1336 | 1330 | } else { |
| 1337 | 1331 | _ = try attributes.removeFnAttr(.cold); |
| 1338 | | Object.removeFnAttr(llvm_func, "cold"); |
| 1339 | 1332 | } |
| 1340 | 1333 | |
| 1341 | 1334 | // TODO: disable this if safety is off for the function scope |
| ... | ... | @@ -1346,10 +1339,6 @@ pub const Object = struct { |
| 1346 | 1339 | .kind = try o.builder.string("stack-protector-buffer-size"), |
| 1347 | 1340 | .value = try o.builder.fmt("{d}", .{ssp_buf_size}), |
| 1348 | 1341 | } }, &o.builder); |
| 1349 | | var buf: [12]u8 = undefined; |
| 1350 | | const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable; |
| 1351 | | o.addFnAttr(llvm_func, "sspstrong"); |
| 1352 | | o.addFnAttrString(llvm_func, "stack-protector-buffer-size", arg); |
| 1353 | 1342 | } |
| 1354 | 1343 | |
| 1355 | 1344 | // TODO: disable this if safety is off for the function scope |
| ... | ... | @@ -1358,13 +1347,11 @@ pub const Object = struct { |
| 1358 | 1347 | .kind = try o.builder.string("probe-stack"), |
| 1359 | 1348 | .value = try o.builder.string("__zig_probe_stack"), |
| 1360 | 1349 | } }, &o.builder); |
| 1361 | | o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); |
| 1362 | 1350 | } else if (target.os.tag == .uefi) { |
| 1363 | 1351 | try attributes.addFnAttr(.{ .string = .{ |
| 1364 | 1352 | .kind = try o.builder.string("no-stack-arg-probe"), |
| 1365 | 1353 | .value = .empty, |
| 1366 | 1354 | } }, &o.builder); |
| 1367 | | o.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); |
| 1368 | 1355 | } |
| 1369 | 1356 | |
| 1370 | 1357 | if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| { |
| ... | ... | @@ -1389,14 +1376,8 @@ pub const Object = struct { |
| 1389 | 1376 | } else .none; |
| 1390 | 1377 | |
| 1391 | 1378 | if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) { |
| 1392 | | .signed => { |
| 1393 | | try attributes.addRetAttr(.signext, &o.builder); |
| 1394 | | o.addAttr(llvm_func, 0, "signext"); |
| 1395 | | }, |
| 1396 | | .unsigned => { |
| 1397 | | try attributes.addRetAttr(.zeroext, &o.builder); |
| 1398 | | o.addAttr(llvm_func, 0, "zeroext"); |
| 1399 | | }, |
| 1379 | .signed => try attributes.addRetAttr(.signext, &o.builder), |
| 1380 | .unsigned => try attributes.addRetAttr(.zeroext, &o.builder), |
| 1400 | 1381 | }; |
| 1401 | 1382 | |
| 1402 | 1383 | const err_return_tracing = fn_info.return_type.toType().isError(mod) and |
| ... | ... | @@ -1437,7 +1418,7 @@ pub const Object = struct { |
| 1437 | 1418 | } else { |
| 1438 | 1419 | args.appendAssumeCapacity(param); |
| 1439 | 1420 | |
| 1440 | | try o.addByValParamAttrsOld(&attributes, llvm_func, param_ty, param_index, fn_info, llvm_arg_i); |
| 1421 | try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, llvm_arg_i); |
| 1441 | 1422 | } |
| 1442 | 1423 | llvm_arg_i += 1; |
| 1443 | 1424 | }, |
| ... | ... | @@ -1447,7 +1428,7 @@ pub const Object = struct { |
| 1447 | 1428 | const param = wip.arg(llvm_arg_i); |
| 1448 | 1429 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 1449 | 1430 | |
| 1450 | | try o.addByRefParamAttrsOld(&attributes, llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); |
| 1431 | try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); |
| 1451 | 1432 | llvm_arg_i += 1; |
| 1452 | 1433 | |
| 1453 | 1434 | if (isByRef(param_ty, mod)) { |
| ... | ... | @@ -1463,7 +1444,6 @@ pub const Object = struct { |
| 1463 | 1444 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 1464 | 1445 | |
| 1465 | 1446 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); |
| 1466 | | o.addArgAttr(llvm_func, llvm_arg_i, "noundef"); |
| 1467 | 1447 | llvm_arg_i += 1; |
| 1468 | 1448 | |
| 1469 | 1449 | if (isByRef(param_ty, mod)) { |
| ... | ... | @@ -1500,23 +1480,19 @@ pub const Object = struct { |
| 1500 | 1480 | if (math.cast(u5, it.zig_index - 1)) |i| { |
| 1501 | 1481 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| 1502 | 1482 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 1503 | | o.addArgAttr(llvm_func, llvm_arg_i, "noalias"); |
| 1504 | 1483 | } |
| 1505 | 1484 | } |
| 1506 | 1485 | if (param_ty.zigTypeTag(mod) != .Optional) { |
| 1507 | 1486 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 1508 | | o.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); |
| 1509 | 1487 | } |
| 1510 | 1488 | if (ptr_info.flags.is_const) { |
| 1511 | 1489 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 1512 | | o.addArgAttr(llvm_func, llvm_arg_i, "readonly"); |
| 1513 | 1490 | } |
| 1514 | 1491 | const elem_align = Builder.Alignment.fromByteUnits( |
| 1515 | 1492 | ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 1516 | 1493 | @max(ptr_info.child.toType().abiAlignment(mod), 1), |
| 1517 | 1494 | ); |
| 1518 | 1495 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 1519 | | o.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0); |
| 1520 | 1496 | const ptr_param = wip.arg(llvm_arg_i); |
| 1521 | 1497 | llvm_arg_i += 1; |
| 1522 | 1498 | const len_param = wip.arg(llvm_arg_i); |
| ... | ... | @@ -1590,7 +1566,7 @@ pub const Object = struct { |
| 1590 | 1566 | } |
| 1591 | 1567 | } |
| 1592 | 1568 | |
| 1593 | | function.ptr(&o.builder).attributes = try attributes.finish(&o.builder); |
| 1569 | function.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 1594 | 1570 | |
| 1595 | 1571 | var di_file: ?*llvm.DIFile = null; |
| 1596 | 1572 | var di_scope: ?*llvm.DIScope = null; |
| ... | ... | @@ -2951,15 +2927,11 @@ pub const Object = struct { |
| 2951 | 2927 | .kind = try o.builder.string("wasm-import-name"), |
| 2952 | 2928 | .value = try o.builder.string(ip.stringToSlice(decl.name)), |
| 2953 | 2929 | } }, &o.builder); |
| 2954 | | o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name)); |
| 2955 | 2930 | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { |
| 2956 | | if (!std.mem.eql(u8, lib_name, "c")) { |
| 2957 | | try attributes.addFnAttr(.{ .string = .{ |
| 2958 | | .kind = try o.builder.string("wasm-import-module"), |
| 2959 | | .value = try o.builder.string(lib_name), |
| 2960 | | } }, &o.builder); |
| 2961 | | o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); |
| 2962 | | } |
| 2931 | if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ |
| 2932 | .kind = try o.builder.string("wasm-import-module"), |
| 2933 | .value = try o.builder.string(lib_name), |
| 2934 | } }, &o.builder); |
| 2963 | 2935 | } |
| 2964 | 2936 | } |
| 2965 | 2937 | } |
| ... | ... | @@ -2969,12 +2941,9 @@ pub const Object = struct { |
| 2969 | 2941 | // Sret pointers must not be address 0 |
| 2970 | 2942 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 2971 | 2943 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 2972 | | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); // Sret pointers must not be address 0 |
| 2973 | | o.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); |
| 2974 | 2944 | |
| 2975 | 2945 | const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType()); |
| 2976 | 2946 | try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder); |
| 2977 | | llvm_fn.addSretAttr(raw_llvm_ret_ty.toLlvm(&o.builder)); |
| 2978 | 2947 | |
| 2979 | 2948 | llvm_arg_i += 1; |
| 2980 | 2949 | } |
| ... | ... | @@ -2984,7 +2953,6 @@ pub const Object = struct { |
| 2984 | 2953 | |
| 2985 | 2954 | if (err_return_tracing) { |
| 2986 | 2955 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 2987 | | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| 2988 | 2956 | llvm_arg_i += 1; |
| 2989 | 2957 | } |
| 2990 | 2958 | |
| ... | ... | @@ -2995,7 +2963,6 @@ pub const Object = struct { |
| 2995 | 2963 | }, |
| 2996 | 2964 | .Naked => { |
| 2997 | 2965 | try attributes.addFnAttr(.naked, &o.builder); |
| 2998 | | o.addFnAttr(llvm_fn, "naked"); |
| 2999 | 2966 | }, |
| 3000 | 2967 | .Async => { |
| 3001 | 2968 | function.call_conv = .fastcc; |
| ... | ... | @@ -3014,11 +2981,10 @@ pub const Object = struct { |
| 3014 | 2981 | } |
| 3015 | 2982 | |
| 3016 | 2983 | // Function attributes that are independent of analysis results of the function body. |
| 3017 | | try o.addCommonFnAttributes(&attributes, llvm_fn); |
| 2984 | try o.addCommonFnAttributes(&attributes); |
| 3018 | 2985 | |
| 3019 | 2986 | if (fn_info.return_type == .noreturn_type) { |
| 3020 | 2987 | try attributes.addFnAttr(.noreturn, &o.builder); |
| 3021 | | o.addFnAttr(llvm_fn, "noreturn"); |
| 3022 | 2988 | } |
| 3023 | 2989 | |
| 3024 | 2990 | // Add parameter attributes. We handle only the case of extern functions (no body) |
| ... | ... | @@ -3031,7 +2997,7 @@ pub const Object = struct { |
| 3031 | 2997 | const param_index = it.zig_index - 1; |
| 3032 | 2998 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 3033 | 2999 | if (!isByRef(param_ty, mod)) { |
| 3034 | | try o.addByValParamAttrsOld(&attributes, llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 3000 | try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 3035 | 3001 | } |
| 3036 | 3002 | }, |
| 3037 | 3003 | .byref => { |
| ... | ... | @@ -3039,11 +3005,10 @@ pub const Object = struct { |
| 3039 | 3005 | const param_llvm_ty = try o.lowerType(param_ty.toType()); |
| 3040 | 3006 | const alignment = |
| 3041 | 3007 | Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod)); |
| 3042 | | try o.addByRefParamAttrsOld(&attributes, llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| 3008 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| 3043 | 3009 | }, |
| 3044 | 3010 | .byref_mut => { |
| 3045 | 3011 | try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder); |
| 3046 | | o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef"); |
| 3047 | 3012 | }, |
| 3048 | 3013 | // No attributes needed for these. |
| 3049 | 3014 | .no_bits, |
| ... | ... | @@ -3060,43 +3025,36 @@ pub const Object = struct { |
| 3060 | 3025 | }; |
| 3061 | 3026 | } |
| 3062 | 3027 | |
| 3063 | | function.attributes = try attributes.finish(&o.builder); |
| 3064 | | |
| 3065 | 3028 | try o.builder.llvm.globals.append(o.gpa, llvm_fn); |
| 3066 | 3029 | gop.value_ptr.* = try o.builder.addGlobal(fqn, global); |
| 3067 | 3030 | try o.builder.functions.append(o.gpa, function); |
| 3031 | global.kind.function.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 3068 | 3032 | return global.kind.function; |
| 3069 | 3033 | } |
| 3070 | 3034 | |
| 3071 | 3035 | fn addCommonFnAttributes( |
| 3072 | 3036 | o: *Object, |
| 3073 | 3037 | attributes: *Builder.FunctionAttributes.Wip, |
| 3074 | | llvm_fn: *llvm.Value, |
| 3075 | 3038 | ) Allocator.Error!void { |
| 3076 | 3039 | const comp = o.module.comp; |
| 3077 | 3040 | |
| 3078 | 3041 | if (!comp.bin_file.options.red_zone) { |
| 3079 | 3042 | try attributes.addFnAttr(.noredzone, &o.builder); |
| 3080 | | o.addFnAttr(llvm_fn, "noredzone"); |
| 3081 | 3043 | } |
| 3082 | 3044 | if (comp.bin_file.options.omit_frame_pointer) { |
| 3083 | 3045 | try attributes.addFnAttr(.{ .string = .{ |
| 3084 | 3046 | .kind = try o.builder.string("frame-pointer"), |
| 3085 | 3047 | .value = try o.builder.string("none"), |
| 3086 | 3048 | } }, &o.builder); |
| 3087 | | o.addFnAttrString(llvm_fn, "frame-pointer", "none"); |
| 3088 | 3049 | } else { |
| 3089 | 3050 | try attributes.addFnAttr(.{ .string = .{ |
| 3090 | 3051 | .kind = try o.builder.string("frame-pointer"), |
| 3091 | 3052 | .value = try o.builder.string("all"), |
| 3092 | 3053 | } }, &o.builder); |
| 3093 | | o.addFnAttrString(llvm_fn, "frame-pointer", "all"); |
| 3094 | 3054 | } |
| 3095 | 3055 | try attributes.addFnAttr(.nounwind, &o.builder); |
| 3096 | | o.addFnAttr(llvm_fn, "nounwind"); |
| 3097 | 3056 | if (comp.unwind_tables) { |
| 3098 | 3057 | try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); |
| 3099 | | o.addFnAttrInt(llvm_fn, "uwtable", 2); |
| 3100 | 3058 | } |
| 3101 | 3059 | if (comp.bin_file.options.skip_linker_dependencies or |
| 3102 | 3060 | comp.bin_file.options.no_builtin) |
| ... | ... | @@ -3107,38 +3065,31 @@ pub const Object = struct { |
| 3107 | 3065 | // body of memcpy with a call to memcpy, which would then cause a stack |
| 3108 | 3066 | // overflow instead of performing memcpy. |
| 3109 | 3067 | try attributes.addFnAttr(.nobuiltin, &o.builder); |
| 3110 | | o.addFnAttr(llvm_fn, "nobuiltin"); |
| 3111 | 3068 | } |
| 3112 | 3069 | if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { |
| 3113 | 3070 | try attributes.addFnAttr(.minsize, &o.builder); |
| 3114 | 3071 | try attributes.addFnAttr(.optsize, &o.builder); |
| 3115 | | o.addFnAttr(llvm_fn, "minsize"); |
| 3116 | | o.addFnAttr(llvm_fn, "optsize"); |
| 3117 | 3072 | } |
| 3118 | 3073 | if (comp.bin_file.options.tsan) { |
| 3119 | 3074 | try attributes.addFnAttr(.sanitize_thread, &o.builder); |
| 3120 | | o.addFnAttr(llvm_fn, "sanitize_thread"); |
| 3121 | 3075 | } |
| 3122 | 3076 | if (comp.getTarget().cpu.model.llvm_name) |s| { |
| 3123 | 3077 | try attributes.addFnAttr(.{ .string = .{ |
| 3124 | 3078 | .kind = try o.builder.string("target-cpu"), |
| 3125 | 3079 | .value = try o.builder.string(s), |
| 3126 | 3080 | } }, &o.builder); |
| 3127 | | llvm_fn.addFunctionAttr("target-cpu", s); |
| 3128 | 3081 | } |
| 3129 | 3082 | if (comp.bin_file.options.llvm_cpu_features) |s| { |
| 3130 | 3083 | try attributes.addFnAttr(.{ .string = .{ |
| 3131 | 3084 | .kind = try o.builder.string("target-features"), |
| 3132 | 3085 | .value = try o.builder.string(std.mem.span(s)), |
| 3133 | 3086 | } }, &o.builder); |
| 3134 | | llvm_fn.addFunctionAttr("target-features", s); |
| 3135 | 3087 | } |
| 3136 | 3088 | if (comp.getTarget().cpu.arch.isBpf()) { |
| 3137 | 3089 | try attributes.addFnAttr(.{ .string = .{ |
| 3138 | 3090 | .kind = try o.builder.string("no-builtins"), |
| 3139 | 3091 | .value = .empty, |
| 3140 | 3092 | } }, &o.builder); |
| 3141 | | llvm_fn.addFunctionAttr("no-builtins", ""); |
| 3142 | 3093 | } |
| 3143 | 3094 | } |
| 3144 | 3095 | |
| ... | ... | @@ -4483,69 +4434,6 @@ pub const Object = struct { |
| 4483 | 4434 | return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty); |
| 4484 | 4435 | } |
| 4485 | 4436 | |
| 4486 | | fn addAttr(o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { |
| 4487 | | return o.addAttrInt(val, index, name, 0); |
| 4488 | | } |
| 4489 | | |
| 4490 | | fn addArgAttr(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8) void { |
| 4491 | | return o.addAttr(fn_val, param_index + 1, attr_name); |
| 4492 | | } |
| 4493 | | |
| 4494 | | fn addArgAttrInt(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8, int: u64) void { |
| 4495 | | return o.addAttrInt(fn_val, param_index + 1, attr_name, int); |
| 4496 | | } |
| 4497 | | |
| 4498 | | fn removeAttr(val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { |
| 4499 | | const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len); |
| 4500 | | assert(kind_id != 0); |
| 4501 | | val.removeEnumAttributeAtIndex(index, kind_id); |
| 4502 | | } |
| 4503 | | |
| 4504 | | fn addAttrInt( |
| 4505 | | o: *Object, |
| 4506 | | val: *llvm.Value, |
| 4507 | | index: llvm.AttributeIndex, |
| 4508 | | name: []const u8, |
| 4509 | | int: u64, |
| 4510 | | ) void { |
| 4511 | | const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len); |
| 4512 | | assert(kind_id != 0); |
| 4513 | | const llvm_attr = o.builder.llvm.context.createEnumAttribute(kind_id, int); |
| 4514 | | val.addAttributeAtIndex(index, llvm_attr); |
| 4515 | | } |
| 4516 | | |
| 4517 | | fn addAttrString( |
| 4518 | | o: *Object, |
| 4519 | | val: *llvm.Value, |
| 4520 | | index: llvm.AttributeIndex, |
| 4521 | | name: []const u8, |
| 4522 | | value: []const u8, |
| 4523 | | ) void { |
| 4524 | | const llvm_attr = o.builder.llvm.context.createStringAttribute( |
| 4525 | | name.ptr, |
| 4526 | | @intCast(name.len), |
| 4527 | | value.ptr, |
| 4528 | | @intCast(value.len), |
| 4529 | | ); |
| 4530 | | val.addAttributeAtIndex(index, llvm_attr); |
| 4531 | | } |
| 4532 | | |
| 4533 | | fn addFnAttr(o: *Object, val: *llvm.Value, name: []const u8) void { |
| 4534 | | o.addAttr(val, std.math.maxInt(llvm.AttributeIndex), name); |
| 4535 | | } |
| 4536 | | |
| 4537 | | fn addFnAttrString(o: *Object, val: *llvm.Value, name: []const u8, value: []const u8) void { |
| 4538 | | o.addAttrString(val, std.math.maxInt(llvm.AttributeIndex), name, value); |
| 4539 | | } |
| 4540 | | |
| 4541 | | fn removeFnAttr(fn_val: *llvm.Value, name: []const u8) void { |
| 4542 | | removeAttr(fn_val, std.math.maxInt(llvm.AttributeIndex), name); |
| 4543 | | } |
| 4544 | | |
| 4545 | | fn addFnAttrInt(o: *Object, fn_val: *llvm.Value, name: []const u8, int: u64) void { |
| 4546 | | return o.addAttrInt(fn_val, std.math.maxInt(llvm.AttributeIndex), name, int); |
| 4547 | | } |
| 4548 | | |
| 4549 | 4437 | /// If the operand type of an atomic operation is not byte sized we need to |
| 4550 | 4438 | /// widen it before using it and then truncate the result. |
| 4551 | 4439 | /// RMW exchange of floating-point values is bitcasted to same-sized integer |
| ... | ... | @@ -4608,80 +4496,13 @@ pub const Object = struct { |
| 4608 | 4496 | attributes: *Builder.FunctionAttributes.Wip, |
| 4609 | 4497 | llvm_arg_i: u32, |
| 4610 | 4498 | alignment: Builder.Alignment, |
| 4611 | | byval_attr: bool, |
| 4499 | byval: bool, |
| 4612 | 4500 | param_llvm_ty: Builder.Type, |
| 4613 | 4501 | ) Allocator.Error!void { |
| 4614 | 4502 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 4615 | 4503 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4616 | 4504 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); |
| 4617 | | if (byval_attr) { |
| 4618 | | try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); |
| 4619 | | } |
| 4620 | | } |
| 4621 | | |
| 4622 | | fn addByValParamAttrsOld( |
| 4623 | | o: *Object, |
| 4624 | | attributes: *Builder.FunctionAttributes.Wip, |
| 4625 | | llvm_fn: *llvm.Value, |
| 4626 | | param_ty: Type, |
| 4627 | | param_index: u32, |
| 4628 | | fn_info: InternPool.Key.FuncType, |
| 4629 | | llvm_arg_i: u32, |
| 4630 | | ) Allocator.Error!void { |
| 4631 | | const mod = o.module; |
| 4632 | | if (param_ty.isPtrAtRuntime(mod)) { |
| 4633 | | const ptr_info = param_ty.ptrInfo(mod); |
| 4634 | | if (math.cast(u5, param_index)) |i| { |
| 4635 | | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| 4636 | | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 4637 | | o.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); |
| 4638 | | } |
| 4639 | | } |
| 4640 | | if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) { |
| 4641 | | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 4642 | | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| 4643 | | } |
| 4644 | | if (ptr_info.flags.is_const) { |
| 4645 | | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4646 | | o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); |
| 4647 | | } |
| 4648 | | const elem_align = Builder.Alignment.fromByteUnits( |
| 4649 | | ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 4650 | | @max(ptr_info.child.toType().abiAlignment(mod), 1), |
| 4651 | | ); |
| 4652 | | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 4653 | | o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0); |
| 4654 | | } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) { |
| 4655 | | .signed => { |
| 4656 | | try attributes.addParamAttr(llvm_arg_i, .signext, &o.builder); |
| 4657 | | o.addArgAttr(llvm_fn, llvm_arg_i, "signext"); |
| 4658 | | }, |
| 4659 | | .unsigned => { |
| 4660 | | try attributes.addParamAttr(llvm_arg_i, .zeroext, &o.builder); |
| 4661 | | o.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"); |
| 4662 | | }, |
| 4663 | | }; |
| 4664 | | } |
| 4665 | | |
| 4666 | | fn addByRefParamAttrsOld( |
| 4667 | | o: *Object, |
| 4668 | | attributes: *Builder.FunctionAttributes.Wip, |
| 4669 | | llvm_fn: *llvm.Value, |
| 4670 | | llvm_arg_i: u32, |
| 4671 | | alignment: Builder.Alignment, |
| 4672 | | byval_attr: bool, |
| 4673 | | param_llvm_ty: Builder.Type, |
| 4674 | | ) Allocator.Error!void { |
| 4675 | | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 4676 | | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4677 | | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); |
| 4678 | | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| 4679 | | o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); |
| 4680 | | o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment.toByteUnits() orelse 0); |
| 4681 | | if (byval_attr) { |
| 4682 | | try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); |
| 4683 | | llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder)); |
| 4684 | | } |
| 4505 | if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); |
| 4685 | 4506 | } |
| 4686 | 4507 | }; |
| 4687 | 4508 | |
| ... | ... | @@ -9503,16 +9324,16 @@ pub const FuncGen = struct { |
| 9503 | 9324 | |
| 9504 | 9325 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9505 | 9326 | defer attributes.deinit(&o.builder); |
| 9506 | | |
| 9507 | | function_index.toLlvm(&o.builder).setLinkage(.Internal); |
| 9508 | | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); |
| 9509 | | try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); |
| 9327 | try o.addCommonFnAttributes(&attributes); |
| 9328 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 9510 | 9329 | |
| 9511 | 9330 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; |
| 9512 | 9331 | function_index.ptr(&o.builder).call_conv = .fastcc; |
| 9513 | | function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder); |
| 9514 | 9332 | gop.value_ptr.* = function_index; |
| 9515 | 9333 | |
| 9334 | function_index.toLlvm(&o.builder).setLinkage(.Internal); |
| 9335 | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); |
| 9336 | |
| 9516 | 9337 | var wip = try Builder.WipFunction.init(&o.builder, function_index); |
| 9517 | 9338 | defer wip.deinit(); |
| 9518 | 9339 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| ... | ... | @@ -9577,16 +9398,16 @@ pub const FuncGen = struct { |
| 9577 | 9398 | |
| 9578 | 9399 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9579 | 9400 | defer attributes.deinit(&o.builder); |
| 9580 | | |
| 9581 | | function_index.toLlvm(&o.builder).setLinkage(.Internal); |
| 9582 | | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); |
| 9583 | | try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); |
| 9401 | try o.addCommonFnAttributes(&attributes); |
| 9402 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 9584 | 9403 | |
| 9585 | 9404 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; |
| 9586 | 9405 | function_index.ptr(&o.builder).call_conv = .fastcc; |
| 9587 | | function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder); |
| 9588 | 9406 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; |
| 9589 | 9407 | |
| 9408 | function_index.toLlvm(&o.builder).setLinkage(.Internal); |
| 9409 | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); |
| 9410 | |
| 9590 | 9411 | var wip = try Builder.WipFunction.init(&o.builder, function_index); |
| 9591 | 9412 | defer wip.deinit(); |
| 9592 | 9413 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| ... | ... | @@ -9659,14 +9480,14 @@ pub const FuncGen = struct { |
| 9659 | 9480 | |
| 9660 | 9481 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9661 | 9482 | defer attributes.deinit(&o.builder); |
| 9662 | | |
| 9663 | | function_index.toLlvm(&o.builder).setLinkage(.Internal); |
| 9664 | | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); |
| 9665 | | try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); |
| 9483 | try o.addCommonFnAttributes(&attributes); |
| 9484 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 9666 | 9485 | |
| 9667 | 9486 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; |
| 9668 | 9487 | function_index.ptr(&o.builder).call_conv = .fastcc; |
| 9669 | | function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder); |
| 9488 | |
| 9489 | function_index.toLlvm(&o.builder).setLinkage(.Internal); |
| 9490 | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); |
| 9670 | 9491 | |
| 9671 | 9492 | return function_index; |
| 9672 | 9493 | } |