Merge pull request #56 from birth-software/rework-sema

rework semantic analysis
This commit is contained in:
David 2024-02-01 12:55:40 +01:00 committed by GitHub
commit 07c1cd7d53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 2394 additions and 2518 deletions

File diff suppressed because it is too large Load Diff

View File

@ -324,6 +324,11 @@ extern "C" DISubprogram* NativityLLVMFunctionGetSubprogram(Function& function)
return subprogram;
}
extern "C" void NativityLLVMGlobalVariableSetInitializer(GlobalVariable& global_variable, Constant* constant_initializer)
{
global_variable.setInitializer(constant_initializer);
}
extern "C" Constant* NativityLLVMConstantStruct(StructType* struct_type, Constant** constant_ptr, size_t constant_count)
{
auto constants = ArrayRef<Constant*>(constant_ptr, constant_count);

File diff suppressed because it is too large Load Diff

View File

@ -116,3 +116,4 @@ pub extern fn NativityLLVMCreatePhiNode(type: *LLVM.Type, reserved_value_count:
pub extern fn NativityLLVMAllocatGetAllocatedType(alloca: *LLVM.Value.Instruction.Alloca) *LLVM.Type;
pub extern fn NativityLLVMValueToAlloca(value: *LLVM.Value) ?*LLVM.Value.Instruction.Alloca;
pub extern fn NativityLLVMGlobalVariableSetInitializer(global_variable: *LLVM.Value.Constant.GlobalVariable, constant_initializer: *LLVM.Value.Constant) void;

View File

@ -13,7 +13,6 @@ const HashMap = data_structures.HashMap;
const lexer = @import("lexer.zig");
const Compilation = @import("../Compilation.zig");
const File = Compilation.File;
const log = Compilation.log;
const logln = Compilation.logln;
const Token = Compilation.Token;
@ -179,10 +178,12 @@ pub const Node = struct {
empty_container_literal_guess,
break_expression,
character_literal,
attribute_naked,
attribute_export,
attribute_extern,
attribute_cc,
function_attribute_naked,
function_attribute_cc,
symbol_attribute_extern,
symbol_attribute_export,
symbol_attributes,
metadata,
};
};
@ -199,7 +200,6 @@ const Analyzer = struct {
nodes: *Node.List,
node_lists: *ArrayList(ArrayList(Node.Index)),
source_file: []const u8,
file_index: File.Index,
allocator: Allocator,
suffix_depth: usize = 0,
@ -288,10 +288,50 @@ const Analyzer = struct {
logln(.parser, .symbol_declaration, "Current token: {}", .{analyzer.peekToken()});
const type_node_index = switch (analyzer.peekToken()) {
const metadata_node_index = switch (analyzer.peekToken()) {
.operator_colon => blk: {
analyzer.consumeToken();
break :blk try analyzer.typeExpression();
const colon = try analyzer.expectToken(.operator_colon);
const type_node_index = if (analyzer.peekToken() != .operator_colon) try analyzer.typeExpression() else .null;
const attribute_node_index: Node.Index = if (analyzer.peekToken() == .operator_colon) b: {
analyzer.consumeToken();
var list = ArrayList(Node.Index){};
while (analyzer.peekToken() != .operator_assign) {
const identifier = try analyzer.expectToken(.identifier);
const identifier_name = analyzer.bytes(identifier);
const attribute_node = inline for (@typeInfo(Compilation.Debug.Declaration.Global.Attribute).Enum.fields) |enum_field| {
if (equal(u8, identifier_name, enum_field.name)) {
const attribute = @field(Compilation.Debug.Declaration.Global.Attribute, enum_field.name);
const attribute_node = switch (attribute) {
.@"export" => try analyzer.addNode(.{
.id = @field(Node.Id, "symbol_attribute_" ++ @tagName(attribute)),
.token = identifier,
.left = .null,
.right = .null,
}),
};
break attribute_node;
}
} else @panic("Not known attribute");
try list.append(analyzer.allocator, attribute_node);
switch (analyzer.peekToken()) {
.operator_assign => {},
.operator_comma => analyzer.consumeToken(),
else => |t| @panic(@tagName(t)),
}
}
break :b try analyzer.nodeList(list);
} else .null;
break :blk try analyzer.addNode(.{
.id = .metadata,
.token = colon,
.left = type_node_index,
.right = attribute_node_index,
});
},
else => Node.Index.null,
};
@ -310,7 +350,7 @@ const Analyzer = struct {
const declaration = Node{
.id = mutability_node_id,
.token = first,
.left = type_node_index,
.left = metadata_node_index,
.right = init_node_index,
};
@ -350,8 +390,8 @@ const Analyzer = struct {
if (equal(u8, identifier_name, enum_field.name)) {
const attribute = @field(Compilation.Function.Attribute, enum_field.name);
const attribute_node = switch (attribute) {
.naked, .@"export", => try analyzer.addNode(.{
.id = @field(Node.Id, "attribute_" ++ @tagName(attribute)),
.naked, => try analyzer.addNode(.{
.id = @field(Node.Id, "function_attribute_" ++ @tagName(attribute)),
.token = identifier,
.left = .null,
.right = .null,
@ -826,9 +866,9 @@ const Analyzer = struct {
_ = try analyzer.expectToken(.operator_left_parenthesis);
const intrinsic_name = analyzer.bytes(intrinsic_token)[1..];
const intrinsic_id = inline for (@typeInfo(Compilation.Intrinsic.Id).Enum.fields) |enum_field| {
const intrinsic_id = inline for (@typeInfo(Compilation.IntrinsicId).Enum.fields) |enum_field| {
if (equal(u8, enum_field.name, intrinsic_name)) {
break @field(Compilation.Intrinsic.Id, enum_field.name);
break @field(Compilation.IntrinsicId, enum_field.name);
}
} else @panic(intrinsic_name);
@ -1902,13 +1942,13 @@ const Analyzer = struct {
fn addNode(analyzer: *Analyzer, node: Node) !Node.Index {
const node_index = try analyzer.nodes.append(analyzer.allocator, node);
logln(.parser, .node_creation, "Adding node #{} {s} to file #{} (left: {}, right: {})", .{ Node.unwrap(node_index), @tagName(node.id), File.unwrap(analyzer.file_index), switch (node.left) {
.null => 0xffff_ffff,
else => Node.unwrap(node.left),
}, switch (node.right) {
.null => 0xffff_ffff,
else => Node.unwrap(node.right),
}});
// logln(.parser, .node_creation, "Adding node #{} {s} to file #{} (left: {}, right: {})", .{ Node.unwrap(node_index), @tagName(node.id), File.unwrap(analyzer.file_index), switch (node.left) {
// .null => 0xffff_ffff,
// else => Node.unwrap(node.left),
// }, switch (node.right) {
// .null => 0xffff_ffff,
// else => Node.unwrap(node.right),
// }});
// if (Logger.bitset.contains(.node_creation_detailed)) {
// const chunk_start = analyzer.lexer.offsets.items[node.token];
// const chunk_end = analyzer.lexer.offsets.items[node.token + 1];
@ -1950,13 +1990,13 @@ const Analyzer = struct {
// Here it is assumed that left brace is consumed
pub fn analyze(allocator: Allocator, lexer_result: lexer.Result, source_file: []const u8, file_index: File.Index, token_buffer: *Token.Buffer, node_list: *Node.List, node_lists: *ArrayList(ArrayList(Node.Index))) !Result {
pub fn analyze(allocator: Allocator, lexer_result: lexer.Result, source_file: []const u8, token_buffer: *Token.Buffer, node_list: *Node.List, node_lists: *ArrayList(ArrayList(Node.Index))) !Result {
const start = std.time.Instant.now() catch unreachable;
var analyzer = Analyzer{
.lexer = lexer_result,
.token_buffer = token_buffer,
.source_file = source_file,
.file_index = file_index,
// .file_index = file_index,
.token_i = lexer_result.offset,
.allocator = allocator,
.nodes = node_list,

View File

@ -5,7 +5,6 @@ pub fn build(b: *std.Build) !void {
const self_hosted_ci = b.option(bool, "self_hosted_ci", "This option enables the self-hosted CI behavior") orelse false;
const third_party_ci = b.option(bool, "third_party_ci", "This option enables the third-party CI behavior") orelse false;
const is_ci = self_hosted_ci or third_party_ci;
_ = is_ci; // autofix
const native_target = b.resolveTargetQuery(.{});
const optimization = b.standardOptimizeOption(.{});
var target_query = b.standardTargetOptionsQueryOnly(.{});
@ -76,9 +75,9 @@ pub fn build(b: *std.Build) !void {
.target = target,
.optimize = optimization,
});
// compiler.formatted_panics = false;
// compiler.root_module.unwind_tables = false;
// compiler.root_module.omit_frame_pointer = false;
compiler.formatted_panics = is_ci;
compiler.root_module.unwind_tables = is_ci;
compiler.root_module.omit_frame_pointer = false;
compiler.want_lto = false;
compiler.linkLibC();

View File

@ -8,7 +8,7 @@ comptime {
}
}
const _start = fn naked, export () noreturn {
const _start:: export = fn naked() noreturn {
#asm({
xor ebp, ebp;
mov rdi, rsp;
@ -21,7 +21,7 @@ var argument_count: usize = 0;
var argument_values: [&]const [&:0]const u8 = undefined;
var environment_values: [&:null]const ?[&:null]const u8 = undefined;
const start = fn export (argc_argv_address: usize) noreturn {
const start:: export = fn (argc_argv_address: usize) noreturn {
var argument_address_iterator = argc_argv_address;
const argument_count_ptr: &usize = #cast(argument_address_iterator);
argument_count = argument_count_ptr.@;
@ -33,6 +33,6 @@ const start = fn export (argc_argv_address: usize) noreturn {
std.os.exit(exit_code = result);
}
const main = fn export (argc: s32, argv: [&:null]?[&:null]u8, env: [&:null]?[&:null]u8) s32 {
const main:: export = fn (argc: s32, argv: [&:null]?[&:null]u8, env: [&:null]?[&:null]u8) s32 {
return #import("main").main();
}