commit
088c8d8d5d
1
TODOLIST
1
TODOLIST
@ -1,3 +1,4 @@
|
|||||||
|
pointers
|
||||||
function pointers
|
function pointers
|
||||||
for loops
|
for loops
|
||||||
arrays
|
arrays
|
||||||
|
@ -141,7 +141,6 @@ pub const LLVM = struct {
|
|||||||
const createConditionalBranch = bindings.NativityLLVMBuilderCreateConditionalBranch;
|
const createConditionalBranch = bindings.NativityLLVMBuilderCreateConditionalBranch;
|
||||||
const createSwitch = bindings.NativityLLVMBuilderCreateSwitch;
|
const createSwitch = bindings.NativityLLVMBuilderCreateSwitch;
|
||||||
const createGEP = bindings.NativityLLVMBuilderCreateGEP;
|
const createGEP = bindings.NativityLLVMBuilderCreateGEP;
|
||||||
const createStructGEP = bindings.NativityLLVMBuilderCreateStructGEP;
|
|
||||||
const createICmp = bindings.NativityLLVMBuilderCreateICmp;
|
const createICmp = bindings.NativityLLVMBuilderCreateICmp;
|
||||||
const createLoad = bindings.NativityLLVMBuilderCreateLoad;
|
const createLoad = bindings.NativityLLVMBuilderCreateLoad;
|
||||||
const createMultiply = bindings.NativityLLVMBuilderCreateMultiply;
|
const createMultiply = bindings.NativityLLVMBuilderCreateMultiply;
|
||||||
|
@ -98,7 +98,6 @@ pub extern fn NativityLLVMBuilderCreateXor(builder: *LLVM.Builder, left: *LLVM.V
|
|||||||
pub extern fn NativityLLVMBuilderCreateAnd(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) *LLVM.Value;
|
pub extern fn NativityLLVMBuilderCreateAnd(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) *LLVM.Value;
|
||||||
pub extern fn NativityLLVMBuilderCreateOr(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) *LLVM.Value;
|
pub extern fn NativityLLVMBuilderCreateOr(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) *LLVM.Value;
|
||||||
pub extern fn NativityLLVMBuilderCreateGEP(builder: *LLVM.Builder, type: *LLVM.Type, pointer: *LLVM.Value, index_ptr: [*]const *LLVM.Value, index_count: usize, name_ptr: [*]const u8, name_len: usize, in_bounds: bool) *LLVM.Value;
|
pub extern fn NativityLLVMBuilderCreateGEP(builder: *LLVM.Builder, type: *LLVM.Type, pointer: *LLVM.Value, index_ptr: [*]const *LLVM.Value, index_count: usize, name_ptr: [*]const u8, name_len: usize, in_bounds: bool) *LLVM.Value;
|
||||||
pub extern fn NativityLLVMBuilderCreateStructGEP(builder: *LLVM.Builder, type: *LLVM.Type, pointer: *LLVM.Value, index: c_uint, name_ptr: [*]const u8, name_len: usize) *LLVM.Value;
|
|
||||||
pub extern fn NativityLLVMBuilderCreateBranch(builder: *LLVM.Builder, basic_block: *LLVM.Value.BasicBlock) *LLVM.Value.Instruction.Branch;
|
pub extern fn NativityLLVMBuilderCreateBranch(builder: *LLVM.Builder, basic_block: *LLVM.Value.BasicBlock) *LLVM.Value.Instruction.Branch;
|
||||||
pub extern fn NativityLLVMBuilderCreateConditionalBranch(builder: *LLVM.Builder, condition: *LLVM.Value, true_block: *LLVM.Value.BasicBlock, false_block: *LLVM.Value.BasicBlock, branch_weights: ?*LLVM.Metadata.Node, unpredictable: ?*LLVM.Metadata.Node) *LLVM.Value.Instruction.Branch;
|
pub extern fn NativityLLVMBuilderCreateConditionalBranch(builder: *LLVM.Builder, condition: *LLVM.Value, true_block: *LLVM.Value.BasicBlock, false_block: *LLVM.Value.BasicBlock, branch_weights: ?*LLVM.Metadata.Node, unpredictable: ?*LLVM.Metadata.Node) *LLVM.Value.Instruction.Branch;
|
||||||
pub extern fn NativityLLVMBuilderCreateSwitch(builder: *LLVM.Builder, condition: *LLVM.Value, default_block: ?*LLVM.Value.BasicBlock, case_ptr: [*]const *LLVM.Value.Constant.Int, case_block_ptr: [*]const *LLVM.Value.BasicBlock, case_count: c_uint, branch_weights: ?*LLVM.Metadata.Node, unpredictable: ?*LLVM.Metadata.Node) *LLVM.Value.Instruction.Switch;
|
pub extern fn NativityLLVMBuilderCreateSwitch(builder: *LLVM.Builder, condition: *LLVM.Value, default_block: ?*LLVM.Value.BasicBlock, case_ptr: [*]const *LLVM.Value.Constant.Int, case_block_ptr: [*]const *LLVM.Value.BasicBlock, case_count: c_uint, branch_weights: ?*LLVM.Metadata.Node, unpredictable: ?*LLVM.Metadata.Node) *LLVM.Value.Instruction.Switch;
|
||||||
|
@ -226,7 +226,7 @@ const Parser = struct{
|
|||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
parser.expect_character(src, '(');
|
parser.expect_character(src, '(');
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
const size_type = parser.parse_type_expression(thread, src);
|
const size_type = parser.parse_type_expression(thread, file);
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
parser.expect_character(src, ')');
|
parser.expect_character(src, ')');
|
||||||
const constant_int = thread.constant_ints.append(.{
|
const constant_int = thread.constant_ints.append(.{
|
||||||
@ -408,8 +408,10 @@ const Parser = struct{
|
|||||||
return integer;
|
return integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type_expression(parser: *Parser, thread: *Thread, src: []const u8) *Type {
|
fn parse_type_expression(parser: *Parser, thread: *Thread, file: *File) *Type {
|
||||||
|
const src = file.source_code;
|
||||||
const starting_ch = src[parser.i];
|
const starting_ch = src[parser.i];
|
||||||
|
const is_array_start = starting_ch == '[';
|
||||||
const is_start_u = starting_ch == 'u';
|
const is_start_u = starting_ch == 'u';
|
||||||
const is_start_s = starting_ch == 's';
|
const is_start_s = starting_ch == 's';
|
||||||
const float_start = starting_ch == 'f';
|
const float_start = starting_ch == 'f';
|
||||||
@ -460,6 +462,28 @@ const Parser = struct{
|
|||||||
} else {
|
} else {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
} else if (is_array_start) {
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
const element_count = parser.parse_constant_expression(thread, file, null);
|
||||||
|
switch (element_count.sema.id) {
|
||||||
|
.constant_int => {
|
||||||
|
const constant_int = element_count.get_payload(.constant_int);
|
||||||
|
parser.skip_space(src);
|
||||||
|
parser.expect_character(src, ']');
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
const element_type = parser.parse_type_expression(thread, file);
|
||||||
|
const array_type = get_array_type(thread, .{
|
||||||
|
.element_type = element_type,
|
||||||
|
.element_count = constant_int.n,
|
||||||
|
});
|
||||||
|
return array_type;
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
exit_with_error("Unrecognized type expression");
|
exit_with_error("Unrecognized type expression");
|
||||||
}
|
}
|
||||||
@ -597,9 +621,64 @@ const Parser = struct{
|
|||||||
const value = parser.parse_intrinsic(analyzer, thread, file, maybe_type) orelse unreachable;
|
const value = parser.parse_intrinsic(analyzer, thread, file, maybe_type) orelse unreachable;
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
'[' => {
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
const ty = maybe_type orelse exit(1);
|
||||||
|
const array_type = ty.get_payload(.array);
|
||||||
|
const element_count = array_type.descriptor.element_count;
|
||||||
|
const element_type = array_type.descriptor.element_type;
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
var values = PinnedArray(*Value){};
|
||||||
|
|
||||||
|
var is_constant = true;
|
||||||
|
while (true) {
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
if (src[parser.i] == ']') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = parser.parse_expression(analyzer, thread, file, element_type, .right);
|
||||||
|
is_constant = is_constant and value.is_constant();
|
||||||
|
_ = values.append(value);
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
switch (src[parser.i]) {
|
||||||
|
']' => {},
|
||||||
|
',' => parser.i += 1,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
if (values.length != element_count) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_constant) {
|
||||||
|
const constant_array = thread.constant_arrays.append(.{
|
||||||
|
.value = .{
|
||||||
|
.sema = .{
|
||||||
|
.thread = thread.get_index(),
|
||||||
|
.resolved = true,
|
||||||
|
.id = .constant_array,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.values = values.const_slice(),
|
||||||
|
.type = ty,
|
||||||
|
});
|
||||||
|
return &constant_array.value;
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
_ = side; // autofix
|
|
||||||
const starting_index = parser.i;
|
const starting_index = parser.i;
|
||||||
const starting_ch = src[starting_index];
|
const starting_ch = src[starting_index];
|
||||||
const is_digit_start = is_decimal_digit(starting_ch);
|
const is_digit_start = is_decimal_digit(starting_ch);
|
||||||
@ -607,7 +686,7 @@ const Parser = struct{
|
|||||||
|
|
||||||
if (is_digit_start) {
|
if (is_digit_start) {
|
||||||
assert(unary == .none);
|
assert(unary == .none);
|
||||||
const ty = maybe_type orelse exit(1);
|
const ty = maybe_type orelse &thread.integers[63].type;
|
||||||
switch (ty.sema.id) {
|
switch (ty.sema.id) {
|
||||||
.integer => {
|
.integer => {
|
||||||
const constant_int = parser.parse_constant_integer(thread, file, ty);
|
const constant_int = parser.parse_constant_integer(thread, file, ty);
|
||||||
@ -751,6 +830,81 @@ const Parser = struct{
|
|||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'[' => {
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
const declaration_type = switch (lookup_result.declaration.*.id) {
|
||||||
|
.local => block: {
|
||||||
|
const local_declaration = lookup_result.declaration.*.get_payload(.local);
|
||||||
|
const local_symbol = local_declaration.to_symbol();
|
||||||
|
break :block local_symbol.type;
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
const declaration_value = switch (lookup_result.declaration.*.id) {
|
||||||
|
.local => block: {
|
||||||
|
const local_declaration = lookup_result.declaration.*.get_payload(.local);
|
||||||
|
const local_symbol = local_declaration.to_symbol();
|
||||||
|
break :block &local_symbol.instruction.value;
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
const declaration_element_type = switch (declaration_type.sema.id) {
|
||||||
|
.array => block: {
|
||||||
|
const array_type = declaration_type.get_payload(.array);
|
||||||
|
break :block array_type.descriptor.element_type;
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
|
||||||
|
const index = parser.parse_expression(analyzer, thread, file, null, .right);
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
parser.expect_character(src, ']');
|
||||||
|
const gep = thread.geps.append(.{
|
||||||
|
.instruction = .{
|
||||||
|
.value = .{
|
||||||
|
.sema = .{
|
||||||
|
.thread = thread.get_index(),
|
||||||
|
.resolved = true,
|
||||||
|
.id = .instruction,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.id = .get_element_pointer,
|
||||||
|
},
|
||||||
|
.pointer = declaration_value,
|
||||||
|
.index = index,
|
||||||
|
.type = declaration_element_type,
|
||||||
|
.is_struct = false,
|
||||||
|
});
|
||||||
|
_ = analyzer.current_basic_block.instructions.append(&gep.instruction);
|
||||||
|
return switch (side) {
|
||||||
|
.left => &gep.instruction.value,
|
||||||
|
.right => block: {
|
||||||
|
const load = thread.loads.append(.{
|
||||||
|
.instruction = .{
|
||||||
|
.value = .{
|
||||||
|
.sema = .{
|
||||||
|
.thread = thread.get_index(),
|
||||||
|
.resolved = true,
|
||||||
|
.id = .instruction,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.id = .load,
|
||||||
|
},
|
||||||
|
.value = &gep.instruction.value,
|
||||||
|
.type = declaration_element_type,
|
||||||
|
.alignment = declaration_type.alignment,
|
||||||
|
.is_volatile = false,
|
||||||
|
});
|
||||||
|
_ = analyzer.current_basic_block.instructions.append(&load.instruction);
|
||||||
|
break :block &load.instruction.value;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
' ', ',', ';', ')' => {
|
' ', ',', ';', ')' => {
|
||||||
const declaration_value = switch (lookup_result.declaration.*.id) {
|
const declaration_value = switch (lookup_result.declaration.*.id) {
|
||||||
.local => block: {
|
.local => block: {
|
||||||
@ -943,7 +1097,7 @@ const Parser = struct{
|
|||||||
const is_alpha_start = is_alphabetic(starting_ch);
|
const is_alpha_start = is_alphabetic(starting_ch);
|
||||||
_ = is_alpha_start; // autofix
|
_ = is_alpha_start; // autofix
|
||||||
if (is_digit_start) {
|
if (is_digit_start) {
|
||||||
const ty = maybe_type orelse exit(1);
|
const ty = maybe_type orelse &thread.integers[63].type;
|
||||||
switch (ty.sema.id) {
|
switch (ty.sema.id) {
|
||||||
.integer => {
|
.integer => {
|
||||||
const constant_int = parser.parse_constant_integer(thread, file, ty);
|
const constant_int = parser.parse_constant_integer(thread, file, ty);
|
||||||
@ -1088,7 +1242,7 @@ const Parser = struct{
|
|||||||
const original_index = parser.i;
|
const original_index = parser.i;
|
||||||
const original = src[original_index];
|
const original = src[original_index];
|
||||||
switch (original) {
|
switch (original) {
|
||||||
')', ';', ',' => return previous_value,
|
')', ';', ',', ']' => return previous_value,
|
||||||
'o' => {
|
'o' => {
|
||||||
const identifier = parser.parse_raw_identifier(src);
|
const identifier = parser.parse_raw_identifier(src);
|
||||||
if (byte_equal(identifier, "orelse")) {
|
if (byte_equal(identifier, "orelse")) {
|
||||||
@ -1501,6 +1655,7 @@ const Value = struct {
|
|||||||
const Id = enum(u8){
|
const Id = enum(u8){
|
||||||
argument,
|
argument,
|
||||||
basic_block,
|
basic_block,
|
||||||
|
constant_array,
|
||||||
constant_int,
|
constant_int,
|
||||||
instruction,
|
instruction,
|
||||||
global_symbol,
|
global_symbol,
|
||||||
@ -1510,12 +1665,20 @@ const Value = struct {
|
|||||||
const id_to_value_map = std.EnumArray(Id, type).init(.{
|
const id_to_value_map = std.EnumArray(Id, type).init(.{
|
||||||
.argument = ArgumentSymbol,
|
.argument = ArgumentSymbol,
|
||||||
.basic_block = BasicBlock,
|
.basic_block = BasicBlock,
|
||||||
|
.constant_array = ConstantArray,
|
||||||
.constant_int = ConstantInt,
|
.constant_int = ConstantInt,
|
||||||
.global_symbol = GlobalSymbol,
|
.global_symbol = GlobalSymbol,
|
||||||
.instruction = Instruction,
|
.instruction = Instruction,
|
||||||
.lazy_expression = LazyExpression,
|
.lazy_expression = LazyExpression,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fn is_constant(value: *Value) bool {
|
||||||
|
return switch (value.sema.id) {
|
||||||
|
.constant_int => true,
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn get_payload(value: *Value, comptime id: Id) *id_to_value_map.get(id) {
|
fn get_payload(value: *Value, comptime id: Id) *id_to_value_map.get(id) {
|
||||||
assert(value.sema.id == id);
|
assert(value.sema.id == id);
|
||||||
return @fieldParentPtr("value", value);
|
return @fieldParentPtr("value", value);
|
||||||
@ -1589,6 +1752,7 @@ const Type = struct {
|
|||||||
unresolved,
|
unresolved,
|
||||||
void,
|
void,
|
||||||
integer,
|
integer,
|
||||||
|
array,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Integer = struct {
|
const Integer = struct {
|
||||||
@ -1602,10 +1766,21 @@ const Type = struct {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Array = struct {
|
||||||
|
type: Type,
|
||||||
|
descriptor: Descriptor,
|
||||||
|
|
||||||
|
const Descriptor = struct{
|
||||||
|
element_count: u64,
|
||||||
|
element_type: *Type,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const id_to_type_map = std.EnumArray(Id, type).init(.{
|
const id_to_type_map = std.EnumArray(Id, type).init(.{
|
||||||
.unresolved = void,
|
.unresolved = void,
|
||||||
.void = void,
|
.void = void,
|
||||||
.integer = Integer,
|
.integer = Integer,
|
||||||
|
.array = Array,
|
||||||
});
|
});
|
||||||
|
|
||||||
fn get_payload(ty: *Type, comptime id: Id) *id_to_type_map.get(id) {
|
fn get_payload(ty: *Type, comptime id: Id) *id_to_type_map.get(id) {
|
||||||
@ -1836,6 +2011,12 @@ const ConstantInt = struct{
|
|||||||
type: *Type,
|
type: *Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ConstantArray = struct{
|
||||||
|
value: Value,
|
||||||
|
values: []const *Value,
|
||||||
|
type: *Type,
|
||||||
|
};
|
||||||
|
|
||||||
const Instruction = struct{
|
const Instruction = struct{
|
||||||
value: Value,
|
value: Value,
|
||||||
id: Id,
|
id: Id,
|
||||||
@ -1844,6 +2025,7 @@ const Instruction = struct{
|
|||||||
argument_storage,
|
argument_storage,
|
||||||
branch,
|
branch,
|
||||||
call,
|
call,
|
||||||
|
get_element_pointer,
|
||||||
integer_binary_operation,
|
integer_binary_operation,
|
||||||
integer_compare,
|
integer_compare,
|
||||||
jump,
|
jump,
|
||||||
@ -1862,6 +2044,7 @@ const Instruction = struct{
|
|||||||
.argument_storage = ArgumentSymbol,
|
.argument_storage = ArgumentSymbol,
|
||||||
.branch = Branch,
|
.branch = Branch,
|
||||||
.call = Call,
|
.call = Call,
|
||||||
|
.get_element_pointer = GEP,
|
||||||
.integer_binary_operation = IntegerBinaryOperation,
|
.integer_binary_operation = IntegerBinaryOperation,
|
||||||
.integer_compare = IntegerCompare,
|
.integer_compare = IntegerCompare,
|
||||||
.jump = Jump,
|
.jump = Jump,
|
||||||
@ -1882,6 +2065,14 @@ const Instruction = struct{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const GEP = struct {
|
||||||
|
instruction: Instruction,
|
||||||
|
pointer: *Value,
|
||||||
|
index: *Value,
|
||||||
|
type: *Type,
|
||||||
|
is_struct: bool,
|
||||||
|
};
|
||||||
|
|
||||||
const IntegerBinaryOperation = struct {
|
const IntegerBinaryOperation = struct {
|
||||||
instruction: Instruction,
|
instruction: Instruction,
|
||||||
left: *Value,
|
left: *Value,
|
||||||
@ -2015,6 +2206,7 @@ const Thread = struct{
|
|||||||
external_functions: PinnedArray(Function.Declaration) = .{},
|
external_functions: PinnedArray(Function.Declaration) = .{},
|
||||||
identifiers: PinnedHashMap(u32, []const u8) = .{},
|
identifiers: PinnedHashMap(u32, []const u8) = .{},
|
||||||
constant_ints: PinnedArray(ConstantInt) = .{},
|
constant_ints: PinnedArray(ConstantInt) = .{},
|
||||||
|
constant_arrays: PinnedArray(ConstantArray) = .{},
|
||||||
basic_blocks: PinnedArray(BasicBlock) = .{},
|
basic_blocks: PinnedArray(BasicBlock) = .{},
|
||||||
task_system: TaskSystem = .{},
|
task_system: TaskSystem = .{},
|
||||||
debug_info_file_map: PinnedHashMap(u32, LLVMFile) = .{},
|
debug_info_file_map: PinnedHashMap(u32, LLVMFile) = .{},
|
||||||
@ -2028,6 +2220,7 @@ const Thread = struct{
|
|||||||
stores: PinnedArray(Store) = .{},
|
stores: PinnedArray(Store) = .{},
|
||||||
phis: PinnedArray(Phi) = .{},
|
phis: PinnedArray(Phi) = .{},
|
||||||
returns: PinnedArray(Return) = .{},
|
returns: PinnedArray(Return) = .{},
|
||||||
|
geps: PinnedArray(GEP) = .{},
|
||||||
lazy_expressions: PinnedArray(LazyExpression) = .{},
|
lazy_expressions: PinnedArray(LazyExpression) = .{},
|
||||||
imports: PinnedArray(Import) = .{},
|
imports: PinnedArray(Import) = .{},
|
||||||
local_blocks: PinnedArray(LocalBlock) = .{},
|
local_blocks: PinnedArray(LocalBlock) = .{},
|
||||||
@ -2037,6 +2230,8 @@ const Thread = struct{
|
|||||||
unreachables: PinnedArray(Unreachable) = .{},
|
unreachables: PinnedArray(Unreachable) = .{},
|
||||||
leading_zeroes: PinnedArray(LeadingZeroes) = .{},
|
leading_zeroes: PinnedArray(LeadingZeroes) = .{},
|
||||||
trailing_zeroes: PinnedArray(TrailingZeroes) = .{},
|
trailing_zeroes: PinnedArray(TrailingZeroes) = .{},
|
||||||
|
array_type_map: PinnedHashMap(Type.Array.Descriptor, *Type) = .{},
|
||||||
|
array_types: PinnedArray(Type.Array) = .{},
|
||||||
analyzed_file_count: u32 = 0,
|
analyzed_file_count: u32 = 0,
|
||||||
assigned_file_count: u32 = 0,
|
assigned_file_count: u32 = 0,
|
||||||
llvm: struct {
|
llvm: struct {
|
||||||
@ -3438,6 +3633,18 @@ fn worker_thread(thread_index: u32, cpu_count: *u32) void {
|
|||||||
const call_i = builder.createCall(intrinsic_function_type, intrinsic_function.toValue(), args.ptr, args.len, "", "".len, null);
|
const call_i = builder.createCall(intrinsic_function_type, intrinsic_function.toValue(), args.ptr, args.len, "", "".len, null);
|
||||||
break :block call_i.toValue();
|
break :block call_i.toValue();
|
||||||
},
|
},
|
||||||
|
.get_element_pointer => block: {
|
||||||
|
const gep = instruction.get_payload(.get_element_pointer);
|
||||||
|
const base_type = llvm_get_type(thread, gep.type);
|
||||||
|
const pointer = llvm_get_value(thread, gep.pointer);
|
||||||
|
const in_bounds = true;
|
||||||
|
const index = llvm_get_value(thread, gep.index);
|
||||||
|
const struct_index = context.getConstantInt(@bitSizeOf(u32), 0, false);
|
||||||
|
const index_buffer = [2]*LLVM.Value{ struct_index.toValue(), index };
|
||||||
|
const indices = index_buffer[@intFromBool(!gep.is_struct)..];
|
||||||
|
const get_element_pointer = builder.createGEP(base_type, pointer, indices.ptr, indices.len, "".ptr, "".len, in_bounds);
|
||||||
|
break :block get_element_pointer;
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3582,6 +3789,17 @@ fn llvm_get_value(thread: *Thread, value: *Value) *LLVM.Value {
|
|||||||
const result = thread.llvm.context.getConstantInt(integer_type.bit_count, constant_int.n, @intFromEnum(integer_type.signedness) != 0);
|
const result = thread.llvm.context.getConstantInt(integer_type.bit_count, constant_int.n, @intFromEnum(integer_type.signedness) != 0);
|
||||||
break :b result.toValue();
|
break :b result.toValue();
|
||||||
},
|
},
|
||||||
|
.constant_array => b: {
|
||||||
|
const constant_array = value.get_payload(.constant_array);
|
||||||
|
const array_type = llvm_get_type(thread, constant_array.type);
|
||||||
|
var values = PinnedArray(*LLVM.Value.Constant){};
|
||||||
|
for (constant_array.values) |v| {
|
||||||
|
const val = llvm_get_value(thread, v);
|
||||||
|
_ = values.append(val.toConstant() orelse unreachable);
|
||||||
|
}
|
||||||
|
const result = array_type.toArray().?.getConstant(values.pointer, values.length);
|
||||||
|
break :b result.toValue();
|
||||||
|
},
|
||||||
.instruction => {
|
.instruction => {
|
||||||
const instruction = value.get_payload(.instruction);
|
const instruction = value.get_payload(.instruction);
|
||||||
switch (instruction.id) {
|
switch (instruction.id) {
|
||||||
@ -3609,6 +3827,12 @@ fn llvm_get_type(thread: *Thread, ty: *Type) *LLVM.Type {
|
|||||||
const integer_type = thread.llvm.context.getIntegerType(int_ty.bit_count);
|
const integer_type = thread.llvm.context.getIntegerType(int_ty.bit_count);
|
||||||
break :b integer_type.toType();
|
break :b integer_type.toType();
|
||||||
},
|
},
|
||||||
|
.array => b: {
|
||||||
|
const array_ty = ty.get_payload(.array);
|
||||||
|
const element_type = llvm_get_type(thread, array_ty.descriptor.element_type);
|
||||||
|
const array_type = LLVM.Type.Array.get(element_type, array_ty.descriptor.element_count);
|
||||||
|
break :b array_type.toType();
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
return llvm_type;
|
return llvm_type;
|
||||||
@ -3835,7 +4059,7 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
const local_type = parser.parse_type_expression(thread, src);
|
const local_type = parser.parse_type_expression(thread, file);
|
||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
parser.expect_character(src, '=');
|
parser.expect_character(src, '=');
|
||||||
@ -4293,7 +4517,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
|||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
const global_type = parser.parse_type_expression(thread, src);
|
const global_type = parser.parse_type_expression(thread, file);
|
||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
@ -4528,7 +4752,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
|||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
const argument_type = parser.parse_type_expression(thread, src);
|
const argument_type = parser.parse_type_expression(thread, file);
|
||||||
_ = arguments.append(.{
|
_ = arguments.append(.{
|
||||||
.type = argument_type,
|
.type = argument_type,
|
||||||
.name = argument_name,
|
.name = argument_name,
|
||||||
@ -4550,7 +4774,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
|||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
function.declaration.return_type = parser.parse_type_expression(thread, src);
|
function.declaration.return_type = parser.parse_type_expression(thread, file);
|
||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
@ -4877,6 +5101,27 @@ fn emit_condition(analyzer: *Analyzer, thread: *Thread, condition: *Value) *Valu
|
|||||||
return compare;
|
return compare;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_array_type(thread: *Thread, descriptor: Type.Array.Descriptor) *Type {
|
||||||
|
assert(descriptor.element_type.sema.resolved);
|
||||||
|
if (thread.array_type_map.get(descriptor)) |result| return result else {
|
||||||
|
const array_type = thread.array_types.append(.{
|
||||||
|
.type = .{
|
||||||
|
.sema = .{
|
||||||
|
.thread = thread.get_index(),
|
||||||
|
.id = .array,
|
||||||
|
.resolved = true,
|
||||||
|
},
|
||||||
|
.size = descriptor.element_type.size * descriptor.element_count,
|
||||||
|
.alignment = descriptor.element_type.alignment,
|
||||||
|
},
|
||||||
|
.descriptor = descriptor,
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.array_type_map.put_no_clobber(descriptor, &array_type.type);
|
||||||
|
return &array_type.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const LLVM = struct {
|
pub const LLVM = struct {
|
||||||
const bindings = @import("backend/llvm_bindings.zig");
|
const bindings = @import("backend/llvm_bindings.zig");
|
||||||
pub const x86_64 = struct {
|
pub const x86_64 = struct {
|
||||||
@ -4974,7 +5219,6 @@ pub const LLVM = struct {
|
|||||||
const createConditionalBranch = bindings.NativityLLVMBuilderCreateConditionalBranch;
|
const createConditionalBranch = bindings.NativityLLVMBuilderCreateConditionalBranch;
|
||||||
const createSwitch = bindings.NativityLLVMBuilderCreateSwitch;
|
const createSwitch = bindings.NativityLLVMBuilderCreateSwitch;
|
||||||
const createGEP = bindings.NativityLLVMBuilderCreateGEP;
|
const createGEP = bindings.NativityLLVMBuilderCreateGEP;
|
||||||
const createStructGEP = bindings.NativityLLVMBuilderCreateStructGEP;
|
|
||||||
const createICmp = bindings.NativityLLVMBuilderCreateICmp;
|
const createICmp = bindings.NativityLLVMBuilderCreateICmp;
|
||||||
const createIsNotNull = bindings.NativityLLVMBuilderCreateIsNotNull;
|
const createIsNotNull = bindings.NativityLLVMBuilderCreateIsNotNull;
|
||||||
const createLoad = bindings.NativityLLVMBuilderCreateLoad;
|
const createLoad = bindings.NativityLLVMBuilderCreateLoad;
|
||||||
@ -6069,7 +6313,3 @@ pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, return_
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
retest/standalone/arrays/main.nat
Normal file
4
retest/standalone/arrays/main.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn[cc(.c)] main[export]() s32 {
|
||||||
|
>array: [1]s32 = [0];
|
||||||
|
return array[0];
|
||||||
|
}
|
@ -603,13 +603,6 @@ extern "C" Value* NativityLLVMBuilderCreateGEP(IRBuilder<>& builder, Type* type,
|
|||||||
return GEP;
|
return GEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" Value* NativityLLVMBuilderCreateStructGEP(IRBuilder<>& builder, Type* type, Value* pointer, unsigned index, const char* name_ptr, size_t name_len)
|
|
||||||
{
|
|
||||||
auto name = StringRef(name_ptr, name_len);
|
|
||||||
auto* gep = builder.CreateStructGEP(type, pointer, index, name);
|
|
||||||
return gep;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" BranchInst* NativityLLVMBuilderCreateBranch(IRBuilder<>& builder, BasicBlock* basic_block)
|
extern "C" BranchInst* NativityLLVMBuilderCreateBranch(IRBuilder<>& builder, BasicBlock* basic_block)
|
||||||
{
|
{
|
||||||
auto* conditional_branch = builder.CreateBr(basic_block);
|
auto* conditional_branch = builder.CreateBr(basic_block);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user