More C ABI coverage
This commit is contained in:
parent
95c1bf6702
commit
3c7fea2526
18
src/LLVM.zig
18
src/LLVM.zig
@ -488,6 +488,12 @@ const targets = [@typeInfo(Architecture).@"enum".fields.len]type{
|
|||||||
api.get_initializer(.X86),
|
api.get_initializer(.X86),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Intrinsic = enum {
|
||||||
|
pub const Id = enum(c_uint) {
|
||||||
|
_,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pub const Context = opaque {
|
pub const Context = opaque {
|
||||||
pub const create = api.LLVMContextCreate;
|
pub const create = api.LLVMContextCreate;
|
||||||
|
|
||||||
@ -518,6 +524,10 @@ pub const Context = opaque {
|
|||||||
pub const get_void_type = api.LLVMVoidTypeInContext;
|
pub const get_void_type = api.LLVMVoidTypeInContext;
|
||||||
pub const get_integer_type = api.LLVMIntTypeInContext;
|
pub const get_integer_type = api.LLVMIntTypeInContext;
|
||||||
pub const get_pointer_type = api.LLVMPointerTypeInContext;
|
pub const get_pointer_type = api.LLVMPointerTypeInContext;
|
||||||
|
|
||||||
|
pub fn get_intrinsic_type(context: *Context, intrinsic_id: Intrinsic.Id, parameter_types: []const *Type) *Type.Function {
|
||||||
|
return api.LLVMIntrinsicGetType(context, intrinsic_id, parameter_types.ptr, parameter_types.len);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const BasicBlock = opaque {
|
pub const BasicBlock = opaque {
|
||||||
@ -568,6 +578,10 @@ pub const Module = opaque {
|
|||||||
result.error_message = string.to_slice();
|
result.error_message = string.to_slice();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_intrinsic_declaration(module: *Module, intrinsic_id: Intrinsic.Id, parameter_types: []const *Type) *Value {
|
||||||
|
return api.LLVMGetIntrinsicDeclaration(module, intrinsic_id, parameter_types.ptr, parameter_types.len);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const VerifyResult = struct {
|
pub const VerifyResult = struct {
|
||||||
@ -1218,6 +1232,10 @@ pub const Dwarf = struct {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn lookup_intrinsic_id(name: []const u8) Intrinsic.Id {
|
||||||
|
return api.LLVMLookupIntrinsicID(name.ptr, name.len);
|
||||||
|
}
|
||||||
|
|
||||||
pub const IntPredicate = enum(c_int) {
|
pub const IntPredicate = enum(c_int) {
|
||||||
eq = 32,
|
eq = 32,
|
||||||
ne,
|
ne,
|
||||||
|
@ -115,6 +115,9 @@ const Module = struct {
|
|||||||
global_scope: *llvm.DI.Scope,
|
global_scope: *llvm.DI.Scope,
|
||||||
file: *llvm.DI.File,
|
file: *llvm.DI.File,
|
||||||
pointer_type: *llvm.Type,
|
pointer_type: *llvm.Type,
|
||||||
|
// intrinsics: struct {
|
||||||
|
// trap:
|
||||||
|
// },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn get_infer_or_ignore_value(module: *Module) *Value {
|
pub fn get_infer_or_ignore_value(module: *Module) *Value {
|
||||||
@ -272,6 +275,31 @@ const Module = struct {
|
|||||||
|
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_pointer_type(module: *Module, element_type: *Type) *Type {
|
||||||
|
const all_types = module.types.get();
|
||||||
|
const pointer_type = for (module.pointer_type_buffer[0..module.pointer_type_count]) |pointer_type_index| {
|
||||||
|
const pointer_type = &all_types[pointer_type_index];
|
||||||
|
if (pointer_type.bb.pointer == element_type) {
|
||||||
|
break pointer_type;
|
||||||
|
}
|
||||||
|
} else blk: {
|
||||||
|
const pointer_name = lib.global.arena.join_string(&.{ "&", element_type.name.? });
|
||||||
|
const pointer_type = module.types.add(.{
|
||||||
|
.name = pointer_name,
|
||||||
|
.llvm = .{
|
||||||
|
.handle = module.llvm.pointer_type,
|
||||||
|
.debug = if (module.llvm.di_builder) |di_builder| di_builder.create_pointer_type(element_type.llvm.debug, 64, 64, 0, pointer_name).to_type() else undefined,
|
||||||
|
},
|
||||||
|
.bb = .{
|
||||||
|
.pointer = element_type,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break :blk pointer_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
return pointer_type;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Function = struct {
|
pub const Function = struct {
|
||||||
@ -612,28 +640,7 @@ const Converter = struct {
|
|||||||
|
|
||||||
const element_type = converter.parse_type(module);
|
const element_type = converter.parse_type(module);
|
||||||
|
|
||||||
const all_types = module.types.get();
|
return module.get_pointer_type(element_type);
|
||||||
const pointer_type = for (module.pointer_type_buffer[0..module.pointer_type_count]) |pointer_type_index| {
|
|
||||||
const pointer_type = &all_types[pointer_type_index];
|
|
||||||
if (pointer_type.bb.pointer == element_type) {
|
|
||||||
break pointer_type;
|
|
||||||
}
|
|
||||||
} else blk: {
|
|
||||||
const pointer_name = lib.global.arena.join_string(&.{ "&", element_type.name.? });
|
|
||||||
const pointer_type = module.types.add(.{
|
|
||||||
.name = pointer_name,
|
|
||||||
.llvm = .{
|
|
||||||
.handle = module.llvm.pointer_type,
|
|
||||||
.debug = if (module.llvm.di_builder) |di_builder| di_builder.create_pointer_type(element_type.llvm.debug, 64, 64, 0, pointer_name).to_type() else undefined,
|
|
||||||
},
|
|
||||||
.bb = .{
|
|
||||||
.pointer = element_type,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
break :blk pointer_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
return pointer_type;
|
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
}
|
}
|
||||||
@ -925,6 +932,12 @@ const Converter = struct {
|
|||||||
} else {
|
} else {
|
||||||
converter.report_error();
|
converter.report_error();
|
||||||
}
|
}
|
||||||
|
} else if (statement_start_ch == '#') {
|
||||||
|
const intrinsic = converter.parse_intrinsic(module, null);
|
||||||
|
switch (intrinsic.type.bb) {
|
||||||
|
.void, .noreturn => {},
|
||||||
|
else => @trap(),
|
||||||
|
}
|
||||||
} else if (is_identifier_start_ch(statement_start_ch)) {
|
} else if (is_identifier_start_ch(statement_start_ch)) {
|
||||||
const statement_start_identifier = converter.parse_identifier();
|
const statement_start_identifier = converter.parse_identifier();
|
||||||
|
|
||||||
@ -970,16 +983,22 @@ const Converter = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var is_second_block_terminated = false;
|
var is_second_block_terminated = false;
|
||||||
|
module.llvm.builder.position_at_end(not_taken_block);
|
||||||
if (is_else) {
|
if (is_else) {
|
||||||
module.llvm.builder.position_at_end(not_taken_block);
|
|
||||||
converter.parse_block(module);
|
converter.parse_block(module);
|
||||||
is_second_block_terminated = current_function.current_basic_block.get_terminator() != null;
|
is_second_block_terminated = current_function.current_basic_block.get_terminator() != null;
|
||||||
} else {
|
|
||||||
@trap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(is_first_block_terminated and is_second_block_terminated)) {
|
if (!(is_first_block_terminated and is_second_block_terminated)) {
|
||||||
@trap();
|
if (!is_first_block_terminated) {
|
||||||
|
@trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_second_block_terminated) {
|
||||||
|
if (is_else) {
|
||||||
|
@trap();
|
||||||
|
} else {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require_semicolon = false;
|
require_semicolon = false;
|
||||||
@ -1252,11 +1271,12 @@ const Converter = struct {
|
|||||||
const Prefix = enum {
|
const Prefix = enum {
|
||||||
none,
|
none,
|
||||||
negative,
|
negative,
|
||||||
|
not_zero,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Intrinsic = enum {
|
const Intrinsic = enum {
|
||||||
extend,
|
extend,
|
||||||
foo,
|
trap,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn parse_intrinsic(noalias converter: *Converter, noalias module: *Module, expected_type: ?*Type) *Value {
|
fn parse_intrinsic(noalias converter: *Converter, noalias module: *Module, expected_type: ?*Type) *Value {
|
||||||
@ -1294,7 +1314,27 @@ const Converter = struct {
|
|||||||
|
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
else => unreachable,
|
.trap => {
|
||||||
|
converter.expect_character(right_parenthesis);
|
||||||
|
|
||||||
|
// TODO: lookup in advance
|
||||||
|
const intrinsic_id = llvm.lookup_intrinsic_id("llvm.trap");
|
||||||
|
const parameter_types: []const *llvm.Type = &.{};
|
||||||
|
const parameter_values: []const *llvm.Value = &.{};
|
||||||
|
const intrinsic_function = module.llvm.handle.get_intrinsic_declaration(intrinsic_id, parameter_types);
|
||||||
|
const intrinsic_function_type = module.llvm.context.get_intrinsic_type(intrinsic_id, parameter_types);
|
||||||
|
const llvm_call = module.llvm.builder.create_call(intrinsic_function_type, intrinsic_function, parameter_values);
|
||||||
|
_ = module.llvm.builder.create_unreachable();
|
||||||
|
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = .{
|
||||||
|
.llvm = llvm_call,
|
||||||
|
.type = module.noreturn_type,
|
||||||
|
.bb = .instruction,
|
||||||
|
};
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1509,12 +1549,19 @@ const Converter = struct {
|
|||||||
converter.offset += 1;
|
converter.offset += 1;
|
||||||
return converter.parse_value(module, expected_type, .pointer);
|
return converter.parse_value(module, expected_type, .pointer);
|
||||||
},
|
},
|
||||||
|
'!' => blk: {
|
||||||
|
converter.offset += 1;
|
||||||
|
|
||||||
|
// TODO: should we skip space here?
|
||||||
|
converter.skip_space();
|
||||||
|
break :blk .not_zero;
|
||||||
|
},
|
||||||
else => os.abort(),
|
else => os.abort(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const value_offset = converter.offset;
|
const value_offset = converter.offset;
|
||||||
const value_start_ch = converter.content[value_offset];
|
const value_start_ch = converter.content[value_offset];
|
||||||
const value = switch (value_start_ch) {
|
var value = switch (value_start_ch) {
|
||||||
'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();
|
||||||
@ -1668,6 +1715,21 @@ const Converter = struct {
|
|||||||
'0'...'9' => converter.parse_integer(module, expected_type.?, prefix == .negative),
|
'0'...'9' => converter.parse_integer(module, expected_type.?, prefix == .negative),
|
||||||
else => os.abort(),
|
else => os.abort(),
|
||||||
};
|
};
|
||||||
|
_ = &value;
|
||||||
|
|
||||||
|
switch (prefix) {
|
||||||
|
.none,
|
||||||
|
.negative, // Already done in 'parse_integer' // TODO:
|
||||||
|
=> {},
|
||||||
|
.not_zero => {
|
||||||
|
const llvm_value = module.llvm.builder.create_compare(.eq, value.llvm, value.type.llvm.handle.to_integer().get_constant(0, 0).to_value());
|
||||||
|
value.* = .{
|
||||||
|
.llvm = llvm_value,
|
||||||
|
.bb = .instruction,
|
||||||
|
.type = module.integer_type(1, false),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -1924,12 +1986,10 @@ pub const Abi = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_int_type_at_offset(ty: *Type, offset: u32, source_type: *Type, source_offset: u32) *Type {
|
fn get_int_type_at_offset(module: *Module, ty: *Type, offset: u32, source_type: *Type, source_offset: u32) *Type {
|
||||||
switch (ty.bb) {
|
switch (ty.bb) {
|
||||||
.bits => {
|
.bits => |bits| {
|
||||||
@trap();
|
return get_int_type_at_offset(module, bits.backing_type, offset, if (source_type == ty) bits.backing_type else source_type, source_offset);
|
||||||
// const bitfield = ty.get_payload(.bitfield);
|
|
||||||
// return get_int_type_at_offset(bitfield.backing_type, offset, if (source_type == ty) bitfield.backing_type else source_type, source_offset);
|
|
||||||
},
|
},
|
||||||
.integer => |integer_type| {
|
.integer => |integer_type| {
|
||||||
switch (integer_type.bit_count) {
|
switch (integer_type.bit_count) {
|
||||||
@ -1948,29 +2008,25 @@ pub const Abi = struct {
|
|||||||
// .typed_pointer => return if (offset == 0) ty else unreachable,
|
// .typed_pointer => return if (offset == 0) ty else unreachable,
|
||||||
.@"struct" => {
|
.@"struct" => {
|
||||||
if (get_member_at_offset(ty, offset)) |field| {
|
if (get_member_at_offset(ty, offset)) |field| {
|
||||||
return get_int_type_at_offset(field.type, @intCast(offset - field.byte_offset), source_type, source_offset);
|
return get_int_type_at_offset(module, field.type, @intCast(offset - field.byte_offset), source_type, source_offset);
|
||||||
}
|
}
|
||||||
unreachable;
|
unreachable;
|
||||||
},
|
},
|
||||||
.array => {
|
.array => |array_type| {
|
||||||
@trap();
|
const element_type = array_type.element_type;
|
||||||
// const array_type = ty.get_payload(.array);
|
const element_size = element_type.get_byte_size();
|
||||||
// const element_type = array_type.descriptor.element_type;
|
const element_offset = (offset / element_size) * element_size;
|
||||||
// const element_size = element_type.size;
|
return get_int_type_at_offset(module, element_type, @intCast(offset - element_offset), source_type, source_offset);
|
||||||
// const element_offset = (offset / element_size) * element_size;
|
|
||||||
// return get_int_type_at_offset(element_type, @intCast(offset - element_offset), source_type, source_offset);
|
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source_type.get_byte_size() - source_offset > 8) {
|
if (source_type.get_byte_size() - source_offset > 8) {
|
||||||
@trap();
|
return module.integer_type(64, false);
|
||||||
// return &instance.threads[ty.sema.thread].integers[63].type;
|
|
||||||
} else {
|
} else {
|
||||||
// const byte_count = source_type.size - source_offset;
|
const byte_count = source_type.get_byte_size() - source_offset;
|
||||||
// const bit_count = byte_count * 8;
|
const bit_count = byte_count * 8;
|
||||||
// return &instance.threads[ty.sema.thread].integers[bit_count - 1].type;
|
return module.integer_type(@intCast(bit_count), false);
|
||||||
@trap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable;
|
unreachable;
|
||||||
@ -2090,13 +2146,13 @@ pub const Abi = struct {
|
|||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn indirect_return(ty: *Type) Function.Abi.Information {
|
fn indirect_return(ty: *Type) Abi.Information {
|
||||||
if (ty.is_aggregate()) {
|
if (ty.is_aggregate()) {
|
||||||
return .{
|
return .{
|
||||||
.kind = .{
|
.kind = .{
|
||||||
.indirect = .{
|
.indirect = .{
|
||||||
.type = ty,
|
.type = ty,
|
||||||
.alignment = ty.alignment,
|
.alignment = @intCast(ty.get_byte_alignment()),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -2324,30 +2380,28 @@ pub noinline fn convert(options: ConvertOptions) void {
|
|||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
.integer => b: {
|
.integer => b: {
|
||||||
const result_type = Abi.SystemV.get_int_type_at_offset(semantic_return_type, 0, semantic_return_type, 0);
|
const result_type = Abi.SystemV.get_int_type_at_offset(module, semantic_return_type, 0, semantic_return_type, 0);
|
||||||
if (type_classes[1] == .none and semantic_return_type.get_bit_size() < 32) {
|
if (type_classes[1] == .none and semantic_return_type.get_bit_size() < 32) {
|
||||||
// const signed = switch (semantic_return_type.sema.id) {
|
const signed = switch (semantic_return_type.bb) {
|
||||||
// .integer => @intFromEnum(semantic_return_type.get_payload(.integer).signedness) != 0,
|
.integer => |integer_type| integer_type.signed,
|
||||||
// .bitfield => false,
|
.bits => false,
|
||||||
// else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
// };
|
};
|
||||||
// _ = signed;
|
// _ = signed;
|
||||||
|
break :ret_ty_abi .{
|
||||||
@trap();
|
.kind = .{
|
||||||
// break :rta .{
|
.direct_coerce = semantic_return_type,
|
||||||
// .kind = .{
|
},
|
||||||
// .direct_coerce = semantic_return_type,
|
.attributes = .{
|
||||||
// },
|
.sign_extend = signed,
|
||||||
// .attributes = .{
|
.zero_extend = !signed,
|
||||||
// .sign_extend = signed,
|
},
|
||||||
// .zero_extend = !signed,
|
};
|
||||||
// },
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break :b result_type;
|
break :b result_type;
|
||||||
},
|
},
|
||||||
.memory => @trap(), // break :rta Abi.SystemV.indirect_return(semantic_return_type),
|
.memory => break :ret_ty_abi Abi.SystemV.indirect_return(semantic_return_type),
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2355,7 +2409,7 @@ pub noinline fn convert(options: ConvertOptions) void {
|
|||||||
.none, .memory => null,
|
.none, .memory => null,
|
||||||
.integer => b: {
|
.integer => b: {
|
||||||
assert(type_classes[0] != .none);
|
assert(type_classes[0] != .none);
|
||||||
const high_part = Abi.SystemV.get_int_type_at_offset(semantic_return_type, 8, semantic_return_type, 8);
|
const high_part = Abi.SystemV.get_int_type_at_offset(module, semantic_return_type, 8, semantic_return_type, 8);
|
||||||
break :b high_part;
|
break :b high_part;
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
@ -2372,12 +2426,11 @@ pub noinline fn convert(options: ConvertOptions) void {
|
|||||||
.kind = .direct,
|
.kind = .direct,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@trap();
|
break :ret_ty_abi Abi.Information{
|
||||||
// break :rta Function.Abi.Information{
|
.kind = .{
|
||||||
// .kind = .{
|
.direct_coerce = result_type,
|
||||||
// .direct_coerce = result_type,
|
},
|
||||||
// },
|
};
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable;
|
unreachable;
|
||||||
@ -2415,7 +2468,7 @@ pub noinline fn convert(options: ConvertOptions) void {
|
|||||||
const result_type = switch (type_classes[0]) {
|
const result_type = switch (type_classes[0]) {
|
||||||
.integer => b: {
|
.integer => b: {
|
||||||
needed_registers.gpr += 1;
|
needed_registers.gpr += 1;
|
||||||
const result_type = Abi.SystemV.get_int_type_at_offset(semantic_argument_type, 0, semantic_argument_type, 0);
|
const result_type = Abi.SystemV.get_int_type_at_offset(module, semantic_argument_type, 0, semantic_argument_type, 0);
|
||||||
if (type_classes[1] == .none and semantic_argument_type.get_bit_size() < 32) {
|
if (type_classes[1] == .none and semantic_argument_type.get_bit_size() < 32) {
|
||||||
const signed = switch (semantic_argument_type.bb) {
|
const signed = switch (semantic_argument_type.bb) {
|
||||||
.integer => |integer_type| integer_type.signed,
|
.integer => |integer_type| integer_type.signed,
|
||||||
@ -2443,7 +2496,7 @@ pub noinline fn convert(options: ConvertOptions) void {
|
|||||||
.integer => b: {
|
.integer => b: {
|
||||||
assert(type_classes[0] != .none);
|
assert(type_classes[0] != .none);
|
||||||
needed_registers.gpr += 1;
|
needed_registers.gpr += 1;
|
||||||
const high_part = Abi.SystemV.get_int_type_at_offset(semantic_argument_type, 8, semantic_argument_type, 8);
|
const high_part = Abi.SystemV.get_int_type_at_offset(module, semantic_argument_type, 8, semantic_argument_type, 8);
|
||||||
break :b high_part;
|
break :b high_part;
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
@ -2497,16 +2550,20 @@ pub noinline fn convert(options: ConvertOptions) void {
|
|||||||
const abi_return_type = switch (return_type_abi.kind) {
|
const abi_return_type = switch (return_type_abi.kind) {
|
||||||
.ignore, .direct => semantic_return_type,
|
.ignore, .direct => semantic_return_type,
|
||||||
.direct_coerce => |coerced_type| coerced_type,
|
.direct_coerce => |coerced_type| coerced_type,
|
||||||
// .indirect => |indirect| b: {
|
.indirect => |indirect| b: {
|
||||||
// _ = abi_argument_types.append(get_typed_pointer(thread, .{
|
const indirect_pointer_type = module.get_pointer_type(indirect.type);
|
||||||
// .pointee = indirect.type,
|
abi_argument_type_buffer[abi_argument_type_count] = indirect_pointer_type;
|
||||||
// }));
|
llvm_abi_argument_type_buffer[abi_argument_type_count] = indirect_pointer_type.llvm.handle;
|
||||||
// break :b &thread.void;
|
abi_argument_type_count += 1;
|
||||||
// },
|
break :b module.void_type;
|
||||||
|
},
|
||||||
.direct_pair => |pair| b: {
|
.direct_pair => |pair| b: {
|
||||||
for (module.anonymous_pair_type_buffer[0..module.anonymous_pair_type_count]) |*anonymous_type| {
|
for (module.anonymous_pair_type_buffer[0..module.anonymous_pair_type_count]) |anonymous_type_index| {
|
||||||
_ = anonymous_type;
|
const anonymous_type = &module.types.get()[anonymous_type_index];
|
||||||
@trap();
|
const fields = anonymous_type.bb.@"struct".fields;
|
||||||
|
if (fields.len == 2 and pair[0] == fields[0].type and pair[1] == fields[1].type) {
|
||||||
|
break :b anonymous_type;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const llvm_pair_members = &.{ pair[0].llvm.handle, pair[1].llvm.handle };
|
const llvm_pair_members = &.{ pair[0].llvm.handle, pair[1].llvm.handle };
|
||||||
const llvm_pair = module.llvm.context.get_struct_type(llvm_pair_members);
|
const llvm_pair = module.llvm.context.get_struct_type(llvm_pair_members);
|
||||||
@ -2572,9 +2629,12 @@ pub noinline fn convert(options: ConvertOptions) void {
|
|||||||
llvm_abi_argument_type_buffer[abi_argument_type_count] = pair[1].llvm.handle;
|
llvm_abi_argument_type_buffer[abi_argument_type_count] = pair[1].llvm.handle;
|
||||||
abi_argument_type_count += 1;
|
abi_argument_type_count += 1;
|
||||||
},
|
},
|
||||||
// .indirect => |indirect| _ = abi_argument_types.append(get_typed_pointer(thread, .{
|
.indirect => |indirect| {
|
||||||
// .pointee = indirect.type,
|
const indirect_pointer_type = module.get_pointer_type(indirect.type);
|
||||||
// })),
|
abi_argument_type_buffer[abi_argument_type_count] = indirect_pointer_type;
|
||||||
|
llvm_abi_argument_type_buffer[abi_argument_type_count] = indirect_pointer_type.llvm.handle;
|
||||||
|
abi_argument_type_count += 1;
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,3 +181,7 @@ test "extern" {
|
|||||||
test "pointer" {
|
test "pointer" {
|
||||||
try invsrc(@src());
|
try invsrc(@src());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "if_no_else" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
@ -65,6 +65,11 @@ pub extern fn LLVMTypeOf(value: *llvm.Value) *llvm.Type;
|
|||||||
pub extern fn LLVMGlobalGetValueType(value: *llvm.GlobalValue) *llvm.Type;
|
pub extern fn LLVMGlobalGetValueType(value: *llvm.GlobalValue) *llvm.Type;
|
||||||
pub extern fn llvm_value_is_instruction(value: *llvm.Value) bool;
|
pub extern fn llvm_value_is_instruction(value: *llvm.Value) bool;
|
||||||
|
|
||||||
|
// Intrinsics
|
||||||
|
pub extern fn LLVMLookupIntrinsicID(name_pointer: [*]const u8, name_length: usize) llvm.Intrinsic.Id;
|
||||||
|
pub extern fn LLVMGetIntrinsicDeclaration(module: *llvm.Module, intrinsic_id: llvm.Intrinsic.Id, parameter_type_pointer: [*]const *llvm.Type, parameter_type_count: usize) *llvm.Value;
|
||||||
|
pub extern fn LLVMIntrinsicGetType(context: *llvm.Context, intrinsic_id: llvm.Intrinsic.Id, parameter_type_pointer: [*]const *llvm.Type, parameter_type_count: usize) *llvm.Type.Function;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
// Types: integers
|
// Types: integers
|
||||||
pub extern fn LLVMVoidTypeInContext(context: *llvm.Context) *llvm.Type;
|
pub extern fn LLVMVoidTypeInContext(context: *llvm.Context) *llvm.Type;
|
||||||
|
@ -138,9 +138,9 @@ ByVal = struct
|
|||||||
[extern] c_ret_struct_with_array = fn [cc(c)] () StructWithArray;
|
[extern] c_ret_struct_with_array = fn [cc(c)] () StructWithArray;
|
||||||
|
|
||||||
[extern] c_modify_by_ref_param = fn [cc(c)] (x: ByRef) ByRef;
|
[extern] c_modify_by_ref_param = fn [cc(c)] (x: ByRef) ByRef;
|
||||||
[extern] c_func_ptr_byval fn [cc(c)] (a: u64, b: u64, c: ByVal, d: u64, e: u64, f: u64) void;
|
[extern] c_func_ptr_byval = fn [cc(c)] (a: u64, b: u64, c: ByVal, d: u64, e: u64, f: u64) void;
|
||||||
|
|
||||||
[export] require = fn [cc(c)] (ok: u8)
|
[export] require = fn [cc(c)] (ok: u8) void
|
||||||
{
|
{
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
|
9
tests/if_no_else.bbb
Normal file
9
tests/if_no_else.bbb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>a: s32 = 5;
|
||||||
|
if (a == 2)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user