wip
This commit is contained in:
parent
0eee2a4ff3
commit
9f6b141400
@ -396,7 +396,7 @@ pub const Type = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(ty: *Type, module: *Module) void {
|
fn resolve_abi(ty: *Type, module: *Module) void {
|
||||||
if (ty.llvm.abi == null) {
|
if (ty.llvm.abi == null) {
|
||||||
const abi_type = switch (ty.bb) {
|
const abi_type = switch (ty.bb) {
|
||||||
.void, .noreturn => module.llvm.void_type,
|
.void, .noreturn => module.llvm.void_type,
|
||||||
@ -439,7 +439,11 @@ pub const Type = struct {
|
|||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
ty.llvm.abi = abi_type;
|
ty.llvm.abi = abi_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_memory(ty: *Type, module: *Module) void {
|
||||||
|
if (ty.llvm.memory == null) {
|
||||||
const memory_type = switch (ty.bb) {
|
const memory_type = switch (ty.bb) {
|
||||||
.void,
|
.void,
|
||||||
.noreturn,
|
.noreturn,
|
||||||
@ -447,7 +451,7 @@ pub const Type = struct {
|
|||||||
.array,
|
.array,
|
||||||
.structure,
|
.structure,
|
||||||
.@"union",
|
.@"union",
|
||||||
=> abi_type,
|
=> ty.llvm.abi.?,
|
||||||
.integer => module.llvm.context.get_integer_type(@intCast(ty.get_byte_size() * 8)).to_type(),
|
.integer => module.llvm.context.get_integer_type(@intCast(ty.get_byte_size() * 8)).to_type(),
|
||||||
.enumerator => |enumerator| enumerator.backing_type.llvm.memory.?,
|
.enumerator => |enumerator| enumerator.backing_type.llvm.memory.?,
|
||||||
.bits => |bits| bits.backing_type.llvm.memory.?, // TODO: see assert below
|
.bits => |bits| bits.backing_type.llvm.memory.?, // TODO: see assert below
|
||||||
@ -456,8 +460,12 @@ pub const Type = struct {
|
|||||||
};
|
};
|
||||||
ty.llvm.memory = memory_type;
|
ty.llvm.memory = memory_type;
|
||||||
if (ty.bb == .bits) assert(ty.llvm.memory == ty.llvm.abi);
|
if (ty.bb == .bits) assert(ty.llvm.memory == ty.llvm.abi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (module.has_debug_info) {
|
fn resolve_debug(ty: *Type, module: *Module) void {
|
||||||
|
if (module.has_debug_info) {
|
||||||
|
if (ty.llvm.debug == null) {
|
||||||
const debug_type = switch (ty.bb) {
|
const debug_type = switch (ty.bb) {
|
||||||
.void, .noreturn => module.llvm.di_builder.create_basic_type(ty.name, 0, .void, .{ .no_return = ty.bb == .noreturn }),
|
.void, .noreturn => module.llvm.di_builder.create_basic_type(ty.name, 0, .void, .{ .no_return = ty.bb == .noreturn }),
|
||||||
.integer => |integer| module.llvm.di_builder.create_basic_type(ty.name, @max(lib.next_power_of_two(integer.bit_count), 8), switch (integer.bit_count) {
|
.integer => |integer| module.llvm.di_builder.create_basic_type(ty.name, @max(lib.next_power_of_two(integer.bit_count), 8), switch (integer.bit_count) {
|
||||||
@ -467,9 +475,10 @@ pub const Type = struct {
|
|||||||
false => .unsigned,
|
false => .unsigned,
|
||||||
},
|
},
|
||||||
}, .{}),
|
}, .{}),
|
||||||
.pointer => |pointer| b: {
|
.pointer => |pointer| if (pointer.type.llvm.debug) |t| t else b: {
|
||||||
pointer.type.resolve(module);
|
pointer.type.resolve_debug(module);
|
||||||
break :b module.llvm.di_builder.create_pointer_type(pointer.type.llvm.debug.?, 64, 64, 0, ty.name).to_type();
|
const pointer_type = module.llvm.di_builder.create_pointer_type(pointer.type.llvm.debug.?, 64, 64, 0, ty.name).to_type();
|
||||||
|
break :b pointer_type;
|
||||||
},
|
},
|
||||||
.array => |array| module.llvm.di_builder.create_array_type(array.element_count, 0, array.element_type.llvm.debug.?, &.{}).to_type(),
|
.array => |array| module.llvm.di_builder.create_array_type(array.element_count, 0, array.element_type.llvm.debug.?, &.{}).to_type(),
|
||||||
.enumerator => |enumerator| blk: {
|
.enumerator => |enumerator| blk: {
|
||||||
@ -483,21 +492,22 @@ pub const Type = struct {
|
|||||||
break :blk enumeration_type.to_type();
|
break :blk enumeration_type.to_type();
|
||||||
},
|
},
|
||||||
.structure => |structure| blk: {
|
.structure => |structure| blk: {
|
||||||
const struct_type = module.llvm.di_builder.create_replaceable_composite_type(module.llvm.debug_tag, ty.name, module.scope.llvm.?, module.llvm.file, structure.line);
|
assert(ty.llvm.debug == null);
|
||||||
ty.llvm.debug = struct_type.to_type();
|
const fwd = module.llvm.di_builder.create_replaceable_composite_type(module.llvm.debug_tag, ty.name, module.scope.llvm.?, module.llvm.file, structure.line);
|
||||||
|
ty.llvm.debug = fwd.to_type();
|
||||||
module.llvm.debug_tag += 1;
|
module.llvm.debug_tag += 1;
|
||||||
|
|
||||||
var llvm_debug_member_type_buffer: [64]*llvm.DI.Type.Derived = undefined;
|
var llvm_debug_member_type_buffer: [64]*llvm.DI.Type.Derived = undefined;
|
||||||
const llvm_debug_member_types = llvm_debug_member_type_buffer[0..structure.fields.len];
|
const llvm_debug_member_types = llvm_debug_member_type_buffer[0..structure.fields.len];
|
||||||
|
|
||||||
for (structure.fields, llvm_debug_member_types) |field, *llvm_debug_member_type| {
|
for (structure.fields, llvm_debug_member_types) |field, *llvm_debug_member_type| {
|
||||||
field.type.resolve(module);
|
field.type.resolve_debug(module);
|
||||||
const member_type = module.llvm.di_builder.create_member_type(module.scope.llvm.?, field.name, module.llvm.file, field.line, field.type.get_byte_size() * 8, @intCast(field.type.get_byte_alignment() * 8), field.bit_offset, .{}, field.type.llvm.debug.?);
|
const member_type = module.llvm.di_builder.create_member_type(module.scope.llvm.?, field.name, module.llvm.file, field.line, field.type.get_byte_size() * 8, @intCast(field.type.get_byte_alignment() * 8), field.bit_offset, .{}, field.type.llvm.debug.?);
|
||||||
llvm_debug_member_type.* = member_type;
|
llvm_debug_member_type.* = member_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
const debug_struct_type = module.llvm.di_builder.create_struct_type(module.scope.llvm.?, ty.name, module.llvm.file, structure.line, structure.bit_size, @intCast(structure.bit_alignment), .{}, llvm_debug_member_types);
|
const debug_struct_type = module.llvm.di_builder.create_struct_type(module.scope.llvm.?, ty.name, module.llvm.file, structure.line, structure.bit_size, @intCast(structure.bit_alignment), .{}, llvm_debug_member_types);
|
||||||
const forward_declared: *llvm.DI.Type.Composite = @ptrCast(ty.llvm.debug);
|
const forward_declared: *llvm.DI.Type.Composite = @ptrCast(fwd);
|
||||||
forward_declared.replace_all_uses_with(debug_struct_type);
|
forward_declared.replace_all_uses_with(debug_struct_type);
|
||||||
break :blk debug_struct_type.to_type();
|
break :blk debug_struct_type.to_type();
|
||||||
},
|
},
|
||||||
@ -524,7 +534,7 @@ pub const Type = struct {
|
|||||||
const llvm_debug_member_types = llvm_debug_member_type_buffer[0..union_type.fields.len];
|
const llvm_debug_member_types = llvm_debug_member_type_buffer[0..union_type.fields.len];
|
||||||
|
|
||||||
for (union_type.fields, llvm_debug_member_types) |field, *llvm_debug_member_type| {
|
for (union_type.fields, llvm_debug_member_types) |field, *llvm_debug_member_type| {
|
||||||
field.type.resolve(module);
|
field.type.resolve_debug(module);
|
||||||
const member_type = module.llvm.di_builder.create_member_type(module.scope.llvm.?, field.name, module.llvm.file, field.line, field.type.get_byte_size() * 8, @intCast(field.type.get_byte_alignment() * 8), 0, .{}, field.type.llvm.debug.?);
|
const member_type = module.llvm.di_builder.create_member_type(module.scope.llvm.?, field.name, module.llvm.file, field.line, field.type.get_byte_size() * 8, @intCast(field.type.get_byte_alignment() * 8), 0, .{}, field.type.llvm.debug.?);
|
||||||
llvm_debug_member_type.* = member_type;
|
llvm_debug_member_type.* = member_type;
|
||||||
}
|
}
|
||||||
@ -536,11 +546,18 @@ pub const Type = struct {
|
|||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
ty.llvm.debug = debug_type;
|
ty.llvm.debug = debug_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve(ty: *Type, module: *Module) void {
|
||||||
|
ty.resolve_abi(module);
|
||||||
|
ty.resolve_memory(module);
|
||||||
|
ty.resolve_debug(module);
|
||||||
|
}
|
||||||
|
|
||||||
const Bits = struct {
|
const Bits = struct {
|
||||||
fields: []const Struct.Field,
|
fields: []const Struct.Field,
|
||||||
backing_type: *Type,
|
backing_type: *Type,
|
||||||
@ -1569,7 +1586,7 @@ pub const Module = struct {
|
|||||||
pub fn get_pointer_type(module: *Module, pointer: Pointer) *Type {
|
pub fn get_pointer_type(module: *Module, pointer: Pointer) *Type {
|
||||||
const p = Type.Pointer{
|
const p = Type.Pointer{
|
||||||
.type = pointer.type,
|
.type = pointer.type,
|
||||||
.alignment = if (pointer.alignment) |a| a else if (pointer.type.bb != .unresolved) pointer.type.get_byte_alignment() else null,
|
.alignment = if (pointer.alignment) |a| a else if (pointer.type.bb != .unresolved and pointer.type.bb != .forward_declaration) pointer.type.get_byte_alignment() else null,
|
||||||
};
|
};
|
||||||
const all_types = module.types.get_slice();
|
const all_types = module.types.get_slice();
|
||||||
const pointer_type = for (module.pointer_types.get_slice()) |pointer_type_index| {
|
const pointer_type = for (module.pointer_types.get_slice()) |pointer_type_index| {
|
||||||
|
176
src/compiler.bbb
176
src/compiler.bbb
@ -586,6 +586,24 @@ CompileOptions = struct
|
|||||||
silent: u1,
|
silent: u1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopeKind = enum
|
||||||
|
{
|
||||||
|
global,
|
||||||
|
function,
|
||||||
|
local,
|
||||||
|
for_each,
|
||||||
|
macro_declaration,
|
||||||
|
macro_instantiation_function,
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope = struct
|
||||||
|
{
|
||||||
|
parent: &Scope,
|
||||||
|
line: u32,
|
||||||
|
column: u32,
|
||||||
|
kind: ScopeKind,
|
||||||
|
}
|
||||||
|
|
||||||
TypeId = enum
|
TypeId = enum
|
||||||
{
|
{
|
||||||
void,
|
void,
|
||||||
@ -655,6 +673,13 @@ module_noreturn_type = fn (module: &Module) &Type
|
|||||||
return module_void_type(module) + 1;
|
return module_void_type(module) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
left_bracket: u8 = '[';
|
||||||
|
right_bracket: u8 = '[';
|
||||||
|
left_parenthesis: u8 = '(';
|
||||||
|
right_parenthesis: u8 = ')';
|
||||||
|
left_brace: u8 = '{';
|
||||||
|
right_brace: u8 = '}';
|
||||||
|
|
||||||
is_space = fn (ch: u8) u1
|
is_space = fn (ch: u8) u1
|
||||||
{
|
{
|
||||||
return ch == ' ' or ch == '\n' or ch == '\t' or ch == '\r';
|
return ch == ' ' or ch == '\n' or ch == '\t' or ch == '\r';
|
||||||
@ -817,8 +842,159 @@ parse_identifier = fn (module: &Module) []u8
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse_type = fn (module: &Module) &Type
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueBuilder = struct
|
||||||
|
{
|
||||||
|
foo: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_value = fn (module: &Module, scope: &Scope, v: ValueBuilder) &Value
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalKeyword = enum
|
||||||
|
{
|
||||||
|
export,
|
||||||
|
extern,
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalKind = enum
|
||||||
|
{
|
||||||
|
bits,
|
||||||
|
enum,
|
||||||
|
fn,
|
||||||
|
macro,
|
||||||
|
struct,
|
||||||
|
typealias,
|
||||||
|
union,
|
||||||
|
}
|
||||||
|
|
||||||
parse = fn (module: &Module) void
|
parse = fn (module: &Module) void
|
||||||
{
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
if (module.offset == module.content.length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
>is_export: u1 = 0;
|
||||||
|
>is_extern: u1 = 0;
|
||||||
|
|
||||||
|
>global_line = get_line(module);
|
||||||
|
>global_column = get_column(module);
|
||||||
|
|
||||||
|
if (consume_character_if_match(module, left_bracket))
|
||||||
|
{
|
||||||
|
while (module.offset < module.content.length)
|
||||||
|
{
|
||||||
|
>global_keyword_string = parse_identifier(module);
|
||||||
|
>global_keyword_s2e = #string_to_enum(GlobalKeyword, global_keyword_string);
|
||||||
|
if (!global_keyword_s2e.is_valid)
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
>global_keyword = global_keyword_s2e.enum_value;
|
||||||
|
switch (global_keyword)
|
||||||
|
{
|
||||||
|
.export => { is_export = 1; }
|
||||||
|
.extern => { is_extern = 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (consume_character_if_match(module, right_bracket))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
>global_name = parse_identifier(module);
|
||||||
|
|
||||||
|
// TODO: check if the name is repeated in global namespace
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
>global_type: &Type = zero;
|
||||||
|
|
||||||
|
if (consume_character_if_match(module, ':'))
|
||||||
|
{
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
global_type = parse_type(module);
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_character(module, '=');
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
>has_global_keyword: u1 = 0;
|
||||||
|
|
||||||
|
if (is_identifier_start(module.content[module.offset]))
|
||||||
|
{
|
||||||
|
>identifier_offset = module.offset;
|
||||||
|
|
||||||
|
>global_string = parse_identifier(module);
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
>global_kind_s2e = #string_to_enum(GlobalKind, global_string);
|
||||||
|
|
||||||
|
if (global_kind_s2e.is_valid)
|
||||||
|
{
|
||||||
|
>global_kind = global_kind_s2e.enum_value;
|
||||||
|
|
||||||
|
switch (global_kind)
|
||||||
|
{
|
||||||
|
.bits => {
|
||||||
|
#trap();
|
||||||
|
},
|
||||||
|
.enum => {
|
||||||
|
#trap();
|
||||||
|
},
|
||||||
|
.fn => {
|
||||||
|
#trap();
|
||||||
|
},
|
||||||
|
.macro => {
|
||||||
|
#trap();
|
||||||
|
},
|
||||||
|
.struct => {
|
||||||
|
#trap();
|
||||||
|
},
|
||||||
|
.typealias => {
|
||||||
|
#trap();
|
||||||
|
},
|
||||||
|
.union => {
|
||||||
|
#trap();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
module.offset = identifier_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_global_keyword)
|
||||||
|
{
|
||||||
|
>v = parse_value(&module.scope, zero);
|
||||||
|
skip_space(module);
|
||||||
|
expect_character(module, ';');
|
||||||
|
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit = fn (module: &Module) void
|
emit = fn (module: &Module) void
|
||||||
|
@ -332,4 +332,5 @@ const names = &[_][]const u8{
|
|||||||
"generic_pointer_macro",
|
"generic_pointer_macro",
|
||||||
"break_continue",
|
"break_continue",
|
||||||
"noreturn_macro",
|
"noreturn_macro",
|
||||||
|
"self_referential_struct",
|
||||||
};
|
};
|
||||||
|
11
tests/self_referential_struct.bbb
Normal file
11
tests/self_referential_struct.bbb
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
S = struct
|
||||||
|
{
|
||||||
|
self: &S,
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>s: S = zero;
|
||||||
|
s.self = &s;
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user