Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix long double casting when same size as double #786

Merged
merged 4 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 11 additions & 20 deletions src/aro/Parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5804,8 +5804,8 @@ pub const Result = struct {
// if either is a float cast to that type
if (a.ty.isFloat() or b.ty.isFloat()) {
const float_types = [6][2]Type.Specifier{
.{ .complex_long_double, .long_double },
.{ .complex_float128, .float128 },
.{ .complex_long_double, .long_double },
.{ .complex_double, .double },
.{ .complex_float, .float },
// No `_Complex __fp16` type
Expand All @@ -5814,20 +5814,9 @@ pub const Result = struct {
};
const a_spec = a.ty.canonicalize(.standard).specifier;
const b_spec = b.ty.canonicalize(.standard).specifier;
if (p.comp.target.cTypeBitSize(.longdouble) == 128) {
if (try a.floatConversion(b, a_spec, b_spec, p, float_types[0])) return;
}
if (try a.floatConversion(b, a_spec, b_spec, p, float_types[1])) return;
if (p.comp.target.cTypeBitSize(.longdouble) >= p.comp.target.cTypeBitSize(.double)) {
if (try a.floatConversion(b, a_spec, b_spec, p, float_types[0])) return;
for (float_types) |ft| {
if (try a.floatConversion(b, a_spec, b_spec, p, ft)) return;
}
if (try a.floatConversion(b, a_spec, b_spec, p, float_types[2])) return;
if (p.comp.target.cTypeBitSize(.longdouble) >= p.comp.target.cTypeBitSize(.float)) {
if (try a.floatConversion(b, a_spec, b_spec, p, float_types[0])) return;
}
if (try a.floatConversion(b, a_spec, b_spec, p, float_types[3])) return;
if (try a.floatConversion(b, a_spec, b_spec, p, float_types[4])) return;
if (try a.floatConversion(b, a_spec, b_spec, p, float_types[5])) return;
unreachable;
}

Expand Down Expand Up @@ -6843,8 +6832,8 @@ fn castExpr(p: *Parser) Error!Result {
switch (p.tok_ids[p.tok_i]) {
.builtin_choose_expr => return p.builtinChooseExpr(),
.builtin_va_arg => return p.builtinVaArg(),
.builtin_offsetof => return p.builtinOffsetof(false),
.builtin_bitoffsetof => return p.builtinOffsetof(true),
.builtin_offsetof => return p.builtinOffsetof(.bytes),
.builtin_bitoffsetof => return p.builtinOffsetof(.bits),
.builtin_types_compatible_p => return p.typesCompatible(),
// TODO: other special-cased builtins
else => {},
Expand Down Expand Up @@ -6968,7 +6957,9 @@ fn builtinVaArg(p: *Parser) Error!Result {
}) };
}

fn builtinOffsetof(p: *Parser, want_bits: bool) Error!Result {
const OffsetKind = enum { bits, bytes };

fn builtinOffsetof(p: *Parser, offset_kind: OffsetKind) Error!Result {
const builtin_tok = p.tok_i;
p.tok_i += 1;

Expand All @@ -6993,7 +6984,7 @@ fn builtinOffsetof(p: *Parser, want_bits: bool) Error!Result {

_ = try p.expectToken(.comma);

const offsetof_expr = try p.offsetofMemberDesignator(ty, want_bits);
const offsetof_expr = try p.offsetofMemberDesignator(ty, offset_kind);

try p.expectClosing(l_paren, .r_paren);

Expand All @@ -7009,7 +7000,7 @@ fn builtinOffsetof(p: *Parser, want_bits: bool) Error!Result {
}

/// offsetofMemberDesignator: IDENTIFIER ('.' IDENTIFIER | '[' expr ']' )*
fn offsetofMemberDesignator(p: *Parser, base_ty: Type, want_bits: bool) Error!Result {
fn offsetofMemberDesignator(p: *Parser, base_ty: Type, offset_kind: OffsetKind) Error!Result {
errdefer p.skipTo(.r_paren);
const base_field_name_tok = try p.expectIdentifier();
const base_field_name = try StrInt.intern(p.comp, p.tokSlice(base_field_name_tok));
Expand Down Expand Up @@ -7062,7 +7053,7 @@ fn offsetofMemberDesignator(p: *Parser, base_ty: Type, want_bits: bool) Error!Re
},
else => break,
};
const val = try Value.int(if (want_bits) total_offset else total_offset / 8, p.comp);
const val = try Value.int(if (offset_kind == .bits) total_offset else total_offset / 8, p.comp);
return Result{ .ty = base_ty, .val = val, .node = lhs.node };
}

Expand Down
2 changes: 1 addition & 1 deletion src/backend/Object/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ pub fn finish(elf: *Elf, file: std.fs.File) !void {
var buf_writer = std.io.bufferedWriter(file.writer());
const w = buf_writer.writer();

var num_sections: std.elf.Elf64_Half = additional_sections;
var num_sections: std.elf.Half = additional_sections;
var relocations_len: std.elf.Elf64_Off = 0;
var sections_len: std.elf.Elf64_Off = 0;
{
Expand Down
5 changes: 3 additions & 2 deletions test/cases/fp16 parameter.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//aro-args --target=x86_64-linux-gnu
__fp16 foo(__fp16 param) {
return 0;
}

#define EXPECTED_ERRORS "fp16 parameter.c:1:19: error: parameters cannot have __fp16 type; did you forget * ?" \
"fp16 parameter.c:1:11: error: function return value cannot have __fp16 type; did you forget * ?" \
#define EXPECTED_ERRORS "fp16 parameter.c:2:19: error: parameters cannot have __fp16 type; did you forget * ?" \
"fp16 parameter.c:2:11: error: function return value cannot have __fp16 type; did you forget * ?" \

22 changes: 20 additions & 2 deletions test/runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ pub fn main() !void {
if (pp.defines.get("TESTS_SKIPPED")) |macro| {
if (macro.is_func or macro.tokens.len != 1 or macro.tokens[0].id != .pp_num) {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print("invalid TESTS_SKIPPED, definition should contain exactly one integer literal {}\n", .{macro});
continue;
}
Expand All @@ -265,12 +266,14 @@ pub fn main() !void {
if (only_preprocess) {
if (try checkExpectedErrors(&pp, &buf)) |some| {
if (!some) {
std.debug.print("in case {s}\n", .{case});
fail_count += 1;
continue;
}
} else {
aro.Diagnostics.render(&comp, std.io.tty.detectConfig(std.io.getStdErr()));
if (comp.diagnostics.errors != 0) {
std.debug.print("in case {s}\n", .{case});
fail_count += 1;
continue;
}
Expand Down Expand Up @@ -299,6 +302,7 @@ pub fn main() !void {
ok_count += 1;
} else {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print("\n====== expected to find: =========\n", .{});
std.debug.print("{s}", .{expected_output});
std.debug.print("\n======== but did not find it in this: =========\n", .{});
Expand All @@ -319,7 +323,10 @@ pub fn main() !void {
var tree = aro.Parser.parse(&pp) catch |err| switch (err) {
error.FatalError => {
if (try checkExpectedErrors(&pp, &buf)) |some| {
if (some) ok_count += 1 else fail_count += 1;
if (some) ok_count += 1 else {
std.debug.print("in case {s}\n", .{case});
fail_count += 1;
}
}
continue;
},
Expand All @@ -337,6 +344,7 @@ pub fn main() !void {

try tree.dump(.no_color, actual_ast.writer());
std.testing.expectEqualStrings(expected_ast, actual_ast.items) catch {
std.debug.print("in case {s}\n", .{case});
fail_count += 1;
break;
};
Expand All @@ -347,6 +355,7 @@ pub fn main() !void {
if (tree.nodes.items(.tag)[@intFromEnum(decl)] == .fn_def) break tree.nodes.items(.data)[@intFromEnum(decl)];
} else {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print("EXPECTED_TYPES requires a function to be defined\n", .{});
break;
};
Expand All @@ -363,6 +372,7 @@ pub fn main() !void {
if (str.id == .macro_ws) continue;
if (str.id != .string_literal) {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print("EXPECTED_TYPES tokens must be string literals (found {s})\n", .{@tagName(str.id)});
continue :next_test;
}
Expand All @@ -373,6 +383,7 @@ pub fn main() !void {
const actual_type = actual.types.items[i];
if (!std.mem.eql(u8, expected_type, actual_type)) {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print("expected type '{s}' did not match actual type '{s}'\n", .{
expected_type,
actual_type,
Expand All @@ -382,6 +393,7 @@ pub fn main() !void {
}
if (i != actual.types.items.len) {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print(
"EXPECTED_TYPES count differs: expected {d} found {d}\n",
.{ i, actual.types.items.len },
Expand All @@ -391,7 +403,10 @@ pub fn main() !void {
}

if (try checkExpectedErrors(&pp, &buf)) |some| {
if (some) ok_count += 1 else fail_count += 1;
if (some) ok_count += 1 else {
std.debug.print("in case {s}\n", .{case});
fail_count += 1;
}
continue;
}

Expand All @@ -408,12 +423,14 @@ pub fn main() !void {

if (macro.is_func) {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print("invalid EXPECTED_OUTPUT {}\n", .{macro});
continue;
}

if (macro.tokens.len != 1 or macro.tokens[0].id != .string_literal) {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print("EXPECTED_OUTPUT takes exactly one string", .{});
continue;
}
Expand Down Expand Up @@ -456,6 +473,7 @@ pub fn main() !void {

if (!std.mem.eql(u8, expected_output, stdout)) {
fail_count += 1;
std.debug.print("{s}:\n", .{case});
std.debug.print(
\\
\\======= expected output =======
Expand Down
Loading