Basic array
This commit is contained in:
parent
eaa64a8d78
commit
e290f61890
32
src/LLVM.zig
32
src/LLVM.zig
@ -490,10 +490,13 @@ const targets = [@typeInfo(Architecture).@"enum".fields.len]type{
|
|||||||
|
|
||||||
pub const Context = opaque {
|
pub const Context = opaque {
|
||||||
pub const create = api.LLVMContextCreate;
|
pub const create = api.LLVMContextCreate;
|
||||||
|
|
||||||
pub fn create_module(context: *Context, name: []const u8) *Module {
|
pub fn create_module(context: *Context, name: []const u8) *Module {
|
||||||
return api.llvm_context_create_module(context, String.from_slice(name));
|
return api.llvm_context_create_module(context, String.from_slice(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const create_builder = api.LLVMCreateBuilderInContext;
|
pub const create_builder = api.LLVMCreateBuilderInContext;
|
||||||
|
|
||||||
pub fn create_basic_block(context: *Context, name: []const u8, parent: *Function) *BasicBlock {
|
pub fn create_basic_block(context: *Context, name: []const u8, parent: *Function) *BasicBlock {
|
||||||
return api.llvm_context_create_basic_block(context, String.from_slice(name), parent);
|
return api.llvm_context_create_basic_block(context, String.from_slice(name), parent);
|
||||||
}
|
}
|
||||||
@ -501,6 +504,7 @@ pub const Context = opaque {
|
|||||||
pub fn create_forward_declared_struct_type(context: *Context, name: []const u8) *Type.Struct {
|
pub fn create_forward_declared_struct_type(context: *Context, name: []const u8) *Type.Struct {
|
||||||
return api.llvm_context_create_forward_declared_struct_type(context, String.from_slice(name));
|
return api.llvm_context_create_forward_declared_struct_type(context, String.from_slice(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_struct_type(context: *Context, element_types: []const *Type, name: []const u8) *Type.Struct {
|
pub fn create_struct_type(context: *Context, element_types: []const *Type, name: []const u8) *Type.Struct {
|
||||||
const is_packed = false;
|
const is_packed = false;
|
||||||
return api.llvm_context_create_struct_type(context, element_types.ptr, @intCast(element_types.len), String.from_slice(name), is_packed);
|
return api.llvm_context_create_struct_type(context, element_types.ptr, @intCast(element_types.len), String.from_slice(name), is_packed);
|
||||||
@ -658,6 +662,10 @@ pub const Builder = opaque {
|
|||||||
return api.LLVMBuildStructGEP2(builder, struct_type, pointer, index, "");
|
return api.LLVMBuildStructGEP2(builder, struct_type, pointer, index, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_gep(builder: *Builder, ty: *Type, aggregate: *Value, indices: []const *Value) *Value {
|
||||||
|
return api.LLVMBuildInBoundsGEP2(builder, ty, aggregate, indices.ptr, @intCast(indices.len), "");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_insert_value(builder: *Builder, aggregate: *Value, element: *Value, index: c_uint) *Value {
|
pub fn create_insert_value(builder: *Builder, aggregate: *Value, element: *Value, index: c_uint) *Value {
|
||||||
return api.LLVMBuildInsertValue(builder, aggregate, element, index, "");
|
return api.LLVMBuildInsertValue(builder, aggregate, element, index, "");
|
||||||
}
|
}
|
||||||
@ -725,6 +733,12 @@ pub const Constant = opaque {
|
|||||||
return @ptrCast(constant);
|
return @ptrCast(constant);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Array = opaque {
|
||||||
|
pub fn to_value(constant: *Constant.Array) *Value {
|
||||||
|
return @ptrCast(constant);
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Argument = opaque {
|
pub const Argument = opaque {
|
||||||
@ -867,6 +881,10 @@ pub const DI = struct {
|
|||||||
return api.LLVMDIBuilderCreateReplaceableCompositeType(builder, tag, name.ptr, name.len, scope, file, line, 0, 0, 0, .{}, null, 0);
|
return api.LLVMDIBuilderCreateReplaceableCompositeType(builder, tag, name.ptr, name.len, scope, file, line, 0, 0, 0, .{}, null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_array_type(builder: *DI.Builder, element_count: u64, align_in_bits: u32, element_type: *DI.Type, subscripts: []const *DI.Metadata) *DI.Type.Composite {
|
||||||
|
return api.LLVMDIBuilderCreateArrayType(builder, element_count, align_in_bits, element_type, subscripts.ptr, @intCast(subscripts.len));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_struct_type(builder: *DI.Builder, scope: *DI.Scope, name: []const u8, file: *DI.File, line: c_uint, bit_size: u64, align_in_bits: u32, flags: DI.Flags, members: []const *DI.Type.Derived) *DI.Type.Composite {
|
pub fn create_struct_type(builder: *DI.Builder, scope: *DI.Scope, name: []const u8, file: *DI.File, line: c_uint, bit_size: u64, align_in_bits: u32, flags: DI.Flags, members: []const *DI.Type.Derived) *DI.Type.Composite {
|
||||||
const derived_from: ?*DI.Type = null;
|
const derived_from: ?*DI.Type = null;
|
||||||
const runtime_language: c_uint = 0;
|
const runtime_language: c_uint = 0;
|
||||||
@ -1040,6 +1058,20 @@ pub const Type = opaque {
|
|||||||
api.LLVMStructSetBody(struct_type, element_types.ptr, @intCast(element_types.len), @intFromBool(is_packed));
|
api.LLVMStructSetBody(struct_type, element_types.ptr, @intCast(element_types.len), @intFromBool(is_packed));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Array = opaque {
|
||||||
|
pub fn to_type(array_type: *Type.Array) *Type {
|
||||||
|
return @ptrCast(array_type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn get_array_type(element_type: *Type, element_count: u64) *Type.Array {
|
||||||
|
return api.LLVMArrayType2(element_type, element_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_constant_array(element_type: *Type, values: []const *Constant) *Constant.Array {
|
||||||
|
return api.LLVMConstArray2(element_type, values.ptr, values.len);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Dwarf = struct {
|
pub const Dwarf = struct {
|
||||||
|
@ -88,6 +88,10 @@ const Module = struct {
|
|||||||
file: *llvm.DI.File,
|
file: *llvm.DI.File,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn get_infer_or_ignore_value(module: *Module) *Value {
|
||||||
|
return &module.values.buffer[0];
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_type(module: *Module, index: usize) *Type {
|
pub fn get_type(module: *Module, index: usize) *Type {
|
||||||
assert(index < module.types.count);
|
assert(index < module.types.count);
|
||||||
const result = &module.types.buffer[index];
|
const result = &module.types.buffer[index];
|
||||||
@ -226,6 +230,13 @@ const Module = struct {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const infer_or_ignore_value = module.values.add();
|
||||||
|
infer_or_ignore_value.* = .{
|
||||||
|
.llvm = undefined,
|
||||||
|
.bb = .infer_or_ignore,
|
||||||
|
.type = undefined,
|
||||||
|
};
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -245,9 +256,11 @@ pub const Value = struct {
|
|||||||
global,
|
global,
|
||||||
argument,
|
argument,
|
||||||
instruction,
|
instruction,
|
||||||
constant_integer,
|
|
||||||
struct_initialization,
|
struct_initialization,
|
||||||
bits_initialization,
|
bits_initialization,
|
||||||
|
infer_or_ignore,
|
||||||
|
constant_integer,
|
||||||
|
constant_array,
|
||||||
},
|
},
|
||||||
type: *Type,
|
type: *Type,
|
||||||
llvm: *llvm.Value,
|
llvm: *llvm.Value,
|
||||||
@ -262,6 +275,13 @@ pub const Value = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn is_constant(value: *Value) bool {
|
||||||
|
return switch (value.bb) {
|
||||||
|
.constant_integer => true,
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Field = struct {
|
const Field = struct {
|
||||||
@ -290,6 +310,11 @@ const Bits = struct {
|
|||||||
backing_type: *Type,
|
backing_type: *Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ArrayType = struct {
|
||||||
|
element_count: ?usize,
|
||||||
|
element_type: *Type,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Type = struct {
|
pub const Type = struct {
|
||||||
bb: BB,
|
bb: BB,
|
||||||
llvm: LLVM,
|
llvm: LLVM,
|
||||||
@ -305,6 +330,7 @@ pub const Type = struct {
|
|||||||
@"struct": StructType,
|
@"struct": StructType,
|
||||||
bits: Bits,
|
bits: Bits,
|
||||||
function: FunctionType,
|
function: FunctionType,
|
||||||
|
array: ArrayType,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn get_bit_size(ty: *const Type) u64 {
|
pub fn get_bit_size(ty: *const Type) u64 {
|
||||||
@ -313,6 +339,7 @@ pub const Type = struct {
|
|||||||
.@"struct" => |struct_type| struct_type.bit_size,
|
.@"struct" => |struct_type| struct_type.bit_size,
|
||||||
.bits => |bits| bits.backing_type.get_bit_size(),
|
.bits => |bits| bits.backing_type.get_bit_size(),
|
||||||
.void, .forward_declaration, .function => unreachable,
|
.void, .forward_declaration, .function => unreachable,
|
||||||
|
.array => |*array| array.element_type.get_bit_size() * array.element_count.?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,6 +349,7 @@ pub const Type = struct {
|
|||||||
.@"struct" => |struct_type| struct_type.byte_size,
|
.@"struct" => |struct_type| struct_type.byte_size,
|
||||||
.bits => |bits| bits.backing_type.get_byte_size(),
|
.bits => |bits| bits.backing_type.get_byte_size(),
|
||||||
.void, .forward_declaration, .function => unreachable,
|
.void, .forward_declaration, .function => unreachable,
|
||||||
|
.array => |*array| array.element_type.get_byte_size() * array.element_count.?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,6 +359,7 @@ pub const Type = struct {
|
|||||||
.@"struct" => |struct_type| struct_type.bit_alignment,
|
.@"struct" => |struct_type| struct_type.bit_alignment,
|
||||||
.bits => |bits| bits.backing_type.get_bit_alignment(),
|
.bits => |bits| bits.backing_type.get_bit_alignment(),
|
||||||
.void, .forward_declaration, .function => unreachable,
|
.void, .forward_declaration, .function => unreachable,
|
||||||
|
.array => |*array| array.element_type.get_bit_alignment(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,6 +369,7 @@ pub const Type = struct {
|
|||||||
.@"struct" => |struct_type| struct_type.byte_alignment,
|
.@"struct" => |struct_type| struct_type.byte_alignment,
|
||||||
.bits => |bits| bits.backing_type.get_byte_alignment(),
|
.bits => |bits| bits.backing_type.get_byte_alignment(),
|
||||||
.void, .forward_declaration, .function => unreachable,
|
.void, .forward_declaration, .function => unreachable,
|
||||||
|
.array => |*array| array.element_type.get_byte_alignment(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +377,8 @@ pub const Type = struct {
|
|||||||
buffer: [1024]Type = undefined,
|
buffer: [1024]Type = undefined,
|
||||||
count: usize = 0,
|
count: usize = 0,
|
||||||
|
|
||||||
|
const buffer_size = 1024;
|
||||||
|
|
||||||
pub fn get(types: *Array) []Type {
|
pub fn get(types: *Array) []Type {
|
||||||
return types.buffer[0..types.count];
|
return types.buffer[0..types.count];
|
||||||
}
|
}
|
||||||
@ -442,26 +474,58 @@ const Converter = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_type(noalias converter: *Converter, noalias module: *Module) *Type {
|
pub fn parse_type(noalias converter: *Converter, noalias module: *Module) *Type {
|
||||||
const identifier = converter.parse_identifier();
|
switch (converter.content[converter.offset]) {
|
||||||
var integer_type = identifier.len > 1 and identifier[0] == 's' or identifier[0] == 'u';
|
'a'...'z', 'A'...'Z', '_' => {
|
||||||
if (integer_type) {
|
const identifier = converter.parse_identifier();
|
||||||
for (identifier[1..]) |ch| {
|
var integer_type = identifier.len > 1 and identifier[0] == 's' or identifier[0] == 'u';
|
||||||
integer_type = integer_type and is_decimal_ch(ch);
|
if (integer_type) {
|
||||||
}
|
for (identifier[1..]) |ch| {
|
||||||
}
|
integer_type = integer_type and is_decimal_ch(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (integer_type) {
|
if (integer_type) {
|
||||||
const signedness = switch (identifier[0]) {
|
const signedness = switch (identifier[0]) {
|
||||||
's' => true,
|
's' => true,
|
||||||
'u' => false,
|
'u' => false,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
const bit_count: u32 = @intCast(lib.parse.integer_decimal(identifier[1..]));
|
const bit_count: u32 = @intCast(lib.parse.integer_decimal(identifier[1..]));
|
||||||
const ty = module.integer_type(bit_count, signedness);
|
const ty = module.integer_type(bit_count, signedness);
|
||||||
return ty;
|
return ty;
|
||||||
} else {
|
} else {
|
||||||
const ty = module.types.find(identifier) orelse @trap();
|
const ty = module.types.find(identifier) orelse @trap();
|
||||||
return ty;
|
return ty;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
left_bracket => {
|
||||||
|
converter.offset += 1;
|
||||||
|
|
||||||
|
converter.skip_space();
|
||||||
|
|
||||||
|
const length_expression = converter.parse_value(module, null);
|
||||||
|
converter.skip_space();
|
||||||
|
converter.expect_character(right_bracket);
|
||||||
|
|
||||||
|
const element_type = converter.parse_type(module);
|
||||||
|
|
||||||
|
if (length_expression.bb == .infer_or_ignore) {
|
||||||
|
const ty = module.types.add(.{
|
||||||
|
.name = undefined,
|
||||||
|
.llvm = undefined,
|
||||||
|
.bb = .{
|
||||||
|
.array = .{
|
||||||
|
.element_count = null,
|
||||||
|
.element_type = element_type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return ty;
|
||||||
|
} else {
|
||||||
|
@trap();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,6 +717,8 @@ const Converter = struct {
|
|||||||
module.llvm.builder.clear_current_debug_location();
|
module.llvm.builder.clear_current_debug_location();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const value = converter.parse_value(module, local_type);
|
||||||
|
|
||||||
const local_storage = module.values.add();
|
const local_storage = module.values.add();
|
||||||
local_storage.* = .{
|
local_storage.* = .{
|
||||||
.llvm = module.llvm.builder.create_alloca(local_type.llvm.handle, local_name),
|
.llvm = module.llvm.builder.create_alloca(local_type.llvm.handle, local_name),
|
||||||
@ -660,8 +726,6 @@ const Converter = struct {
|
|||||||
.bb = .local,
|
.bb = .local,
|
||||||
};
|
};
|
||||||
|
|
||||||
const value = converter.parse_value(module, local_type);
|
|
||||||
|
|
||||||
if (module.llvm.di_builder) |di_builder| {
|
if (module.llvm.di_builder) |di_builder| {
|
||||||
module.llvm.builder.set_current_debug_location(statement_debug_location);
|
module.llvm.builder.set_current_debug_location(statement_debug_location);
|
||||||
const debug_type = local_type.llvm.debug;
|
const debug_type = local_type.llvm.debug;
|
||||||
@ -827,8 +891,6 @@ const Converter = struct {
|
|||||||
const left = previous_value;
|
const left = previous_value;
|
||||||
const right = current_value;
|
const right = current_value;
|
||||||
const next_ty = if (previous_value) |pv| pv.type else current_value.type;
|
const next_ty = if (previous_value) |pv| pv.type else current_value.type;
|
||||||
// _ = left;
|
|
||||||
// _ = right;
|
|
||||||
|
|
||||||
const llvm_value = switch (value_state) {
|
const llvm_value = switch (value_state) {
|
||||||
.none => current_value.llvm,
|
.none => current_value.llvm,
|
||||||
@ -848,16 +910,21 @@ const Converter = struct {
|
|||||||
.icmp_ne => |icmp| module.llvm.builder.create_compare(icmp.to_int_predicate(), left.?.llvm, right.llvm),
|
.icmp_ne => |icmp| module.llvm.builder.create_compare(icmp.to_int_predicate(), left.?.llvm, right.llvm),
|
||||||
};
|
};
|
||||||
|
|
||||||
previous_value = module.values.add();
|
switch (value_state) {
|
||||||
previous_value.?.* = .{
|
.none => previous_value = current_value,
|
||||||
.llvm = llvm_value,
|
else => {
|
||||||
.type = next_ty,
|
previous_value = module.values.add();
|
||||||
.bb = .instruction,
|
previous_value.?.* = .{
|
||||||
};
|
.llvm = llvm_value,
|
||||||
|
.type = next_ty,
|
||||||
|
.bb = .instruction,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
const ch = converter.content[converter.offset];
|
const ch = converter.content[converter.offset];
|
||||||
value_state = switch (ch) {
|
value_state = switch (ch) {
|
||||||
',', ';', right_parenthesis => break previous_value.?,
|
',', ';', right_parenthesis, right_bracket => break previous_value.?,
|
||||||
'-' => blk: {
|
'-' => blk: {
|
||||||
converter.offset += 1;
|
converter.offset += 1;
|
||||||
break :blk .sub;
|
break :blk .sub;
|
||||||
@ -1016,6 +1083,7 @@ const Converter = struct {
|
|||||||
|
|
||||||
const prefix_offset = converter.offset;
|
const prefix_offset = converter.offset;
|
||||||
const prefix_ch = converter.content[prefix_offset];
|
const prefix_ch = converter.content[prefix_offset];
|
||||||
|
const must_be_constant = module.current_function == null;
|
||||||
const prefix: Prefix = switch (prefix_ch) {
|
const prefix: Prefix = switch (prefix_ch) {
|
||||||
'a'...'z', 'A'...'Z', '_', '0'...'9' => .none,
|
'a'...'z', 'A'...'Z', '_', '0'...'9' => .none,
|
||||||
'-' => blk: {
|
'-' => blk: {
|
||||||
@ -1031,7 +1099,6 @@ const Converter = struct {
|
|||||||
converter.skip_space();
|
converter.skip_space();
|
||||||
|
|
||||||
const ty = expected_type orelse converter.report_error();
|
const ty = expected_type orelse converter.report_error();
|
||||||
const must_be_constant = module.current_function == null;
|
|
||||||
|
|
||||||
switch (ty.bb) {
|
switch (ty.bb) {
|
||||||
.@"struct" => |*struct_type| {
|
.@"struct" => |*struct_type| {
|
||||||
@ -1152,6 +1219,75 @@ const Converter = struct {
|
|||||||
|
|
||||||
@trap();
|
@trap();
|
||||||
},
|
},
|
||||||
|
left_bracket => {
|
||||||
|
converter.offset += 1;
|
||||||
|
|
||||||
|
const ty = expected_type orelse converter.report_error();
|
||||||
|
switch (ty.bb) {
|
||||||
|
.array => |*array| {
|
||||||
|
var element_count: usize = 0;
|
||||||
|
var element_buffer: [64]*llvm.Value = undefined;
|
||||||
|
|
||||||
|
var elements_are_constant = true;
|
||||||
|
|
||||||
|
while (true) : (element_count += 1) {
|
||||||
|
converter.skip_space();
|
||||||
|
|
||||||
|
if (converter.consume_character_if_match(right_bracket)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const element_value = converter.parse_value(module, array.element_type);
|
||||||
|
elements_are_constant = elements_are_constant and element_value.is_constant();
|
||||||
|
element_buffer[element_count] = element_value.llvm;
|
||||||
|
|
||||||
|
converter.skip_space();
|
||||||
|
|
||||||
|
_ = converter.consume_character_if_match(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array.element_count) |ec| {
|
||||||
|
_ = ec;
|
||||||
|
@trap();
|
||||||
|
} else {
|
||||||
|
array.element_count = element_count;
|
||||||
|
ty.llvm = .{
|
||||||
|
.handle = array.element_type.llvm.handle.get_array_type(element_count).to_type(),
|
||||||
|
.debug = if (module.llvm.di_builder) |di_builder| di_builder.create_array_type(element_count, @intCast(array.element_type.get_bit_alignment()), array.element_type.llvm.debug, &.{}).to_type() else undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
var buffer: [256]u8 = undefined;
|
||||||
|
var i: usize = 0;
|
||||||
|
buffer[i] = left_bracket;
|
||||||
|
i += 1;
|
||||||
|
i += lib.string_format.integer_decimal(buffer[i..], element_count);
|
||||||
|
buffer[i] = right_bracket;
|
||||||
|
i += 1;
|
||||||
|
const element_name = array.element_type.name.?;
|
||||||
|
@memcpy(buffer[i..][0..element_name.len], element_name);
|
||||||
|
i += element_name.len;
|
||||||
|
ty.name = lib.global.arena.duplicate_string(buffer[0..i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const array_elements = element_buffer[0..element_count];
|
||||||
|
if (elements_are_constant) {
|
||||||
|
const array_constant = array.element_type.llvm.handle.get_constant_array(@ptrCast(array_elements));
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = .{
|
||||||
|
.llvm = array_constant.to_value(),
|
||||||
|
.type = ty,
|
||||||
|
.bb = .constant_array,
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
@trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@trap();
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
}
|
||||||
|
},
|
||||||
'#' => return converter.parse_intrinsic(module, expected_type),
|
'#' => return converter.parse_intrinsic(module, expected_type),
|
||||||
else => os.abort(),
|
else => os.abort(),
|
||||||
};
|
};
|
||||||
@ -1162,104 +1298,128 @@ const Converter = struct {
|
|||||||
'a'...'z', 'A'...'Z', '_' => b: {
|
'a'...'z', 'A'...'Z', '_' => b: {
|
||||||
if (module.current_function) |current_function| {
|
if (module.current_function) |current_function| {
|
||||||
const identifier = converter.parse_identifier();
|
const identifier = converter.parse_identifier();
|
||||||
const variable = blk: {
|
if (lib.string.equal(identifier, "_")) {
|
||||||
if (current_function.value.bb.function.locals.find(identifier)) |local| {
|
return module.get_infer_or_ignore_value();
|
||||||
break :blk local;
|
} else {
|
||||||
} else if (current_function.value.bb.function.arguments.find(identifier)) |argument| {
|
const variable = blk: {
|
||||||
break :blk argument;
|
if (current_function.value.bb.function.locals.find(identifier)) |local| {
|
||||||
} else if (module.globals.find(identifier)) |global| {
|
break :blk local;
|
||||||
break :blk global;
|
} else if (current_function.value.bb.function.arguments.find(identifier)) |argument| {
|
||||||
} else {
|
break :blk argument;
|
||||||
converter.report_error();
|
} else if (module.globals.find(identifier)) |global| {
|
||||||
}
|
break :blk global;
|
||||||
};
|
} else {
|
||||||
|
converter.report_error();
|
||||||
converter.skip_space();
|
|
||||||
|
|
||||||
if (converter.consume_character_if_match(left_parenthesis)) {
|
|
||||||
var llvm_arguments: [64]*llvm.Value = undefined;
|
|
||||||
var argument_count: usize = 0;
|
|
||||||
while (true) : (argument_count += 1) {
|
|
||||||
converter.skip_space();
|
|
||||||
|
|
||||||
if (converter.consume_character_if_match(right_parenthesis)) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (variable.value.type.bb.function.calling_convention) {
|
|
||||||
.c => {
|
|
||||||
@trap();
|
|
||||||
},
|
|
||||||
.unknown => {
|
|
||||||
const argument_value = converter.parse_value(module, variable.value.type.bb.function.semantic_argument_types[argument_count]);
|
|
||||||
llvm_arguments[argument_count] = argument_value.llvm;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const llvm_argument_values = llvm_arguments[0..argument_count];
|
|
||||||
const llvm_call = module.llvm.builder.create_call(variable.value.type.llvm.handle.to_function(), variable.value.llvm, llvm_argument_values);
|
|
||||||
llvm_call.to_instruction().set_calling_convention(variable.value.llvm.get_calling_convention());
|
|
||||||
const call = module.values.add();
|
|
||||||
call.* = .{
|
|
||||||
.llvm = llvm_call,
|
|
||||||
.type = variable.value.type,
|
|
||||||
.bb = .instruction,
|
|
||||||
};
|
};
|
||||||
break :b call;
|
|
||||||
} else if (converter.consume_character_if_match('.')) {
|
|
||||||
converter.skip_space();
|
converter.skip_space();
|
||||||
|
|
||||||
switch (variable.value.type.bb) {
|
if (converter.consume_character_if_match(left_parenthesis)) {
|
||||||
.@"struct" => |*struct_type| {
|
var llvm_arguments: [64]*llvm.Value = undefined;
|
||||||
const field_name = converter.parse_identifier();
|
var argument_count: usize = 0;
|
||||||
const field_index: u32 = for (struct_type.fields, 0..) |field, field_index| {
|
while (true) : (argument_count += 1) {
|
||||||
if (lib.string.equal(field.name, field_name)) {
|
converter.skip_space();
|
||||||
break @intCast(field_index);
|
|
||||||
}
|
|
||||||
} else converter.report_error();
|
|
||||||
const field = struct_type.fields[field_index];
|
|
||||||
const gep = module.llvm.builder.create_struct_gep(variable.value.type.llvm.handle.to_struct(), variable.value.llvm, field_index);
|
|
||||||
const load = module.values.add();
|
|
||||||
load.* = .{
|
|
||||||
.llvm = module.llvm.builder.create_load(field.type.llvm.handle, gep),
|
|
||||||
.type = field.type,
|
|
||||||
.bb = .instruction,
|
|
||||||
};
|
|
||||||
break :b load;
|
|
||||||
},
|
|
||||||
.bits => |*bits| {
|
|
||||||
const field_name = converter.parse_identifier();
|
|
||||||
const field_index: u32 = for (bits.fields, 0..) |field, field_index| {
|
|
||||||
if (lib.string.equal(field.name, field_name)) {
|
|
||||||
break @intCast(field_index);
|
|
||||||
}
|
|
||||||
} else converter.report_error();
|
|
||||||
const field = bits.fields[field_index];
|
|
||||||
|
|
||||||
const bitfield_load = module.llvm.builder.create_load(bits.backing_type.llvm.handle, variable.value.llvm);
|
if (converter.consume_character_if_match(right_parenthesis)) {
|
||||||
const bitfield_shifted = module.llvm.builder.create_lshr(bitfield_load, bits.backing_type.llvm.handle.to_integer().get_constant(field.bit_offset, @intFromBool(false)).to_value());
|
break;
|
||||||
const bitfield_masked = module.llvm.builder.create_and(bitfield_shifted, bits.backing_type.llvm.handle.to_integer().get_constant((@as(u64, 1) << @intCast(field.type.get_bit_size())) - 1, @intFromBool(false)).to_value());
|
}
|
||||||
|
|
||||||
const value = module.values.add();
|
switch (variable.value.type.bb.function.calling_convention) {
|
||||||
value.* = .{
|
.c => {
|
||||||
.type = bits.backing_type,
|
@trap();
|
||||||
.llvm = bitfield_masked,
|
},
|
||||||
.bb = .instruction,
|
.unknown => {
|
||||||
};
|
const argument_value = converter.parse_value(module, variable.value.type.bb.function.semantic_argument_types[argument_count]);
|
||||||
|
llvm_arguments[argument_count] = argument_value.llvm;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break :b value;
|
const llvm_argument_values = llvm_arguments[0..argument_count];
|
||||||
},
|
const llvm_call = module.llvm.builder.create_call(variable.value.type.llvm.handle.to_function(), variable.value.llvm, llvm_argument_values);
|
||||||
else => @trap(),
|
llvm_call.to_instruction().set_calling_convention(variable.value.llvm.get_calling_convention());
|
||||||
|
const call = module.values.add();
|
||||||
|
call.* = .{
|
||||||
|
.llvm = llvm_call,
|
||||||
|
.type = variable.value.type,
|
||||||
|
.bb = .instruction,
|
||||||
|
};
|
||||||
|
break :b call;
|
||||||
|
} else if (converter.consume_character_if_match('.')) {
|
||||||
|
converter.skip_space();
|
||||||
|
|
||||||
|
switch (variable.value.type.bb) {
|
||||||
|
.@"struct" => |*struct_type| {
|
||||||
|
const field_name = converter.parse_identifier();
|
||||||
|
const field_index: u32 = for (struct_type.fields, 0..) |field, field_index| {
|
||||||
|
if (lib.string.equal(field.name, field_name)) {
|
||||||
|
break @intCast(field_index);
|
||||||
|
}
|
||||||
|
} else converter.report_error();
|
||||||
|
const field = struct_type.fields[field_index];
|
||||||
|
const gep = module.llvm.builder.create_struct_gep(variable.value.type.llvm.handle.to_struct(), variable.value.llvm, field_index);
|
||||||
|
const load = module.values.add();
|
||||||
|
load.* = .{
|
||||||
|
.llvm = module.llvm.builder.create_load(field.type.llvm.handle, gep),
|
||||||
|
.type = field.type,
|
||||||
|
.bb = .instruction,
|
||||||
|
};
|
||||||
|
break :b load;
|
||||||
|
},
|
||||||
|
.bits => |*bits| {
|
||||||
|
const field_name = converter.parse_identifier();
|
||||||
|
const field_index: u32 = for (bits.fields, 0..) |field, field_index| {
|
||||||
|
if (lib.string.equal(field.name, field_name)) {
|
||||||
|
break @intCast(field_index);
|
||||||
|
}
|
||||||
|
} else converter.report_error();
|
||||||
|
const field = bits.fields[field_index];
|
||||||
|
|
||||||
|
const bitfield_load = module.llvm.builder.create_load(bits.backing_type.llvm.handle, variable.value.llvm);
|
||||||
|
const bitfield_shifted = module.llvm.builder.create_lshr(bitfield_load, bits.backing_type.llvm.handle.to_integer().get_constant(field.bit_offset, @intFromBool(false)).to_value());
|
||||||
|
const bitfield_masked = module.llvm.builder.create_and(bitfield_shifted, bits.backing_type.llvm.handle.to_integer().get_constant((@as(u64, 1) << @intCast(field.type.get_bit_size())) - 1, @intFromBool(false)).to_value());
|
||||||
|
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = .{
|
||||||
|
.type = bits.backing_type,
|
||||||
|
.llvm = bitfield_masked,
|
||||||
|
.bb = .instruction,
|
||||||
|
};
|
||||||
|
|
||||||
|
break :b value;
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
}
|
||||||
|
} else if (converter.consume_character_if_match(left_bracket)) {
|
||||||
|
converter.skip_space();
|
||||||
|
|
||||||
|
const index_type = module.integer_type(64, false);
|
||||||
|
const llvm_index_type = module.integer_type(64, false).llvm.handle.to_integer();
|
||||||
|
const zero_index = llvm_index_type.get_constant(0, @intFromBool(false)).to_value();
|
||||||
|
const index = converter.parse_value(module, index_type);
|
||||||
|
|
||||||
|
converter.skip_space();
|
||||||
|
converter.expect_character(right_bracket);
|
||||||
|
|
||||||
|
const gep = module.llvm.builder.create_gep(variable.value.type.llvm.handle, variable.value.llvm, &.{ zero_index, index.llvm });
|
||||||
|
const load = module.values.add();
|
||||||
|
const load_type = variable.value.type.bb.array.element_type;
|
||||||
|
load.* = .{
|
||||||
|
.llvm = module.llvm.builder.create_load(load_type.llvm.handle, gep),
|
||||||
|
.type = load_type,
|
||||||
|
.bb = .instruction,
|
||||||
|
};
|
||||||
|
break :b load;
|
||||||
|
} else {
|
||||||
|
const load = module.values.add();
|
||||||
|
load.* = .{
|
||||||
|
.llvm = module.llvm.builder.create_load(variable.value.type.llvm.handle, variable.value.llvm),
|
||||||
|
.type = variable.value.type,
|
||||||
|
.bb = .instruction,
|
||||||
|
};
|
||||||
|
break :b load;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
const load = module.values.add();
|
|
||||||
load.* = .{
|
|
||||||
.llvm = module.llvm.builder.create_load(variable.value.type.llvm.handle, variable.value.llvm),
|
|
||||||
.type = variable.value.type,
|
|
||||||
.bb = .instruction,
|
|
||||||
};
|
|
||||||
break :b load;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
converter.report_error();
|
converter.report_error();
|
||||||
|
@ -168,3 +168,7 @@ test "extend" {
|
|||||||
test "bits" {
|
test "bits" {
|
||||||
try invsrc(@src());
|
try invsrc(@src());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "basic_array" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
@ -9,6 +9,11 @@ test {
|
|||||||
_ = @import("lib_test.zig");
|
_ = @import("lib_test.zig");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CSlice = extern struct {
|
||||||
|
pointer: ?*anyopaque,
|
||||||
|
length: usize,
|
||||||
|
};
|
||||||
|
|
||||||
pub const KB = 1024;
|
pub const KB = 1024;
|
||||||
pub const MB = 1024 * 1024;
|
pub const MB = 1024 * 1024;
|
||||||
pub const GB = 1024 * 1024 * 1024;
|
pub const GB = 1024 * 1024 * 1024;
|
||||||
|
@ -52,6 +52,8 @@ pub extern fn LLVMBuildStore(builder: *llvm.Builder, value: *llvm.Value, pointer
|
|||||||
pub extern fn LLVMBuildLoad2(builder: *llvm.Builder, ty: *llvm.Type, pointer: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildLoad2(builder: *llvm.Builder, ty: *llvm.Type, pointer: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildCall2(builder: *llvm.Builder, ty: *llvm.Type.Function, pointer: *llvm.Value, argument_pointer: [*]const *llvm.Value, argument_count: c_uint, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildCall2(builder: *llvm.Builder, ty: *llvm.Type.Function, pointer: *llvm.Value, argument_pointer: [*]const *llvm.Value, argument_count: c_uint, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildStructGEP2(builder: *llvm.Builder, struct_type: *llvm.Type.Struct, pointer: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildStructGEP2(builder: *llvm.Builder, struct_type: *llvm.Type.Struct, pointer: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
||||||
|
pub extern fn LLVMBuildInBoundsGEP2(builder: *llvm.Builder, ty: *llvm.Type, aggregate: *llvm.Value, index_pointer: [*]const *llvm.Value, index_count: c_uint, name: [*:0]const u8) *llvm.Value;
|
||||||
|
|
||||||
pub extern fn LLVMBuildInsertValue(builder: *llvm.Builder, aggregate: *llvm.Value, element: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildInsertValue(builder: *llvm.Builder, aggregate: *llvm.Value, element: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildZExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildZExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildSExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildSExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
@ -112,6 +114,7 @@ pub extern fn llvm_integer_type_get_bit_count(integer_type: *llvm.Type.Integer)
|
|||||||
// VALUES
|
// VALUES
|
||||||
pub extern fn LLVMGetPoison(type: *llvm.Type) *llvm.Value;
|
pub extern fn LLVMGetPoison(type: *llvm.Type) *llvm.Value;
|
||||||
pub extern fn LLVMConstInt(type: *llvm.Type.Integer, value: c_ulonglong, sign_extend: Bool) *llvm.Constant.Integer;
|
pub extern fn LLVMConstInt(type: *llvm.Type.Integer, value: c_ulonglong, sign_extend: Bool) *llvm.Constant.Integer;
|
||||||
|
pub extern fn LLVMConstArray2(element_type: *llvm.Type, value_pointer: [*]const *llvm.Constant, value_length: u64) *llvm.Constant.Array;
|
||||||
|
|
||||||
pub extern fn LLVMGetValueKind(value: *llvm.Value) llvm.Value.Kind;
|
pub extern fn LLVMGetValueKind(value: *llvm.Value) llvm.Value.Kind;
|
||||||
pub extern fn LLVMIsConstant(value: *llvm.Value) Bool;
|
pub extern fn LLVMIsConstant(value: *llvm.Value) Bool;
|
||||||
@ -134,6 +137,7 @@ pub extern fn LLVMDIBuilderCreateGlobalVariableExpression(builder: *llvm.DI.Buil
|
|||||||
pub extern fn llvm_global_variable_add_debug_info(global_variable: *llvm.GlobalVariable, debug_global_variable: *llvm.DI.GlobalVariableExpression) void;
|
pub extern fn llvm_global_variable_add_debug_info(global_variable: *llvm.GlobalVariable, debug_global_variable: *llvm.DI.GlobalVariableExpression) void;
|
||||||
pub extern fn LLVMDIBuilderCreateLexicalBlock(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, file: *llvm.DI.File, line: c_uint, column: c_uint) *llvm.DI.LexicalBlock;
|
pub extern fn LLVMDIBuilderCreateLexicalBlock(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, file: *llvm.DI.File, line: c_uint, column: c_uint) *llvm.DI.LexicalBlock;
|
||||||
pub extern fn LLVMDIBuilderCreateReplaceableCompositeType(builder: *llvm.DI.Builder, tag: c_uint, name_pointer: [*]const u8, name_length: usize, scope: *llvm.DI.Scope, file: *llvm.DI.File, line: c_uint, runtime_language: c_uint, bit_size: u64, align_in_bits: u32, flags: llvm.DI.Flags, unique_identifier_pointer: ?[*]const u8, unique_identifier_length: usize) *llvm.DI.Type.Composite;
|
pub extern fn LLVMDIBuilderCreateReplaceableCompositeType(builder: *llvm.DI.Builder, tag: c_uint, name_pointer: [*]const u8, name_length: usize, scope: *llvm.DI.Scope, file: *llvm.DI.File, line: c_uint, runtime_language: c_uint, bit_size: u64, align_in_bits: u32, flags: llvm.DI.Flags, unique_identifier_pointer: ?[*]const u8, unique_identifier_length: usize) *llvm.DI.Type.Composite;
|
||||||
|
pub extern fn LLVMDIBuilderCreateArrayType(builder: *llvm.DI.Builder, element_count: u64, align_in_bits: u32, element_type: *llvm.DI.Type, subscript_pointer: ?[*]const *llvm.DI.Metadata, subscript_count: c_uint) *llvm.DI.Type.Composite;
|
||||||
pub extern fn LLVMDIBuilderCreateStructType(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, flags: llvm.DI.Flags, derived_from: ?*llvm.DI.Type, member_pointer: [*]const *llvm.DI.Type.Derived, member_length: c_uint, runtime_language: c_uint, vtable_holder: ?*llvm.DI.Metadata, unique_id_pointer: ?[*]const u8, unique_id_length: usize) *llvm.DI.Type.Composite;
|
pub extern fn LLVMDIBuilderCreateStructType(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, flags: llvm.DI.Flags, derived_from: ?*llvm.DI.Type, member_pointer: [*]const *llvm.DI.Type.Derived, member_length: c_uint, runtime_language: c_uint, vtable_holder: ?*llvm.DI.Metadata, unique_id_pointer: ?[*]const u8, unique_id_length: usize) *llvm.DI.Type.Composite;
|
||||||
pub extern fn LLVMDIBuilderCreateMemberType(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, bit_offset: u64, flags: llvm.DI.Flags, member_type: *llvm.DI.Type) *llvm.DI.Type.Derived;
|
pub extern fn LLVMDIBuilderCreateMemberType(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, bit_offset: u64, flags: llvm.DI.Flags, member_type: *llvm.DI.Type) *llvm.DI.Type.Derived;
|
||||||
pub extern fn LLVMDIBuilderCreateBitFieldMemberType(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, bit_offset: u64, bit_storage_offset: u64, flags: llvm.DI.Flags, member_type: *llvm.DI.Type) *llvm.DI.Type.Derived;
|
pub extern fn LLVMDIBuilderCreateBitFieldMemberType(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, bit_offset: u64, bit_storage_offset: u64, flags: llvm.DI.Flags, member_type: *llvm.DI.Type) *llvm.DI.Type.Derived;
|
||||||
|
5
tests/basic_array.bbb
Normal file
5
tests/basic_array.bbb
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>array: [_]s32 = [3, 2, 1, 0];
|
||||||
|
return array[3];
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user