diff --git a/src/bootstrap.zig b/src/bootstrap.zig index 0668561..1ea93b5 100644 --- a/src/bootstrap.zig +++ b/src/bootstrap.zig @@ -207,18 +207,41 @@ pub const Global = struct { }; }; -pub const GenericArgument = struct { - foo: u32, +const ConstantArgument = struct { + kind: Kind, + index: u8, + const Kind = enum { + type, + value, + }; }; pub const Macro = struct { arguments: []const *Local, argument_types: []const *Type, - generic_arguments: []const GenericArgument, + constant_argument_names: []const []const u8, + constant_argument_values: []const *Value, + type_arguments: []const *Type, + constant_arguments: []const ConstantArgument, return_type: *Type, block: *LexicalBlock, name: []const u8, scope: Scope, + is_generic: bool, + + pub const Instantiation = struct { + declaration: *Macro, + function: *Global, + arguments: []const *Local, + instantiation_arguments: []const *Value, + constant_argument_values: []const *Value, + type_arguments: []*Type, + return_type: *Type, + block: *LexicalBlock, + return_alloca: *llvm.Value, + return_block: *llvm.BasicBlock, + scope: Scope, + }; pub const Buffer = struct { buffer: lib.VirtualBuffer(Macro), @@ -248,10 +271,6 @@ pub const Macro = struct { return globals.buffer.add(); } }; - - pub fn is_generic(macro: *const Macro) bool { - return macro.generic_arguments.len != 0; - } }; pub const ResolvedType = struct { @@ -294,6 +313,7 @@ pub const Type = struct { vector, forward_declaration, alias: Type.Alias, + unresolved, }, name: []const u8, llvm: LLVM = .{}, @@ -351,7 +371,7 @@ pub const Type = struct { }; } - pub fn get_llvm(ty: *Type, kind: Kind) *llvm.Type { + pub fn get_llvm(ty: *Type, kind: Type.Kind) *llvm.Type { return switch (kind) { .abi => ty.llvm.abi.?, .memory => ty.llvm.memory.?, @@ -837,15 +857,6 @@ pub const FieldAccess = struct { field: []const u8, }; -pub const MacroInstantiation = struct { - arguments: []const *Value, - macro: *Macro, - function: *Global, - parent_scope: *Scope, - return_alloca: *llvm.Value, - return_block: *llvm.BasicBlock, -}; - pub const Value = struct { bb: union(enum) { external_function, @@ -872,11 +883,11 @@ pub const Value = struct { @"unreachable", undefined, macro_reference: *Macro, - macro_instantiation: MacroInstantiation, + macro_instantiation: Macro.Instantiation, }, type: ?*Type = null, llvm: ?*llvm.Value = null, - kind: Kind = .right, + kind: Value.Kind = .right, pub const SliceExpression = struct { array_like: *Value, @@ -1009,7 +1020,7 @@ pub const Value = struct { }; const Builder = struct { - kind: Kind = .right, + kind: Value.Kind = .right, precedence: Precedence = .none, left: ?*Value = null, token: Token = .none, @@ -1033,7 +1044,7 @@ pub const Value = struct { return v; } - fn with_kind(vb: Builder, kind: Kind) Builder { + fn with_kind(vb: Builder, kind: Value.Kind) Builder { var v = vb; v.kind = kind; return v; @@ -1093,7 +1104,7 @@ pub const Scope = struct { line: u32, column: u32, llvm: ?*llvm.DI.Scope = null, - kind: Kind, + kind: Scope.Kind, parent: ?*Scope, pub const Kind = enum { @@ -1101,7 +1112,8 @@ pub const Scope = struct { function, local, for_each, - macro, + macro_declaration, + macro_instantiation, }; }; @@ -3046,7 +3058,7 @@ pub const Module = struct { } } }, - .macro => { + .macro_declaration => { assert(scope.parent != null); const macro: *Macro = @fieldParentPtr("scope", scope); for (macro.arguments) |argument| { @@ -3055,6 +3067,7 @@ pub const Module = struct { } } }, + .macro_instantiation => @trap(), } } else { module.report_error(); @@ -3538,39 +3551,123 @@ pub const Module = struct { // Array-like subscript 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(scope, .{}) else null; - const value = module.values.add(); - value.* = .{ - .bb = if (module.consume_character_if_match(right_bracket)) .{ - .array_expression = .{ - .array_like = left, - .index = start orelse module.report_error(), - }, - } else blk: { - module.expect_character('.'); - module.expect_character('.'); - const end = switch (module.consume_character_if_match(right_bracket)) { - true => null, - false => b: { - const end = module.parse_value(scope, .{}); - module.expect_character(right_bracket); - break :b end; - }, - }; - break :blk .{ - .slice_expression = .{ - .array_like = left, - .start = start, - .end = end, + const value = module.values.add(); + + switch (left.bb) { + .macro_reference => |macro| { + if (!macro.is_generic) { + module.report_error(); + } + + const type_arguments = module.arena.allocate(*Type, macro.type_arguments.len); + var type_argument_count: u64 = 0; + const constant_values = module.arena.allocate(*Value, macro.constant_argument_values.len); + var constant_value_count: u64 = 0; + var constant_argument_count: u64 = 0; + + while (true) { + module.skip_space(); + + if (module.consume_character_if_match(right_bracket)) { + break; + } + + const constant_argument = macro.constant_arguments[constant_argument_count]; + constant_argument_count += 1; + + switch (constant_argument.kind) { + .value => { + _ = &constant_value_count; + @trap(); + }, + .type => { + if (type_argument_count >= macro.type_arguments.len) { + module.report_error(); + } + + if (constant_argument.index != type_argument_count) { + module.report_error(); + } + + const argument_type = module.parse_type(); + type_arguments[constant_argument.index] = argument_type; + + type_argument_count += 1; + }, + } + + module.skip_space(); + + _ = module.consume_character_if_match(','); + } + + module.skip_space(); + + module.expect_character(left_parenthesis); + + const instantiation_arguments = module.parse_call_arguments(scope); + + value.* = .{ + .bb = .{ + .macro_instantiation = .{ + .declaration = macro, + .function = module.current_function.?, + .arguments = &.{}, + .instantiation_arguments = instantiation_arguments, + .constant_argument_values = constant_values, + .type_arguments = type_arguments, + .return_type = macro.return_type, + .block = undefined, + .return_alloca = undefined, + .return_block = undefined, + .scope = .{ + .line = macro.scope.line, + .column = macro.scope.column, + .kind = .macro_instantiation, + .parent = macro.scope.parent, + }, + }, }, }; }, - .kind = value_builder.kind, - }; + else => { + left.kind = .left; + + const is_start = !(module.content[module.offset] == '.' and module.content[module.offset + 1] == '.'); + const start = if (is_start) module.parse_value(scope, .{}) else null; + value.* = .{ + .bb = if (module.consume_character_if_match(right_bracket)) .{ + .array_expression = .{ + .array_like = left, + .index = start orelse module.report_error(), + }, + } else blk: { + module.expect_character('.'); + module.expect_character('.'); + + const end = switch (module.consume_character_if_match(right_bracket)) { + true => null, + false => b: { + const end = module.parse_value(scope, .{}); + module.expect_character(right_bracket); + break :b end; + }, + }; + break :blk .{ + .slice_expression = .{ + .array_like = left, + .start = start, + .end = end, + }, + }; + }, + .kind = value_builder.kind, + }; + }, + } + return value; } @@ -3616,23 +3713,36 @@ pub const Module = struct { switch (may_be_callable.bb) { .macro_reference => |macro| { - if (macro.is_generic()) { - @trap(); + if (macro.is_generic) { + module.report_error(); } + const arguments = module.parse_call_arguments(scope); const macro_invocation = module.values.add(); + macro_invocation.* = .{ .bb = .{ .macro_instantiation = .{ - .macro = macro, - .arguments = arguments, + .declaration = macro, + .instantiation_arguments = arguments, + .type_arguments = &.{}, .function = module.current_function.?, .return_alloca = undefined, .return_block = undefined, - .parent_scope = scope, + .block = undefined, + .return_type = macro.return_type, + .constant_argument_values = &.{}, + .arguments = &.{}, + .scope = .{ + .line = macro.scope.line, + .column = macro.scope.column, + .kind = .macro_instantiation, + .parent = macro.scope.parent, + }, }, }, }; + return macro_invocation; }, else => { @@ -4206,22 +4316,91 @@ pub const Module = struct { _ = alias_type; }, .macro => { + var type_argument_buffer: [64]*Type = undefined; + var type_argument_count: u64 = 0; + + var constant_argument_value_buffer: [64]*Value = undefined; + var constant_argument_name_buffer: [64][]const u8 = undefined; + var constant_argument_buffer: [64]ConstantArgument = undefined; + var constant_argument_value_count: u64 = 0; + var constant_argument_count: u64 = 0; + + const is_generic = module.consume_character_if_match(left_bracket); + if (is_generic) { + while (true) { + module.skip_space(); + + if (module.consume_character_if_match(right_bracket)) { + break; + } + + const argument_name = module.parse_identifier(); + + module.skip_space(); + + const has_value = module.consume_character_if_match(':'); + const index: u64 = if (has_value) { + _ = &constant_argument_value_buffer; + _ = &constant_argument_name_buffer; + _ = &constant_argument_value_count; + @trap(); + } else blk: { + const ty = module.types.append(.{ + .bb = .unresolved, + .name = argument_name, + }); + const index = type_argument_count; + type_argument_buffer[index] = ty; + type_argument_count = index + 1; + break :blk index; + }; + + constant_argument_buffer[constant_argument_count] = .{ + .kind = switch (has_value) { + true => .value, + false => .type, + }, + .index = @intCast(index), + }; + + constant_argument_count += 1; + } + + module.skip_space(); + } + module.expect_character(left_parenthesis); + const type_arguments = module.arena.allocate(*Type, type_argument_count); + @memcpy(type_arguments, type_argument_buffer[0..type_argument_count]); + + const constant_argument_names = module.arena.allocate([]const u8, constant_argument_value_count); + @memcpy(constant_argument_names, constant_argument_name_buffer[0..constant_argument_value_count]); + + const constant_argument_values = module.arena.allocate(*Value, constant_argument_value_count); + @memcpy(constant_argument_values, constant_argument_value_buffer[0..constant_argument_value_count]); + + const constant_arguments = module.arena.allocate(ConstantArgument, constant_argument_count); + @memcpy(constant_arguments, constant_argument_buffer[0..constant_argument_count]); + const macro = module.macros.add(); macro.* = .{ .arguments = &.{}, .argument_types = &.{}, - .generic_arguments = &.{}, + .constant_argument_names = constant_argument_names, + .constant_argument_values = constant_argument_values, + .constant_arguments = constant_arguments, + .type_arguments = type_arguments, .return_type = undefined, .block = undefined, .name = global_name, .scope = .{ .parent = &module.scope, - .kind = .macro, + .kind = .macro_declaration, .line = global_line, .column = global_column, }, + .is_generic = is_generic, }; module.current_macro_declaration = macro; @@ -5737,10 +5916,38 @@ pub const Module = struct { return result; } - pub fn analyze_value_type(module: *Module, value: *Value, analysis: ValueAnalysis) void { + pub fn analyze_value_type(module: *Module, value: *Value, a: ValueAnalysis) void { assert(value.type == null); assert(value.llvm == null); + var analysis = a; + if (analysis.type) |expected_type| switch (expected_type.bb) { + .unresolved => { + _ = &analysis; + // const macro_instantiation = (module.current_macro_instantiation orelse module.report_error()).bb.macro_instantiation; + // const macro_declaration = macro_instantiation.macro; + // + // const resolved_type = for (macro_declaration.type_arguments, macro_instantiation.types) |t, result_type| { + // if (t == expected_type) { + // result_type.resolve(module); + // break result_type; + // } + // } else unreachable; + // ty.bb = .{ + // .alias = .{ + // .type = resolved_type, + // .line = 0, // TODO + // }, + // }; + // break :blk resolved_type.llvm.abi.?; + @trap(); + }, + else => {}, + }; + // .unresolved => blk: { + // // TODO: nest macros + // }, + const value_type = switch (value.bb) { .unary => |unary| b: { if (unary.id.is_boolean()) { @@ -5768,8 +5975,15 @@ pub const Module = struct { }, .constant_integer => |constant_integer| blk: { const expected_type = analysis.type orelse module.report_error(); + expected_type.resolve(module); const et = switch (expected_type.bb) { - .alias => |alias| alias.type, + .alias => b: { + var it = expected_type; + while (it.bb == .alias) { + it = it.bb.alias.type; + } + break :b it; + }, else => expected_type, }; const ty = switch (et.bb) { @@ -6624,57 +6838,78 @@ pub const Module = struct { module.current_macro_instantiation = value; defer module.current_macro_instantiation = current_macro_instantiation; - const macro = module.macros.add(); - const old_macro = macro_instantiation.macro; - macro_instantiation.macro = macro; + const declaration = macro_instantiation.declaration; - const arguments = module.arena.allocate(*Local, old_macro.arguments.len); - macro.* = .{ - .arguments = arguments, - .argument_types = old_macro.argument_types, - .generic_arguments = &.{}, // TODO - .return_type = old_macro.return_type, - .block = undefined, - .name = old_macro.name, - .scope = old_macro.scope, - }; + if (declaration.is_generic) { + const arguments = module.arena.allocate(*Local, declaration.arguments.len); - for (old_macro.arguments, arguments) |old_argument, *new_argument| { - const argument = module.locals.add(); - argument.* = .{ - .variable = .{ - .initial_value = undefined, - .type = old_argument.variable.type, - .scope = ¯o.scope, - .name = old_argument.variable.name, - .line = old_argument.variable.line, - .column = old_argument.variable.column, - }, - .argument_index = old_argument.argument_index, - }; - new_argument.* = argument; + for (declaration.arguments, arguments) |old_argument, *new_argument| { + const argument = module.locals.add(); + argument.* = .{ + .variable = .{ + .initial_value = undefined, + .type = old_argument.variable.type, + .scope = ¯o_instantiation.scope, + .name = old_argument.variable.name, + .line = old_argument.variable.line, + .column = old_argument.variable.column, + }, + .argument_index = old_argument.argument_index, + }; + new_argument.* = argument; + } + + macro_instantiation.arguments = arguments; } - macro.block = module.lexical_blocks.add(); + for (macro_instantiation.type_arguments, declaration.type_arguments) |*instantiation_type_argument_pointer, declaration_type_argument| { + assert(declaration_type_argument.bb == .unresolved); + const original_instantiation_type_argument = instantiation_type_argument_pointer.*; + const instantiation_type_argument = module.types.append(.{ + .name = declaration_type_argument.name, + .bb = .{ + .alias = .{ + .type = original_instantiation_type_argument, + .line = 0, // TODO + }, + }, + }); + instantiation_type_argument_pointer.* = instantiation_type_argument; + } - const old_block = old_macro.block; - module.copy_block(¯o.scope, .{ - .source = old_block, - .destination = macro.block, + declaration.return_type = module.resolve_type(declaration.return_type); + + for (macro_instantiation.arguments) |argument| { + argument.variable.type = module.resolve_type(argument.variable.type.?); + } + + value.bb.macro_instantiation.block = module.lexical_blocks.add(); + module.copy_block(macro_instantiation.scope.parent.?, .{ + .source = declaration.block, + .destination = value.bb.macro_instantiation.block, }); - const result_type = macro.return_type; - module.typecheck(analysis, result_type); + if (true) @trap(); - if (macro.argument_types.len != macro.arguments.len) { - module.report_error(); - } - - for (macro_instantiation.arguments, macro.argument_types) |argument, argument_type| { - module.analyze_value_type(argument, .{ .type = argument_type }); - } - - break :blk result_type; + // + // macro.block = module.lexical_blocks.add(); + // + // const old_block = old_macro.block; + // + // const result_type = macro.return_type; + // module.typecheck(analysis, result_type); + // + // if (macro.argument_types.len != macro.arguments.len) { + // module.report_error(); + // } + // + // for (macro_instantiation.arguments, macro.argument_types) |argument, argument_type| { + // module.analyze_value_type(argument, .{ .type = argument_type }); + // } + // + // break :blk result_type; + if (true) @trap(); + break :blk undefined; }, else => @trap(), }; @@ -6979,7 +7214,11 @@ pub const Module = struct { module.emit_value(binary.right, .abi); break :b binary.right.llvm orelse unreachable; }; - const result = switch (value_type.bb) { + var it = value_type; + while (it.bb == .alias) { + it = it.bb.alias.type; + } + const result = switch (it.bb) { .integer => |integer| switch (binary.id) { .@"+" => module.llvm.builder.create_add(left, right), .@"-" => module.llvm.builder.create_sub(left, right), @@ -7544,87 +7783,84 @@ pub const Module = struct { module.current_macro_instantiation = value; defer module.current_macro_instantiation = current_macro_instantiation; - const macro = macro_instantiation.macro; + _ = macro_instantiation; + if (true) @trap(); + break :blk undefined; - switch (macro.is_generic()) { - true => { - @trap(); - }, - false => { - for (macro_instantiation.arguments) |call_argument| { - module.emit_value(call_argument, .abi); - } - - var debug_argument_type_buffer: [64 + 1]*llvm.DI.Type = undefined; - const semantic_debug_argument_types = debug_argument_type_buffer[0 .. macro.argument_types.len + 1]; - semantic_debug_argument_types[0] = macro.return_type.llvm.debug.?; - - for (macro.argument_types, semantic_debug_argument_types[1..][0..macro.argument_types.len]) |argument_type, *debug_argument_type| { - debug_argument_type.* = argument_type.llvm.debug.?; - } - - module.llvm.builder.set_current_debug_location(null); - - const caller_debug_location = llvm.DI.create_debug_location(module.llvm.context, macro.scope.line, macro.scope.column, macro_instantiation.parent_scope.llvm.?, null); - module.inline_at_debug_location = caller_debug_location; - defer module.inline_at_debug_location = null; - - const subroutine_type_flags = llvm.DI.Flags{}; - const subroutine_type = module.llvm.di_builder.create_subroutine_type(module.llvm.file, semantic_debug_argument_types, subroutine_type_flags); - const local_to_unit = true; - const is_definition = true; - - const flags: llvm.DI.Flags = .{}; - const subprogram = module.llvm.di_builder.create_function(module.scope.llvm.?, macro.name, macro.name, module.llvm.file, macro.scope.line, subroutine_type, local_to_unit, is_definition, macro.scope.line, flags, module.build_mode.is_optimized()); - macro.scope.llvm = @ptrCast(subprogram); - module.llvm.builder.set_current_debug_location(llvm.DI.create_debug_location(module.llvm.context, macro.scope.line, macro.scope.column, macro.scope.llvm.?, @ptrCast(caller_debug_location))); - - const llvm_function = current_function.variable.storage.?.llvm.?.to_function(); - const macro_entry_block = module.llvm.context.create_basic_block("macro.entry", llvm_function); - _ = module.llvm.builder.create_branch(macro_entry_block); - module.llvm.builder.position_at_end(macro_entry_block); - - const macro_return_alloca = module.create_alloca(.{ - .type = macro.return_type, - .name = "macro.return", - }); - macro_instantiation.return_alloca = macro_return_alloca; - - const macro_return_block = module.llvm.context.create_basic_block("macro.return_block", llvm_function); - macro_instantiation.return_block = macro_return_block; - - for (macro_instantiation.arguments, macro.arguments) |call_argument, declaration_argument| { - const inlined_at = caller_debug_location; - const debug_location = llvm.DI.create_debug_location(module.llvm.context, declaration_argument.variable.line, declaration_argument.variable.column, macro.scope.llvm.?, @ptrCast(inlined_at)); - module.llvm.builder.set_current_debug_location(debug_location); - module.emit_local_storage(declaration_argument, debug_location); - const storage = declaration_argument.variable.storage.?.llvm.?; - - switch (declaration_argument.variable.type.?.get_evaluation_kind()) { - .scalar => { - _ = module.create_store(.{ - .source_value = call_argument.llvm.?, - .destination_value = storage, - .type = declaration_argument.variable.type.?, - }); - }, - .aggregate => @trap(), - .complex => @trap(), - } - } - - module.analyze_block(macro.block); - module.llvm.builder.position_at_end(macro_return_block); - - const load = module.create_load(.{ - .type = macro.return_type, - .value = macro_return_alloca, - .type_kind = type_kind, - }); - - break :blk load; - }, - } + // const macro = macro_instantiation.macro; + // + // for (macro_instantiation.arguments) |call_argument| { + // module.emit_value(call_argument, .abi); + // } + // + // var debug_argument_type_buffer: [64 + 1]*llvm.DI.Type = undefined; + // const semantic_debug_argument_types = debug_argument_type_buffer[0 .. macro.argument_types.len + 1]; + // semantic_debug_argument_types[0] = macro.return_type.llvm.debug.?; + // + // for (macro.argument_types, semantic_debug_argument_types[1..][0..macro.argument_types.len]) |argument_type, *debug_argument_type| { + // debug_argument_type.* = argument_type.llvm.debug.?; + // } + // + // module.llvm.builder.set_current_debug_location(null); + // + // const caller_debug_location = llvm.DI.create_debug_location(module.llvm.context, macro.scope.line, macro.scope.column, macro_instantiation.parent_scope.llvm.?, null); + // module.inline_at_debug_location = caller_debug_location; + // defer module.inline_at_debug_location = null; + // + // const subroutine_type_flags = llvm.DI.Flags{}; + // const subroutine_type = module.llvm.di_builder.create_subroutine_type(module.llvm.file, semantic_debug_argument_types, subroutine_type_flags); + // const local_to_unit = true; + // const is_definition = true; + // + // const flags: llvm.DI.Flags = .{}; + // const subprogram = module.llvm.di_builder.create_function(module.scope.llvm.?, macro.name, macro.name, module.llvm.file, macro.scope.line, subroutine_type, local_to_unit, is_definition, macro.scope.line, flags, module.build_mode.is_optimized()); + // macro.scope.llvm = @ptrCast(subprogram); + // module.llvm.builder.set_current_debug_location(llvm.DI.create_debug_location(module.llvm.context, macro.scope.line, macro.scope.column, macro.scope.llvm.?, @ptrCast(caller_debug_location))); + // + // const llvm_function = current_function.variable.storage.?.llvm.?.to_function(); + // const macro_entry_block = module.llvm.context.create_basic_block("macro.entry", llvm_function); + // _ = module.llvm.builder.create_branch(macro_entry_block); + // module.llvm.builder.position_at_end(macro_entry_block); + // + // const macro_return_alloca = module.create_alloca(.{ + // .type = macro.return_type, + // .name = "macro.return", + // }); + // macro_instantiation.return_alloca = macro_return_alloca; + // + // const macro_return_block = module.llvm.context.create_basic_block("macro.return_block", llvm_function); + // macro_instantiation.return_block = macro_return_block; + // + // for (macro_instantiation.arguments, macro.arguments) |call_argument, declaration_argument| { + // const inlined_at = caller_debug_location; + // const debug_location = llvm.DI.create_debug_location(module.llvm.context, declaration_argument.variable.line, declaration_argument.variable.column, macro.scope.llvm.?, @ptrCast(inlined_at)); + // module.llvm.builder.set_current_debug_location(debug_location); + // module.emit_local_storage(declaration_argument, debug_location); + // const storage = declaration_argument.variable.storage.?.llvm.?; + // + // switch (declaration_argument.variable.type.?.get_evaluation_kind()) { + // .scalar => { + // _ = module.create_store(.{ + // .source_value = call_argument.llvm.?, + // .destination_value = storage, + // .type = declaration_argument.variable.type.?, + // }); + // }, + // .aggregate => @trap(), + // .complex => @trap(), + // } + // } + // + // module.analyze_block(macro.block); + // module.llvm.builder.position_at_end(macro_return_block); + // + // const load = module.create_load(.{ + // .type = macro.return_type, + // .value = macro_return_alloca, + // .type_kind = type_kind, + // }); + // + // break :blk load; }, else => @trap(), }; @@ -7754,12 +7990,14 @@ pub const Module = struct { _ = module.llvm.builder.create_branch(return_block); _ = module.llvm.builder.clear_insertion_position(); } else if (module.current_macro_instantiation) |m| { - const macro_instantiation = &m.bb.macro_instantiation; - const macro = macro_instantiation.macro; - module.analyze_value_type(rv.?, .{ .type = macro.return_type }); - module.emit_assignment(macro_instantiation.return_alloca, module.get_pointer_type(.{ .type = macro.return_type }), rv.?); - _ = module.llvm.builder.create_branch(macro_instantiation.return_block); - module.llvm.builder.clear_insertion_position(); + _ = m; + @trap(); + // const macro_instantiation = &m.bb.macro_instantiation; + // const macro = macro_instantiation.declaration; + // module.analyze_value_type(rv.?, .{ .type = macro.return_type }); + // module.emit_assignment(macro_instantiation.return_alloca, module.get_pointer_type(.{ .type = macro.return_type }), rv.?); + // _ = module.llvm.builder.create_branch(macro_instantiation.return_block); + // module.llvm.builder.clear_insertion_position(); } else { module.report_error(); } @@ -8720,6 +8958,27 @@ pub const Module = struct { }, } } + + fn resolve_type(module: *Module, ty: *Type) *Type { + const result_type = switch (ty.bb) { + .unresolved => blk: { + const macro_instantiation_value = module.current_macro_instantiation orelse module.report_error(); + const macro_instantiation = ¯o_instantiation_value.bb.macro_instantiation; + + const result_type = for (macro_instantiation.type_arguments, macro_instantiation.declaration.type_arguments) |instantiation_type_argument, declaration_type_argument| { + if (declaration_type_argument == ty) { + assert(lib.string.equal(declaration_type_argument.name, instantiation_type_argument.name)); + break instantiation_type_argument; + } + } else module.report_error(); + + break :blk result_type; + }, + else => ty, + }; + + return result_type; + } }; pub const Options = struct { @@ -8901,7 +9160,7 @@ pub const Abi = struct { }; const Flags = struct { - kind: Kind, + kind: Abi.Kind, padding_in_reg: bool = false, in_alloca_sret: bool = false, in_alloca_indirect: bool = false, diff --git a/tests/generic_macro.bbb b/tests/generic_macro.bbb new file mode 100644 index 0000000..432dbe5 --- /dev/null +++ b/tests/generic_macro.bbb @@ -0,0 +1,11 @@ +sub = macro [T] (a: T, b: T) T +{ + return a - b; +} + +[export] main = fn [cc(c)] () s32 +{ + >a = sub[s32](1, 1); + >b = sub[u8](2, 2); + return a + #extend(b); +}