Make more progress
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 2m53s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 2m52s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 2m58s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 4m26s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 3m2s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 2m59s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 3m10s
CI / ci (Debug, ubuntu-latest) (push) Successful in 4m32s
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 2m53s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 2m52s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 2m58s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 4m26s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 3m2s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 2m59s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 3m10s
CI / ci (Debug, ubuntu-latest) (push) Successful in 4m32s
This commit is contained in:
parent
1b0a5c4636
commit
0eee2a4ff3
@ -6124,6 +6124,47 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn copy_statement(module: *Module, scope: *Scope, old_statement: *Statement) *Statement {
|
||||||
|
const new_statement = module.statements.add();
|
||||||
|
new_statement.line = old_statement.line;
|
||||||
|
new_statement.column = old_statement.column;
|
||||||
|
|
||||||
|
new_statement.bb = switch (old_statement.bb) {
|
||||||
|
.@"return" => |rv| if (rv) |v| .{
|
||||||
|
.@"return" = module.clone_value(scope, v),
|
||||||
|
} else old_statement.bb,
|
||||||
|
.@"if" => |if_stmt| blk: {
|
||||||
|
const condition = module.clone_value(scope, if_stmt.condition);
|
||||||
|
const if_statement = module.copy_statement(scope, if_stmt.if_statement);
|
||||||
|
const else_statement = if (if_stmt.else_statement) |else_statement| module.copy_statement(scope, else_statement) else null;
|
||||||
|
break :blk .{
|
||||||
|
.@"if" = .{
|
||||||
|
.condition = condition,
|
||||||
|
.if_statement = if_statement,
|
||||||
|
.else_statement = else_statement,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.block => |block| blk: {
|
||||||
|
const lexical_block = module.lexical_blocks.add();
|
||||||
|
module.copy_block(scope, .{
|
||||||
|
.source = block,
|
||||||
|
.destination = lexical_block,
|
||||||
|
});
|
||||||
|
|
||||||
|
break :blk .{
|
||||||
|
.block = lexical_block,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.expression => |v| .{
|
||||||
|
.expression = module.clone_value(scope, v),
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return new_statement;
|
||||||
|
}
|
||||||
|
|
||||||
const BlockCopy = struct {
|
const BlockCopy = struct {
|
||||||
source: *LexicalBlock,
|
source: *LexicalBlock,
|
||||||
destination: *LexicalBlock,
|
destination: *LexicalBlock,
|
||||||
@ -6142,20 +6183,12 @@ pub const Module = struct {
|
|||||||
.parent = parent_scope,
|
.parent = parent_scope,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const scope = &destination.scope;
|
const scope = &destination.scope;
|
||||||
|
|
||||||
for (source.statements.get_slice()) |old_statement| {
|
for (source.statements.get_slice()) |old_statement| {
|
||||||
const new_statement = module.statements.add();
|
const statement = module.copy_statement(scope, old_statement);
|
||||||
_ = destination.statements.append(new_statement);
|
_ = destination.statements.append(statement);
|
||||||
new_statement.line = old_statement.line;
|
|
||||||
new_statement.column = old_statement.column;
|
|
||||||
|
|
||||||
new_statement.bb = switch (old_statement.bb) {
|
|
||||||
.@"return" => |rv| if (rv) |v| .{
|
|
||||||
.@"return" = module.clone_value(scope, v),
|
|
||||||
} else old_statement.bb,
|
|
||||||
else => @trap(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6167,6 +6200,12 @@ pub const Module = struct {
|
|||||||
|
|
||||||
result.* = .{
|
result.* = .{
|
||||||
.bb = switch (source.bb) {
|
.bb = switch (source.bb) {
|
||||||
|
.unary => |unary| .{
|
||||||
|
.unary = .{
|
||||||
|
.value = module.clone_value(scope, unary.value),
|
||||||
|
.id = unary.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
.binary => |binary| .{
|
.binary => |binary| .{
|
||||||
.binary = .{
|
.binary = .{
|
||||||
.left = module.clone_value(scope, binary.left),
|
.left = module.clone_value(scope, binary.left),
|
||||||
@ -6203,6 +6242,7 @@ pub const Module = struct {
|
|||||||
else => @trap(),
|
else => @trap(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.@"unreachable" => .@"unreachable",
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
},
|
},
|
||||||
.kind = source.kind,
|
.kind = source.kind,
|
||||||
@ -6489,9 +6529,10 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.typecheck(analysis, integer_max_type);
|
const result_type = if (analysis.type) |et| et else integer_max_type;
|
||||||
|
module.typecheck(analysis, result_type);
|
||||||
|
|
||||||
break :blk integer_max_type;
|
break :blk result_type;
|
||||||
},
|
},
|
||||||
.int_from_enum => |enum_value| blk: {
|
.int_from_enum => |enum_value| blk: {
|
||||||
module.analyze_value_type(enum_value, .{});
|
module.analyze_value_type(enum_value, .{});
|
||||||
@ -7728,7 +7769,7 @@ pub const Module = struct {
|
|||||||
max_type.resolve(module);
|
max_type.resolve(module);
|
||||||
const bit_count = max_type.bb.integer.bit_count;
|
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 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.llvm.abi.?.to_integer().get_constant(max_value, @intFromBool(false));
|
const constant_integer = value_type.llvm.abi.?.to_integer().get_constant(max_value, @intFromBool(false));
|
||||||
break :blk constant_integer.to_value();
|
break :blk constant_integer.to_value();
|
||||||
},
|
},
|
||||||
.int_from_enum => |enum_value| blk: {
|
.int_from_enum => |enum_value| blk: {
|
||||||
@ -8193,11 +8234,15 @@ pub const Module = struct {
|
|||||||
_ = module.llvm.builder.create_branch(macro_entry_block);
|
_ = module.llvm.builder.create_branch(macro_entry_block);
|
||||||
module.llvm.builder.position_at_end(macro_entry_block);
|
module.llvm.builder.position_at_end(macro_entry_block);
|
||||||
|
|
||||||
const macro_return_alloca = module.create_alloca(.{
|
const valid_return_value = switch (macro_instantiation.return_type.bb) {
|
||||||
|
.void, .noreturn => false,
|
||||||
|
else => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_instantiation.return_alloca = if (valid_return_value) module.create_alloca(.{
|
||||||
.type = macro_instantiation.return_type,
|
.type = macro_instantiation.return_type,
|
||||||
.name = "macro.return",
|
.name = "macro.return",
|
||||||
});
|
}) else undefined;
|
||||||
macro_instantiation.return_alloca = macro_return_alloca;
|
|
||||||
|
|
||||||
const macro_return_block = module.llvm.context.create_basic_block("macro.return_block", llvm_function);
|
const macro_return_block = module.llvm.context.create_basic_block("macro.return_block", llvm_function);
|
||||||
macro_instantiation.return_block = macro_return_block;
|
macro_instantiation.return_block = macro_return_block;
|
||||||
@ -8220,14 +8265,21 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.analyze_block(macro_instantiation.block);
|
module.analyze_block(macro_instantiation.block);
|
||||||
|
|
||||||
|
if (module.llvm.builder.get_insert_block() != null) {
|
||||||
|
_ = module.llvm.builder.create_branch(macro_return_block);
|
||||||
|
}
|
||||||
|
|
||||||
module.llvm.builder.position_at_end(macro_return_block);
|
module.llvm.builder.position_at_end(macro_return_block);
|
||||||
|
|
||||||
const load = module.create_load(.{
|
const load = switch (valid_return_value) {
|
||||||
|
true => module.create_load(.{
|
||||||
.type = macro_instantiation.return_type,
|
.type = macro_instantiation.return_type,
|
||||||
.value = macro_return_alloca,
|
.value = macro_instantiation.return_alloca,
|
||||||
.type_kind = type_kind,
|
.type_kind = type_kind,
|
||||||
});
|
}),
|
||||||
|
false => return,
|
||||||
|
};
|
||||||
break :blk load;
|
break :blk load;
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
@ -8645,7 +8697,6 @@ pub const Module = struct {
|
|||||||
const loop_exit_block = module.llvm.context.create_basic_block("foreach.exit", llvm_function);
|
const loop_exit_block = module.llvm.context.create_basic_block("foreach.exit", llvm_function);
|
||||||
module.exit_block = loop_exit_block;
|
module.exit_block = loop_exit_block;
|
||||||
|
|
||||||
|
|
||||||
switch (for_loop.kind) {
|
switch (for_loop.kind) {
|
||||||
.slice => {
|
.slice => {
|
||||||
const index_zero = index_type.llvm.abi.?.get_zero().to_value();
|
const index_zero = index_type.llvm.abi.?.get_zero().to_value();
|
||||||
@ -9565,6 +9616,7 @@ pub const Module = struct {
|
|||||||
@trap();
|
@trap();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.void => ty,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
128
src/compiler.bbb
128
src/compiler.bbb
@ -81,7 +81,7 @@ O = bits u32
|
|||||||
[extern] write = fn [cc(c)] (fd: File, pointer: &u8, byte_count: u64) ssize;
|
[extern] write = fn [cc(c)] (fd: File, pointer: &u8, byte_count: u64) ssize;
|
||||||
[extern] read = fn [cc(c)] (fd: File, pointer: &u8, byte_count: u64) ssize;
|
[extern] read = fn [cc(c)] (fd: File, pointer: &u8, byte_count: u64) ssize;
|
||||||
|
|
||||||
assert = fn (ok: u1) void
|
assert = macro (ok: u1) void
|
||||||
{
|
{
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
@ -660,7 +660,71 @@ is_space = fn (ch: u8) u1
|
|||||||
return ch == ' ' or ch == '\n' or ch == '\t' or ch == '\r';
|
return ch == ' ' or ch == '\n' or ch == '\t' or ch == '\r';
|
||||||
}
|
}
|
||||||
|
|
||||||
module_skip_space = fn (module: &Module) void
|
is_decimal = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return ch >= '0' and ch <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
is_octal = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return ch >= '0' and ch <= '7';
|
||||||
|
}
|
||||||
|
|
||||||
|
is_binary = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return ch == '0' or ch == '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
is_hex_alpha_lower = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return ch >= 'a' and ch <= 'f';
|
||||||
|
}
|
||||||
|
|
||||||
|
is_hex_alpha_upper = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return ch >= 'A' and ch <= 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
is_hex_alpha = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return is_hex_alpha_lower(ch) or is_hex_alpha_upper(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_hex = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return is_decimal(ch) or is_hex_alpha(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_identifier_start = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return (ch >= 'a' and ch >= 'z') or (ch >= 'A' and ch <= 'Z') or ch == '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
is_identifier = fn (ch: u8) u1
|
||||||
|
{
|
||||||
|
return is_identifier_start(ch) or is_decimal(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
report_error = fn () noreturn
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
get_line = fn (module: &Module) u32
|
||||||
|
{
|
||||||
|
>line = module.line_offset + 1;
|
||||||
|
assert(line <= #integer_max(u32));
|
||||||
|
return #truncate(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_column = fn (module: &Module) u32
|
||||||
|
{
|
||||||
|
>column = module.offset - module.line_character_offset + 1;
|
||||||
|
assert(column <= #integer_max(u32));
|
||||||
|
return #truncate(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_space = fn (module: &Module) void
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@ -701,11 +765,63 @@ module_skip_space = fn (module: &Module) void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module_parse = fn (module: &Module) void
|
consume_character_if_match = fn (module: &Module, expected_character: u8) u1
|
||||||
|
{
|
||||||
|
>is_ch: u1 = 0;
|
||||||
|
|
||||||
|
if (module.offset < module.content.length)
|
||||||
|
{
|
||||||
|
>ch = module.content[module.offset];
|
||||||
|
is_ch = expected_character == ch;
|
||||||
|
module.offset += #extend(is_ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_character = fn (module: &Module, expected_character: u8) void
|
||||||
|
{
|
||||||
|
if (!consume_character_if_match(module, expected_character))
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_identifier = fn (module: &Module) []u8
|
||||||
|
{
|
||||||
|
>start = module.offset;
|
||||||
|
|
||||||
|
if (is_identifier_start(module.content[start]))
|
||||||
|
{
|
||||||
|
module.offset += 1;
|
||||||
|
|
||||||
|
while (module.offset < module.content.length)
|
||||||
|
{
|
||||||
|
if (is_identifier(module.content[module.offset]))
|
||||||
|
{
|
||||||
|
module.offset += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module.offset - start == 0)
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
>result = module.content[start..module.offset];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse = fn (module: &Module) void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
module_emit = fn (module: &Module) void
|
emit = fn (module: &Module) void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,8 +910,8 @@ compile = fn (arena: &Arena, options: CompileOptions) void
|
|||||||
.line_character_offset = 0,
|
.line_character_offset = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_parse(&module);
|
parse(&module);
|
||||||
module_emit(&module);
|
emit(&module);
|
||||||
}
|
}
|
||||||
|
|
||||||
compile_file = fn (arena: &Arena, compile_options: CompileFile) void
|
compile_file = fn (arena: &Arena, compile_options: CompileFile) void
|
||||||
|
@ -331,4 +331,5 @@ const names = &[_][]const u8{
|
|||||||
"constant_global_reference",
|
"constant_global_reference",
|
||||||
"generic_pointer_macro",
|
"generic_pointer_macro",
|
||||||
"break_continue",
|
"break_continue",
|
||||||
|
"noreturn_macro",
|
||||||
};
|
};
|
||||||
|
27
tests/noreturn_macro.bbb
Normal file
27
tests/noreturn_macro.bbb
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
assert = macro (ok: u1) void
|
||||||
|
{
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
align_forward = fn (value: u64, alignment: u64) u64
|
||||||
|
{
|
||||||
|
assert(alignment != 0);
|
||||||
|
>mask = alignment - 1;
|
||||||
|
>result = (value + mask) & ~mask;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>result = align_forward(1, 64);
|
||||||
|
|
||||||
|
if (result != 64)
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user