authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-07 03:36:11-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-08 21:32:50-04:00
log5b79f08ee82a48d84146706faf2229e7c298340d
tree183317a107a16cb78c8dd5c15cbd31fbebb53f95
parentb63d9745b5d7413acea4f4723ac9f696e3fb8149

llvm: finish converting attributes to use Builder and the C LLVM API


5 files changed, 133 insertions(+), 288 deletions(-)

src/codegen/llvm.zig+30-209
......@@ -1314,28 +1314,21 @@ pub const Object = struct {
13141314
13151315 if (func.analysis(ip).is_noinline) {
13161316 try attributes.addFnAttr(.@"noinline", &o.builder);
1317 o.addFnAttr(llvm_func, "noinline");
13181317 } else {
13191318 _ = try attributes.removeFnAttr(.@"noinline");
1320 Object.removeFnAttr(llvm_func, "noinline");
13211319 }
13221320
13231321 if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
13241322 try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder);
13251323 try attributes.addFnAttr(.@"noinline", &o.builder);
1326 o.addFnAttrInt(llvm_func, "alignstack", alignment);
1327 o.addFnAttr(llvm_func, "noinline");
13281324 } else {
13291325 _ = try attributes.removeFnAttr(.alignstack);
1330 Object.removeFnAttr(llvm_func, "alignstack");
13311326 }
13321327
13331328 if (func.analysis(ip).is_cold) {
13341329 try attributes.addFnAttr(.cold, &o.builder);
1335 o.addFnAttr(llvm_func, "cold");
13361330 } else {
13371331 _ = try attributes.removeFnAttr(.cold);
1338 Object.removeFnAttr(llvm_func, "cold");
13391332 }
13401333
13411334 // TODO: disable this if safety is off for the function scope
......@@ -1346,10 +1339,6 @@ pub const Object = struct {
13461339 .kind = try o.builder.string("stack-protector-buffer-size"),
13471340 .value = try o.builder.fmt("{d}", .{ssp_buf_size}),
13481341 } }, &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);
13531342 }
13541343
13551344 // TODO: disable this if safety is off for the function scope
......@@ -1358,13 +1347,11 @@ pub const Object = struct {
13581347 .kind = try o.builder.string("probe-stack"),
13591348 .value = try o.builder.string("__zig_probe_stack"),
13601349 } }, &o.builder);
1361 o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack");
13621350 } else if (target.os.tag == .uefi) {
13631351 try attributes.addFnAttr(.{ .string = .{
13641352 .kind = try o.builder.string("no-stack-arg-probe"),
13651353 .value = .empty,
13661354 } }, &o.builder);
1367 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
13681355 }
13691356
13701357 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| {
......@@ -1389,14 +1376,8 @@ pub const Object = struct {
13891376 } else .none;
13901377
13911378 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),
14001381 };
14011382
14021383 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
......@@ -1437,7 +1418,7 @@ pub const Object = struct {
14371418 } else {
14381419 args.appendAssumeCapacity(param);
14391420
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);
14411422 }
14421423 llvm_arg_i += 1;
14431424 },
......@@ -1447,7 +1428,7 @@ pub const Object = struct {
14471428 const param = wip.arg(llvm_arg_i);
14481429 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
14491430
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);
14511432 llvm_arg_i += 1;
14521433
14531434 if (isByRef(param_ty, mod)) {
......@@ -1463,7 +1444,6 @@ pub const Object = struct {
14631444 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
14641445
14651446 try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
1466 o.addArgAttr(llvm_func, llvm_arg_i, "noundef");
14671447 llvm_arg_i += 1;
14681448
14691449 if (isByRef(param_ty, mod)) {
......@@ -1500,23 +1480,19 @@ pub const Object = struct {
15001480 if (math.cast(u5, it.zig_index - 1)) |i| {
15011481 if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
15021482 try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
1503 o.addArgAttr(llvm_func, llvm_arg_i, "noalias");
15041483 }
15051484 }
15061485 if (param_ty.zigTypeTag(mod) != .Optional) {
15071486 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
1508 o.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
15091487 }
15101488 if (ptr_info.flags.is_const) {
15111489 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
1512 o.addArgAttr(llvm_func, llvm_arg_i, "readonly");
15131490 }
15141491 const elem_align = Builder.Alignment.fromByteUnits(
15151492 ptr_info.flags.alignment.toByteUnitsOptional() orelse
15161493 @max(ptr_info.child.toType().abiAlignment(mod), 1),
15171494 );
15181495 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);
15201496 const ptr_param = wip.arg(llvm_arg_i);
15211497 llvm_arg_i += 1;
15221498 const len_param = wip.arg(llvm_arg_i);
......@@ -1590,7 +1566,7 @@ pub const Object = struct {
15901566 }
15911567 }
15921568
1593 function.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
1569 function.setAttributes(try attributes.finish(&o.builder), &o.builder);
15941570
15951571 var di_file: ?*llvm.DIFile = null;
15961572 var di_scope: ?*llvm.DIScope = null;
......@@ -2951,15 +2927,11 @@ pub const Object = struct {
29512927 .kind = try o.builder.string("wasm-import-name"),
29522928 .value = try o.builder.string(ip.stringToSlice(decl.name)),
29532929 } }, &o.builder);
2954 o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
29552930 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);
29632935 }
29642936 }
29652937 }
......@@ -2969,12 +2941,9 @@ pub const Object = struct {
29692941 // Sret pointers must not be address 0
29702942 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
29712943 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");
29742944
29752945 const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType());
29762946 try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder);
2977 llvm_fn.addSretAttr(raw_llvm_ret_ty.toLlvm(&o.builder));
29782947
29792948 llvm_arg_i += 1;
29802949 }
......@@ -2984,7 +2953,6 @@ pub const Object = struct {
29842953
29852954 if (err_return_tracing) {
29862955 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
2987 o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
29882956 llvm_arg_i += 1;
29892957 }
29902958
......@@ -2995,7 +2963,6 @@ pub const Object = struct {
29952963 },
29962964 .Naked => {
29972965 try attributes.addFnAttr(.naked, &o.builder);
2998 o.addFnAttr(llvm_fn, "naked");
29992966 },
30002967 .Async => {
30012968 function.call_conv = .fastcc;
......@@ -3014,11 +2981,10 @@ pub const Object = struct {
30142981 }
30152982
30162983 // Function attributes that are independent of analysis results of the function body.
3017 try o.addCommonFnAttributes(&attributes, llvm_fn);
2984 try o.addCommonFnAttributes(&attributes);
30182985
30192986 if (fn_info.return_type == .noreturn_type) {
30202987 try attributes.addFnAttr(.noreturn, &o.builder);
3021 o.addFnAttr(llvm_fn, "noreturn");
30222988 }
30232989
30242990 // Add parameter attributes. We handle only the case of extern functions (no body)
......@@ -3031,7 +2997,7 @@ pub const Object = struct {
30312997 const param_index = it.zig_index - 1;
30322998 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
30332999 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);
30353001 }
30363002 },
30373003 .byref => {
......@@ -3039,11 +3005,10 @@ pub const Object = struct {
30393005 const param_llvm_ty = try o.lowerType(param_ty.toType());
30403006 const alignment =
30413007 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);
30433009 },
30443010 .byref_mut => {
30453011 try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder);
3046 o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef");
30473012 },
30483013 // No attributes needed for these.
30493014 .no_bits,
......@@ -3060,43 +3025,36 @@ pub const Object = struct {
30603025 };
30613026 }
30623027
3063 function.attributes = try attributes.finish(&o.builder);
3064
30653028 try o.builder.llvm.globals.append(o.gpa, llvm_fn);
30663029 gop.value_ptr.* = try o.builder.addGlobal(fqn, global);
30673030 try o.builder.functions.append(o.gpa, function);
3031 global.kind.function.setAttributes(try attributes.finish(&o.builder), &o.builder);
30683032 return global.kind.function;
30693033 }
30703034
30713035 fn addCommonFnAttributes(
30723036 o: *Object,
30733037 attributes: *Builder.FunctionAttributes.Wip,
3074 llvm_fn: *llvm.Value,
30753038 ) Allocator.Error!void {
30763039 const comp = o.module.comp;
30773040
30783041 if (!comp.bin_file.options.red_zone) {
30793042 try attributes.addFnAttr(.noredzone, &o.builder);
3080 o.addFnAttr(llvm_fn, "noredzone");
30813043 }
30823044 if (comp.bin_file.options.omit_frame_pointer) {
30833045 try attributes.addFnAttr(.{ .string = .{
30843046 .kind = try o.builder.string("frame-pointer"),
30853047 .value = try o.builder.string("none"),
30863048 } }, &o.builder);
3087 o.addFnAttrString(llvm_fn, "frame-pointer", "none");
30883049 } else {
30893050 try attributes.addFnAttr(.{ .string = .{
30903051 .kind = try o.builder.string("frame-pointer"),
30913052 .value = try o.builder.string("all"),
30923053 } }, &o.builder);
3093 o.addFnAttrString(llvm_fn, "frame-pointer", "all");
30943054 }
30953055 try attributes.addFnAttr(.nounwind, &o.builder);
3096 o.addFnAttr(llvm_fn, "nounwind");
30973056 if (comp.unwind_tables) {
30983057 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
3099 o.addFnAttrInt(llvm_fn, "uwtable", 2);
31003058 }
31013059 if (comp.bin_file.options.skip_linker_dependencies or
31023060 comp.bin_file.options.no_builtin)
......@@ -3107,38 +3065,31 @@ pub const Object = struct {
31073065 // body of memcpy with a call to memcpy, which would then cause a stack
31083066 // overflow instead of performing memcpy.
31093067 try attributes.addFnAttr(.nobuiltin, &o.builder);
3110 o.addFnAttr(llvm_fn, "nobuiltin");
31113068 }
31123069 if (comp.bin_file.options.optimize_mode == .ReleaseSmall) {
31133070 try attributes.addFnAttr(.minsize, &o.builder);
31143071 try attributes.addFnAttr(.optsize, &o.builder);
3115 o.addFnAttr(llvm_fn, "minsize");
3116 o.addFnAttr(llvm_fn, "optsize");
31173072 }
31183073 if (comp.bin_file.options.tsan) {
31193074 try attributes.addFnAttr(.sanitize_thread, &o.builder);
3120 o.addFnAttr(llvm_fn, "sanitize_thread");
31213075 }
31223076 if (comp.getTarget().cpu.model.llvm_name) |s| {
31233077 try attributes.addFnAttr(.{ .string = .{
31243078 .kind = try o.builder.string("target-cpu"),
31253079 .value = try o.builder.string(s),
31263080 } }, &o.builder);
3127 llvm_fn.addFunctionAttr("target-cpu", s);
31283081 }
31293082 if (comp.bin_file.options.llvm_cpu_features) |s| {
31303083 try attributes.addFnAttr(.{ .string = .{
31313084 .kind = try o.builder.string("target-features"),
31323085 .value = try o.builder.string(std.mem.span(s)),
31333086 } }, &o.builder);
3134 llvm_fn.addFunctionAttr("target-features", s);
31353087 }
31363088 if (comp.getTarget().cpu.arch.isBpf()) {
31373089 try attributes.addFnAttr(.{ .string = .{
31383090 .kind = try o.builder.string("no-builtins"),
31393091 .value = .empty,
31403092 } }, &o.builder);
3141 llvm_fn.addFunctionAttr("no-builtins", "");
31423093 }
31433094 }
31443095
......@@ -4483,69 +4434,6 @@ pub const Object = struct {
44834434 return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty);
44844435 }
44854436
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
45494437 /// If the operand type of an atomic operation is not byte sized we need to
45504438 /// widen it before using it and then truncate the result.
45514439 /// RMW exchange of floating-point values is bitcasted to same-sized integer
......@@ -4608,80 +4496,13 @@ pub const Object = struct {
46084496 attributes: *Builder.FunctionAttributes.Wip,
46094497 llvm_arg_i: u32,
46104498 alignment: Builder.Alignment,
4611 byval_attr: bool,
4499 byval: bool,
46124500 param_llvm_ty: Builder.Type,
46134501 ) Allocator.Error!void {
46144502 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
46154503 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
46164504 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);
46854506 }
46864507};
46874508
......@@ -9503,16 +9324,16 @@ pub const FuncGen = struct {
95039324
95049325 var attributes: Builder.FunctionAttributes.Wip = .{};
95059326 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);
95109329
95119330 function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
95129331 function_index.ptr(&o.builder).call_conv = .fastcc;
9513 function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
95149332 gop.value_ptr.* = function_index;
95159333
9334 function_index.toLlvm(&o.builder).setLinkage(.Internal);
9335 function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
9336
95169337 var wip = try Builder.WipFunction.init(&o.builder, function_index);
95179338 defer wip.deinit();
95189339 wip.cursor = .{ .block = try wip.block(0, "Entry") };
......@@ -9577,16 +9398,16 @@ pub const FuncGen = struct {
95779398
95789399 var attributes: Builder.FunctionAttributes.Wip = .{};
95799400 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);
95849403
95859404 function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
95869405 function_index.ptr(&o.builder).call_conv = .fastcc;
9587 function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
95889406 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
95899407
9408 function_index.toLlvm(&o.builder).setLinkage(.Internal);
9409 function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
9410
95909411 var wip = try Builder.WipFunction.init(&o.builder, function_index);
95919412 defer wip.deinit();
95929413 wip.cursor = .{ .block = try wip.block(0, "Entry") };
......@@ -9659,14 +9480,14 @@ pub const FuncGen = struct {
96599480
96609481 var attributes: Builder.FunctionAttributes.Wip = .{};
96619482 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);
96669485
96679486 function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
96689487 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);
96709491
96719492 return function_index;
96729493 }
src/codegen/llvm/Builder.zig+98-11
......@@ -1349,21 +1349,29 @@ pub const Attribute = union(Kind) {
13491349 //sanitize_memtag,
13501350 sanitize_address_dyninit,
13511351
1352 string = std.math.maxInt(u31) - 1,
1353 none = std.math.maxInt(u31),
1352 string = std.math.maxInt(u31),
1353 none = std.math.maxInt(u32),
13541354 _,
13551355
13561356 pub const len = @typeInfo(Kind).Enum.fields.len - 2;
13571357
13581358 pub fn fromString(str: String) Kind {
13591359 assert(!str.isAnon());
1360 return @enumFromInt(@intFromEnum(str));
1360 const kind: Kind = @enumFromInt(@intFromEnum(str));
1361 assert(kind != .none);
1362 return kind;
13611363 }
13621364
13631365 fn toString(self: Kind) ?String {
1366 assert(self != .none);
13641367 const str: String = @enumFromInt(@intFromEnum(self));
13651368 return if (str.isAnon()) null else str;
13661369 }
1370
1371 fn toLlvm(self: Kind, builder: *const Builder) *c_uint {
1372 assert(builder.useLibLlvm());
1373 return &builder.llvm.attribute_kind_ids.?[@intFromEnum(self)];
1374 }
13671375 };
13681376
13691377 pub const FpClass = packed struct(u32) {
......@@ -3147,6 +3155,86 @@ pub const Function = struct {
31473155 return self.toConst(builder).toValue();
31483156 }
31493157
3158 pub fn setAttributes(
3159 self: Index,
3160 new_function_attributes: FunctionAttributes,
3161 builder: *Builder,
3162 ) void {
3163 if (builder.useLibLlvm()) {
3164 const llvm_function = self.toLlvm(builder);
3165 const old_function_attributes = self.ptrConst(builder).attributes;
3166 for (0..@max(
3167 old_function_attributes.slice(builder).len,
3168 new_function_attributes.slice(builder).len,
3169 )) |function_attribute_index| {
3170 const llvm_attribute_index =
3171 @as(llvm.AttributeIndex, @intCast(function_attribute_index)) -% 1;
3172 const old_attributes_slice =
3173 old_function_attributes.get(function_attribute_index, builder).slice(builder);
3174 const new_attributes_slice =
3175 new_function_attributes.get(function_attribute_index, builder).slice(builder);
3176 var old_attribute_index: usize = 0;
3177 var new_attribute_index: usize = 0;
3178 while (true) {
3179 const old_attribute_kind = if (old_attribute_index < old_attributes_slice.len)
3180 old_attributes_slice[old_attribute_index].getKind(builder)
3181 else
3182 .none;
3183 const new_attribute_kind = if (new_attribute_index < new_attributes_slice.len)
3184 new_attributes_slice[new_attribute_index].getKind(builder)
3185 else
3186 .none;
3187 switch (std.math.order(
3188 @intFromEnum(old_attribute_kind),
3189 @intFromEnum(new_attribute_kind),
3190 )) {
3191 .lt => {
3192 // Removed
3193 if (old_attribute_kind.toString()) |name| {
3194 const slice = name.slice(builder).?;
3195 llvm_function.removeStringAttributeAtIndex(
3196 llvm_attribute_index,
3197 slice.ptr,
3198 @intCast(slice.len),
3199 );
3200 } else {
3201 const llvm_kind_id = old_attribute_kind.toLlvm(builder).*;
3202 assert(llvm_kind_id != 0);
3203 llvm_function.removeEnumAttributeAtIndex(
3204 llvm_attribute_index,
3205 llvm_kind_id,
3206 );
3207 }
3208 old_attribute_index += 1;
3209 continue;
3210 },
3211 .eq => {
3212 // Iteration finished
3213 if (old_attribute_kind == .none) break;
3214 // No change
3215 if (old_attributes_slice[old_attribute_index] ==
3216 new_attributes_slice[new_attribute_index])
3217 {
3218 old_attribute_index += 1;
3219 new_attribute_index += 1;
3220 continue;
3221 }
3222 old_attribute_index += 1;
3223 },
3224 .gt => {},
3225 }
3226 // New or changed
3227 llvm_function.addAttributeAtIndex(
3228 llvm_attribute_index,
3229 new_attributes_slice[new_attribute_index].toLlvm(builder),
3230 );
3231 new_attribute_index += 1;
3232 }
3233 }
3234 }
3235 self.ptr(builder).attributes = new_function_attributes;
3236 }
3237
31503238 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
31513239 return self.ptrConst(builder).global.toLlvm(builder);
31523240 }
......@@ -5048,9 +5136,8 @@ pub const WipFunction = struct {
50485136 .tail, .tail_fast => .Tail,
50495137 });
50505138 for (0.., function_attributes.slice(self.builder)) |index, attributes| {
5051 const attribute_index = @as(llvm.AttributeIndex, @intCast(index)) -% 1;
50525139 for (attributes.slice(self.builder)) |attribute| llvm_instruction.addCallSiteAttribute(
5053 attribute_index,
5140 @as(llvm.AttributeIndex, @intCast(index)) -% 1,
50545141 attribute.toLlvm(self.builder),
50555142 );
50565143 }
......@@ -7368,16 +7455,16 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde
73687455 gop.value_ptr.* = {};
73697456 if (self.useLibLlvm()) self.llvm.attributes.appendAssumeCapacity(switch (attribute) {
73707457 else => llvm_attr: {
7371 const kind_id = &self.llvm.attribute_kind_ids.?[@intFromEnum(attribute)];
7372 if (kind_id.* == 0) {
7458 const llvm_kind_id = attribute.getKind().toLlvm(self);
7459 if (llvm_kind_id.* == 0) {
73737460 const name = @tagName(attribute);
7374 kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);
7375 assert(kind_id.* != 0);
7461 llvm_kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);
7462 assert(llvm_kind_id.* != 0);
73767463 }
73777464 break :llvm_attr switch (attribute) {
73787465 else => switch (attribute) {
73797466 inline else => |value| self.llvm.context.createEnumAttribute(
7380 kind_id.*,
7467 llvm_kind_id.*,
73817468 switch (@TypeOf(value)) {
73827469 void => 0,
73837470 u32 => value,
......@@ -7411,7 +7498,7 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde
74117498 .inalloca,
74127499 .sret,
74137500 .elementtype,
7414 => |ty| self.llvm.context.createTypeAttribute(kind_id.*, ty.toLlvm(self)),
7501 => |ty| self.llvm.context.createTypeAttribute(llvm_kind_id.*, ty.toLlvm(self)),
74157502 .string, .none => unreachable,
74167503 };
74177504 },
src/codegen/llvm/bindings.zig+5-8
......@@ -115,12 +115,15 @@ pub const Context = opaque {
115115};
116116
117117pub const Value = opaque {
118 pub const addAttributeAtIndex = ZigLLVMAddAttributeAtIndex;
119 extern fn ZigLLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void;
118 pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
119 extern fn LLVMAddAttributeAtIndex(F: *Value, Idx: AttributeIndex, A: *Attribute) void;
120120
121121 pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;
122122 extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void;
123123
124 pub const removeStringAttributeAtIndex = LLVMRemoveStringAttributeAtIndex;
125 extern fn LLVMRemoveStringAttributeAtIndex(F: *Value, Idx: AttributeIndex, K: [*]const u8, KLen: c_uint) void;
126
124127 pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;
125128 extern fn LLVMGetFirstBasicBlock(Fn: *Value) ?*BasicBlock;
126129
......@@ -342,9 +345,6 @@ pub const Value = opaque {
342345 pub const deleteFunction = LLVMDeleteFunction;
343346 extern fn LLVMDeleteFunction(Fn: *Value) void;
344347
345 pub const addSretAttr = ZigLLVMAddSretAttr;
346 extern fn ZigLLVMAddSretAttr(fn_ref: *Value, type_val: *Type) void;
347
348348 pub const getParam = LLVMGetParam;
349349 extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
350350
......@@ -369,9 +369,6 @@ pub const Value = opaque {
369369 pub const getAlignment = LLVMGetAlignment;
370370 extern fn LLVMGetAlignment(V: *Value) c_uint;
371371
372 pub const addFunctionAttr = ZigLLVMAddFunctionAttr;
373 extern fn ZigLLVMAddFunctionAttr(Fn: *Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void;
374
375372 pub const addByValAttr = ZigLLVMAddByValAttr;
376373 extern fn ZigLLVMAddByValAttr(Fn: *Value, ArgNo: c_uint, type: *Type) void;
377374
src/zig_llvm.cpp-46
......@@ -408,14 +408,6 @@ void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCall
408408 unwrap<CallInst>(Call)->setTailCallKind(TCK);
409409}
410410
411void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A) {
412 if (isa<Function>(unwrap(Val))) {
413 unwrap<Function>(Val)->addAttributeAtIndex(Idx, unwrap(A));
414 } else {
415 unwrap<CallInst>(Val)->addAttributeAtIndex(Idx, unwrap(A));
416 }
417}
418
419411LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
420412 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile)
421413{
......@@ -950,36 +942,6 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {
950942 }
951943}
952944
953void ZigLLVMAddByValAttr(LLVMValueRef Val, unsigned ArgNo, LLVMTypeRef type_val) {
954 if (isa<Function>(unwrap(Val))) {
955 Function *func = unwrap<Function>(Val);
956 AttrBuilder attr_builder(func->getContext());
957 Type *llvm_type = unwrap<Type>(type_val);
958 attr_builder.addByValAttr(llvm_type);
959 func->addParamAttrs(ArgNo, attr_builder);
960 } else {
961 CallInst *call = unwrap<CallInst>(Val);
962 AttrBuilder attr_builder(call->getContext());
963 Type *llvm_type = unwrap<Type>(type_val);
964 attr_builder.addByValAttr(llvm_type);
965 // NOTE: +1 here since index 0 refers to the return value
966 call->addAttributeAtIndex(ArgNo + 1, attr_builder.getAttribute(Attribute::ByVal));
967 }
968}
969
970void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) {
971 Function *func = unwrap<Function>(fn_ref);
972 AttrBuilder attr_builder(func->getContext());
973 Type *llvm_type = unwrap<Type>(type_val);
974 attr_builder.addStructRetAttr(llvm_type);
975 func->addParamAttrs(0, attr_builder);
976}
977
978void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) {
979 Function *func = unwrap<Function>(fn_ref);
980 func->addFnAttr(attr_name, attr_value);
981}
982
983945void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
984946 cl::ParseCommandLineOptions(argc, argv);
985947}
......@@ -1172,14 +1134,6 @@ bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disab
11721134 return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
11731135}
11741136
1175inline LLVMAttributeRef wrap(Attribute Attr) {
1176 return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer());
1177}
1178
1179inline Attribute unwrap(LLVMAttributeRef Attr) {
1180 return Attribute::fromRawPointer(Attr);
1181}
1182
11831137LLVMValueRef ZigLLVMBuildAndReduce(LLVMBuilderRef B, LLVMValueRef Val) {
11841138 return wrap(unwrap(B)->CreateAndReduce(unwrap(Val)));
11851139}
src/zig_llvm.h-14
......@@ -122,15 +122,6 @@ enum ZigLLVM_CallingConv {
122122 ZigLLVM_MaxID = 1023,
123123};
124124
125enum ZigLLVM_CallAttr {
126 ZigLLVM_CallAttrAuto,
127 ZigLLVM_CallAttrNeverTail,
128 ZigLLVM_CallAttrNeverInline,
129 ZigLLVM_CallAttrAlwaysTail,
130 ZigLLVM_CallAttrAlwaysInline,
131};
132ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A);
133
134125ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
135126 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
136127
......@@ -301,11 +292,6 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu
301292
302293ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
303294
304ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
305ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val);
306ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val);
307ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);
308
309295ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);
310296
311297ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression);