mirror of
https://github.com/ziglang/zig.git
synced 2026-01-16 12:25:21 +00:00
llvm: finish converting attributes to use Builder and the C LLVM API
This commit is contained in:
parent
b63d9745b5
commit
5b79f08ee8
@ -1314,28 +1314,21 @@ pub const Object = struct {
|
||||
|
||||
if (func.analysis(ip).is_noinline) {
|
||||
try attributes.addFnAttr(.@"noinline", &o.builder);
|
||||
o.addFnAttr(llvm_func, "noinline");
|
||||
} else {
|
||||
_ = try attributes.removeFnAttr(.@"noinline");
|
||||
Object.removeFnAttr(llvm_func, "noinline");
|
||||
}
|
||||
|
||||
if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
|
||||
try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder);
|
||||
try attributes.addFnAttr(.@"noinline", &o.builder);
|
||||
o.addFnAttrInt(llvm_func, "alignstack", alignment);
|
||||
o.addFnAttr(llvm_func, "noinline");
|
||||
} else {
|
||||
_ = try attributes.removeFnAttr(.alignstack);
|
||||
Object.removeFnAttr(llvm_func, "alignstack");
|
||||
}
|
||||
|
||||
if (func.analysis(ip).is_cold) {
|
||||
try attributes.addFnAttr(.cold, &o.builder);
|
||||
o.addFnAttr(llvm_func, "cold");
|
||||
} else {
|
||||
_ = try attributes.removeFnAttr(.cold);
|
||||
Object.removeFnAttr(llvm_func, "cold");
|
||||
}
|
||||
|
||||
// TODO: disable this if safety is off for the function scope
|
||||
@ -1346,10 +1339,6 @@ pub const Object = struct {
|
||||
.kind = try o.builder.string("stack-protector-buffer-size"),
|
||||
.value = try o.builder.fmt("{d}", .{ssp_buf_size}),
|
||||
} }, &o.builder);
|
||||
var buf: [12]u8 = undefined;
|
||||
const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable;
|
||||
o.addFnAttr(llvm_func, "sspstrong");
|
||||
o.addFnAttrString(llvm_func, "stack-protector-buffer-size", arg);
|
||||
}
|
||||
|
||||
// TODO: disable this if safety is off for the function scope
|
||||
@ -1358,13 +1347,11 @@ pub const Object = struct {
|
||||
.kind = try o.builder.string("probe-stack"),
|
||||
.value = try o.builder.string("__zig_probe_stack"),
|
||||
} }, &o.builder);
|
||||
o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack");
|
||||
} else if (target.os.tag == .uefi) {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("no-stack-arg-probe"),
|
||||
.value = .empty,
|
||||
} }, &o.builder);
|
||||
o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
|
||||
}
|
||||
|
||||
if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| {
|
||||
@ -1389,14 +1376,8 @@ pub const Object = struct {
|
||||
} else .none;
|
||||
|
||||
if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) {
|
||||
.signed => {
|
||||
try attributes.addRetAttr(.signext, &o.builder);
|
||||
o.addAttr(llvm_func, 0, "signext");
|
||||
},
|
||||
.unsigned => {
|
||||
try attributes.addRetAttr(.zeroext, &o.builder);
|
||||
o.addAttr(llvm_func, 0, "zeroext");
|
||||
},
|
||||
.signed => try attributes.addRetAttr(.signext, &o.builder),
|
||||
.unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
|
||||
};
|
||||
|
||||
const err_return_tracing = fn_info.return_type.toType().isError(mod) and
|
||||
@ -1437,7 +1418,7 @@ pub const Object = struct {
|
||||
} else {
|
||||
args.appendAssumeCapacity(param);
|
||||
|
||||
try o.addByValParamAttrsOld(&attributes, llvm_func, param_ty, param_index, fn_info, llvm_arg_i);
|
||||
try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, llvm_arg_i);
|
||||
}
|
||||
llvm_arg_i += 1;
|
||||
},
|
||||
@ -1447,7 +1428,7 @@ pub const Object = struct {
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
|
||||
|
||||
try o.addByRefParamAttrsOld(&attributes, llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);
|
||||
try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);
|
||||
llvm_arg_i += 1;
|
||||
|
||||
if (isByRef(param_ty, mod)) {
|
||||
@ -1463,7 +1444,6 @@ pub const Object = struct {
|
||||
const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
|
||||
|
||||
try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
|
||||
o.addArgAttr(llvm_func, llvm_arg_i, "noundef");
|
||||
llvm_arg_i += 1;
|
||||
|
||||
if (isByRef(param_ty, mod)) {
|
||||
@ -1500,23 +1480,19 @@ pub const Object = struct {
|
||||
if (math.cast(u5, it.zig_index - 1)) |i| {
|
||||
if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
|
||||
o.addArgAttr(llvm_func, llvm_arg_i, "noalias");
|
||||
}
|
||||
}
|
||||
if (param_ty.zigTypeTag(mod) != .Optional) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
o.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
|
||||
}
|
||||
if (ptr_info.flags.is_const) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
|
||||
o.addArgAttr(llvm_func, llvm_arg_i, "readonly");
|
||||
}
|
||||
const elem_align = Builder.Alignment.fromByteUnits(
|
||||
ptr_info.flags.alignment.toByteUnitsOptional() orelse
|
||||
@max(ptr_info.child.toType().abiAlignment(mod), 1),
|
||||
);
|
||||
try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder);
|
||||
o.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0);
|
||||
const ptr_param = wip.arg(llvm_arg_i);
|
||||
llvm_arg_i += 1;
|
||||
const len_param = wip.arg(llvm_arg_i);
|
||||
@ -1590,7 +1566,7 @@ pub const Object = struct {
|
||||
}
|
||||
}
|
||||
|
||||
function.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
|
||||
function.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
|
||||
var di_file: ?*llvm.DIFile = null;
|
||||
var di_scope: ?*llvm.DIScope = null;
|
||||
@ -2951,15 +2927,11 @@ pub const Object = struct {
|
||||
.kind = try o.builder.string("wasm-import-name"),
|
||||
.value = try o.builder.string(ip.stringToSlice(decl.name)),
|
||||
} }, &o.builder);
|
||||
o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
|
||||
if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
|
||||
if (!std.mem.eql(u8, lib_name, "c")) {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("wasm-import-module"),
|
||||
.value = try o.builder.string(lib_name),
|
||||
} }, &o.builder);
|
||||
o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
|
||||
}
|
||||
if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("wasm-import-module"),
|
||||
.value = try o.builder.string(lib_name),
|
||||
} }, &o.builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2969,12 +2941,9 @@ pub const Object = struct {
|
||||
// Sret pointers must not be address 0
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); // Sret pointers must not be address 0
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "noalias");
|
||||
|
||||
const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType());
|
||||
try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder);
|
||||
llvm_fn.addSretAttr(raw_llvm_ret_ty.toLlvm(&o.builder));
|
||||
|
||||
llvm_arg_i += 1;
|
||||
}
|
||||
@ -2984,7 +2953,6 @@ pub const Object = struct {
|
||||
|
||||
if (err_return_tracing) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
|
||||
llvm_arg_i += 1;
|
||||
}
|
||||
|
||||
@ -2995,7 +2963,6 @@ pub const Object = struct {
|
||||
},
|
||||
.Naked => {
|
||||
try attributes.addFnAttr(.naked, &o.builder);
|
||||
o.addFnAttr(llvm_fn, "naked");
|
||||
},
|
||||
.Async => {
|
||||
function.call_conv = .fastcc;
|
||||
@ -3014,11 +2981,10 @@ pub const Object = struct {
|
||||
}
|
||||
|
||||
// Function attributes that are independent of analysis results of the function body.
|
||||
try o.addCommonFnAttributes(&attributes, llvm_fn);
|
||||
try o.addCommonFnAttributes(&attributes);
|
||||
|
||||
if (fn_info.return_type == .noreturn_type) {
|
||||
try attributes.addFnAttr(.noreturn, &o.builder);
|
||||
o.addFnAttr(llvm_fn, "noreturn");
|
||||
}
|
||||
|
||||
// Add parameter attributes. We handle only the case of extern functions (no body)
|
||||
@ -3031,7 +2997,7 @@ pub const Object = struct {
|
||||
const param_index = it.zig_index - 1;
|
||||
const param_ty = fn_info.param_types.get(ip)[param_index].toType();
|
||||
if (!isByRef(param_ty, mod)) {
|
||||
try o.addByValParamAttrsOld(&attributes, llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
|
||||
try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
|
||||
}
|
||||
},
|
||||
.byref => {
|
||||
@ -3039,11 +3005,10 @@ pub const Object = struct {
|
||||
const param_llvm_ty = try o.lowerType(param_ty.toType());
|
||||
const alignment =
|
||||
Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod));
|
||||
try o.addByRefParamAttrsOld(&attributes, llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
|
||||
try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
|
||||
},
|
||||
.byref_mut => {
|
||||
try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder);
|
||||
o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef");
|
||||
},
|
||||
// No attributes needed for these.
|
||||
.no_bits,
|
||||
@ -3060,43 +3025,36 @@ pub const Object = struct {
|
||||
};
|
||||
}
|
||||
|
||||
function.attributes = try attributes.finish(&o.builder);
|
||||
|
||||
try o.builder.llvm.globals.append(o.gpa, llvm_fn);
|
||||
gop.value_ptr.* = try o.builder.addGlobal(fqn, global);
|
||||
try o.builder.functions.append(o.gpa, function);
|
||||
global.kind.function.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
return global.kind.function;
|
||||
}
|
||||
|
||||
fn addCommonFnAttributes(
|
||||
o: *Object,
|
||||
attributes: *Builder.FunctionAttributes.Wip,
|
||||
llvm_fn: *llvm.Value,
|
||||
) Allocator.Error!void {
|
||||
const comp = o.module.comp;
|
||||
|
||||
if (!comp.bin_file.options.red_zone) {
|
||||
try attributes.addFnAttr(.noredzone, &o.builder);
|
||||
o.addFnAttr(llvm_fn, "noredzone");
|
||||
}
|
||||
if (comp.bin_file.options.omit_frame_pointer) {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("frame-pointer"),
|
||||
.value = try o.builder.string("none"),
|
||||
} }, &o.builder);
|
||||
o.addFnAttrString(llvm_fn, "frame-pointer", "none");
|
||||
} else {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("frame-pointer"),
|
||||
.value = try o.builder.string("all"),
|
||||
} }, &o.builder);
|
||||
o.addFnAttrString(llvm_fn, "frame-pointer", "all");
|
||||
}
|
||||
try attributes.addFnAttr(.nounwind, &o.builder);
|
||||
o.addFnAttr(llvm_fn, "nounwind");
|
||||
if (comp.unwind_tables) {
|
||||
try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
|
||||
o.addFnAttrInt(llvm_fn, "uwtable", 2);
|
||||
}
|
||||
if (comp.bin_file.options.skip_linker_dependencies or
|
||||
comp.bin_file.options.no_builtin)
|
||||
@ -3107,38 +3065,31 @@ pub const Object = struct {
|
||||
// body of memcpy with a call to memcpy, which would then cause a stack
|
||||
// overflow instead of performing memcpy.
|
||||
try attributes.addFnAttr(.nobuiltin, &o.builder);
|
||||
o.addFnAttr(llvm_fn, "nobuiltin");
|
||||
}
|
||||
if (comp.bin_file.options.optimize_mode == .ReleaseSmall) {
|
||||
try attributes.addFnAttr(.minsize, &o.builder);
|
||||
try attributes.addFnAttr(.optsize, &o.builder);
|
||||
o.addFnAttr(llvm_fn, "minsize");
|
||||
o.addFnAttr(llvm_fn, "optsize");
|
||||
}
|
||||
if (comp.bin_file.options.tsan) {
|
||||
try attributes.addFnAttr(.sanitize_thread, &o.builder);
|
||||
o.addFnAttr(llvm_fn, "sanitize_thread");
|
||||
}
|
||||
if (comp.getTarget().cpu.model.llvm_name) |s| {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("target-cpu"),
|
||||
.value = try o.builder.string(s),
|
||||
} }, &o.builder);
|
||||
llvm_fn.addFunctionAttr("target-cpu", s);
|
||||
}
|
||||
if (comp.bin_file.options.llvm_cpu_features) |s| {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("target-features"),
|
||||
.value = try o.builder.string(std.mem.span(s)),
|
||||
} }, &o.builder);
|
||||
llvm_fn.addFunctionAttr("target-features", s);
|
||||
}
|
||||
if (comp.getTarget().cpu.arch.isBpf()) {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("no-builtins"),
|
||||
.value = .empty,
|
||||
} }, &o.builder);
|
||||
llvm_fn.addFunctionAttr("no-builtins", "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -4483,69 +4434,6 @@ pub const Object = struct {
|
||||
return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty);
|
||||
}
|
||||
|
||||
fn addAttr(o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void {
|
||||
return o.addAttrInt(val, index, name, 0);
|
||||
}
|
||||
|
||||
fn addArgAttr(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8) void {
|
||||
return o.addAttr(fn_val, param_index + 1, attr_name);
|
||||
}
|
||||
|
||||
fn addArgAttrInt(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8, int: u64) void {
|
||||
return o.addAttrInt(fn_val, param_index + 1, attr_name, int);
|
||||
}
|
||||
|
||||
fn removeAttr(val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void {
|
||||
const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len);
|
||||
assert(kind_id != 0);
|
||||
val.removeEnumAttributeAtIndex(index, kind_id);
|
||||
}
|
||||
|
||||
fn addAttrInt(
|
||||
o: *Object,
|
||||
val: *llvm.Value,
|
||||
index: llvm.AttributeIndex,
|
||||
name: []const u8,
|
||||
int: u64,
|
||||
) void {
|
||||
const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len);
|
||||
assert(kind_id != 0);
|
||||
const llvm_attr = o.builder.llvm.context.createEnumAttribute(kind_id, int);
|
||||
val.addAttributeAtIndex(index, llvm_attr);
|
||||
}
|
||||
|
||||
fn addAttrString(
|
||||
o: *Object,
|
||||
val: *llvm.Value,
|
||||
index: llvm.AttributeIndex,
|
||||
name: []const u8,
|
||||
value: []const u8,
|
||||
) void {
|
||||
const llvm_attr = o.builder.llvm.context.createStringAttribute(
|
||||
name.ptr,
|
||||
@intCast(name.len),
|
||||
value.ptr,
|
||||
@intCast(value.len),
|
||||
);
|
||||
val.addAttributeAtIndex(index, llvm_attr);
|
||||
}
|
||||
|
||||
fn addFnAttr(o: *Object, val: *llvm.Value, name: []const u8) void {
|
||||
o.addAttr(val, std.math.maxInt(llvm.AttributeIndex), name);
|
||||
}
|
||||
|
||||
fn addFnAttrString(o: *Object, val: *llvm.Value, name: []const u8, value: []const u8) void {
|
||||
o.addAttrString(val, std.math.maxInt(llvm.AttributeIndex), name, value);
|
||||
}
|
||||
|
||||
fn removeFnAttr(fn_val: *llvm.Value, name: []const u8) void {
|
||||
removeAttr(fn_val, std.math.maxInt(llvm.AttributeIndex), name);
|
||||
}
|
||||
|
||||
fn addFnAttrInt(o: *Object, fn_val: *llvm.Value, name: []const u8, int: u64) void {
|
||||
return o.addAttrInt(fn_val, std.math.maxInt(llvm.AttributeIndex), name, int);
|
||||
}
|
||||
|
||||
/// If the operand type of an atomic operation is not byte sized we need to
|
||||
/// widen it before using it and then truncate the result.
|
||||
/// RMW exchange of floating-point values is bitcasted to same-sized integer
|
||||
@ -4608,80 +4496,13 @@ pub const Object = struct {
|
||||
attributes: *Builder.FunctionAttributes.Wip,
|
||||
llvm_arg_i: u32,
|
||||
alignment: Builder.Alignment,
|
||||
byval_attr: bool,
|
||||
byval: bool,
|
||||
param_llvm_ty: Builder.Type,
|
||||
) Allocator.Error!void {
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
|
||||
try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder);
|
||||
if (byval_attr) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder);
|
||||
}
|
||||
}
|
||||
|
||||
fn addByValParamAttrsOld(
|
||||
o: *Object,
|
||||
attributes: *Builder.FunctionAttributes.Wip,
|
||||
llvm_fn: *llvm.Value,
|
||||
param_ty: Type,
|
||||
param_index: u32,
|
||||
fn_info: InternPool.Key.FuncType,
|
||||
llvm_arg_i: u32,
|
||||
) Allocator.Error!void {
|
||||
const mod = o.module;
|
||||
if (param_ty.isPtrAtRuntime(mod)) {
|
||||
const ptr_info = param_ty.ptrInfo(mod);
|
||||
if (math.cast(u5, param_index)) |i| {
|
||||
if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "noalias");
|
||||
}
|
||||
}
|
||||
if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
|
||||
}
|
||||
if (ptr_info.flags.is_const) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "readonly");
|
||||
}
|
||||
const elem_align = Builder.Alignment.fromByteUnits(
|
||||
ptr_info.flags.alignment.toByteUnitsOptional() orelse
|
||||
@max(ptr_info.child.toType().abiAlignment(mod), 1),
|
||||
);
|
||||
try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder);
|
||||
o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0);
|
||||
} else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) {
|
||||
.signed => {
|
||||
try attributes.addParamAttr(llvm_arg_i, .signext, &o.builder);
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "signext");
|
||||
},
|
||||
.unsigned => {
|
||||
try attributes.addParamAttr(llvm_arg_i, .zeroext, &o.builder);
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "zeroext");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn addByRefParamAttrsOld(
|
||||
o: *Object,
|
||||
attributes: *Builder.FunctionAttributes.Wip,
|
||||
llvm_fn: *llvm.Value,
|
||||
llvm_arg_i: u32,
|
||||
alignment: Builder.Alignment,
|
||||
byval_attr: bool,
|
||||
param_llvm_ty: Builder.Type,
|
||||
) Allocator.Error!void {
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
|
||||
try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder);
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
|
||||
o.addArgAttr(llvm_fn, llvm_arg_i, "readonly");
|
||||
o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment.toByteUnits() orelse 0);
|
||||
if (byval_attr) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder);
|
||||
llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder));
|
||||
}
|
||||
if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder);
|
||||
}
|
||||
};
|
||||
|
||||
@ -9503,16 +9324,16 @@ pub const FuncGen = struct {
|
||||
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
|
||||
function_index.toLlvm(&o.builder).setLinkage(.Internal);
|
||||
function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
|
||||
try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder));
|
||||
try o.addCommonFnAttributes(&attributes);
|
||||
function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
|
||||
function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
|
||||
function_index.ptr(&o.builder).call_conv = .fastcc;
|
||||
function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
|
||||
gop.value_ptr.* = function_index;
|
||||
|
||||
function_index.toLlvm(&o.builder).setLinkage(.Internal);
|
||||
function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
|
||||
|
||||
var wip = try Builder.WipFunction.init(&o.builder, function_index);
|
||||
defer wip.deinit();
|
||||
wip.cursor = .{ .block = try wip.block(0, "Entry") };
|
||||
@ -9577,16 +9398,16 @@ pub const FuncGen = struct {
|
||||
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
|
||||
function_index.toLlvm(&o.builder).setLinkage(.Internal);
|
||||
function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
|
||||
try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder));
|
||||
try o.addCommonFnAttributes(&attributes);
|
||||
function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
|
||||
function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
|
||||
function_index.ptr(&o.builder).call_conv = .fastcc;
|
||||
function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
|
||||
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
|
||||
|
||||
function_index.toLlvm(&o.builder).setLinkage(.Internal);
|
||||
function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
|
||||
|
||||
var wip = try Builder.WipFunction.init(&o.builder, function_index);
|
||||
defer wip.deinit();
|
||||
wip.cursor = .{ .block = try wip.block(0, "Entry") };
|
||||
@ -9659,14 +9480,14 @@ pub const FuncGen = struct {
|
||||
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
|
||||
function_index.toLlvm(&o.builder).setLinkage(.Internal);
|
||||
function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
|
||||
try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder));
|
||||
try o.addCommonFnAttributes(&attributes);
|
||||
function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
|
||||
function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
|
||||
function_index.ptr(&o.builder).call_conv = .fastcc;
|
||||
function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
|
||||
|
||||
function_index.toLlvm(&o.builder).setLinkage(.Internal);
|
||||
function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
|
||||
|
||||
return function_index;
|
||||
}
|
||||
|
||||
@ -1349,21 +1349,29 @@ pub const Attribute = union(Kind) {
|
||||
//sanitize_memtag,
|
||||
sanitize_address_dyninit,
|
||||
|
||||
string = std.math.maxInt(u31) - 1,
|
||||
none = std.math.maxInt(u31),
|
||||
string = std.math.maxInt(u31),
|
||||
none = std.math.maxInt(u32),
|
||||
_,
|
||||
|
||||
pub const len = @typeInfo(Kind).Enum.fields.len - 2;
|
||||
|
||||
pub fn fromString(str: String) Kind {
|
||||
assert(!str.isAnon());
|
||||
return @enumFromInt(@intFromEnum(str));
|
||||
const kind: Kind = @enumFromInt(@intFromEnum(str));
|
||||
assert(kind != .none);
|
||||
return kind;
|
||||
}
|
||||
|
||||
fn toString(self: Kind) ?String {
|
||||
assert(self != .none);
|
||||
const str: String = @enumFromInt(@intFromEnum(self));
|
||||
return if (str.isAnon()) null else str;
|
||||
}
|
||||
|
||||
fn toLlvm(self: Kind, builder: *const Builder) *c_uint {
|
||||
assert(builder.useLibLlvm());
|
||||
return &builder.llvm.attribute_kind_ids.?[@intFromEnum(self)];
|
||||
}
|
||||
};
|
||||
|
||||
pub const FpClass = packed struct(u32) {
|
||||
@ -3147,6 +3155,86 @@ pub const Function = struct {
|
||||
return self.toConst(builder).toValue();
|
||||
}
|
||||
|
||||
pub fn setAttributes(
|
||||
self: Index,
|
||||
new_function_attributes: FunctionAttributes,
|
||||
builder: *Builder,
|
||||
) void {
|
||||
if (builder.useLibLlvm()) {
|
||||
const llvm_function = self.toLlvm(builder);
|
||||
const old_function_attributes = self.ptrConst(builder).attributes;
|
||||
for (0..@max(
|
||||
old_function_attributes.slice(builder).len,
|
||||
new_function_attributes.slice(builder).len,
|
||||
)) |function_attribute_index| {
|
||||
const llvm_attribute_index =
|
||||
@as(llvm.AttributeIndex, @intCast(function_attribute_index)) -% 1;
|
||||
const old_attributes_slice =
|
||||
old_function_attributes.get(function_attribute_index, builder).slice(builder);
|
||||
const new_attributes_slice =
|
||||
new_function_attributes.get(function_attribute_index, builder).slice(builder);
|
||||
var old_attribute_index: usize = 0;
|
||||
var new_attribute_index: usize = 0;
|
||||
while (true) {
|
||||
const old_attribute_kind = if (old_attribute_index < old_attributes_slice.len)
|
||||
old_attributes_slice[old_attribute_index].getKind(builder)
|
||||
else
|
||||
.none;
|
||||
const new_attribute_kind = if (new_attribute_index < new_attributes_slice.len)
|
||||
new_attributes_slice[new_attribute_index].getKind(builder)
|
||||
else
|
||||
.none;
|
||||
switch (std.math.order(
|
||||
@intFromEnum(old_attribute_kind),
|
||||
@intFromEnum(new_attribute_kind),
|
||||
)) {
|
||||
.lt => {
|
||||
// Removed
|
||||
if (old_attribute_kind.toString()) |name| {
|
||||
const slice = name.slice(builder).?;
|
||||
llvm_function.removeStringAttributeAtIndex(
|
||||
llvm_attribute_index,
|
||||
slice.ptr,
|
||||
@intCast(slice.len),
|
||||
);
|
||||
} else {
|
||||
const llvm_kind_id = old_attribute_kind.toLlvm(builder).*;
|
||||
assert(llvm_kind_id != 0);
|
||||
llvm_function.removeEnumAttributeAtIndex(
|
||||
llvm_attribute_index,
|
||||
llvm_kind_id,
|
||||
);
|
||||
}
|
||||
old_attribute_index += 1;
|
||||
continue;
|
||||
},
|
||||
.eq => {
|
||||
// Iteration finished
|
||||
if (old_attribute_kind == .none) break;
|
||||
// No change
|
||||
if (old_attributes_slice[old_attribute_index] ==
|
||||
new_attributes_slice[new_attribute_index])
|
||||
{
|
||||
old_attribute_index += 1;
|
||||
new_attribute_index += 1;
|
||||
continue;
|
||||
}
|
||||
old_attribute_index += 1;
|
||||
},
|
||||
.gt => {},
|
||||
}
|
||||
// New or changed
|
||||
llvm_function.addAttributeAtIndex(
|
||||
llvm_attribute_index,
|
||||
new_attributes_slice[new_attribute_index].toLlvm(builder),
|
||||
);
|
||||
new_attribute_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ptr(builder).attributes = new_function_attributes;
|
||||
}
|
||||
|
||||
pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
|
||||
return self.ptrConst(builder).global.toLlvm(builder);
|
||||
}
|
||||
@ -5048,9 +5136,8 @@ pub const WipFunction = struct {
|
||||
.tail, .tail_fast => .Tail,
|
||||
});
|
||||
for (0.., function_attributes.slice(self.builder)) |index, attributes| {
|
||||
const attribute_index = @as(llvm.AttributeIndex, @intCast(index)) -% 1;
|
||||
for (attributes.slice(self.builder)) |attribute| llvm_instruction.addCallSiteAttribute(
|
||||
attribute_index,
|
||||
@as(llvm.AttributeIndex, @intCast(index)) -% 1,
|
||||
attribute.toLlvm(self.builder),
|
||||
);
|
||||
}
|
||||
@ -7368,16 +7455,16 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde
|
||||
gop.value_ptr.* = {};
|
||||
if (self.useLibLlvm()) self.llvm.attributes.appendAssumeCapacity(switch (attribute) {
|
||||
else => llvm_attr: {
|
||||
const kind_id = &self.llvm.attribute_kind_ids.?[@intFromEnum(attribute)];
|
||||
if (kind_id.* == 0) {
|
||||
const llvm_kind_id = attribute.getKind().toLlvm(self);
|
||||
if (llvm_kind_id.* == 0) {
|
||||
const name = @tagName(attribute);
|
||||
kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);
|
||||
assert(kind_id.* != 0);
|
||||
llvm_kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);
|
||||
assert(llvm_kind_id.* != 0);
|
||||
}
|
||||
break :llvm_attr switch (attribute) {
|
||||
else => switch (attribute) {
|
||||
inline else => |value| self.llvm.context.createEnumAttribute(
|
||||
kind_id.*,
|
||||
llvm_kind_id.*,
|
||||
switch (@TypeOf(value)) {
|
||||
void => 0,
|
||||
u32 => value,
|
||||
@ -7411,7 +7498,7 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde
|
||||
.inalloca,
|
||||
.sret,
|
||||
.elementtype,
|
||||
=> |ty| self.llvm.context.createTypeAttribute(kind_id.*, ty.toLlvm(self)),
|
||||
=> |ty| self.llvm.context.createTypeAttribute(llvm_kind_id.*, ty.toLlvm(self)),
|
||||
.string, .none => unreachable,
|
||||
};
|
||||
},
|
||||
|
||||
@ -115,12 +115,15 @@ pub const Context = opaque {
|
||||
};
|
||||
|
||||
pub const Value = opaque {
|
||||
pub const addAttributeAtIndex = ZigLLVMAddAttributeAtIndex;
|
||||
extern fn ZigLLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void;
|
||||
pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
|
||||
extern fn LLVMAddAttributeAtIndex(F: *Value, Idx: AttributeIndex, A: *Attribute) void;
|
||||
|
||||
pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;
|
||||
extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void;
|
||||
|
||||
pub const removeStringAttributeAtIndex = LLVMRemoveStringAttributeAtIndex;
|
||||
extern fn LLVMRemoveStringAttributeAtIndex(F: *Value, Idx: AttributeIndex, K: [*]const u8, KLen: c_uint) void;
|
||||
|
||||
pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;
|
||||
extern fn LLVMGetFirstBasicBlock(Fn: *Value) ?*BasicBlock;
|
||||
|
||||
@ -342,9 +345,6 @@ pub const Value = opaque {
|
||||
pub const deleteFunction = LLVMDeleteFunction;
|
||||
extern fn LLVMDeleteFunction(Fn: *Value) void;
|
||||
|
||||
pub const addSretAttr = ZigLLVMAddSretAttr;
|
||||
extern fn ZigLLVMAddSretAttr(fn_ref: *Value, type_val: *Type) void;
|
||||
|
||||
pub const getParam = LLVMGetParam;
|
||||
extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
|
||||
|
||||
@ -369,9 +369,6 @@ pub const Value = opaque {
|
||||
pub const getAlignment = LLVMGetAlignment;
|
||||
extern fn LLVMGetAlignment(V: *Value) c_uint;
|
||||
|
||||
pub const addFunctionAttr = ZigLLVMAddFunctionAttr;
|
||||
extern fn ZigLLVMAddFunctionAttr(Fn: *Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void;
|
||||
|
||||
pub const addByValAttr = ZigLLVMAddByValAttr;
|
||||
extern fn ZigLLVMAddByValAttr(Fn: *Value, ArgNo: c_uint, type: *Type) void;
|
||||
|
||||
|
||||
@ -408,14 +408,6 @@ void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCall
|
||||
unwrap<CallInst>(Call)->setTailCallKind(TCK);
|
||||
}
|
||||
|
||||
void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A) {
|
||||
if (isa<Function>(unwrap(Val))) {
|
||||
unwrap<Function>(Val)->addAttributeAtIndex(Idx, unwrap(A));
|
||||
} else {
|
||||
unwrap<CallInst>(Val)->addAttributeAtIndex(Idx, unwrap(A));
|
||||
}
|
||||
}
|
||||
|
||||
LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
|
||||
LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile)
|
||||
{
|
||||
@ -950,36 +942,6 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {
|
||||
}
|
||||
}
|
||||
|
||||
void ZigLLVMAddByValAttr(LLVMValueRef Val, unsigned ArgNo, LLVMTypeRef type_val) {
|
||||
if (isa<Function>(unwrap(Val))) {
|
||||
Function *func = unwrap<Function>(Val);
|
||||
AttrBuilder attr_builder(func->getContext());
|
||||
Type *llvm_type = unwrap<Type>(type_val);
|
||||
attr_builder.addByValAttr(llvm_type);
|
||||
func->addParamAttrs(ArgNo, attr_builder);
|
||||
} else {
|
||||
CallInst *call = unwrap<CallInst>(Val);
|
||||
AttrBuilder attr_builder(call->getContext());
|
||||
Type *llvm_type = unwrap<Type>(type_val);
|
||||
attr_builder.addByValAttr(llvm_type);
|
||||
// NOTE: +1 here since index 0 refers to the return value
|
||||
call->addAttributeAtIndex(ArgNo + 1, attr_builder.getAttribute(Attribute::ByVal));
|
||||
}
|
||||
}
|
||||
|
||||
void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) {
|
||||
Function *func = unwrap<Function>(fn_ref);
|
||||
AttrBuilder attr_builder(func->getContext());
|
||||
Type *llvm_type = unwrap<Type>(type_val);
|
||||
attr_builder.addStructRetAttr(llvm_type);
|
||||
func->addParamAttrs(0, attr_builder);
|
||||
}
|
||||
|
||||
void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) {
|
||||
Function *func = unwrap<Function>(fn_ref);
|
||||
func->addFnAttr(attr_name, attr_value);
|
||||
}
|
||||
|
||||
void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
|
||||
cl::ParseCommandLineOptions(argc, argv);
|
||||
}
|
||||
@ -1172,14 +1134,6 @@ bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disab
|
||||
return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
|
||||
}
|
||||
|
||||
inline LLVMAttributeRef wrap(Attribute Attr) {
|
||||
return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer());
|
||||
}
|
||||
|
||||
inline Attribute unwrap(LLVMAttributeRef Attr) {
|
||||
return Attribute::fromRawPointer(Attr);
|
||||
}
|
||||
|
||||
LLVMValueRef ZigLLVMBuildAndReduce(LLVMBuilderRef B, LLVMValueRef Val) {
|
||||
return wrap(unwrap(B)->CreateAndReduce(unwrap(Val)));
|
||||
}
|
||||
|
||||
@ -122,15 +122,6 @@ enum ZigLLVM_CallingConv {
|
||||
ZigLLVM_MaxID = 1023,
|
||||
};
|
||||
|
||||
enum ZigLLVM_CallAttr {
|
||||
ZigLLVM_CallAttrAuto,
|
||||
ZigLLVM_CallAttrNeverTail,
|
||||
ZigLLVM_CallAttrNeverInline,
|
||||
ZigLLVM_CallAttrAlwaysTail,
|
||||
ZigLLVM_CallAttrAlwaysInline,
|
||||
};
|
||||
ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A);
|
||||
|
||||
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
|
||||
LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
|
||||
|
||||
@ -301,11 +292,6 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu
|
||||
|
||||
ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
|
||||
|
||||
ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
|
||||
ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val);
|
||||
ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val);
|
||||
ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);
|
||||
|
||||
ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);
|
||||
|
||||
ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user