From 3cbd427f14913c3ef42ff6f0eab5d4f3989bc843 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Sun, 20 Apr 2025 20:08:12 -0600 Subject: [PATCH] Introduce typealias --- src/LLVM.zig | 4 ++++ src/bootstrap.zig | 51 ++++++++++++++++++++++++++++++++++++++++---- src/compiler.bbb | 7 ++++++ src/llvm_api.zig | 1 + tests/type_alias.bbb | 6 ++++++ 5 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 tests/type_alias.bbb diff --git a/src/LLVM.zig b/src/LLVM.zig index 6165a49..0990666 100644 --- a/src/LLVM.zig +++ b/src/LLVM.zig @@ -1313,6 +1313,10 @@ pub const DI = struct { pub fn create_enumeration_type(builder: *DI.Builder, scope: *DI.Scope, name: []const u8, file: *DI.File, line: c_uint, bit_size: u64, align_in_bits: u32, enumeration_types: []const *DI.Enumerator, backing_type: *DI.Type) *DI.Type.Composite { return api.LLVMDIBuilderCreateEnumerationType(builder, scope, name.ptr, name.len, file, line, bit_size, align_in_bits, enumeration_types.ptr, @intCast(enumeration_types.len), backing_type); } + + pub fn create_typedef(builder: *DI.Builder, ty: *DI.Type, name: []const u8, file: *DI.File, line: c_uint, scope: *DI.Scope, align_in_bits: u32) *DI.Type.Derived { + return api.LLVMDIBuilderCreateTypedef(builder, ty, name.ptr, name.len, file, line, scope, align_in_bits); + } }; pub const create_debug_location = api.LLVMDIBuilderCreateDebugLocation; diff --git a/src/bootstrap.zig b/src/bootstrap.zig index 158eb5e..a1b3eac 100644 --- a/src/bootstrap.zig +++ b/src/bootstrap.zig @@ -238,6 +238,7 @@ pub const Type = struct { structure: Type.Struct, vector, forward_declaration, + alias: Type.Alias, }, name: []const u8, llvm: LLVM = .{}, @@ -258,6 +259,11 @@ pub const Type = struct { }; }; + pub const Alias = struct { + type: *Type, + line: u32, + }; + pub const Float = struct { const Kind = enum { half, @@ -327,6 +333,10 @@ pub const Type = struct { const t = bits.backing_type.llvm.abi.?; break :blk t; }, + .alias => |alias| blk: { + alias.type.resolve(module); + break :blk alias.type.llvm.abi.?; + }, else => @trap(), }; ty.llvm.abi = abi_type; @@ -341,6 +351,7 @@ pub const Type = struct { .integer => module.llvm.context.get_integer_type(@intCast(ty.get_byte_size() * 8)).to_type(), .enumerator => |enumerator| enumerator.backing_type.llvm.memory.?, .bits => |bits| bits.backing_type.llvm.memory.?, // TODO: see assert below + .alias => |alias| alias.type.llvm.memory.?, else => @trap(), }; ty.llvm.memory = memory_type; @@ -400,6 +411,10 @@ pub const Type = struct { const struct_type = module.llvm.di_builder.create_struct_type(module.scope.llvm.?, ty.name, module.llvm.file, bits.line, ty.get_bit_size(), @intCast(ty.get_bit_alignment()), .{}, llvm_debug_member_types); break :blk struct_type.to_type(); }, + .alias => |alias| blk: { + const typedef = module.llvm.di_builder.create_typedef(alias.type.llvm.debug.?, ty.name, module.llvm.file, alias.line, module.scope.llvm.?, 0); + break :blk typedef.to_type(); + }, else => @trap(), }; ty.llvm.debug = debug_type; @@ -497,11 +512,12 @@ pub const Type = struct { }; } - pub fn is_integral_or_enumeration_type(ty: *Type) bool { + pub fn is_integral_or_enumeration_type(ty: *const Type) bool { return switch (ty.bb) { .integer => true, .bits => true, .structure => false, + .alias => |alias| alias.type.is_integral_or_enumeration_type(), else => @trap(), }; } @@ -522,6 +538,7 @@ pub const Type = struct { return switch (ty.bb) { .integer => |integer| integer.bit_count < 32, .bits => |bits| bits.backing_type.is_promotable_integer_type_for_abi(), + .alias => |alias| alias.type.is_promotable_integer_type_for_abi(), else => @trap(), }; } @@ -536,6 +553,7 @@ pub const Type = struct { .enumerator => |enumerator| enumerator.backing_type.get_byte_alignment(), .structure => |structure| structure.byte_alignment, .bits => |bits| bits.backing_type.get_byte_alignment(), + .alias => |alias| alias.type.get_byte_alignment(), else => @trap(), }; return result; @@ -562,6 +580,7 @@ pub const Type = struct { .array => |array| array.element_type.get_byte_size() * array.element_count, .bits => |bits| bits.backing_type.get_byte_size(), .enumerator => |enumerator| enumerator.backing_type.get_byte_size(), + .alias => |alias| alias.type.get_byte_size(), else => @trap(), }; return byte_size; @@ -600,6 +619,7 @@ pub const Type = struct { return switch (ty.bb) { .structure, .array => .aggregate, .integer, .bits, .pointer, .enumerator => .scalar, + .alias => |alias| alias.type.get_evaluation_kind(), else => @trap(), }; } @@ -973,10 +993,11 @@ const Precedence = enum { }; const GlobalKind = enum { - @"fn", - @"struct", bits, @"enum", + @"fn", + @"struct", + typealias, }; const CallingConvention = enum { @@ -4001,6 +4022,22 @@ pub const Module = struct { }, }; }, + .typealias => { + const aliased_type = module.parse_type(null); + if (!module.consume_character_if_match(';')) { + module.report_error(); + } + const alias_type = module.types.append(.{ + .bb = .{ + .alias = .{ + .type = aliased_type, + .line = global_line, + }, + }, + .name = global_name, + }); + _ = alias_type; + }, } } else { module.offset -= global_string.len; @@ -5415,7 +5452,11 @@ pub const Module = struct { }, .constant_integer => |constant_integer| blk: { const expected_type = analysis.type orelse module.report_error(); - const ty = switch (expected_type.bb) { + const et = switch (expected_type.bb) { + .alias => |alias| alias.type, + else => expected_type, + }; + const ty = switch (et.bb) { .integer => |integer| switch (constant_integer.signed) { true => { if (!integer.signed) { @@ -8780,6 +8821,7 @@ pub const Abi = struct { } } }, + .alias => |alias| return classify(alias.type, options), else => @trap(), } @@ -8864,6 +8906,7 @@ pub const Abi = struct { const element_offset = (offset / element_size) * element_size; return get_int_type_at_offset(module, element_type, @intCast(offset - element_offset), source_type, source_offset); }, + .alias => |alias| return get_int_type_at_offset(module, alias.type, offset, source_type, source_offset), else => |t| @panic(@tagName(t)), } diff --git a/src/compiler.bbb b/src/compiler.bbb index 4d35295..4882790 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -1,6 +1,9 @@ +mode_t = typealias u64; + [extern] memcmp = fn [cc(c)] (a: &u8, b: &u8, byte_count: u64) s32; [extern] memcpy = fn [cc(c)] (destination: &u8, source: &u8, byte_count: u64) &u8; [extern] exit = fn [cc(c)] (exit_code: s32) noreturn; +[extern] mkdir = fn [cc(c)] (path: &u8, mode: mode_t) s32; assert = fn (ok: u1) void { @@ -169,6 +172,10 @@ os_commit = fn (address: u64, size: u64, protection: OS_ProtectionFlags) void } } +os_make_directory = fn (path: &u8) void +{ +} + Arena = struct { reserved_size: u64, diff --git a/src/llvm_api.zig b/src/llvm_api.zig index 5ce10e6..5464ce3 100644 --- a/src/llvm_api.zig +++ b/src/llvm_api.zig @@ -231,6 +231,7 @@ pub extern fn LLVMDIBuilderCreateBitFieldMemberType(builder: *llvm.DI.Builder, s pub extern fn LLVMDIBuilderCreatePointerType(builder: *llvm.DI.Builder, element_type: *llvm.DI.Type, bit_size: u64, align_in_bits: u32, address_space: c_uint, name_pointer: [*]const u8, name_length: usize) *llvm.DI.Type.Derived; pub extern fn LLVMDIBuilderCreateEnumerator(builder: *llvm.DI.Builder, name_pointer: [*]const u8, name_length: usize, value: i64, is_unsigned: Bool) *llvm.DI.Enumerator; pub extern fn LLVMDIBuilderCreateEnumerationType(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, file: *llvm.DI.File, line: c_uint, bit_size: u64, align_in_bits: u32, enumerator_pointer: [*]const *llvm.DI.Enumerator, enumerator_count: c_uint, backing_type: *llvm.DI.Type) *llvm.DI.Type.Composite; +pub extern fn LLVMDIBuilderCreateTypedef(builder: *llvm.DI.Builder, ty: *llvm.DI.Type, name_pointer: [*]const u8, name_length: usize, file: *llvm.DI.File, line_number: c_uint, scope: *llvm.DI.Scope, align_in_bits: u32) *llvm.DI.Type.Derived; pub extern fn LLVMMetadataReplaceAllUsesWith(forward: *llvm.DI.Type.Composite, complete: *llvm.DI.Type.Composite) void; diff --git a/tests/type_alias.bbb b/tests/type_alias.bbb new file mode 100644 index 0000000..4ca70d3 --- /dev/null +++ b/tests/type_alias.bbb @@ -0,0 +1,6 @@ +int = typealias s32; + +[export] main = fn [cc(c)] () int +{ + return 0; +}