Pass C abi tests
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 1m39s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 1m36s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 1m45s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 2m45s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 1m33s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 1m31s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 1m39s
CI / ci (Debug, ubuntu-latest) (push) Successful in 2m38s
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 1m39s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 1m36s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 1m45s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 2m45s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 1m33s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 1m31s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 1m39s
CI / ci (Debug, ubuntu-latest) (push) Successful in 2m38s
This commit is contained in:
parent
9bee8064f2
commit
eaeaa0f3b2
@ -449,7 +449,7 @@ pub const Type = struct {
|
|||||||
pub fn is_signed(ty: *const Type) bool {
|
pub fn is_signed(ty: *const Type) bool {
|
||||||
return switch (ty.bb) {
|
return switch (ty.bb) {
|
||||||
.integer => |integer| integer.signed,
|
.integer => |integer| integer.signed,
|
||||||
// .bits => |bits| bits.backing_type.is_signed(),
|
.bits => |bits| bits.backing_type.is_signed(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -477,7 +477,7 @@ pub const Type = struct {
|
|||||||
pub fn is_promotable_integer_type_for_abi(ty: *Type) bool {
|
pub fn is_promotable_integer_type_for_abi(ty: *Type) bool {
|
||||||
return switch (ty.bb) {
|
return switch (ty.bb) {
|
||||||
.integer => |integer| integer.bit_count < 32,
|
.integer => |integer| integer.bit_count < 32,
|
||||||
// .bits => |bits| bits.backing_type.is_promotable_integer_type_for_abi(),
|
.bits => |bits| bits.backing_type.is_promotable_integer_type_for_abi(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -504,6 +504,7 @@ pub const Type = struct {
|
|||||||
.pointer => 64,
|
.pointer => 64,
|
||||||
.bits => |bits| bits.backing_type.get_bit_alignment(),
|
.bits => |bits| bits.backing_type.get_bit_alignment(),
|
||||||
.array => |array| array.element_type.get_bit_alignment(),
|
.array => |array| array.element_type.get_bit_alignment(),
|
||||||
|
.structure => |structure| structure.bit_alignment,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -514,6 +515,7 @@ pub const Type = struct {
|
|||||||
.structure => |structure| structure.byte_size,
|
.structure => |structure| structure.byte_size,
|
||||||
.pointer => 8,
|
.pointer => 8,
|
||||||
.array => |array| array.element_type.get_byte_size() * array.element_count,
|
.array => |array| array.element_type.get_byte_size() * array.element_count,
|
||||||
|
.bits => |bits| bits.backing_type.get_byte_size(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
return byte_size;
|
return byte_size;
|
||||||
@ -525,6 +527,7 @@ pub const Type = struct {
|
|||||||
.pointer => 64,
|
.pointer => 64,
|
||||||
.bits => |bits| bits.backing_type.get_bit_size(),
|
.bits => |bits| bits.backing_type.get_bit_size(),
|
||||||
.array => |array| array.element_type.get_bit_size() * array.element_count,
|
.array => |array| array.element_type.get_bit_size() * array.element_count,
|
||||||
|
.structure => |structure| structure.bit_size,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
return bit_size;
|
return bit_size;
|
||||||
@ -1110,8 +1113,8 @@ pub const Module = struct {
|
|||||||
const argument_attribute = &argument_attributes[abi_index];
|
const argument_attribute = &argument_attributes[abi_index];
|
||||||
|
|
||||||
argument_attribute.* = .{
|
argument_attribute.* = .{
|
||||||
.semantic_type = argument_type_abi.semantic_type.llvm.handle.?,
|
.semantic_type = argument_type_abi.semantic_type.resolve(module).handle,
|
||||||
.abi_type = options.abi_argument_types[abi_index].llvm.handle.?,
|
.abi_type = options.abi_argument_types[abi_index].resolve(module).handle,
|
||||||
.dereferenceable_bytes = 0,
|
.dereferenceable_bytes = 0,
|
||||||
.alignment = if (argument_type_abi.flags.kind == .indirect) 8 else 0,
|
.alignment = if (argument_type_abi.flags.kind == .indirect) 8 else 0,
|
||||||
.flags = .{
|
.flags = .{
|
||||||
@ -3813,15 +3816,13 @@ pub const Module = struct {
|
|||||||
const raw_function_type = call.function_type;
|
const raw_function_type = call.function_type;
|
||||||
// TODO: improve this code, which works for now
|
// TODO: improve this code, which works for now
|
||||||
const llvm_callable = switch (call.callable.bb) {
|
const llvm_callable = switch (call.callable.bb) {
|
||||||
.variable_reference => |variable| switch (call.callable.kind) {
|
.variable_reference => |variable| switch (variable.type.?.bb) {
|
||||||
.left => switch (call.callable.type == raw_function_type) {
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
true => unreachable,
|
.function => module.create_load(.{ .type = module.get_pointer_type(.{ .type = raw_function_type }), .value = variable.storage.?.llvm.? }),
|
||||||
false => variable.storage.?.llvm.?,
|
else => @trap(),
|
||||||
},
|
|
||||||
.right => switch (call.callable.type == raw_function_type) {
|
|
||||||
true => variable.storage.?.llvm.?,
|
|
||||||
false => module.create_load(.{ .type = module.get_pointer_type(.{ .type = raw_function_type }), .value = variable.storage.?.llvm.? }),
|
|
||||||
},
|
},
|
||||||
|
.function => variable.storage.?.llvm.?,
|
||||||
|
else => @trap(),
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
@ -5037,16 +5038,16 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.call => |*call| {
|
.call => |*call| {
|
||||||
module.analyze_value_type(function, call.callable, .{});
|
module.analyze_value_type(function, call.callable, .{});
|
||||||
call.function_type = switch (call.callable.type.?.bb) {
|
call.function_type = switch (call.callable.bb) {
|
||||||
.function => blk: {
|
.variable_reference => |variable| switch (variable.type.?.bb) {
|
||||||
assert(call.callable.kind == .right);
|
.function => variable.type.?,
|
||||||
break :blk call.callable.type.?;
|
|
||||||
},
|
|
||||||
.pointer => |pointer| switch (pointer.type.bb) {
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
.function => pointer.type,
|
.function => pointer.type,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (call.arguments.len != call.function_type.bb.function.semantic_argument_types.len) {
|
if (call.arguments.len != call.function_type.bb.function.semantic_argument_types.len) {
|
||||||
@ -5311,6 +5312,14 @@ pub const Module = struct {
|
|||||||
const enum_backing_type = enum_value.type.?.bb.enumerator.backing_type;
|
const enum_backing_type = enum_value.type.?.bb.enumerator.backing_type;
|
||||||
break :blk enum_backing_type;
|
break :blk enum_backing_type;
|
||||||
},
|
},
|
||||||
|
.int_from_pointer => |pointer_value| blk: {
|
||||||
|
module.analyze_value_type(function, pointer_value, .{});
|
||||||
|
if (pointer_value.type.?.bb != .pointer) {
|
||||||
|
module.report_error();
|
||||||
|
}
|
||||||
|
const int_ty = module.integer_type(64, false);
|
||||||
|
break :blk int_ty;
|
||||||
|
},
|
||||||
.trap => module.noreturn_type,
|
.trap => module.noreturn_type,
|
||||||
.va_start => module.get_va_list_type(),
|
.va_start => module.get_va_list_type(),
|
||||||
.va_end => |va_list| blk: {
|
.va_end => |va_list| blk: {
|
||||||
@ -5337,14 +5346,14 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.call => |*call| blk: {
|
.call => |*call| blk: {
|
||||||
module.analyze_value_type(function, call.callable, .{});
|
module.analyze_value_type(function, call.callable, .{});
|
||||||
call.function_type = switch (call.callable.type.?.bb) {
|
call.function_type = switch (call.callable.bb) {
|
||||||
|
.variable_reference => |variable| switch (variable.type.?.bb) {
|
||||||
|
.function => variable.type.?,
|
||||||
.pointer => |pointer| switch (pointer.type.bb) {
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
.function => pointer.type,
|
.function => pointer.type,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
},
|
},
|
||||||
.function => b: {
|
else => @trap(),
|
||||||
assert(call.callable.kind == .right);
|
|
||||||
break :b call.callable.type.?;
|
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
@ -7353,7 +7362,7 @@ pub const Abi = struct {
|
|||||||
|
|
||||||
switch (ty.bb) {
|
switch (ty.bb) {
|
||||||
.void, .noreturn => result[current_index] = .none,
|
.void, .noreturn => result[current_index] = .none,
|
||||||
// .bits => result[current_index] = .integer,
|
.bits => result[current_index] = .integer,
|
||||||
.pointer => result[current_index] = .integer,
|
.pointer => result[current_index] = .integer,
|
||||||
.integer => |integer| {
|
.integer => |integer| {
|
||||||
if (integer.bit_count <= 64) {
|
if (integer.bit_count <= 64) {
|
||||||
@ -7488,9 +7497,9 @@ pub const Abi = struct {
|
|||||||
|
|
||||||
fn get_int_type_at_offset(module: *Module, 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 => |bits| {
|
||||||
// return get_int_type_at_offset(module, bits.backing_type, offset, if (source_type == ty) bits.backing_type else source_type, source_offset);
|
return get_int_type_at_offset(module, bits.backing_type, offset, if (source_type == ty) bits.backing_type else source_type, source_offset);
|
||||||
// },
|
},
|
||||||
.integer => |integer_type| {
|
.integer => |integer_type| {
|
||||||
switch (integer_type.bit_count) {
|
switch (integer_type.bit_count) {
|
||||||
64 => return ty,
|
64 => return ty,
|
||||||
|
@ -244,4 +244,6 @@ const names = &[_][]const u8{
|
|||||||
"c_split_struct_ints",
|
"c_split_struct_ints",
|
||||||
"c_string_to_slice",
|
"c_string_to_slice",
|
||||||
"c_struct_with_array",
|
"c_struct_with_array",
|
||||||
|
"c_function_pointer",
|
||||||
|
"c_abi",
|
||||||
};
|
};
|
||||||
|
@ -330,7 +330,7 @@ require = fn (ok: u1) void
|
|||||||
|
|
||||||
[export] bb_ptr = fn [cc(c)] (x: &u8) void
|
[export] bb_ptr = fn [cc(c)] (x: &u8) void
|
||||||
{
|
{
|
||||||
require(#cast_to(u64, x) == 0xdeadbeef);
|
require(#int_from_pointer(x) == 0xdeadbeef);
|
||||||
}
|
}
|
||||||
|
|
||||||
[export] bb_five_integers = fn [cc(c)] (a: s32, b: s32, c: s32, d: s32, e: s32) void
|
[export] bb_five_integers = fn [cc(c)] (a: s32, b: s32, c: s32, d: s32, e: s32) void
|
||||||
|
7
tests/c_function_pointer.bbb
Normal file
7
tests/c_function_pointer.bbb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[extern] exit = fn [cc(c)] (exit_code: s32) noreturn;
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>c_function_pointer = &exit;
|
||||||
|
c_function_pointer(0);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user