Pass more tests
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 36s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 36s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 44s
CI / ci (Debug, ubuntu-latest) (push) Successful in 59s

This commit is contained in:
David Gonzalez Martin 2025-04-06 20:47:41 +02:00
parent 0d910fd58d
commit 3309329911
2 changed files with 94 additions and 12 deletions

View File

@ -505,13 +505,13 @@ pub const Value = struct {
cast, cast,
cast_to, cast_to,
extend: *Value, extend: *Value,
integer_max, integer_max: *Type,
int_from_enum, int_from_enum,
int_from_pointer, int_from_pointer,
pointer_cast, pointer_cast,
select, select,
trap, trap,
truncate, truncate: *Value,
va_start, va_start,
va_end, va_end,
va_copy, va_copy,
@ -755,6 +755,21 @@ pub const Module = struct {
} }
} }
fn parse_hexadecimal(noalias module: *Module) u64 {
var value: u64 = 0;
while (true) {
const ch = module.content[module.offset];
if (!lib.is_hex_digit(ch)) {
break;
}
module.offset += 1;
value = lib.parse.accumulate_hexadecimal(value, ch);
}
return value;
}
fn parse_decimal(noalias module: *Module) u64 { fn parse_decimal(noalias module: *Module) u64 {
var value: u64 = 0; var value: u64 = 0;
while (true) { while (true) {
@ -1351,6 +1366,8 @@ pub const Module = struct {
else => .decimal, else => .decimal,
}; };
const value: u64 = switch (token_integer_kind) { const value: u64 = switch (token_integer_kind) {
.binary => @trap(),
.octal => @trap(),
.decimal => switch (next_ch) { .decimal => switch (next_ch) {
0...9 => module.report_error(), 0...9 => module.report_error(),
else => b: { else => b: {
@ -1358,7 +1375,11 @@ pub const Module = struct {
break :b 0; break :b 0;
}, },
}, },
else => @trap(), .hexadecimal => b: {
module.offset += 2;
const v = module.parse_hexadecimal();
break :b v;
},
}; };
if (module.content[module.offset] == '.') { if (module.content[module.offset] == '.') {
@ -1721,26 +1742,53 @@ pub const Module = struct {
fn rule_before_value_intrinsic(noalias module: *Module, value_builder: Value.Builder) *Value { fn rule_before_value_intrinsic(noalias module: *Module, value_builder: Value.Builder) *Value {
const intrinsic = value_builder.token.value_intrinsic; const intrinsic = value_builder.token.value_intrinsic;
switch (intrinsic) { const value = module.values.add();
.extend => { value.* = switch (intrinsic) {
.extend => blk: {
module.skip_space(); module.skip_space();
module.expect_character(left_parenthesis); module.expect_character(left_parenthesis);
module.skip_space(); module.skip_space();
const arg_value = module.parse_value(.{}); const arg_value = module.parse_value(.{});
module.expect_character(right_parenthesis); module.expect_character(right_parenthesis);
const value = module.values.add(); break :blk .{
value.* = .{
.bb = .{ .bb = .{
.intrinsic = .{ .intrinsic = .{
.extend = arg_value, .extend = arg_value,
}, },
}, },
}; };
return value; },
.integer_max => blk: {
module.skip_space();
module.expect_character(left_parenthesis);
module.skip_space();
const ty = module.parse_type();
module.expect_character(right_parenthesis);
break :blk .{
.bb = .{
.intrinsic = .{
.integer_max = ty,
},
},
};
},
.truncate => blk: {
module.skip_space();
module.expect_character(left_parenthesis);
module.skip_space();
const v = module.parse_value(.{});
module.expect_character(right_parenthesis);
break :blk .{
.bb = .{
.intrinsic = .{
.truncate = v,
},
},
};
}, },
else => @trap(), else => @trap(),
} };
@trap(); return value;
} }
fn rule_before_integer(noalias module: *Module, value_builder: Value.Builder) *Value { fn rule_before_integer(noalias module: *Module, value_builder: Value.Builder) *Value {
@ -2720,6 +2768,20 @@ pub const Module = struct {
}; };
break :blk extension_instruction; break :blk extension_instruction;
}, },
.integer_max => |max_type| blk: {
const bit_count = max_type.bb.integer.bit_count;
const max_value = if (bit_count == 64) ~@as(u64, 0) else (@as(u64, 1) << @intCast(bit_count - @intFromBool(max_type.bb.integer.signed))) - 1;
const constant_integer = max_type.resolve(module).handle.to_integer().get_constant(max_value, @intFromBool(false));
break :blk constant_integer.to_value();
},
.truncate => |value_to_truncate| blk: {
if (value_to_truncate.llvm == null) {
module.emit_value(function, value_to_truncate);
}
const llvm_value = value_to_truncate.llvm orelse unreachable;
const truncate = module.llvm.builder.create_truncate(llvm_value, value_type.llvm.handle.?);
break :blk truncate;
},
else => @trap(), else => @trap(),
}, },
.dereference => |dereferenceable_value| blk: { .dereference => |dereferenceable_value| blk: {
@ -2756,8 +2818,10 @@ pub const Module = struct {
@trap(); @trap();
}, },
false => { false => {
const type_max = (@as(u64, 1) << @intCast(integer.bit_count)) - 1; const bit_count = integer.bit_count;
if (constant_integer.value > type_max) { const max_value = if (bit_count == 64) ~@as(u64, 0) else (@as(u64, 1) << @intCast(bit_count - @intFromBool(integer.signed))) - 1;
if (constant_integer.value > max_value) {
module.report_error(); module.report_error();
} }
}, },
@ -2811,6 +2875,12 @@ pub const Module = struct {
module.report_error(); module.report_error();
} }
}, },
.truncate => |value_to_truncate| {
module.analyze_value_type(function, value_to_truncate, .{});
if (expected_type.get_bit_size() >= value_to_truncate.type.?.get_bit_size()) {
module.report_error();
}
},
else => @trap(), else => @trap(),
}, },
.dereference => |dereferenceable_value| { .dereference => |dereferenceable_value| {
@ -2863,6 +2933,16 @@ pub const Module = struct {
.right => variable.type, .right => variable.type,
else => variable.storage.?.type.?, else => variable.storage.?.type.?,
}, },
.intrinsic => |intrinsic| switch (intrinsic) {
// TODO: typecheck
.integer_max => |integer_max_type| blk: {
if (integer_max_type.bb != .integer) {
module.report_error();
}
break :blk integer_max_type;
},
else => @trap(),
},
else => @trap(), else => @trap(),
}; };

View File

@ -189,5 +189,7 @@ const names = &[_][]const u8{
"extend", "extend",
"stack_negation", "stack_negation",
"basic_pointer", "basic_pointer",
"integer_max",
"integer_hex",
// "pointer", // "pointer",
}; };