Zig rewrite start #1

Merged
davidgmbb merged 100 commits from zig into main 2025-04-05 11:22:15 +02:00
4 changed files with 196 additions and 72 deletions
Showing only changes of commit 3f66a9587d - Show all commits

View File

@ -1566,6 +1566,43 @@ const Converter = struct {
}
}
pub fn parse_condition_parenthesis(noalias converter: *Converter, noalias module: *Module) *Value {
converter.skip_space();
converter.expect_character(left_parenthesis);
converter.skip_space();
const condition = converter.parse_condition_raw(module);
converter.skip_space();
converter.expect_character(right_parenthesis);
return condition;
}
pub fn parse_condition_raw(noalias converter: *Converter, noalias module: *Module) *Value {
const condition = converter.parse_value(module, null, .value);
const boolean_type = module.integer_type(1, false);
if (condition.type != boolean_type) {
const llvm_value = switch (condition.type.bb) {
.integer => module.llvm.builder.create_compare(.ne, condition.llvm, condition.type.llvm.handle.to_integer().get_constant(0, 0).to_value()),
else => @trap(),
};
const value = module.values.add();
value.* = .{
.llvm = llvm_value,
.type = boolean_type,
.bb = .instruction,
.lvalue = false,
.dereference_to_assign = false,
};
return value;
} else {
return condition;
}
}
pub fn parse_type(noalias converter: *Converter, noalias module: *Module) *Type {
switch (converter.content[converter.offset]) {
'a'...'z', 'A'...'Z', '_' => {
@ -2406,15 +2443,7 @@ const Converter = struct {
const not_taken_block = module.llvm.context.create_basic_block("if.false", current_function_global.value.llvm.to_function());
const exit_block = module.llvm.context.create_basic_block("if.end", null);
converter.skip_space();
converter.expect_character(left_parenthesis);
converter.skip_space();
const condition = converter.parse_value(module, null, .value);
converter.skip_space();
converter.expect_character(right_parenthesis);
const condition = converter.parse_condition_parenthesis(module);
_ = module.llvm.builder.create_conditional_branch(condition.llvm, taken_block, not_taken_block);
module.llvm.builder.position_at_end(taken_block);
@ -2479,6 +2508,36 @@ const Converter = struct {
exit_block.delete();
}
require_semicolon = false;
},
.@"while" => {
const loop_entry_block = module.llvm.context.create_basic_block("while.entry", current_function_global.value.llvm.to_function());
_ = module.llvm.builder.create_branch(loop_entry_block);
module.llvm.builder.position_at_end(loop_entry_block);
const condition = converter.parse_condition_parenthesis(module);
const loop_body_block = module.llvm.context.create_basic_block("while.body", current_function_global.value.llvm.to_function());
const loop_end_block = module.llvm.context.create_basic_block("while.end", current_function_global.value.llvm.to_function());
_ = module.llvm.builder.create_conditional_branch(condition.llvm, loop_body_block, loop_end_block);
module.llvm.builder.position_at_end(loop_body_block);
converter.skip_space();
converter.parse_block(module);
if (module.llvm.builder.get_insert_block() != null) {
_ = module.llvm.builder.create_branch(loop_entry_block);
}
if (loop_body_block.to_value().use_empty()) {
@trap();
}
if (loop_end_block.to_value().use_empty()) {
@trap();
}
module.llvm.builder.position_at_end(loop_end_block);
require_semicolon = false;
},
}
@ -2545,26 +2604,27 @@ const Converter = struct {
const ExpressionState = enum {
none,
add,
sub,
mul,
udiv,
sdiv,
urem,
srem,
integer_add,
integer_sub,
integer_mul,
integer_udiv,
integer_sdiv,
integer_urem,
integer_srem,
shl,
ashr,
lshr,
@"and",
@"or",
xor,
icmp_eq,
icmp_ne,
integer_compare_equal,
integer_compare_not_equal,
pointer_add,
pub fn to_int_predicate(expression_state: ExpressionState) llvm.IntPredicate {
return switch (expression_state) {
.icmp_ne => .ne,
.icmp_eq => .eq,
.integer_compare_not_equal => .ne,
.integer_compare_equal => .eq,
else => @trap(),
};
}
@ -2589,6 +2649,12 @@ const Converter = struct {
iterative_expected_type = previous_value.?.type;
}
const old_iterative_expected_type = iterative_expected_type;
iterative_expected_type = switch (value_state) {
.pointer_add => module.integer_type(64, false),
else => iterative_expected_type,
};
const current_value = switch (converter.consume_character_if_match(left_parenthesis)) {
true => blk: {
const r = converter.parse_value(module, iterative_expected_type, value_kind);
@ -2599,6 +2665,8 @@ const Converter = struct {
false => converter.parse_single_value(module, iterative_expected_type, value_kind),
};
iterative_expected_type = old_iterative_expected_type;
converter.skip_space();
const left = switch (value_state) {
@ -2610,20 +2678,26 @@ const Converter = struct {
const llvm_value = switch (value_state) {
.none => current_value.llvm,
.sub => module.llvm.builder.create_sub(left, right),
.add => module.llvm.builder.create_add(left, right),
.mul => module.llvm.builder.create_mul(left, right),
.sdiv => module.llvm.builder.create_sdiv(left, right),
.udiv => module.llvm.builder.create_udiv(left, right),
.srem => module.llvm.builder.create_srem(left, right),
.urem => module.llvm.builder.create_urem(left, right),
.integer_sub => module.llvm.builder.create_sub(left, right),
.integer_add => module.llvm.builder.create_add(left, right),
.integer_mul => module.llvm.builder.create_mul(left, right),
.integer_sdiv => module.llvm.builder.create_sdiv(left, right),
.integer_udiv => module.llvm.builder.create_udiv(left, right),
.integer_srem => module.llvm.builder.create_srem(left, right),
.integer_urem => module.llvm.builder.create_urem(left, right),
.shl => module.llvm.builder.create_shl(left, right),
.ashr => module.llvm.builder.create_ashr(left, right),
.lshr => module.llvm.builder.create_lshr(left, right),
.@"and" => module.llvm.builder.create_and(left, right),
.@"or" => module.llvm.builder.create_or(left, right),
.xor => module.llvm.builder.create_xor(left, right),
.icmp_ne, .icmp_eq => |icmp| module.llvm.builder.create_compare(icmp.to_int_predicate(), left, right),
.integer_compare_equal, .integer_compare_not_equal => |icmp| module.llvm.builder.create_compare(icmp.to_int_predicate(), left, right),
.pointer_add => module.llvm.builder.create_gep(.{
.type = next_ty.bb.pointer.type.llvm.handle,
.aggregate = left,
.indices = &.{right},
.inbounds = false,
}),
};
switch (value_state) {
@ -2634,14 +2708,14 @@ const Converter = struct {
.llvm = llvm_value,
.type = switch (value_state) {
.none => unreachable,
.icmp_eq, .icmp_ne => module.integer_type(1, false),
.sub,
.add,
.mul,
.sdiv,
.udiv,
.srem,
.urem,
.integer_compare_equal, .integer_compare_not_equal => module.integer_type(1, false),
.integer_sub,
.integer_add,
.integer_mul,
.integer_sdiv,
.integer_udiv,
.integer_srem,
.integer_urem,
.shl,
.ashr,
.lshr,
@ -2649,6 +2723,7 @@ const Converter = struct {
.@"or",
.xor,
=> next_ty,
.pointer_add => next_ty,
},
.bb = .instruction,
.lvalue = false,
@ -2663,29 +2738,33 @@ const Converter = struct {
'=' => switch (converter.content[converter.offset + 1]) {
'=' => blk: {
converter.offset += 2;
break :blk .icmp_eq;
break :blk .integer_compare_equal;
},
else => break previous_value.?,
},
'-' => blk: {
converter.offset += 1;
break :blk .sub;
break :blk .integer_sub;
},
'+' => blk: {
converter.offset += 1;
break :blk .add;
break :blk switch (next_ty.bb) {
.integer => .integer_add,
.pointer => .pointer_add,
else => @trap(),
};
},
'*' => blk: {
converter.offset += 1;
break :blk .mul;
break :blk .integer_mul;
},
'/' => blk: {
converter.offset += 1;
const ty = iterative_expected_type orelse unreachable;
break :blk switch (ty.bb) {
.integer => |int| switch (int.signed) {
true => .sdiv,
false => .udiv,
true => .integer_sdiv,
false => .integer_udiv,
},
else => unreachable,
};
@ -2695,8 +2774,8 @@ const Converter = struct {
const ty = iterative_expected_type orelse unreachable;
break :blk switch (ty.bb) {
.integer => |int| switch (int.signed) {
true => .srem,
false => .urem,
true => .integer_srem,
false => .integer_urem,
},
else => unreachable,
};
@ -2747,7 +2826,7 @@ const Converter = struct {
break :blk switch (converter.content[converter.offset]) {
'=' => b: {
converter.offset += 1;
break :b .icmp_ne;
break :b .integer_compare_not_equal;
},
else => os.abort(),
};
@ -2979,15 +3058,7 @@ const Converter = struct {
return value;
},
.select => {
const condition_value = converter.parse_value(module, null, .value);
if (condition_value.type.bb != .integer) {
converter.report_error();
}
if (condition_value.type.bb.integer.bit_count != 1) {
converter.report_error();
}
const condition_value = converter.parse_condition_raw(module);
converter.skip_space();
converter.expect_character(',');
@ -3950,11 +4021,12 @@ const Converter = struct {
if (expected_ty == appointee_type) {
@trap();
} else {
if (appointee_type.bb == .pointer and appointee_type.bb.pointer.type == expected_ty) {
assert(appointee_type.bb == .pointer); // TODO ?????
if (appointee_type.bb == .pointer and element_type == expected_ty) {
const load = module.values.add();
load.* = .{
.llvm = module.create_load(.{ .type = expected_ty, .value = pointer_load.llvm }),
.type = expected_ty,
.llvm = module.create_load(.{ .type = element_type, .value = pointer_load.llvm }),
.type = element_type,
.bb = .instruction,
.lvalue = false,
.dereference_to_assign = false,
@ -3965,7 +4037,15 @@ const Converter = struct {
}
}
} else {
@trap();
const load = module.values.add();
load.* = .{
.llvm = module.create_load(.{ .type = element_type, .value = pointer_load.llvm }),
.type = element_type,
.bb = .instruction,
.lvalue = false,
.dereference_to_assign = false,
};
break :b load;
}
},
.maybe_pointer, .pointer => {
@ -4165,6 +4245,8 @@ fn is_space(ch: u8) bool {
const StatementStartKeyword = enum {
@"return",
@"if",
// TODO: make `unreachable` a statement start keyword?
@"while",
};
pub const BuildMode = enum {

View File

@ -443,3 +443,7 @@ test "basic_string" {
test "argv" {
try invsrc(@src());
}
test "basic_while" {
try invsrc(@src());
}

View File

@ -7,6 +7,20 @@ const Arena = lib.Arena;
pub const panic = lib.panic_struct;
comptime {
if (!lib.is_test) {
@export(&main, .{
.name = "main",
});
}
}
test {
_ = lib;
_ = llvm;
_ = converter;
}
pub fn main(argc: c_int, argv: [*:null]const ?[*:0]const u8) callconv(.C) c_int {
if (argc != 2) {
lib.print_string("Failed to match argument count\n");
@ -50,17 +64,3 @@ pub fn main(argc: c_int, argv: [*:null]const ?[*:0]const u8) callconv(.C) c_int
});
return 0;
}
comptime {
if (!lib.is_test) {
@export(&main, .{
.name = "main",
});
}
}
test {
_ = lib;
_ = llvm;
_ = converter;
}

38
tests/basic_while.bbb Normal file
View File

@ -0,0 +1,38 @@
c_string_length = fn (c_string: &u8) u64
{
>it = c_string;
while (it.&)
{
it = it + 1;
}
return #int_from_pointer(it) - #int_from_pointer(c_string);
}
[export] main = fn (argument_count: u32, argument_pointer: &&u8) s32
{
if (argument_count == 0)
{
return 1;
}
>first_arg = argument_pointer[0];
if (!first_arg)
{
return 1;
}
>arg_length = c_string_length(first_arg);
if (arg_length == 0)
{
return 1;
}
if (first_arg[arg_length] != 0)
{
return 1;
}
return 0;
}