From 3ca318bdf4b9af879c2158f37853bb949ac03aec Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Mon, 21 Apr 2025 19:59:02 -0600 Subject: [PATCH] wip --- src/bootstrap.zig | 531 +++++++++++++++++++++++------------------- tests/basic_macro.bbb | 6 + 2 files changed, 302 insertions(+), 235 deletions(-) create mode 100644 tests/basic_macro.bbb diff --git a/src/bootstrap.zig b/src/bootstrap.zig index aad8ab7..fcbba78 100644 --- a/src/bootstrap.zig +++ b/src/bootstrap.zig @@ -207,6 +207,39 @@ pub const Global = struct { }; }; +pub const Macro = struct { + foo: u32 = 0, + + pub const Buffer = struct { + buffer: lib.VirtualBuffer(Macro), + + pub fn get_slice(buffer: Buffer) []Macro { + return buffer.buffer.get_slice(); + } + + pub fn initialize() Buffer { + return .{ + .buffer = .initialize(), + }; + } + + pub fn find_by_name(globals: *Buffer, name: []const u8) ?*Macro { + const slice = globals.buffer.get_slice(); + for (slice) |*global| { + if (lib.string.equal(global.variable.name, name)) { + return global; + } + } else { + return null; + } + } + + pub fn add(globals: *Buffer) *Macro { + return globals.buffer.add(); + } + }; +}; + pub const ResolvedType = struct { handle: *llvm.Type, debug: *llvm.DI.Type, @@ -1006,6 +1039,7 @@ const GlobalKind = enum { bits, @"enum", @"fn", + macro, @"struct", typealias, }; @@ -1106,6 +1140,7 @@ pub const Module = struct { lexical_blocks: lib.VirtualBuffer(LexicalBlock), statements: lib.VirtualBuffer(Statement), current_function: ?*Global = null, + current_macro: ?*Macro = null, name: []const u8, path: []const u8, executable: [:0]const u8, @@ -1441,7 +1476,7 @@ pub const Module = struct { return pointer_type; } - fn parse_type(module: *Module, function: ?*Global) *Type { + fn parse_type(module: *Module) *Type { const start_character = module.content[module.offset]; switch (start_character) { 'a'...'z', 'A'...'Z', '_' => { @@ -1472,7 +1507,7 @@ pub const Module = struct { '&' => { module.offset += 1; module.skip_space(); - const element_type = module.parse_type(function); + const element_type = module.parse_type(); const pointer_type = module.get_pointer_type(.{ .type = element_type, }); @@ -1486,7 +1521,7 @@ pub const Module = struct { switch (is_slice) { true => { module.skip_space(); - const element_type = module.parse_type(function); + const element_type = module.parse_type(); const slice_type = module.get_slice_type(.{ .type = element_type }); return slice_type; }, @@ -1520,7 +1555,7 @@ pub const Module = struct { module.skip_space(); - const element_type = module.parse_type(function); + const element_type = module.parse_type(); const array_type = switch (element_count) { 0 => blk: { @@ -1548,7 +1583,7 @@ pub const Module = struct { const identifier = module.parse_identifier(); if (lib.string.to_enum(Type.Intrinsic.Id, identifier)) |intrinsic| switch (intrinsic) { .ReturnType => { - const return_type = function.?.variable.type.?.bb.function.semantic_return_type; + const return_type = module.current_function.?.variable.type.?.bb.function.semantic_return_type; return return_type; }, else => @trap(), @@ -2344,30 +2379,30 @@ pub const Module = struct { after: ?*const Rule.Function, precedence: Precedence, - const Function = fn (noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value; + const Function = fn (noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value; }; - fn parse_value(module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn parse_value(module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { assert(value_builder.precedence == .none); assert(value_builder.left == null); - const value = module.parse_precedence(function, scope, value_builder.with_precedence(.assignment)); + const value = module.parse_precedence(scope, value_builder.with_precedence(.assignment)); return value; } - fn parse_precedence(module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn parse_precedence(module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { assert(value_builder.token == .none); const token = module.tokenize(); const rule = &rules[@intFromEnum(token)]; if (rule.before) |before| { - const left = before(module, function, scope, value_builder.with_precedence(.none).with_token(token)); - const result = module.parse_precedence_left(function, scope, value_builder.with_left(left)); + const left = before(module, scope, value_builder.with_precedence(.none).with_token(token)); + const result = module.parse_precedence_left(scope, value_builder.with_left(left)); return result; } else { module.report_error(); } } - fn parse_precedence_left(module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn parse_precedence_left(module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { var result = value_builder.left; _ = &result; const precedence = value_builder.precedence; @@ -2389,14 +2424,14 @@ pub const Module = struct { const after_rule = token_rule.after orelse module.report_error(); const old = result; - const new = after_rule(module, function, scope, value_builder.with_token(token).with_precedence(.none).with_left(old)); + const new = after_rule(module, scope, value_builder.with_token(token).with_precedence(.none).with_left(old)); result = new; } return result.?; } - fn parse_statement(module: *Module, function: *Global, scope: *Scope) *Statement { + fn parse_statement(module: *Module, scope: *Scope) *Statement { const statement_line = module.get_line(); const statement_column = module.get_column(); @@ -2412,12 +2447,12 @@ pub const Module = struct { module.skip_space(); const local_type: ?*Type = if (module.consume_character_if_match(':')) b: { module.skip_space(); - const t = module.parse_type(function); + const t = module.parse_type(); module.skip_space(); break :b t; } else null; module.expect_character('='); - const local_value = module.parse_value(function, scope, .{}); + const local_value = module.parse_value(scope, .{}); const local = module.locals.add(); local.* = .{ .variable = .{ @@ -2442,7 +2477,7 @@ pub const Module = struct { }; }, '#' => .{ - .expression = module.parse_value(function, scope, .{}), + .expression = module.parse_value(scope, .{}), }, 'A'...'Z', 'a'...'z' => blk: { const statement_start_identifier = module.parse_identifier(); @@ -2450,7 +2485,7 @@ pub const Module = struct { if (lib.string.to_enum(StatementStartKeyword, statement_start_identifier)) |statement_start_keyword| switch (statement_start_keyword) { ._ => @trap(), .@"return" => break :blk .{ - .@"return" = module.parse_value(function, scope, .{}), + .@"return" = module.parse_value(scope, .{}), }, .@"if" => { module.skip_space(); @@ -2458,14 +2493,14 @@ pub const Module = struct { module.expect_character(left_parenthesis); module.skip_space(); - const condition = module.parse_value(function, scope, .{}); + const condition = module.parse_value(scope, .{}); module.skip_space(); module.expect_character(right_parenthesis); module.skip_space(); - const if_statement = module.parse_statement(function, scope); + const if_statement = module.parse_statement(scope); module.skip_space(); @@ -2481,7 +2516,7 @@ pub const Module = struct { } const else_block = switch (is_else) { - true => module.parse_statement(function, scope), + true => module.parse_statement(scope), false => null, }; @@ -2501,14 +2536,14 @@ pub const Module = struct { module.expect_character(left_parenthesis); module.skip_space(); - const condition = module.parse_value(function, scope, .{}); + const condition = module.parse_value(scope, .{}); module.skip_space(); module.expect_character(right_parenthesis); module.skip_space(); - const while_block = module.parse_block(function, scope); + const while_block = module.parse_block(scope); require_semicolon = false; @@ -2599,7 +2634,7 @@ pub const Module = struct { while (true) { module.skip_space(); - const identifier = module.parse_value(function, scope, .{ + const identifier = module.parse_value(scope, .{ .kind = .left, }); right_value_buffer[right_value_count] = identifier; @@ -2630,7 +2665,7 @@ pub const Module = struct { statement.bb.for_each.left_values = left_values; statement.bb.for_each.right_values = right_values; - const predicate = module.parse_statement(function, &statement.bb.for_each.scope); + const predicate = module.parse_statement(&statement.bb.for_each.scope); statement.bb.for_each.predicate = predicate; module.skip_space(); @@ -2644,7 +2679,7 @@ pub const Module = struct { module.expect_character(left_parenthesis); module.skip_space(); - const discriminant = module.parse_value(function, scope, .{}); + const discriminant = module.parse_value(scope, .{}); module.skip_space(); module.expect_character(right_parenthesis); @@ -2682,7 +2717,7 @@ pub const Module = struct { var case_count: u64 = 0; while (true) { - const case_value = module.parse_value(function, scope, .{}); + const case_value = module.parse_value(scope, .{}); case_buffer[case_count] = case_value; case_count += 1; @@ -2703,7 +2738,7 @@ pub const Module = struct { module.skip_space(); - const clause_block = module.parse_block(function, scope); + const clause_block = module.parse_block(scope); clause_buffer[clause_count] = .{ .values = clause_values, @@ -2735,7 +2770,7 @@ pub const Module = struct { } else { module.offset -= statement_start_identifier.len; - const left = module.parse_value(function, scope, .{ + const left = module.parse_value(scope, .{ .kind = .left, }); @@ -2818,7 +2853,7 @@ pub const Module = struct { module.skip_space(); - const right = module.parse_value(function, scope, .{}); + const right = module.parse_value(scope, .{}); break :blk .{ .assignment = .{ @@ -2833,7 +2868,7 @@ pub const Module = struct { left_brace => blk: { require_semicolon = false; break :blk .{ - .block = module.parse_block(function, scope), + .block = module.parse_block(scope), }; }, else => @trap(), @@ -2849,7 +2884,7 @@ pub const Module = struct { return statement; } - fn parse_block(module: *Module, function: *Global, parent_scope: *Scope) *LexicalBlock { + fn parse_block(module: *Module, parent_scope: *Scope) *LexicalBlock { const block = module.lexical_blocks.append(.{ .statements = .initialize(), .locals = .initialize(), @@ -2875,16 +2910,15 @@ pub const Module = struct { break; } - const statement = module.parse_statement(function, scope); + const statement = module.parse_statement(scope); _ = block.statements.append(statement); } return block; } - fn rule_before_dot(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_dot(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { _ = scope; - _ = function; _ = value_builder; module.skip_space(); const identifier = module.parse_identifier(); @@ -2898,9 +2932,8 @@ pub const Module = struct { return value; } - fn rule_after_dot(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_after_dot(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { _ = scope; - _ = function; module.skip_space(); const left = value_builder.left orelse module.report_error(); left.kind = .left; @@ -2918,9 +2951,8 @@ pub const Module = struct { return value; } - fn rule_before_string_literal(noalias module: *Module, function: ?*Global, parent_scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_string_literal(noalias module: *Module, parent_scope: *Scope, value_builder: Value.Builder) *Value { _ = parent_scope; - _ = function; const value = module.values.add(); value.* = .{ .bb = .{ @@ -2930,8 +2962,7 @@ pub const Module = struct { return value; } - fn rule_before_identifier(noalias module: *Module, function: ?*Global, current_scope: *Scope, value_builder: Value.Builder) *Value { - _ = function; + fn rule_before_identifier(noalias module: *Module, current_scope: *Scope, value_builder: Value.Builder) *Value { const identifier = value_builder.token.identifier; assert(!lib.string.equal(identifier, "")); assert(!lib.string.equal(identifier, "_")); @@ -2990,9 +3021,8 @@ pub const Module = struct { return value; } - fn rule_before_value_keyword(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_value_keyword(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { _ = scope; - _ = function; const value = module.values.add(); const new_value: Value = switch (value_builder.token.value_keyword) { .zero => .{ @@ -3009,7 +3039,7 @@ pub const Module = struct { return value; } - fn rule_before_value_intrinsic(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_value_intrinsic(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { const intrinsic = value_builder.token.value_intrinsic; const value = module.values.add(); @@ -3018,7 +3048,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const ty = module.parse_type(function); + const ty = module.parse_type(); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3032,7 +3062,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const arg_value = module.parse_value(function, scope, .{}); + const arg_value = module.parse_value(scope, .{}); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3046,7 +3076,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const arg_value = module.parse_value(function, scope, .{}); + const arg_value = module.parse_value(scope, .{}); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3060,7 +3090,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const ty = module.parse_type(function); + const ty = module.parse_type(); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3074,7 +3104,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const arg_value = module.parse_value(function, scope, .{}); + const arg_value = module.parse_value(scope, .{}); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3088,7 +3118,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const arg_value = module.parse_value(function, scope, .{}); + const arg_value = module.parse_value(scope, .{}); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3102,7 +3132,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const v = module.parse_value(function, scope, .{}); + const v = module.parse_value(scope, .{}); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3116,13 +3146,13 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const condition = module.parse_value(function, scope, .{}); + const condition = module.parse_value(scope, .{}); module.expect_character(','); module.skip_space(); - const true_value = module.parse_value(function, scope, .{}); + const true_value = module.parse_value(scope, .{}); module.expect_character(','); module.skip_space(); - const false_value = module.parse_value(function, scope, .{}); + const false_value = module.parse_value(scope, .{}); module.skip_space(); module.expect_character(right_parenthesis); break :blk .{ @@ -3141,10 +3171,10 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const enum_type = module.parse_type(function); + const enum_type = module.parse_type(); module.expect_character(','); module.skip_space(); - const string_value = module.parse_value(function, scope, .{}); + const string_value = module.parse_value(scope, .{}); module.skip_space(); module.expect_character(right_parenthesis); @@ -3174,7 +3204,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const v = module.parse_value(function, scope, .{}); + const v = module.parse_value(scope, .{}); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3199,7 +3229,7 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const va_list = module.parse_value(function, scope, .{}); + const va_list = module.parse_value(scope, .{}); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3213,11 +3243,11 @@ pub const Module = struct { module.skip_space(); module.expect_character(left_parenthesis); module.skip_space(); - const va_list = module.parse_value(function, scope, .{}); + const va_list = module.parse_value(scope, .{}); module.skip_space(); module.expect_character(','); module.skip_space(); - const ty = module.parse_type(function); + const ty = module.parse_type(); module.expect_character(right_parenthesis); break :blk .{ .bb = .{ @@ -3236,9 +3266,8 @@ pub const Module = struct { return value; } - fn rule_before_integer(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_integer(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { _ = scope; - _ = function; const v = value_builder.token.integer.value; const value = module.values.add(); value.* = .{ @@ -3252,13 +3281,13 @@ pub const Module = struct { return value; } - fn rule_after_binary(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_after_binary(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { const binary_operator_token = value_builder.token; const binary_operator_token_precedence = rules[@intFromEnum(binary_operator_token)].precedence; const left = value_builder.left orelse module.report_error(); assert(binary_operator_token_precedence != .assignment); // TODO: this may be wrong. Assignment operator is not allowed in expressions const right_precedence = if (binary_operator_token_precedence == .assignment) .assignment else binary_operator_token_precedence.increment(); - const right = module.parse_precedence(function, scope, value_builder.with_precedence(right_precedence).with_token(.none).with_left(null)); + const right = module.parse_precedence(scope, value_builder.with_precedence(right_precedence).with_token(.none).with_left(null)); const binary_operation_kind: Binary.Id = switch (binary_operator_token) { .none => unreachable, @@ -3299,7 +3328,7 @@ pub const Module = struct { return value; } - fn rule_before_unary(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_unary(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { assert(value_builder.left == null); const unary_token = value_builder.token; const unary_id: Unary.Id = switch (unary_token) { @@ -3312,7 +3341,7 @@ pub const Module = struct { else => @trap(), }; - const right = module.parse_precedence(function, scope, value_builder.with_precedence(.prefix).with_token(.none).with_kind(if (unary_id == .@"&") .left else value_builder.kind)); + const right = module.parse_precedence(scope, value_builder.with_precedence(.prefix).with_token(.none).with_kind(if (unary_id == .@"&") .left else value_builder.kind)); const value = module.values.add(); value.* = .{ @@ -3326,9 +3355,8 @@ pub const Module = struct { return value; } - fn rule_after_dereference(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_after_dereference(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { _ = scope; - _ = function; const value = module.values.add(); value.* = .{ .bb = .{ @@ -3338,7 +3366,7 @@ pub const Module = struct { return value; } - fn rule_before_brace(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_brace(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { assert(value_builder.left == null); var name_buffer: [64][]const u8 = undefined; @@ -3363,7 +3391,7 @@ pub const Module = struct { module.skip_space(); - const value = module.parse_value(function, scope, .{}); + const value = module.parse_value(scope, .{}); value_buffer[field_count] = value; module.skip_space(); @@ -3417,7 +3445,7 @@ pub const Module = struct { } // Array initialization - fn rule_before_bracket(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_bracket(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { assert(value_builder.left == null); var value_buffer: [64]*Value = undefined; @@ -3430,7 +3458,7 @@ pub const Module = struct { if (module.consume_character_if_match(right_bracket)) { break; } - const v = module.parse_value(function, scope, .{}); + const v = module.parse_value(scope, .{}); value_buffer[element_count] = v; _ = module.consume_character_if_match(','); @@ -3453,12 +3481,12 @@ pub const Module = struct { } // Array-like subscript - fn rule_after_bracket(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_after_bracket(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { const left = value_builder.left orelse module.report_error(); left.kind = .left; module.skip_space(); const is_start = !(module.content[module.offset] == '.' and module.content[module.offset + 1] == '.'); - const start = if (is_start) module.parse_value(function, scope, .{}) else null; + const start = if (is_start) module.parse_value(scope, .{}) else null; const value = module.values.add(); value.* = .{ .bb = if (module.consume_character_if_match(right_bracket)) .{ @@ -3473,7 +3501,7 @@ pub const Module = struct { const end = switch (module.consume_character_if_match(right_bracket)) { true => null, false => b: { - const end = module.parse_value(function, scope, .{}); + const end = module.parse_value(scope, .{}); module.expect_character(right_bracket); break :b end; }, @@ -3491,15 +3519,15 @@ pub const Module = struct { return value; } - fn rule_before_parenthesis(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_before_parenthesis(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { _ = value_builder; module.skip_space(); - const v = module.parse_value(function, scope, .{}); + const v = module.parse_value(scope, .{}); module.expect_character(right_parenthesis); return v; } - fn rule_after_call(noalias module: *Module, function: ?*Global, scope: *Scope, value_builder: Value.Builder) *Value { + fn rule_after_call(noalias module: *Module, scope: *Scope, value_builder: Value.Builder) *Value { const may_be_callable = value_builder.left orelse module.report_error(); assert(value_builder.token == .@"("); var semantic_argument_count: u32 = 0; @@ -3514,7 +3542,7 @@ pub const Module = struct { break; } - const argument = module.parse_value(function, scope, .{}); + const argument = module.parse_value(scope, .{}); const argument_index = semantic_argument_count; semantic_argument_buffer[argument_index] = argument; @@ -3641,7 +3669,7 @@ pub const Module = struct { if (module.consume_character_if_match(':')) { module.skip_space(); - global_type = module.parse_type(null); + global_type = module.parse_type(); module.skip_space(); } @@ -3732,7 +3760,7 @@ pub const Module = struct { module.skip_space(); - const argument_type = module.parse_type(null); + const argument_type = module.parse_type(); semantic_argument_type_buffer[semantic_argument_count] = argument_type; module.skip_space(); @@ -3744,7 +3772,7 @@ pub const Module = struct { module.skip_space(); - const return_type = module.parse_type(null); + const return_type = module.parse_type(); const argument_types: []const *Type = if (semantic_argument_count == 0) &.{} else blk: { const argument_types = module.arena.allocate(*Type, semantic_argument_count); @memcpy(argument_types, semantic_argument_type_buffer[0..argument_types.len]); @@ -3825,7 +3853,7 @@ pub const Module = struct { } } - storage.bb.function.main_block = module.parse_block(global, &storage.bb.function.scope); + storage.bb.function.main_block = module.parse_block(&storage.bb.function.scope); } else { storage.bb = .external_function; } @@ -3834,7 +3862,7 @@ pub const Module = struct { const is_implicit_type = module.content[module.offset] == left_brace; const maybe_backing_type: ?*Type = switch (is_implicit_type) { true => null, - false => module.parse_type(null), + false => module.parse_type(), }; module.skip_space(); @@ -3912,7 +3940,7 @@ pub const Module = struct { const is_implicit_type = module.content[module.offset] == left_brace; const maybe_backing_type: ?*Type = switch (is_implicit_type) { true => null, - false => module.parse_type(null), + false => module.parse_type(), }; module.skip_space(); @@ -3943,7 +3971,7 @@ pub const Module = struct { module.skip_space(); - const field_type = module.parse_type(null); + const field_type = module.parse_type(); field_buffer[field_count] = .{ .name = field_name, @@ -4026,7 +4054,7 @@ pub const Module = struct { module.skip_space(); - const field_type = module.parse_type(null); + const field_type = module.parse_type(); const field_byte_alignment = field_type.get_byte_alignment(); const field_bit_alignment = field_byte_alignment * 8; @@ -4079,7 +4107,7 @@ pub const Module = struct { }; }, .typealias => { - const aliased_type = module.parse_type(null); + const aliased_type = module.parse_type(); if (!module.consume_character_if_match(';')) { module.report_error(); } @@ -4094,6 +4122,36 @@ pub const Module = struct { }); _ = alias_type; }, + .macro => { + module.expect_character(left_parenthesis); + + while (true) { + module.skip_space(); + + if (module.consume_character_if_match(right_parenthesis)) { + break; + } + + const argument_name = module.parse_identifier(); + _ = argument_name; + + module.skip_space(); + module.expect_character(':'); + module.skip_space(); + + const argument_type = module.parse_type(); + _ = argument_type; + module.skip_space(); + _ = module.consume_character_if_match(','); + } + + module.skip_space(); + + const return_type = module.parse_type(); + _ = return_type; + + @trap(); + }, } } else { module.offset -= global_string.len; @@ -4101,7 +4159,7 @@ pub const Module = struct { } if (!global_keyword) { - const v = module.parse_value(null, &module.scope, .{}); + const v = module.parse_value(&module.scope, .{}); module.skip_space(); module.expect_character(';'); @@ -4212,7 +4270,7 @@ pub const Module = struct { }; } - pub fn emit_block(module: *Module, function: *Global, block: *llvm.BasicBlock) void { + pub fn emit_block(module: *Module, block: *llvm.BasicBlock) void { const maybe_current_block = module.llvm.builder.get_insert_block(); var emit_branch = false; @@ -4227,18 +4285,18 @@ pub const Module = struct { if (maybe_current_block != null and maybe_current_block.?.get_parent() != null) { module.llvm.builder.insert_basic_block_after_insert_block(block); } else { - function.variable.storage.?.llvm.?.to_function().append_basic_block(block); + module.current_function.?.variable.storage.?.llvm.?.to_function().append_basic_block(block); } module.llvm.builder.position_at_end(block); } - pub fn emit_va_arg(module: *Module, function: *Global, value: *Value, left_llvm: ?*llvm.Value, left_type: ?*Type) *llvm.Value { + pub fn emit_va_arg(module: *Module, value: *Value, left_llvm: ?*llvm.Value, left_type: ?*Type) *llvm.Value { switch (value.bb) { .intrinsic => |intrinsic| switch (intrinsic) { .va_arg => |va_arg| { const raw_va_list_type = module.get_va_list_type(); - module.emit_value(function, va_arg.list, .memory); + module.emit_value(va_arg.list, .memory); const uint64 = module.integer_type(64, false); uint64.resolve(module); const va_list = module.llvm.builder.create_gep(.{ @@ -4280,7 +4338,7 @@ pub const Module = struct { const in_mem_block = module.llvm.context.create_basic_block("va_arg.in_mem", null); const end_block = module.llvm.context.create_basic_block("va_arg.end", null); _ = module.llvm.builder.create_conditional_branch(in_regs, in_reg_block, in_mem_block); - module.emit_block(function, in_reg_block); + module.emit_block(in_reg_block); const reg_save_area = module.create_load(.{ .type = va_list_struct.bb.structure.fields[3].type, .value = module.llvm.builder.create_struct_gep(va_list_struct_llvm, va_list, 3), .alignment = 16 }); @@ -4318,10 +4376,10 @@ pub const Module = struct { _ = module.llvm.builder.create_branch(end_block); - module.emit_block(function, in_mem_block); + module.emit_block(in_mem_block); const memory_address = Abi.SystemV.emit_va_arg_from_memory(module, va_list, va_list_struct, va_arg.type); - module.emit_block(function, end_block); + module.emit_block(end_block); const values = &.{ register_address, memory_address }; const blocks = &.{ in_reg_block, in_mem_block }; @@ -4347,7 +4405,7 @@ pub const Module = struct { } } - pub fn emit_call(module: *Module, function: *Global, value: *Value, left_llvm: ?*llvm.Value, left_type: ?*Type) *llvm.Value { + pub fn emit_call(module: *Module, value: *Value, left_llvm: ?*llvm.Value, left_type: ?*Type) *llvm.Value { switch (value.bb) { .call => |call| { const raw_function_type = call.function_type; @@ -4447,7 +4505,7 @@ pub const Module = struct { const coerce_to_type = argument_abi.get_coerce_to_type(); coerce_to_type.resolve(module); if (coerce_to_type.bb != .structure and semantic_argument_type.is_abi_equal(coerce_to_type, module) and argument_abi.attributes.direct.offset == 0) { - module.emit_value(function, semantic_argument_value, .memory); + module.emit_value(semantic_argument_value, .memory); var v = switch (argument_abi.semantic_type.get_evaluation_kind()) { .aggregate => @trap(), else => semantic_argument_value, @@ -4494,10 +4552,10 @@ pub const Module = struct { if (src.bb == .variable_reference) { src.type = null; src.kind = .left; - module.analyze_value_type(function, src, .{}); + module.analyze_value_type(src, .{}); } } - module.emit_value(function, semantic_argument_value, .memory); + module.emit_value(semantic_argument_value, .memory); const destination_size = coerce_to_type.get_byte_size(); const source_size = argument_abi.semantic_type.get_byte_size(); @@ -4579,9 +4637,9 @@ pub const Module = struct { assert(src.type.?.bb == .structure); src.type = null; src.kind = .left; - module.analyze_value_type(function, src, .{}); + module.analyze_value_type(src, .{}); } - module.emit_value(function, src, .memory); + module.emit_value(src, .memory); assert(src.type.?.bb == .pointer); const source_type = src.type.?.bb.pointer.type; @@ -4616,7 +4674,7 @@ pub const Module = struct { @trap(); } else if (abi_argument_type.bb == .pointer and abi_argument_type.bb.pointer.type == semantic_argument_value.type) switch (semantic_argument_value.is_constant()) { true => { - module.emit_value(function, semantic_argument_value, .memory); + module.emit_value(semantic_argument_value, .memory); const global_variable = module.llvm.module.create_global_variable(.{ .linkage = .InternalLinkage, .name = "conststruct", // TODO: format properly @@ -4635,7 +4693,7 @@ pub const Module = struct { const pointer_type = module.get_pointer_type(.{ .type = semantic_argument_value.type.? }); semantic_argument_value.type = null; semantic_argument_value.kind = .left; - module.analyze(function, semantic_argument_value, .{ .type = pointer_type }, .memory); + module.analyze(semantic_argument_value, .{ .type = pointer_type }, .memory); llvm_abi_argument_value_buffer[abi_argument_count] = semantic_argument_value.llvm.?; abi_argument_count += 1; break :indirect; @@ -4646,7 +4704,7 @@ pub const Module = struct { .type = semantic_argument_value.type.?, }); const pointer_type = module.get_pointer_type(.{ .type = semantic_argument_value.type.? }); - module.emit_assignment(function, alloca, pointer_type, semantic_argument_value); + module.emit_assignment(alloca, pointer_type, semantic_argument_value); llvm_abi_argument_value_buffer[abi_argument_count] = alloca; abi_argument_count += 1; break :indirect; @@ -4964,6 +5022,9 @@ pub const Module = struct { } else undefined; if (global.variable.storage.?.bb == .function) { + module.current_function = global; + defer module.current_function = null; + global.variable.storage.?.bb.function.scope.llvm = function_scope; const entry_block = module.llvm.context.create_basic_block("entry", llvm_function_value); @@ -5160,7 +5221,7 @@ pub const Module = struct { } } - module.analyze_block(global, global.variable.storage.?.bb.function.main_block); + module.analyze_block(global.variable.storage.?.bb.function.main_block); // Handle jump to the return block const return_block = global.variable.storage.?.bb.function.return_block orelse module.report_error(); @@ -5172,7 +5233,7 @@ pub const Module = struct { return_block.to_value().replace_all_uses_with(current_basic_block.to_value()); return_block.delete(); } else { - module.emit_block(global, return_block); + module.emit_block(return_block); } } else { var is_reachable = false; @@ -5190,7 +5251,7 @@ pub const Module = struct { } if (!is_reachable) { - module.emit_block(global, return_block); + module.emit_block(return_block); } } @@ -5266,7 +5327,7 @@ pub const Module = struct { } }, .global => { - module.analyze(null, global.variable.initial_value, .{ .type = global.variable.type }, .memory); + module.analyze(global.variable.initial_value, .{ .type = global.variable.type }, .memory); if (global.variable.type == null) { global.variable.type = global.variable.initial_value.type; @@ -5418,12 +5479,12 @@ pub const Module = struct { type: ?*Type = null, }; - pub fn analyze(module: *Module, function: ?*Global, value: *Value, analysis: ValueAnalysis, type_kind: Type.Kind) void { - module.analyze_value_type(function, value, analysis); - module.emit_value(function, value, type_kind); + pub fn analyze(module: *Module, value: *Value, analysis: ValueAnalysis, type_kind: Type.Kind) void { + module.analyze_value_type(value, analysis); + module.emit_value(value, type_kind); } - pub fn analyze_binary(module: *Module, function: ?*Global, left: *Value, right: *Value, is_boolean: bool, analysis: ValueAnalysis) void { + pub fn analyze_binary(module: *Module, left: *Value, right: *Value, is_boolean: bool, analysis: ValueAnalysis) void { const is_left_constant = left.is_constant(); const is_right_constant = right.is_constant(); if (analysis.type == null) { @@ -5436,25 +5497,25 @@ pub const Module = struct { if (is_boolean or analysis.type == null) { if (is_left_constant) { - module.analyze_value_type(function, right, .{}); - module.analyze_value_type(function, left, .{ + module.analyze_value_type(right, .{}); + module.analyze_value_type(left, .{ .type = right.type, }); } else if (is_right_constant) { - module.analyze_value_type(function, left, .{}); - module.analyze_value_type(function, right, .{ + module.analyze_value_type(left, .{}); + module.analyze_value_type(right, .{ .type = left.type, }); } else { - module.analyze_value_type(function, left, .{}); - module.analyze_value_type(function, right, .{ .type = left.type }); + module.analyze_value_type(left, .{}); + module.analyze_value_type(right, .{ .type = left.type }); } } else if (!is_boolean and analysis.type != null) { const expected_type = analysis.type.?; - module.analyze_value_type(function, left, .{ + module.analyze_value_type(left, .{ .type = expected_type, }); - module.analyze_value_type(function, right, .{ + module.analyze_value_type(right, .{ .type = expected_type, }); } else { @@ -5484,19 +5545,19 @@ pub const Module = struct { } } - pub fn analyze_value_type(module: *Module, function: ?*Global, value: *Value, analysis: ValueAnalysis) void { + pub fn analyze_value_type(module: *Module, value: *Value, analysis: ValueAnalysis) void { assert(value.type == null); assert(value.llvm == null); const value_type = switch (value.bb) { .unary => |unary| b: { if (unary.id.is_boolean()) { - module.analyze_value_type(function, unary.value, .{}); + module.analyze_value_type(unary.value, .{}); const boolean_type = module.integer_type(1, false); module.typecheck(analysis, boolean_type); break :b boolean_type; } else { - module.analyze_value_type(function, unary.value, analysis); + module.analyze_value_type(unary.value, analysis); const result_type = unary.value.type.?; module.typecheck(analysis, result_type); @@ -5506,7 +5567,7 @@ pub const Module = struct { .binary => |binary| blk: { const is_boolean = binary.id.is_boolean(); - module.analyze_binary(function, binary.left, binary.right, is_boolean, analysis); + module.analyze_binary(binary.left, binary.right, is_boolean, analysis); module.check_types(binary.left.type.?, binary.right.type.?); const result_type = if (is_boolean) module.integer_type(1, false) else binary.left.type.?; @@ -5555,7 +5616,7 @@ pub const Module = struct { }, .@"unreachable" => module.noreturn_type, .call => |*call| blk: { - module.analyze_value_type(function, call.callable, .{}); + module.analyze_value_type(call.callable, .{}); call.function_type = switch (call.callable.bb) { .variable_reference => |variable| switch (variable.type.?.bb) { .function => variable.type.?, @@ -5580,12 +5641,12 @@ pub const Module = struct { } for (declaration_argument_types, call.arguments[0..declaration_argument_types.len]) |argument_type, call_argument| { - module.analyze_value_type(function, call_argument, .{ .type = argument_type }); + module.analyze_value_type(call_argument, .{ .type = argument_type }); module.check_types(argument_type, call_argument.type.?); } for (call.arguments[declaration_argument_types.len..]) |call_argument| { - module.analyze_value_type(function, call_argument, .{}); + module.analyze_value_type(call_argument, .{}); } const semantic_return_type = call.function_type.bb.function.semantic_return_type; @@ -5611,7 +5672,7 @@ pub const Module = struct { .enum_name => |enum_value| blk: { const string_type = module.get_slice_type(.{ .type = module.integer_type(8, false) }); module.typecheck(analysis, string_type); - module.analyze_value_type(function, enum_value, .{}); + module.analyze_value_type(enum_value, .{}); const enum_type = enum_value.type.?; switch (enum_type.bb) { .enumerator => |*enumerator| { @@ -5691,7 +5752,7 @@ pub const Module = struct { }, .extend => |extended_value| blk: { const expected_type = analysis.type orelse module.report_error(); - module.analyze_value_type(function, extended_value, .{}); + module.analyze_value_type(extended_value, .{}); assert(extended_value.type != null); const destination_type = expected_type; const source_type = extended_value.type.?; @@ -5719,7 +5780,7 @@ pub const Module = struct { break :blk integer_max_type; }, .int_from_enum => |enum_value| blk: { - module.analyze_value_type(function, enum_value, .{}); + module.analyze_value_type(enum_value, .{}); if (enum_value.type.?.bb != .enumerator) { module.report_error(); } @@ -5729,7 +5790,7 @@ pub const Module = struct { break :blk enum_backing_type; }, .int_from_pointer => |pointer_value| blk: { - module.analyze_value_type(function, pointer_value, .{}); + module.analyze_value_type(pointer_value, .{}); assert(pointer_value.type != null); if (pointer_value.type.?.bb != .pointer) { module.report_error(); @@ -5745,7 +5806,7 @@ pub const Module = struct { if (expected_type.bb != .pointer) { module.report_error(); } - module.analyze_value_type(function, pointer_value, .{}); + module.analyze_value_type(pointer_value, .{}); const pointer_type = pointer_value.type orelse module.report_error(); if (pointer_type == expected_type) { @@ -5759,9 +5820,9 @@ pub const Module = struct { break :blk expected_type; }, .select => |select| blk: { - module.analyze_value_type(function, select.condition, .{}); + module.analyze_value_type(select.condition, .{}); const is_boolean = false; // This indicates that the result type must not be a boolean type - module.analyze_binary(function, select.true_value, select.false_value, is_boolean, analysis); + module.analyze_binary(select.true_value, select.false_value, is_boolean, analysis); const left_type = select.true_value.type.?; const right_type = select.false_value.type.?; @@ -6038,14 +6099,14 @@ pub const Module = struct { const string_type = module.get_slice_type(.{ .type = module.integer_type(8, false) }); - module.analyze_value_type(function, string_to_enum.string_value, .{ .type = string_type }); + module.analyze_value_type(string_to_enum.string_value, .{ .type = string_type }); break :blk result_type; }, .truncate => |value_to_truncate| blk: { // TODO: better typechecking const expected_type = analysis.type orelse module.report_error(); - module.analyze_value_type(function, value_to_truncate, .{}); + module.analyze_value_type(value_to_truncate, .{}); if (expected_type.get_bit_size() >= value_to_truncate.type.?.get_bit_size()) { module.report_error(); } @@ -6053,7 +6114,7 @@ pub const Module = struct { }, .trap => module.noreturn_type, .va_arg => |va_arg| blk: { - module.analyze_value_type(function, va_arg.list, .{ + module.analyze_value_type(va_arg.list, .{ .type = module.get_pointer_type(.{ .type = module.get_va_list_type() }), }); const result_type = va_arg.type; @@ -6061,7 +6122,7 @@ pub const Module = struct { break :blk result_type; }, .va_end => |va_list| blk: { - module.analyze_value_type(function, va_list, .{ + module.analyze_value_type(va_list, .{ .type = module.get_pointer_type(.{ .type = module.get_va_list_type() }), }); const result_type = module.void_type; @@ -6076,7 +6137,7 @@ pub const Module = struct { else => @trap(), }, .dereference => |dereferenced_value| blk: { - module.analyze_value_type(function, dereferenced_value, .{}); + module.analyze_value_type(dereferenced_value, .{}); const dereference_type = switch (value.kind) { .left => @trap(), @@ -6091,7 +6152,7 @@ pub const Module = struct { if (slice_expression.array_like.kind != .left) { module.report_error(); } - module.analyze_value_type(function, slice_expression.array_like, .{}); + module.analyze_value_type(slice_expression.array_like, .{}); const pointer_type = slice_expression.array_like.type.?; if (pointer_type.bb != .pointer) { @@ -6119,7 +6180,7 @@ pub const Module = struct { const index_type = module.integer_type(64, false); if (slice_expression.start) |start| { - module.analyze_value_type(function, start, .{ .type = index_type }); + module.analyze_value_type(start, .{ .type = index_type }); if (start.type.?.bb != .integer) { module.report_error(); @@ -6127,7 +6188,7 @@ pub const Module = struct { } if (slice_expression.end) |end| { - module.analyze_value_type(function, end, .{ .type = index_type }); + module.analyze_value_type(end, .{ .type = index_type }); if (end.type.?.bb != .integer) { module.report_error(); @@ -6137,7 +6198,7 @@ pub const Module = struct { break :blk slice_type; }, .field_access => |field_access| blk: { - module.analyze_value_type(function, field_access.aggregate, .{}); + module.analyze_value_type(field_access.aggregate, .{}); const field_name = field_access.field; const field_type = switch (field_access.aggregate.kind) { @@ -6203,13 +6264,13 @@ pub const Module = struct { break :blk field_type; }, .array_expression => |array_expression| blk: { - module.analyze_value_type(function, array_expression.index, .{ + module.analyze_value_type(array_expression.index, .{ .type = module.integer_type(64, false), }); // Overwrite side of the expression array_expression.array_like.kind = .left; - module.analyze_value_type(function, array_expression.array_like, .{}); + module.analyze_value_type(array_expression.array_like, .{}); const element_type = switch (array_expression.array_like.kind) { .left => switch (array_expression.array_like.type.?.bb) { .pointer => |pointer| switch (pointer.type.bb) { @@ -6250,7 +6311,7 @@ pub const Module = struct { is_ordered = is_ordered and declaration_index == initialization_index; const field = &bits.fields[declaration_index]; const declaration_type = field.type; - module.analyze_value_type(function, field_value, .{ .type = declaration_type }); + module.analyze_value_type(field_value, .{ .type = declaration_type }); is_constant = is_constant and field_value.is_constant(); } @@ -6270,7 +6331,7 @@ pub const Module = struct { is_ordered = is_ordered and declaration_index == initialization_index; const field = &structure.fields[declaration_index]; const declaration_type = field.type; - module.analyze_value_type(function, field_value, .{ .type = declaration_type }); + module.analyze_value_type(field_value, .{ .type = declaration_type }); is_constant = is_constant and field_value.is_constant(); } @@ -6303,7 +6364,7 @@ pub const Module = struct { var is_constant = true; for (array_initialization.values) |v| { - module.analyze_value_type(function, v, .{ + module.analyze_value_type(v, .{ .type = array.element_type, }); is_constant = is_constant and v.is_constant(); @@ -6326,7 +6387,7 @@ pub const Module = struct { var is_constant = true; for (array_initialization.values) |v| { - module.analyze_value_type(function, v, .{ + module.analyze_value_type(v, .{ .type = expected_type, }); @@ -6452,7 +6513,7 @@ pub const Module = struct { } } - pub fn emit_slice_expression(module: *Module, function: ?*Global, value: *Value) struct { *llvm.Value, *llvm.Value } { + pub fn emit_slice_expression(module: *Module, value: *Value) struct { *llvm.Value, *llvm.Value } { const value_type = value.type.?; assert(value_type.is_slice()); @@ -6467,7 +6528,7 @@ pub const Module = struct { switch (value.bb) { .slice_expression => |slice_expression| { assert(slice_expression.array_like.kind == .left); - module.emit_value(function, slice_expression.array_like, .memory); + module.emit_value(slice_expression.array_like, .memory); const pointer_type = slice_expression.array_like.type.?; assert(pointer_type.bb == .pointer); @@ -6478,11 +6539,11 @@ pub const Module = struct { } else false; if (slice_expression.start) |start| { - module.emit_value(function, start, .memory); + module.emit_value(start, .memory); } if (slice_expression.end) |end| { - module.emit_value(function, end, .memory); + module.emit_value(end, .memory); } switch (sliceable_type.bb) { @@ -6552,7 +6613,7 @@ pub const Module = struct { } } - pub fn emit_value(module: *Module, function: ?*Global, value: *Value, type_kind: Type.Kind) void { + pub fn emit_value(module: *Module, value: *Value, type_kind: Type.Kind) void { const value_type = value.type orelse unreachable; assert(value.llvm == null); value_type.resolve(module); @@ -6562,31 +6623,31 @@ pub const Module = struct { .unary => |unary| switch (unary.id) { .@"-" => blk: { const unary_value = unary.value.llvm orelse b: { - module.emit_value(function, unary.value, type_kind); + module.emit_value(unary.value, type_kind); break :b unary.value.llvm orelse unreachable; }; break :blk module.negate_llvm_value(unary_value, unary.value.is_constant()); }, .@"&" => blk: { assert(value_type == unary.value.type); - module.emit_value(function, unary.value, type_kind); + module.emit_value(unary.value, type_kind); break :blk unary.value.llvm orelse unreachable; }, .@"!" => switch (unary.value.type == value_type) { true => b: { - module.emit_value(function, unary.value, type_kind); + module.emit_value(unary.value, type_kind); break :b module.llvm.builder.create_not(unary.value.llvm.?); }, false => switch (unary.value.type.?.bb) { .pointer => b: { - module.emit_value(function, unary.value, type_kind); + module.emit_value(unary.value, type_kind); break :b module.llvm.builder.create_integer_compare(.eq, unary.value.llvm.?, unary.value.type.?.llvm.abi.?.get_zero().to_value()); }, else => @trap(), }, }, .@"~" => b: { - module.emit_value(function, unary.value, type_kind); + module.emit_value(unary.value, type_kind); break :b module.llvm.builder.create_not(unary.value.llvm.?); }, else => @trap(), @@ -6603,7 +6664,7 @@ pub const Module = struct { else => unreachable, }; const left = if (binary.left.llvm) |left_llvm| left_llvm else b: { - module.emit_value(function, binary.left, .abi); + module.emit_value(binary.left, .abi); break :b binary.left.llvm orelse unreachable; }; const left_condition = switch (binary.left.type.?.bb) { @@ -6613,7 +6674,7 @@ pub const Module = struct { }, else => @trap(), }; - const llvm_function = function.?.variable.storage.?.llvm.?.to_function(); + const llvm_function = module.current_function.?.variable.storage.?.llvm.?.to_function(); const current_bb = module.llvm.builder.get_insert_block().?; const right_block = module.llvm.context.create_basic_block(switch (op) { inline else => |o| @tagName(o) ++ ".right", @@ -6631,7 +6692,7 @@ pub const Module = struct { module.llvm.builder.position_at_end(right_block); const right = if (binary.right.llvm) |right_llvm| right_llvm else b: { - module.emit_value(function, binary.right, .abi); + module.emit_value(binary.right, .abi); break :b binary.right.llvm orelse unreachable; }; const right_condition = switch (binary.left.type.?.bb) { @@ -6657,11 +6718,11 @@ pub const Module = struct { }; } else { const left = if (binary.left.llvm) |left_llvm| left_llvm else b: { - module.emit_value(function, binary.left, .abi); + module.emit_value(binary.left, .abi); break :b binary.left.llvm orelse unreachable; }; const right = if (binary.right.llvm) |right_llvm| right_llvm else b: { - module.emit_value(function, binary.right, .abi); + module.emit_value(binary.right, .abi); break :b binary.right.llvm orelse unreachable; }; const result = switch (value_type.bb) { @@ -6776,14 +6837,14 @@ pub const Module = struct { .enum_name => |enum_value| blk: { const enum_type = enum_value.type.?; const enum_to_string = enum_type.bb.enumerator.enum_to_string.?; - module.emit_value(function, enum_value, .abi); + module.emit_value(enum_value, .abi); const call = module.llvm.builder.create_call(enum_to_string.get_type(), enum_to_string.to_value(), &.{enum_value.llvm.?}); call.to_instruction().to_call_base().set_calling_convention(.fast); break :blk call; }, .extend => |extended_value| blk: { if (extended_value.llvm == null) { - module.emit_value(function, extended_value, type_kind); + module.emit_value(extended_value, type_kind); } const llvm_value = extended_value.llvm orelse unreachable; const destination_type = value_type.llvm.abi.?; @@ -6805,20 +6866,20 @@ pub const Module = struct { break :blk constant_integer.to_value(); }, .int_from_enum => |enum_value| blk: { - module.emit_value(function, enum_value, type_kind); + module.emit_value(enum_value, type_kind); break :blk enum_value.llvm.?; }, .int_from_pointer => |pointer_value| blk: { - module.emit_value(function, pointer_value, type_kind); + module.emit_value(pointer_value, type_kind); const int = module.llvm.builder.create_ptr_to_int(pointer_value.llvm.?, value_type.llvm.abi.?); break :blk int; }, .pointer_cast => |pointer_value| blk: { - module.emit_value(function, pointer_value, type_kind); + module.emit_value(pointer_value, type_kind); break :blk pointer_value.llvm.?; }, .select => |select| blk: { - module.emit_value(function, select.condition, type_kind); + module.emit_value(select.condition, type_kind); const condition = switch (select.condition.type.?.bb) { .integer => |integer| switch (integer.bit_count) { 1 => select.condition.llvm.?, @@ -6826,13 +6887,13 @@ pub const Module = struct { }, else => @trap(), }; - module.emit_value(function, select.true_value, type_kind); - module.emit_value(function, select.false_value, type_kind); + module.emit_value(select.true_value, type_kind); + module.emit_value(select.false_value, type_kind); const result = module.llvm.builder.create_select(condition, select.true_value.llvm.?, select.false_value.llvm.?); break :blk result; }, .string_to_enum => |string_to_enum| blk: { - module.emit_value(function, string_to_enum.string_value, type_kind); + module.emit_value(string_to_enum.string_value, type_kind); const s2e = string_to_enum.enum_type.bb.enumerator.string_to_enum orelse unreachable; const first_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 0); const second_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 1); @@ -6855,15 +6916,15 @@ pub const Module = struct { }, .truncate => |value_to_truncate| blk: { if (value_to_truncate.llvm == null) { - module.emit_value(function, value_to_truncate, type_kind); + module.emit_value(value_to_truncate, type_kind); } const llvm_value = value_to_truncate.llvm orelse unreachable; const truncate = module.llvm.builder.create_truncate(llvm_value, value_type.llvm.abi.?); break :blk truncate; }, - .va_arg => module.emit_va_arg(function.?, value, null, null), + .va_arg => module.emit_va_arg(value, null, null), .va_end => |va_list| blk: { - module.emit_value(function, va_list, .memory); + module.emit_value(va_list, .memory); const intrinsic_id = module.llvm.intrinsic_table.va_end; const argument_types: []const *llvm.Type = &.{module.llvm.pointer_type}; @@ -6876,7 +6937,7 @@ pub const Module = struct { else => @trap(), }, .dereference => |dereferenceable_value| blk: { - module.emit_value(function, dereferenceable_value, .memory); + module.emit_value(dereferenceable_value, .memory); const result = switch (value.kind) { .left => @trap(), .right => module.create_load(.{ @@ -6887,7 +6948,7 @@ pub const Module = struct { }; break :blk result; }, - .call => module.emit_call(function.?, value, null, null), + .call => module.emit_call(value, null, null), .array_initialization => |array_initialization| switch (array_initialization.is_constant) { true => blk: { assert(value.kind == .right); @@ -6896,7 +6957,7 @@ pub const Module = struct { const llvm_values = llvm_value_buffer[0..element_count]; for (array_initialization.values, llvm_values) |v, *llvm_value| { - module.emit_value(function, v, .memory); + module.emit_value(v, .memory); llvm_value.* = v.llvm.?.to_constant(); } @@ -6922,7 +6983,7 @@ pub const Module = struct { .aggregate = alloca, .indices = &.{ u64_zero, uint64.get_constant(i, 0).to_value() }, }); - module.emit_assignment(function.?, alloca_gep, pointer_to_element_type, v); + module.emit_assignment(alloca_gep, pointer_to_element_type, v); } break :blk alloca; @@ -6934,8 +6995,8 @@ pub const Module = struct { .left => switch (array_expression.array_like.type.?.bb) { .pointer => |pointer| switch (pointer.type.bb) { .array => |array| blk: { - module.emit_value(function, array_expression.array_like, .memory); - module.emit_value(function, array_expression.index, .memory); + module.emit_value(array_expression.array_like, .memory); + module.emit_value(array_expression.index, .memory); const uint64 = module.integer_type(64, false); uint64.resolve(module); const zero_index = uint64.llvm.abi.?.to_integer().get_constant(0, @intFromBool(false)).to_value(); @@ -6954,8 +7015,8 @@ pub const Module = struct { }, .structure => |structure| blk: { assert(structure.is_slice); - module.emit_value(function, array_expression.array_like, .memory); - module.emit_value(function, array_expression.index, .memory); + module.emit_value(array_expression.array_like, .memory); + module.emit_value(array_expression.index, .memory); const pointer_type = structure.fields[0].type; const element_type = pointer_type.bb.pointer.type; element_type.resolve(module); @@ -6975,8 +7036,8 @@ pub const Module = struct { }; }, .pointer => |real_pointer| blk: { - module.emit_value(function, array_expression.array_like, .memory); - module.emit_value(function, array_expression.index, .memory); + module.emit_value(array_expression.array_like, .memory); + module.emit_value(array_expression.index, .memory); // TODO: consider not emitting the and doing straight GEP? const pointer_load = module.create_load(.{ .type = pointer.type, .value = array_expression.array_like.llvm.? }); const element_type = real_pointer.type; @@ -6999,8 +7060,8 @@ pub const Module = struct { }, .right => switch (array_expression.array_like.type.?.bb) { .pointer => |pointer| blk: { - module.emit_value(function, array_expression.array_like, .memory); - module.emit_value(function, array_expression.index, .memory); + module.emit_value(array_expression.array_like, .memory); + module.emit_value(array_expression.index, .memory); const gep = module.llvm.builder.create_gep(.{ .type = pointer.type.llvm.memory.?, .aggregate = array_expression.array_like.llvm.?, @@ -7015,8 +7076,8 @@ pub const Module = struct { }, .structure => |structure| switch (structure.is_slice) { true => blk: { - module.emit_value(function, array_expression.array_like, .memory); - module.emit_value(function, array_expression.index, .memory); + module.emit_value(array_expression.array_like, .memory); + module.emit_value(array_expression.index, .memory); const pointer_extract = module.llvm.builder.create_extract_value(array_expression.array_like.llvm.?, 0); const element_type = structure.fields[0].type.bb.pointer.type; const gep = module.llvm.builder.create_gep(.{ @@ -7046,7 +7107,7 @@ pub const Module = struct { break :blk llvm_value.to_value(); }, .field_access => |field_access| blk: { - module.emit_value(function, field_access.aggregate, .memory); + module.emit_value(field_access.aggregate, .memory); const field_name = field_access.field; switch (field_access.aggregate.kind) { .left => { @@ -7137,7 +7198,7 @@ pub const Module = struct { } } else unreachable; const field = &bits.fields[declaration_index]; - module.emit_value(function, field_value, .memory); + module.emit_value(field_value, .memory); const extended = module.llvm.builder.create_zero_extend(field_value.llvm.?, llvm_type); const shl = module.llvm.builder.create_shl(extended, llvm_type.to_integer().get_constant(field.bit_offset, 0).to_value()); const or_value = module.llvm.builder.create_or(result, shl); @@ -7152,7 +7213,7 @@ pub const Module = struct { const constants = constant_buffer[0..structure.fields.len]; for (aggregate_initialization.values, constants[0..aggregate_initialization.values.len]) |field_value, *constant| { - module.emit_value(function, field_value, .memory); + module.emit_value(field_value, .memory); constant.* = field_value.llvm.?.to_constant(); } @@ -7184,7 +7245,7 @@ pub const Module = struct { }, .slice_expression => blk: { assert(value.kind == .right); - const slice_values = module.emit_slice_expression(function, value); + const slice_values = module.emit_slice_expression(value); const slice_poison = value_type.llvm.memory.?.get_poison(); const slice_pointer = module.llvm.builder.create_insert_value(slice_poison, slice_values[0], 0); const slice_length = module.llvm.builder.create_insert_value(slice_pointer, slice_values[1], 1); @@ -7225,9 +7286,9 @@ pub const Module = struct { value.llvm = llvm_value; } - pub fn analyze_statement(module: *Module, function: *Global, scope: *Scope, statement: *Statement, last_line: *u32, last_column: *u32, last_statement_debug_location: **llvm.DI.Location) void { - const llvm_function = function.variable.storage.?.llvm.?.to_function(); - const current_function = &function.variable.storage.?.bb.function; + pub fn analyze_statement(module: *Module, scope: *Scope, statement: *Statement, last_line: *u32, last_column: *u32, last_statement_debug_location: **llvm.DI.Location) void { + const llvm_function = module.current_function.?.variable.storage.?.llvm.?.to_function(); + const current_function = &module.current_function.?.variable.storage.?.bb.function; if (module.has_debug_info) { if (statement.line != last_line.* or statement.column != last_column.*) { const inlined_at: ?*llvm.DI.Metadata = null; // TODO @@ -7240,7 +7301,7 @@ pub const Module = struct { switch (statement.bb) { .@"return" => |rv| { - const function_type = &function.variable.storage.?.type.?.bb.pointer.type.bb.function; + const function_type = &module.current_function.?.variable.storage.?.type.?.bb.pointer.type.bb.function; const return_abi = function_type.return_abi; switch (return_abi.semantic_type.bb) { @@ -7252,7 +7313,7 @@ pub const Module = struct { .noreturn => module.report_error(), else => { const return_value = rv orelse module.report_error(); - module.analyze(function, return_value, .{ + module.analyze(return_value, .{ .type = return_abi.semantic_type, }, .memory); @@ -7261,7 +7322,7 @@ pub const Module = struct { } // Clang equivalent: CodeGenFunction::EmitReturnStmt - const return_alloca = function.variable.storage.?.bb.function.return_alloca orelse module.report_error(); + const return_alloca = module.current_function.?.variable.storage.?.bb.function.return_alloca orelse module.report_error(); switch (return_abi.semantic_type.get_evaluation_kind()) { .scalar => { @@ -7341,7 +7402,7 @@ pub const Module = struct { }, } - const return_block = function.variable.storage.?.bb.function.return_block orelse module.report_error(); + const return_block = module.current_function.?.variable.storage.?.bb.function.return_block orelse module.report_error(); _ = module.llvm.builder.create_branch(return_block); _ = module.llvm.builder.clear_insertion_position(); @@ -7349,26 +7410,26 @@ pub const Module = struct { .local => |local| { const expected_type = local.variable.type; assert(local.variable.storage == null); - module.analyze_value_type(function, local.variable.initial_value, .{ .type = local.variable.type }); + module.analyze_value_type(local.variable.initial_value, .{ .type = local.variable.type }); local.variable.resolve_type(local.variable.initial_value.type.?); if (expected_type) |lvt| assert(lvt == local.variable.type); module.emit_local_storage(local, last_statement_debug_location.*); - module.emit_assignment(function, local.variable.storage.?.llvm.?, local.variable.storage.?.type.?, local.variable.initial_value); + module.emit_assignment(local.variable.storage.?.llvm.?, local.variable.storage.?.type.?, local.variable.initial_value); }, .assignment => |assignment| { - module.analyze(function, assignment.left, .{}, .memory); + module.analyze(assignment.left, .{}, .memory); switch (assignment.kind) { .@"=" => { - module.analyze_value_type(function, assignment.right, .{ .type = assignment.left.type.?.bb.pointer.type }); - module.emit_assignment(function, assignment.left.llvm.?, assignment.left.type.?, assignment.right); + module.analyze_value_type(assignment.right, .{ .type = assignment.left.type.?.bb.pointer.type }); + module.emit_assignment(assignment.left.llvm.?, assignment.left.type.?, assignment.right); }, else => |kind| { const pointer_type = assignment.left.type.?.bb.pointer; const element_type = pointer_type.type; assert(element_type.get_evaluation_kind() == .scalar); const load = module.create_load(.{ .type = element_type, .value = assignment.left.llvm.?, .alignment = pointer_type.alignment }); - module.analyze(function, assignment.right, .{ .type = element_type }, .memory); + module.analyze(assignment.right, .{ .type = element_type }, .memory); const a = load; const b = assignment.right.llvm.?; const right = switch (kind) { @@ -7444,14 +7505,14 @@ pub const Module = struct { } }, .expression => |expression_value| { - module.analyze(function, expression_value, .{}, .memory); + module.analyze(expression_value, .{}, .memory); }, .@"if" => |if_statement| { const taken_block = module.llvm.context.create_basic_block("if.true", llvm_function); const not_taken_block = module.llvm.context.create_basic_block("if.false", llvm_function); const exit_block = module.llvm.context.create_basic_block("if.end", llvm_function); - module.analyze(function, if_statement.condition, .{}, .abi); + module.analyze(if_statement.condition, .{}, .abi); const llvm_condition = switch (if_statement.condition.type.?.bb) { .integer => |integer| if (integer.bit_count != 1) module.llvm.builder.create_integer_compare(.ne, if_statement.condition.llvm.?, if_statement.condition.type.?.llvm.abi.?.get_zero().to_value()) else if_statement.condition.llvm.?, .pointer => module.llvm.builder.create_integer_compare(.ne, if_statement.condition.llvm.?, if_statement.condition.type.?.llvm.abi.?.get_zero().to_value()), @@ -7466,14 +7527,14 @@ pub const Module = struct { current_function.exit_block = exit_block; - module.analyze_statement(function, scope, if_statement.if_statement, last_line, last_line, last_statement_debug_location); + module.analyze_statement(scope, if_statement.if_statement, last_line, last_line, last_statement_debug_location); if (module.llvm.builder.get_insert_block() != null) { _ = module.llvm.builder.create_branch(exit_block); } module.llvm.builder.position_at_end(not_taken_block); if (if_statement.else_statement) |else_statement| { - module.analyze_statement(function, scope, else_statement, last_line, last_line, last_statement_debug_location); + module.analyze_statement(scope, else_statement, last_line, last_line, last_statement_debug_location); } if (module.llvm.builder.get_insert_block() != null) { @@ -7487,7 +7548,7 @@ pub const Module = struct { _ = module.llvm.builder.create_branch(loop_entry_block); module.llvm.builder.position_at_end(loop_entry_block); - module.analyze(function, while_loop.condition, .{}, .abi); + module.analyze(while_loop.condition, .{}, .abi); const boolean_type = module.integer_type(1, false); const condition_value = switch (while_loop.condition.type == boolean_type) { @@ -7503,7 +7564,7 @@ pub const Module = struct { _ = module.llvm.builder.create_conditional_branch(condition_value, loop_body_block, loop_end_block); module.llvm.builder.position_at_end(loop_body_block); - module.analyze_block(function, while_loop.block); + module.analyze_block(while_loop.block); if (module.llvm.builder.get_insert_block() != null) { _ = module.llvm.builder.create_branch(loop_entry_block); @@ -7526,7 +7587,7 @@ pub const Module = struct { const exit_block = module.llvm.context.create_basic_block("exit_block", llvm_function); current_function.exit_block = exit_block; - module.analyze(function, switch_statement.discriminant, .{}, .abi); + module.analyze(switch_statement.discriminant, .{}, .abi); const switch_discriminant_type = switch_statement.discriminant.type.?; switch (switch_discriminant_type.bb) { @@ -7544,7 +7605,7 @@ pub const Module = struct { else_clause_index = clause_index; } else { for (clause.values) |v| { - module.analyze(function, v, .{ .type = switch_discriminant_type }, .abi); + module.analyze(v, .{ .type = switch_discriminant_type }, .abi); if (!v.is_constant()) { module.report_error(); } @@ -7564,7 +7625,7 @@ pub const Module = struct { current_function.exit_block = exit_block; module.llvm.builder.position_at_end(clause.basic_block); - module.analyze_block(function, clause.block); + module.analyze_block(clause.block); if (module.llvm.builder.get_insert_block() != null) { all_blocks_terminated = false; _ = module.llvm.builder.create_branch(exit_block); @@ -7587,7 +7648,7 @@ pub const Module = struct { else => @trap(), } }, - .block => |child_block| module.analyze_block(function, child_block), + .block => |child_block| module.analyze_block(child_block), .for_each => |*for_loop| { if (module.has_debug_info) { const lexical_block = module.llvm.di_builder.create_lexical_block(for_loop.scope.parent.?.llvm.?, module.llvm.file, for_loop.scope.line, for_loop.scope.column); @@ -7600,7 +7661,7 @@ pub const Module = struct { for (for_loop.locals, for_loop.left_values, for_loop.right_values) |local, kind, right| { assert(right.kind == .left); - module.analyze_value_type(function, right, .{}); + module.analyze_value_type(right, .{}); const pointer_type = right.type.?; if (pointer_type.bb != .pointer) { module.report_error(); @@ -7621,7 +7682,7 @@ pub const Module = struct { }; local.variable.type = local_type; module.emit_local_storage(local, last_statement_debug_location.*); - module.emit_value(function, right, .memory); + module.emit_value(right, .memory); } const length_value = for (for_loop.right_values) |right| { @@ -7716,7 +7777,7 @@ pub const Module = struct { } } - module.analyze_statement(function, &for_loop.scope, for_loop.predicate, last_line, last_column, last_statement_debug_location); + module.analyze_statement(&for_loop.scope, for_loop.predicate, last_line, last_column, last_statement_debug_location); if (module.llvm.builder.get_insert_block() != null) { _ = module.llvm.builder.create_branch(loop_continue_block); @@ -7733,7 +7794,7 @@ pub const Module = struct { } } - pub fn analyze_block(module: *Module, function: *Global, block: *LexicalBlock) void { + pub fn analyze_block(module: *Module, block: *LexicalBlock) void { if (module.has_debug_info) { const lexical_block = module.llvm.di_builder.create_lexical_block(block.scope.parent.?.llvm.?, module.llvm.file, block.scope.line, block.scope.column); block.scope.llvm = lexical_block.to_scope(); @@ -7744,11 +7805,11 @@ pub const Module = struct { var last_statement_debug_location: *llvm.DI.Location = undefined; for (block.statements.get_slice()) |statement| { - module.analyze_statement(function, &block.scope, statement, &last_line, &last_column, &last_statement_debug_location); + module.analyze_statement(&block.scope, statement, &last_line, &last_column, &last_statement_debug_location); } } - fn emit_assignment(module: *Module, function: *Global, left_llvm: *llvm.Value, left_type: *Type, right: *Value) void { + fn emit_assignment(module: *Module, left_llvm: *llvm.Value, left_type: *Type, right: *Value) void { assert(right.llvm == null); const pointer_type = left_type; const value_type = right.type.?; @@ -7759,7 +7820,7 @@ pub const Module = struct { switch (value_type.get_evaluation_kind()) { .scalar => { - module.emit_value(function, right, .memory); + module.emit_value(right, .memory); _ = module.create_store(.{ .source_value = right.llvm.?, .destination_value = left_llvm, @@ -7770,7 +7831,7 @@ pub const Module = struct { .aggregate => switch (right.bb) { .array_initialization => |array_initialization| switch (array_initialization.is_constant) { true => { - module.emit_value(function, right, .memory); + module.emit_value(right, .memory); const global_variable = module.llvm.module.create_global_variable(.{ .linkage = .InternalLinkage, .name = "constarray", // TODO: format properly @@ -7789,7 +7850,7 @@ pub const Module = struct { }, .aggregate_initialization => |aggregate_initialization| switch (aggregate_initialization.is_constant) { true => { - module.emit_value(function, right, .memory); + module.emit_value(right, .memory); const global_variable = module.llvm.module.create_global_variable(.{ .linkage = .InternalLinkage, .name = "conststruct", // TODO: format properly @@ -7818,7 +7879,7 @@ pub const Module = struct { max_field_index = @max(field_index, max_field_index); const field = &fields[field_index]; const destination_pointer = module.llvm.builder.create_struct_gep(value_type.llvm.abi.?.to_struct(), left_llvm, @intCast(field_index)); - module.emit_assignment(function, destination_pointer, module.get_pointer_type(.{ .type = field.type }), initialization_value); + module.emit_assignment(destination_pointer, module.get_pointer_type(.{ .type = field.type }), initialization_value); } if (aggregate_initialization.zero) { @@ -7895,7 +7956,7 @@ pub const Module = struct { }, .intrinsic => |intrinsic| switch (intrinsic) { .enum_name => { - module.emit_value(function, right, .memory); + module.emit_value(right, .memory); _ = module.create_store(.{ .type = right.type.?, .source_value = right.llvm.?, @@ -7904,7 +7965,7 @@ pub const Module = struct { }, .select => { if (right.type.?.get_evaluation_kind() == .scalar or right.type.?.is_slice()) { - module.emit_value(function, right, .memory); + module.emit_value(right, .memory); _ = module.create_store(.{ .type = right.type.?, .source_value = right.llvm.?, @@ -7915,7 +7976,7 @@ pub const Module = struct { } }, .string_to_enum => |string_to_enum| { - module.emit_value(function, string_to_enum.string_value, .memory); + module.emit_value(string_to_enum.string_value, .memory); const s2e = string_to_enum.enum_type.bb.enumerator.string_to_enum orelse unreachable; const first_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 0); const second_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 1); @@ -7939,7 +8000,7 @@ pub const Module = struct { _ = module.llvm.builder.create_call(intrinsic_function_type, intrinsic_function, argument_values); }, .va_arg => { - const result = module.emit_va_arg(function, right, left_llvm, left_type); + const result = module.emit_va_arg(right, left_llvm, left_type); switch (result == left_llvm) { true => {}, false => switch (value_type.get_evaluation_kind()) { @@ -7954,7 +8015,7 @@ pub const Module = struct { else => @trap(), }, .call => { - const result = module.emit_call(function, right, left_llvm, left_type); + const result = module.emit_call(right, left_llvm, left_type); assert(result == left_llvm); // if (result != left.llvm) { // const call_ret_type_ev_kind = right.type.?.get_evaluation_kind(); @@ -7969,7 +8030,7 @@ pub const Module = struct { // } }, .slice_expression => { - const slice_values = module.emit_slice_expression(function, right); + const slice_values = module.emit_slice_expression(right); const slice_pointer_type = value_type.bb.structure.fields[0].type; _ = module.create_store(.{ .source_value = slice_values[0], @@ -8006,7 +8067,7 @@ pub const Module = struct { break @intCast(field_index); } } else module.report_error(); - module.emit_value(function, field_access.aggregate, .memory); + module.emit_value(field_access.aggregate, .memory); const gep = module.llvm.builder.create_struct_gep(struct_type.llvm.abi.?.to_struct(), field_access.aggregate.llvm.?, field_index); const uint64 = module.integer_type(64, false); _ = module.llvm.builder.create_memcpy(left_llvm, pointer_type.bb.pointer.alignment, gep, value_type.get_byte_alignment(), uint64.llvm.abi.?.to_integer().get_constant(value_type.get_byte_size(), @intFromBool(false)).to_value()); diff --git a/tests/basic_macro.bbb b/tests/basic_macro.bbb new file mode 100644 index 0000000..fbdc738 --- /dev/null +++ b/tests/basic_macro.bbb @@ -0,0 +1,6 @@ +add = macro (a: u32, a: u32) u32 => a + b + +[export] main = fn [cc(c)] () s32 +{ + return 0; +}