Skip to content

Commit 35e7011

Browse files
committed
LLVM: implement signext/zeroext attributes
For calling convention ABI purposes, integer attributes and return values need to have an LLVM attribute signext or zeroext added sometimes. This commit implements that logic. It also implements a proof-of-concept of moving the F16T type from being a compiler_rt hack to being how the compiler lowers f16 in functions that need to match certain calling conventions. Closes #12054
1 parent efe3424 commit 35e7011

File tree

3 files changed

+69
-32
lines changed

3 files changed

+69
-32
lines changed

lib/compiler_rt/common.zig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,11 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) nore
6868
/// need for extending them to wider fp types.
6969
/// TODO remove this; do this type selection in the language rather than
7070
/// here in compiler-rt.
71-
pub const F16T = if (builtin.cpu.arch.isAARCH64()) f16 else u16;
71+
pub const F16T = switch (builtin.cpu.arch) {
72+
.aarch64, .aarch64_be, .aarch64_32 => f16,
73+
.riscv64 => if (builtin.zig_backend == .stage1) u16 else f16,
74+
else => u16,
75+
};
7276

7377
pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
7478
switch (Z) {

src/codegen/llvm.zig

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,11 @@ pub const Object = struct {
717717
const ret_ptr = if (sret) llvm_func.getParam(0) else null;
718718
const gpa = dg.gpa;
719719

720+
if (ccAbiPromoteInt(fn_info.cc, target, fn_info.return_type)) |s| switch (s) {
721+
.signed => dg.addAttr(llvm_func, 0, "signext"),
722+
.unsigned => dg.addAttr(llvm_func, 0, "zeroext"),
723+
};
724+
720725
const err_return_tracing = fn_info.return_type.isError() and
721726
dg.module.comp.bin_file.options.error_return_tracing;
722727

@@ -774,7 +779,10 @@ pub const Object = struct {
774779
);
775780
dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align);
776781
}
777-
}
782+
} else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) {
783+
.signed => dg.addArgAttr(llvm_func, llvm_arg_i, "signext"),
784+
.unsigned => dg.addArgAttr(llvm_func, llvm_arg_i, "zeroext"),
785+
};
778786
}
779787
llvm_arg_i += 1;
780788
},
@@ -887,6 +895,13 @@ pub const Object = struct {
887895
};
888896
try args.append(loaded);
889897
},
898+
.as_u16 => {
899+
const param = llvm_func.getParam(llvm_arg_i);
900+
llvm_arg_i += 1;
901+
const casted = builder.buildBitCast(param, dg.context.halfType(), "");
902+
try args.ensureUnusedCapacity(1);
903+
args.appendAssumeCapacity(casted);
904+
},
890905
};
891906
}
892907

@@ -2794,6 +2809,9 @@ pub const DeclGen = struct {
27942809
llvm_params.appendAssumeCapacity(big_int_ty);
27952810
}
27962811
},
2812+
.as_u16 => {
2813+
try llvm_params.append(dg.context.intType(16));
2814+
},
27972815
};
27982816

27992817
return llvm.functionType(
@@ -4234,6 +4252,12 @@ pub const FuncGen = struct {
42344252
llvm_args.appendAssumeCapacity(load_inst);
42354253
}
42364254
},
4255+
.as_u16 => {
4256+
const arg = args[it.zig_index - 1];
4257+
const llvm_arg = try self.resolveInst(arg);
4258+
const casted = self.builder.buildBitCast(llvm_arg, self.dg.context.intType(16), "");
4259+
try llvm_args.append(casted);
4260+
},
42374261
};
42384262

42394263
const call = self.builder.buildCall(
@@ -8965,6 +8989,7 @@ const ParamTypeIterator = struct {
89658989
abi_sized_int,
89668990
multiple_llvm_ints,
89678991
slice,
8992+
as_u16,
89688993
};
89698994

89708995
pub fn next(it: *ParamTypeIterator) ?Lowering {
@@ -9025,6 +9050,15 @@ const ParamTypeIterator = struct {
90259050
else => false,
90269051
};
90279052
switch (it.target.cpu.arch) {
9053+
.riscv32, .riscv64 => {
9054+
it.zig_index += 1;
9055+
it.llvm_index += 1;
9056+
if (ty.tag() == .f16) {
9057+
return .as_u16;
9058+
} else {
9059+
return .byval;
9060+
}
9061+
},
90289062
.mips, .mipsel => {
90299063
it.zig_index += 1;
90309064
it.llvm_index += 1;
@@ -9135,6 +9169,35 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp
91359169
};
91369170
}
91379171

9172+
fn ccAbiPromoteInt(
9173+
cc: std.builtin.CallingConvention,
9174+
target: std.Target,
9175+
ty: Type,
9176+
) ?std.builtin.Signedness {
9177+
switch (cc) {
9178+
.Unspecified, .Inline, .Async => return null,
9179+
else => {},
9180+
}
9181+
const int_info = switch (ty.zigTypeTag()) {
9182+
.Int, .Enum, .ErrorSet => ty.intInfo(target),
9183+
else => return null,
9184+
};
9185+
if (int_info.bits <= 16) return int_info.signedness;
9186+
switch (target.cpu.arch) {
9187+
.sparc64,
9188+
.riscv64,
9189+
.powerpc64,
9190+
.powerpc64le,
9191+
=> {
9192+
if (int_info.bits < 64) {
9193+
return int_info.signedness;
9194+
}
9195+
},
9196+
else => {},
9197+
}
9198+
return null;
9199+
}
9200+
91389201
fn isByRef(ty: Type) bool {
91399202
// For tuples and structs, if there are more than this many non-void
91409203
// fields, then we make it byref, otherwise byval.

test/behavior/math.zig

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,11 +1168,6 @@ test "remainder division" {
11681168
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11691169
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11701170

1171-
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) {
1172-
// https://github.com/ziglang/zig/issues/12054
1173-
return error.SkipZigTest;
1174-
}
1175-
11761171
comptime try remdiv(f16);
11771172
comptime try remdiv(f32);
11781173
comptime try remdiv(f64);
@@ -1204,11 +1199,6 @@ test "float remainder division using @rem" {
12041199
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12051200
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12061201

1207-
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) {
1208-
// https://github.com/ziglang/zig/issues/12054
1209-
return error.SkipZigTest;
1210-
}
1211-
12121202
comptime try frem(f16);
12131203
comptime try frem(f32);
12141204
comptime try frem(f64);
@@ -1251,11 +1241,6 @@ test "float modulo division using @mod" {
12511241
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12521242
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12531243

1254-
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) {
1255-
// https://github.com/ziglang/zig/issues/12054
1256-
return error.SkipZigTest;
1257-
}
1258-
12591244
comptime try fmod(f16);
12601245
comptime try fmod(f32);
12611246
comptime try fmod(f64);
@@ -1431,11 +1416,6 @@ test "@ceil f80" {
14311416
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14321417
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14331418

1434-
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) {
1435-
// https://github.com/ziglang/zig/issues/12054
1436-
return error.SkipZigTest;
1437-
}
1438-
14391419
try testCeil(f80, 12.0);
14401420
comptime try testCeil(f80, 12.0);
14411421
}
@@ -1447,11 +1427,6 @@ test "@ceil f128" {
14471427
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14481428
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14491429

1450-
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) {
1451-
// https://github.com/ziglang/zig/issues/12054
1452-
return error.SkipZigTest;
1453-
}
1454-
14551430
try testCeil(f128, 12.0);
14561431
comptime try testCeil(f128, 12.0);
14571432
}
@@ -1600,11 +1575,6 @@ test "NaN comparison" {
16001575
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16011576
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16021577

1603-
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) {
1604-
// https://github.com/ziglang/zig/issues/12054
1605-
return error.SkipZigTest;
1606-
}
1607-
16081578
try testNanEqNan(f16);
16091579
try testNanEqNan(f32);
16101580
try testNanEqNan(f64);

0 commit comments

Comments
 (0)