Merge pull request #221 from birth-software/array

Implement arrays
This commit is contained in:
David 2024-06-07 00:14:32 -06:00 committed by GitHub
commit 088c8d8d5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 260 additions and 24 deletions

View File

@ -1,3 +1,4 @@
pointers
function pointers function pointers
for loops for loops
arrays arrays

View File

@ -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;

View File

@ -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;

View File

@ -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_
}, },
} }
} }

View File

@ -0,0 +1,4 @@
fn[cc(.c)] main[export]() s32 {
>array: [1]s32 = [0];
return array[0];
}

View File

@ -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);