| ... | @@ -1314,28 +1314,21 @@ pub const Object = struct { | ... | @@ -1314,28 +1314,21 @@ pub const Object = struct { |
| 1314 | | 1314 | |
| 1315 | if (func.analysis(ip).is_noinline) { | 1315 | if (func.analysis(ip).is_noinline) { |
| 1316 | try attributes.addFnAttr(.@"noinline", &o.builder); | 1316 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| 1317 | o.addFnAttr(llvm_func, "noinline"); | | |
| 1318 | } else { | 1317 | } else { |
| 1319 | _ = try attributes.removeFnAttr(.@"noinline"); | 1318 | _ = try attributes.removeFnAttr(.@"noinline"); |
| 1320 | Object.removeFnAttr(llvm_func, "noinline"); | | |
| 1321 | } | 1319 | } |
| 1322 | | 1320 | |
| 1323 | if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| { | 1321 | if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| { |
| 1324 | try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder); | 1322 | try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder); |
| 1325 | try attributes.addFnAttr(.@"noinline", &o.builder); | 1323 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| 1326 | o.addFnAttrInt(llvm_func, "alignstack", alignment); | | |
| 1327 | o.addFnAttr(llvm_func, "noinline"); | | |
| 1328 | } else { | 1324 | } else { |
| 1329 | _ = try attributes.removeFnAttr(.alignstack); | 1325 | _ = try attributes.removeFnAttr(.alignstack); |
| 1330 | Object.removeFnAttr(llvm_func, "alignstack"); | | |
| 1331 | } | 1326 | } |
| 1332 | | 1327 | |
| 1333 | if (func.analysis(ip).is_cold) { | 1328 | if (func.analysis(ip).is_cold) { |
| 1334 | try attributes.addFnAttr(.cold, &o.builder); | 1329 | try attributes.addFnAttr(.cold, &o.builder); |
| 1335 | o.addFnAttr(llvm_func, "cold"); | | |
| 1336 | } else { | 1330 | } else { |
| 1337 | _ = try attributes.removeFnAttr(.cold); | 1331 | _ = try attributes.removeFnAttr(.cold); |
| 1338 | Object.removeFnAttr(llvm_func, "cold"); | | |
| 1339 | } | 1332 | } |
| 1340 | | 1333 | |
| 1341 | // TODO: disable this if safety is off for the function scope | 1334 | // TODO: disable this if safety is off for the function scope |
| ... | @@ -1346,10 +1339,6 @@ pub const Object = struct { | ... | @@ -1346,10 +1339,6 @@ pub const Object = struct { |
| 1346 | .kind = try o.builder.string("stack-protector-buffer-size"), | 1339 | .kind = try o.builder.string("stack-protector-buffer-size"), |
| 1347 | .value = try o.builder.fmt("{d}", .{ssp_buf_size}), | 1340 | .value = try o.builder.fmt("{d}", .{ssp_buf_size}), |
| 1348 | } }, &o.builder); | 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 | // TODO: disable this if safety is off for the function scope | 1344 | // TODO: disable this if safety is off for the function scope |
| ... | @@ -1358,13 +1347,11 @@ pub const Object = struct { | ... | @@ -1358,13 +1347,11 @@ pub const Object = struct { |
| 1358 | .kind = try o.builder.string("probe-stack"), | 1347 | .kind = try o.builder.string("probe-stack"), |
| 1359 | .value = try o.builder.string("__zig_probe_stack"), | 1348 | .value = try o.builder.string("__zig_probe_stack"), |
| 1360 | } }, &o.builder); | 1349 | } }, &o.builder); |
| 1361 | o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); | | |
| 1362 | } else if (target.os.tag == .uefi) { | 1350 | } else if (target.os.tag == .uefi) { |
| 1363 | try attributes.addFnAttr(.{ .string = .{ | 1351 | try attributes.addFnAttr(.{ .string = .{ |
| 1364 | .kind = try o.builder.string("no-stack-arg-probe"), | 1352 | .kind = try o.builder.string("no-stack-arg-probe"), |
| 1365 | .value = .empty, | 1353 | .value = .empty, |
| 1366 | } }, &o.builder); | 1354 | } }, &o.builder); |
| 1367 | o.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); | | |
| 1368 | } | 1355 | } |
| 1369 | | 1356 | |
| 1370 | if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| { | 1357 | if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| { |
| ... | @@ -1389,14 +1376,8 @@ pub const Object = struct { | ... | @@ -1389,14 +1376,8 @@ pub const Object = struct { |
| 1389 | } else .none; | 1376 | } else .none; |
| 1390 | | 1377 | |
| 1391 | if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) { | 1378 | if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) { |
| 1392 | .signed => { | 1379 | .signed => try attributes.addRetAttr(.signext, &o.builder), |
| 1393 | try attributes.addRetAttr(.signext, &o.builder); | 1380 | .unsigned => try attributes.addRetAttr(.zeroext, &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 | }, | | |
| 1400 | }; | 1381 | }; |
| 1401 | | 1382 | |
| 1402 | const err_return_tracing = fn_info.return_type.toType().isError(mod) and | 1383 | const err_return_tracing = fn_info.return_type.toType().isError(mod) and |
| ... | @@ -1437,7 +1418,7 @@ pub const Object = struct { | ... | @@ -1437,7 +1418,7 @@ pub const Object = struct { |
| 1437 | } else { | 1418 | } else { |
| 1438 | args.appendAssumeCapacity(param); | 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 | llvm_arg_i += 1; | 1423 | llvm_arg_i += 1; |
| 1443 | }, | 1424 | }, |
| ... | @@ -1447,7 +1428,7 @@ pub const Object = struct { | ... | @@ -1447,7 +1428,7 @@ pub const Object = struct { |
| 1447 | const param = wip.arg(llvm_arg_i); | 1428 | const param = wip.arg(llvm_arg_i); |
| 1448 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | 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 | llvm_arg_i += 1; | 1432 | llvm_arg_i += 1; |
| 1452 | | 1433 | |
| 1453 | if (isByRef(param_ty, mod)) { | 1434 | if (isByRef(param_ty, mod)) { |
| ... | @@ -1463,7 +1444,6 @@ pub const Object = struct { | ... | @@ -1463,7 +1444,6 @@ pub const Object = struct { |
| 1463 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | 1444 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 1464 | | 1445 | |
| 1465 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); | 1446 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); |
| 1466 | o.addArgAttr(llvm_func, llvm_arg_i, "noundef"); | | |
| 1467 | llvm_arg_i += 1; | 1447 | llvm_arg_i += 1; |
| 1468 | | 1448 | |
| 1469 | if (isByRef(param_ty, mod)) { | 1449 | if (isByRef(param_ty, mod)) { |
| ... | @@ -1500,23 +1480,19 @@ pub const Object = struct { | ... | @@ -1500,23 +1480,19 @@ pub const Object = struct { |
| 1500 | if (math.cast(u5, it.zig_index - 1)) |i| { | 1480 | if (math.cast(u5, it.zig_index - 1)) |i| { |
| 1501 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { | 1481 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| 1502 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); | 1482 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 1503 | o.addArgAttr(llvm_func, llvm_arg_i, "noalias"); | | |
| 1504 | } | 1483 | } |
| 1505 | } | 1484 | } |
| 1506 | if (param_ty.zigTypeTag(mod) != .Optional) { | 1485 | if (param_ty.zigTypeTag(mod) != .Optional) { |
| 1507 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | 1486 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 1508 | o.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); | | |
| 1509 | } | 1487 | } |
| 1510 | if (ptr_info.flags.is_const) { | 1488 | if (ptr_info.flags.is_const) { |
| 1511 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); | 1489 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 1512 | o.addArgAttr(llvm_func, llvm_arg_i, "readonly"); | | |
| 1513 | } | 1490 | } |
| 1514 | const elem_align = Builder.Alignment.fromByteUnits( | 1491 | const elem_align = Builder.Alignment.fromByteUnits( |
| 1515 | ptr_info.flags.alignment.toByteUnitsOptional() orelse | 1492 | ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 1516 | @max(ptr_info.child.toType().abiAlignment(mod), 1), | 1493 | @max(ptr_info.child.toType().abiAlignment(mod), 1), |
| 1517 | ); | 1494 | ); |
| 1518 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); | 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 | const ptr_param = wip.arg(llvm_arg_i); | 1496 | const ptr_param = wip.arg(llvm_arg_i); |
| 1521 | llvm_arg_i += 1; | 1497 | llvm_arg_i += 1; |
| 1522 | const len_param = wip.arg(llvm_arg_i); | 1498 | const len_param = wip.arg(llvm_arg_i); |
| ... | @@ -1590,7 +1566,7 @@ pub const Object = struct { | ... | @@ -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 | var di_file: ?*llvm.DIFile = null; | 1571 | var di_file: ?*llvm.DIFile = null; |
| 1596 | var di_scope: ?*llvm.DIScope = null; | 1572 | var di_scope: ?*llvm.DIScope = null; |
| ... | @@ -2951,15 +2927,11 @@ pub const Object = struct { | ... | @@ -2951,15 +2927,11 @@ pub const Object = struct { |
| 2951 | .kind = try o.builder.string("wasm-import-name"), | 2927 | .kind = try o.builder.string("wasm-import-name"), |
| 2952 | .value = try o.builder.string(ip.stringToSlice(decl.name)), | 2928 | .value = try o.builder.string(ip.stringToSlice(decl.name)), |
| 2953 | } }, &o.builder); | 2929 | } }, &o.builder); |
| 2954 | o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name)); | | |
| 2955 | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { | 2930 | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { |
| 2956 | if (!std.mem.eql(u8, lib_name, "c")) { | 2931 | if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ |
| 2957 | try attributes.addFnAttr(.{ .string = .{ | 2932 | .kind = try o.builder.string("wasm-import-module"), |
| 2958 | .kind = try o.builder.string("wasm-import-module"), | 2933 | .value = try o.builder.string(lib_name), |
| 2959 | .value = try o.builder.string(lib_name), | 2934 | } }, &o.builder); |
| 2960 | } }, &o.builder); | | |
| 2961 | o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); | | |
| 2962 | } | | |
| 2963 | } | 2935 | } |
| 2964 | } | 2936 | } |
| 2965 | } | 2937 | } |
| ... | @@ -2969,12 +2941,9 @@ pub const Object = struct { | ... | @@ -2969,12 +2941,9 @@ pub const Object = struct { |
| 2969 | // Sret pointers must not be address 0 | 2941 | // Sret pointers must not be address 0 |
| 2970 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | 2942 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 2971 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); | 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 | const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType()); | 2945 | const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType()); |
| 2976 | try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder); | 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 | llvm_arg_i += 1; | 2948 | llvm_arg_i += 1; |
| 2980 | } | 2949 | } |
| ... | @@ -2984,7 +2953,6 @@ pub const Object = struct { | ... | @@ -2984,7 +2953,6 @@ pub const Object = struct { |
| 2984 | | 2953 | |
| 2985 | if (err_return_tracing) { | 2954 | if (err_return_tracing) { |
| 2986 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | 2955 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 2987 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); | | |
| 2988 | llvm_arg_i += 1; | 2956 | llvm_arg_i += 1; |
| 2989 | } | 2957 | } |
| 2990 | | 2958 | |
| ... | @@ -2995,7 +2963,6 @@ pub const Object = struct { | ... | @@ -2995,7 +2963,6 @@ pub const Object = struct { |
| 2995 | }, | 2963 | }, |
| 2996 | .Naked => { | 2964 | .Naked => { |
| 2997 | try attributes.addFnAttr(.naked, &o.builder); | 2965 | try attributes.addFnAttr(.naked, &o.builder); |
| 2998 | o.addFnAttr(llvm_fn, "naked"); | | |
| 2999 | }, | 2966 | }, |
| 3000 | .Async => { | 2967 | .Async => { |
| 3001 | function.call_conv = .fastcc; | 2968 | function.call_conv = .fastcc; |
| ... | @@ -3014,11 +2981,10 @@ pub const Object = struct { | ... | @@ -3014,11 +2981,10 @@ pub const Object = struct { |
| 3014 | } | 2981 | } |
| 3015 | | 2982 | |
| 3016 | // Function attributes that are independent of analysis results of the function body. | 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 | if (fn_info.return_type == .noreturn_type) { | 2986 | if (fn_info.return_type == .noreturn_type) { |
| 3020 | try attributes.addFnAttr(.noreturn, &o.builder); | 2987 | try attributes.addFnAttr(.noreturn, &o.builder); |
| 3021 | o.addFnAttr(llvm_fn, "noreturn"); | | |
| 3022 | } | 2988 | } |
| 3023 | | 2989 | |
| 3024 | // Add parameter attributes. We handle only the case of extern functions (no body) | 2990 | // Add parameter attributes. We handle only the case of extern functions (no body) |
| ... | @@ -3031,7 +2997,7 @@ pub const Object = struct { | ... | @@ -3031,7 +2997,7 @@ pub const Object = struct { |
| 3031 | const param_index = it.zig_index - 1; | 2997 | const param_index = it.zig_index - 1; |
| 3032 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); | 2998 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 3033 | if (!isByRef(param_ty, mod)) { | 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 | .byref => { | 3003 | .byref => { |
| ... | @@ -3039,11 +3005,10 @@ pub const Object = struct { | ... | @@ -3039,11 +3005,10 @@ pub const Object = struct { |
| 3039 | const param_llvm_ty = try o.lowerType(param_ty.toType()); | 3005 | const param_llvm_ty = try o.lowerType(param_ty.toType()); |
| 3040 | const alignment = | 3006 | const alignment = |
| 3041 | Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod)); | 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 | .byref_mut => { | 3010 | .byref_mut => { |
| 3045 | try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder); | 3011 | try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder); |
| 3046 | o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef"); | | |
| 3047 | }, | 3012 | }, |
| 3048 | // No attributes needed for these. | 3013 | // No attributes needed for these. |
| 3049 | .no_bits, | 3014 | .no_bits, |
| ... | @@ -3060,43 +3025,36 @@ pub const Object = struct { | ... | @@ -3060,43 +3025,36 @@ pub const Object = struct { |
| 3060 | }; | 3025 | }; |
| 3061 | } | 3026 | } |
| 3062 | | 3027 | |
| 3063 | function.attributes = try attributes.finish(&o.builder); | | |
| 3064 | | | |
| 3065 | try o.builder.llvm.globals.append(o.gpa, llvm_fn); | 3028 | try o.builder.llvm.globals.append(o.gpa, llvm_fn); |
| 3066 | gop.value_ptr.* = try o.builder.addGlobal(fqn, global); | 3029 | gop.value_ptr.* = try o.builder.addGlobal(fqn, global); |
| 3067 | try o.builder.functions.append(o.gpa, function); | 3030 | try o.builder.functions.append(o.gpa, function); |
| | 3031 | global.kind.function.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 3068 | return global.kind.function; | 3032 | return global.kind.function; |
| 3069 | } | 3033 | } |
| 3070 | | 3034 | |
| 3071 | fn addCommonFnAttributes( | 3035 | fn addCommonFnAttributes( |
| 3072 | o: *Object, | 3036 | o: *Object, |
| 3073 | attributes: *Builder.FunctionAttributes.Wip, | 3037 | attributes: *Builder.FunctionAttributes.Wip, |
| 3074 | llvm_fn: *llvm.Value, | | |
| 3075 | ) Allocator.Error!void { | 3038 | ) Allocator.Error!void { |
| 3076 | const comp = o.module.comp; | 3039 | const comp = o.module.comp; |
| 3077 | | 3040 | |
| 3078 | if (!comp.bin_file.options.red_zone) { | 3041 | if (!comp.bin_file.options.red_zone) { |
| 3079 | try attributes.addFnAttr(.noredzone, &o.builder); | 3042 | try attributes.addFnAttr(.noredzone, &o.builder); |
| 3080 | o.addFnAttr(llvm_fn, "noredzone"); | | |
| 3081 | } | 3043 | } |
| 3082 | if (comp.bin_file.options.omit_frame_pointer) { | 3044 | if (comp.bin_file.options.omit_frame_pointer) { |
| 3083 | try attributes.addFnAttr(.{ .string = .{ | 3045 | try attributes.addFnAttr(.{ .string = .{ |
| 3084 | .kind = try o.builder.string("frame-pointer"), | 3046 | .kind = try o.builder.string("frame-pointer"), |
| 3085 | .value = try o.builder.string("none"), | 3047 | .value = try o.builder.string("none"), |
| 3086 | } }, &o.builder); | 3048 | } }, &o.builder); |
| 3087 | o.addFnAttrString(llvm_fn, "frame-pointer", "none"); | | |
| 3088 | } else { | 3049 | } else { |
| 3089 | try attributes.addFnAttr(.{ .string = .{ | 3050 | try attributes.addFnAttr(.{ .string = .{ |
| 3090 | .kind = try o.builder.string("frame-pointer"), | 3051 | .kind = try o.builder.string("frame-pointer"), |
| 3091 | .value = try o.builder.string("all"), | 3052 | .value = try o.builder.string("all"), |
| 3092 | } }, &o.builder); | 3053 | } }, &o.builder); |
| 3093 | o.addFnAttrString(llvm_fn, "frame-pointer", "all"); | | |
| 3094 | } | 3054 | } |
| 3095 | try attributes.addFnAttr(.nounwind, &o.builder); | 3055 | try attributes.addFnAttr(.nounwind, &o.builder); |
| 3096 | o.addFnAttr(llvm_fn, "nounwind"); | | |
| 3097 | if (comp.unwind_tables) { | 3056 | if (comp.unwind_tables) { |
| 3098 | try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); | 3057 | try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); |
| 3099 | o.addFnAttrInt(llvm_fn, "uwtable", 2); | | |
| 3100 | } | 3058 | } |
| 3101 | if (comp.bin_file.options.skip_linker_dependencies or | 3059 | if (comp.bin_file.options.skip_linker_dependencies or |
| 3102 | comp.bin_file.options.no_builtin) | 3060 | comp.bin_file.options.no_builtin) |
| ... | @@ -3107,38 +3065,31 @@ pub const Object = struct { | ... | @@ -3107,38 +3065,31 @@ pub const Object = struct { |
| 3107 | // body of memcpy with a call to memcpy, which would then cause a stack | 3065 | // body of memcpy with a call to memcpy, which would then cause a stack |
| 3108 | // overflow instead of performing memcpy. | 3066 | // overflow instead of performing memcpy. |
| 3109 | try attributes.addFnAttr(.nobuiltin, &o.builder); | 3067 | try attributes.addFnAttr(.nobuiltin, &o.builder); |
| 3110 | o.addFnAttr(llvm_fn, "nobuiltin"); | | |
| 3111 | } | 3068 | } |
| 3112 | if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { | 3069 | if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { |
| 3113 | try attributes.addFnAttr(.minsize, &o.builder); | 3070 | try attributes.addFnAttr(.minsize, &o.builder); |
| 3114 | try attributes.addFnAttr(.optsize, &o.builder); | 3071 | try attributes.addFnAttr(.optsize, &o.builder); |
| 3115 | o.addFnAttr(llvm_fn, "minsize"); | | |
| 3116 | o.addFnAttr(llvm_fn, "optsize"); | | |
| 3117 | } | 3072 | } |
| 3118 | if (comp.bin_file.options.tsan) { | 3073 | if (comp.bin_file.options.tsan) { |
| 3119 | try attributes.addFnAttr(.sanitize_thread, &o.builder); | 3074 | try attributes.addFnAttr(.sanitize_thread, &o.builder); |
| 3120 | o.addFnAttr(llvm_fn, "sanitize_thread"); | | |
| 3121 | } | 3075 | } |
| 3122 | if (comp.getTarget().cpu.model.llvm_name) |s| { | 3076 | if (comp.getTarget().cpu.model.llvm_name) |s| { |
| 3123 | try attributes.addFnAttr(.{ .string = .{ | 3077 | try attributes.addFnAttr(.{ .string = .{ |
| 3124 | .kind = try o.builder.string("target-cpu"), | 3078 | .kind = try o.builder.string("target-cpu"), |
| 3125 | .value = try o.builder.string(s), | 3079 | .value = try o.builder.string(s), |
| 3126 | } }, &o.builder); | 3080 | } }, &o.builder); |
| 3127 | llvm_fn.addFunctionAttr("target-cpu", s); | | |
| 3128 | } | 3081 | } |
| 3129 | if (comp.bin_file.options.llvm_cpu_features) |s| { | 3082 | if (comp.bin_file.options.llvm_cpu_features) |s| { |
| 3130 | try attributes.addFnAttr(.{ .string = .{ | 3083 | try attributes.addFnAttr(.{ .string = .{ |
| 3131 | .kind = try o.builder.string("target-features"), | 3084 | .kind = try o.builder.string("target-features"), |
| 3132 | .value = try o.builder.string(std.mem.span(s)), | 3085 | .value = try o.builder.string(std.mem.span(s)), |
| 3133 | } }, &o.builder); | 3086 | } }, &o.builder); |
| 3134 | llvm_fn.addFunctionAttr("target-features", s); | | |
| 3135 | } | 3087 | } |
| 3136 | if (comp.getTarget().cpu.arch.isBpf()) { | 3088 | if (comp.getTarget().cpu.arch.isBpf()) { |
| 3137 | try attributes.addFnAttr(.{ .string = .{ | 3089 | try attributes.addFnAttr(.{ .string = .{ |
| 3138 | .kind = try o.builder.string("no-builtins"), | 3090 | .kind = try o.builder.string("no-builtins"), |
| 3139 | .value = .empty, | 3091 | .value = .empty, |
| 3140 | } }, &o.builder); | 3092 | } }, &o.builder); |
| 3141 | llvm_fn.addFunctionAttr("no-builtins", ""); | | |
| 3142 | } | 3093 | } |
| 3143 | } | 3094 | } |
| 3144 | | 3095 | |
| ... | @@ -4483,69 +4434,6 @@ pub const Object = struct { | ... | @@ -4483,69 +4434,6 @@ pub const Object = struct { |
| 4483 | return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty); | 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 | /// If the operand type of an atomic operation is not byte sized we need to | 4437 | /// If the operand type of an atomic operation is not byte sized we need to |
| 4550 | /// widen it before using it and then truncate the result. | 4438 | /// widen it before using it and then truncate the result. |
| 4551 | /// RMW exchange of floating-point values is bitcasted to same-sized integer | 4439 | /// RMW exchange of floating-point values is bitcasted to same-sized integer |
| ... | @@ -4608,80 +4496,13 @@ pub const Object = struct { | ... | @@ -4608,80 +4496,13 @@ pub const Object = struct { |
| 4608 | attributes: *Builder.FunctionAttributes.Wip, | 4496 | attributes: *Builder.FunctionAttributes.Wip, |
| 4609 | llvm_arg_i: u32, | 4497 | llvm_arg_i: u32, |
| 4610 | alignment: Builder.Alignment, | 4498 | alignment: Builder.Alignment, |
| 4611 | byval_attr: bool, | 4499 | byval: bool, |
| 4612 | param_llvm_ty: Builder.Type, | 4500 | param_llvm_ty: Builder.Type, |
| 4613 | ) Allocator.Error!void { | 4501 | ) Allocator.Error!void { |
| 4614 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | 4502 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 4615 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); | 4503 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4616 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); | 4504 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); |
| 4617 | if (byval_attr) { | 4505 | if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); |
| 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 | } | | |
| 4685 | } | 4506 | } |
| 4686 | }; | 4507 | }; |
| 4687 | | 4508 | |
| ... | @@ -9503,16 +9324,16 @@ pub const FuncGen = struct { | ... | @@ -9503,16 +9324,16 @@ pub const FuncGen = struct { |
| 9503 | | 9324 | |
| 9504 | var attributes: Builder.FunctionAttributes.Wip = .{}; | 9325 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9505 | defer attributes.deinit(&o.builder); | 9326 | defer attributes.deinit(&o.builder); |
| 9506 | | 9327 | try o.addCommonFnAttributes(&attributes); |
| 9507 | function_index.toLlvm(&o.builder).setLinkage(.Internal); | 9328 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 9508 | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); | | |
| 9509 | try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); | | |
| 9510 | | 9329 | |
| 9511 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; | 9330 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; |
| 9512 | function_index.ptr(&o.builder).call_conv = .fastcc; | 9331 | function_index.ptr(&o.builder).call_conv = .fastcc; |
| 9513 | function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder); | | |
| 9514 | gop.value_ptr.* = function_index; | 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 | var wip = try Builder.WipFunction.init(&o.builder, function_index); | 9337 | var wip = try Builder.WipFunction.init(&o.builder, function_index); |
| 9517 | defer wip.deinit(); | 9338 | defer wip.deinit(); |
| 9518 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; | 9339 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| ... | @@ -9577,16 +9398,16 @@ pub const FuncGen = struct { | ... | @@ -9577,16 +9398,16 @@ pub const FuncGen = struct { |
| 9577 | | 9398 | |
| 9578 | var attributes: Builder.FunctionAttributes.Wip = .{}; | 9399 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9579 | defer attributes.deinit(&o.builder); | 9400 | defer attributes.deinit(&o.builder); |
| 9580 | | 9401 | try o.addCommonFnAttributes(&attributes); |
| 9581 | function_index.toLlvm(&o.builder).setLinkage(.Internal); | 9402 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 9582 | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); | | |
| 9583 | try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); | | |
| 9584 | | 9403 | |
| 9585 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; | 9404 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; |
| 9586 | function_index.ptr(&o.builder).call_conv = .fastcc; | 9405 | function_index.ptr(&o.builder).call_conv = .fastcc; |
| 9587 | function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder); | | |
| 9588 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; | 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 | var wip = try Builder.WipFunction.init(&o.builder, function_index); | 9411 | var wip = try Builder.WipFunction.init(&o.builder, function_index); |
| 9591 | defer wip.deinit(); | 9412 | defer wip.deinit(); |
| 9592 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; | 9413 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| ... | @@ -9659,14 +9480,14 @@ pub const FuncGen = struct { | ... | @@ -9659,14 +9480,14 @@ pub const FuncGen = struct { |
| 9659 | | 9480 | |
| 9660 | var attributes: Builder.FunctionAttributes.Wip = .{}; | 9481 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9661 | defer attributes.deinit(&o.builder); | 9482 | defer attributes.deinit(&o.builder); |
| 9662 | | 9483 | try o.addCommonFnAttributes(&attributes); |
| 9663 | function_index.toLlvm(&o.builder).setLinkage(.Internal); | 9484 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 9664 | function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); | | |
| 9665 | try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); | | |
| 9666 | | 9485 | |
| 9667 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; | 9486 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; |
| 9668 | function_index.ptr(&o.builder).call_conv = .fastcc; | 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 | return function_index; | 9492 | return function_index; |
| 9672 | } | 9493 | } |