External functions and array type refinements

This commit is contained in:
David Gonzalez Martin 2025-02-25 11:54:02 -06:00
parent e290f61890
commit 6135ade3a7
2 changed files with 270 additions and 223 deletions

View File

@ -23,6 +23,28 @@ const right_brace = '}';
const left_parenthesis = '(';
const right_parenthesis = ')';
fn array_type_name(element_count: u64, noalias array: *ArrayType) [:0]const u8 {
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;
return lib.global.arena.duplicate_string(buffer[0..i]);
}
fn array_type_llvm(noalias module: *Module, noalias array: *ArrayType) Type.LLVM {
const element_count = array.element_count.?;
return .{
.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,
};
}
fn is_identifier_start_ch(ch: u8) bool {
return (ch >= 'a' and ch <= 'z') or (ch >= 'A' and ch <= 'Z') or ch == '_';
}
@ -249,6 +271,11 @@ pub const Function = struct {
calling_convention: CallingConvention,
};
pub const ConstantInteger = struct {
value: u64,
signed: bool,
};
pub const Value = struct {
bb: union(enum) {
function: Function,
@ -259,8 +286,9 @@ pub const Value = struct {
struct_initialization,
bits_initialization,
infer_or_ignore,
constant_integer,
constant_integer: ConstantInteger,
constant_array,
external_function,
},
type: *Type,
llvm: *llvm.Value,
@ -503,7 +531,7 @@ const Converter = struct {
converter.skip_space();
const length_expression = converter.parse_value(module, null);
const length_expression = converter.parse_value(module, module.integer_type(64, false));
converter.skip_space();
converter.expect_character(right_bracket);
@ -522,7 +550,17 @@ const Converter = struct {
});
return ty;
} else {
@trap();
const ty = module.types.add(.{
.name = undefined,
.llvm = undefined,
.bb = .{
.array = .{
.element_count = length_expression.bb.constant_integer.value,
.element_type = element_type,
},
},
});
return ty;
}
},
else => @trap(),
@ -592,7 +630,7 @@ const Converter = struct {
assert(!is_space(integer_start_ch));
assert(is_decimal_ch(integer_start_ch));
const value: u64 = switch (integer_start_ch) {
const absolute_value: u64 = switch (integer_start_ch) {
'0' => blk: {
converter.offset += 1;
@ -619,25 +657,32 @@ const Converter = struct {
},
true => switch (next_ch) {
'x', 'o', 'b', '0' => converter.report_error(),
'1'...'9' => @bitCast(-@as(i64, @intCast(converter.parse_decimal()))),
'1'...'9' => converter.parse_decimal(),
else => unreachable,
},
};
},
'1'...'9' => switch (sign) {
true => @bitCast(-@as(i64, @intCast(converter.parse_decimal()))),
false => converter.parse_decimal(),
},
'1'...'9' => converter.parse_decimal(),
else => unreachable,
};
const value: u64 = switch (sign) {
true => @bitCast(-@as(i64, @intCast(absolute_value))),
false => absolute_value,
};
const integer_type = expected_type.llvm.handle.to_integer();
const llvm_integer_value = integer_type.get_constant(value, @intFromBool(expected_type.bb.integer.signed));
const integer_value = module.values.add();
integer_value.* = .{
.llvm = llvm_integer_value.to_value(),
.type = expected_type,
.bb = .constant_integer,
.bb = .{
.constant_integer = .{
.value = absolute_value,
.signed = sign,
},
},
};
return integer_value;
}
@ -1251,22 +1296,8 @@ const Converter = struct {
@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]);
ty.llvm = array_type_llvm(module, array);
ty.name = array_type_name(element_count, array);
}
const array_elements = element_buffer[0..element_count];
@ -1511,6 +1542,7 @@ pub noinline fn convert(options: ConvertOptions) void {
}
var is_export = false;
var is_extern = false;
const global_line = converter.get_line();
const global_column = converter.get_column();
@ -1525,7 +1557,7 @@ pub noinline fn convert(options: ConvertOptions) void {
const global_keyword = string_to_enum(GlobalKeyword, global_keyword_string) orelse converter.report_error();
switch (global_keyword) {
.@"export" => is_export = true,
else => converter.report_error(),
.@"extern" => is_extern = true,
}
switch (converter.content[converter.offset]) {
@ -1667,9 +1699,6 @@ pub noinline fn convert(options: ConvertOptions) void {
for (arguments, argument_types, debug_argument_types[1..]) |*argument, *argument_type, *debug_argument_type| {
argument_type.* = argument.type.llvm.handle;
debug_argument_type.* = argument.type.llvm.debug;
if (module.llvm.di_builder) |_| {
assert(@intFromPtr(argument.type.llvm.debug) != 0xaaaa_aaaa_aaaa_aaaa);
}
}
},
// TODO: C calling convention
@ -1680,7 +1709,7 @@ pub noinline fn convert(options: ConvertOptions) void {
const llvm_function_type = llvm.Type.Function.get(return_type.llvm.handle, argument_types, false);
const llvm_handle = module.llvm.handle.create_function(.{
.name = global_name,
.linkage = switch (is_export) {
.linkage = switch (is_export or is_extern) {
true => .ExternalLinkage,
false => .InternalLinkage,
},
@ -1688,19 +1717,15 @@ pub noinline fn convert(options: ConvertOptions) void {
});
llvm_handle.set_calling_convention(calling_convention.to_llvm());
const entry_block = module.llvm.context.create_basic_block("entry", llvm_handle);
module.llvm.builder.position_at_end(entry_block);
const global = module.globals.add();
var subroutine_type: *llvm.DI.Type.Subroutine = undefined;
const current_scope: *llvm.DI.Scope = if (module.llvm.di_builder) |di_builder| blk: {
const subroutine_type_flags = llvm.DI.Flags{};
subroutine_type = di_builder.create_subroutine_type(module.llvm.file, debug_argument_types, subroutine_type_flags);
const scope_line: u32 = @intCast(converter.line_offset + 1);
const local_to_unit = !is_export;
const local_to_unit = !is_export and !is_extern;
const flags = llvm.DI.Flags{};
const is_definition = true;
const is_definition = !is_extern;
const subprogram = di_builder.create_function(module.llvm.global_scope, global_name, linkage_name, module.llvm.file, global_line, subroutine_type, local_to_unit, is_definition, scope_line, flags, options.build_mode.is_optimized());
llvm_handle.set_subprogram(subprogram);
@ -1729,76 +1754,98 @@ pub noinline fn convert(options: ConvertOptions) void {
},
});
const value = module.values.add();
value.* = .{
.llvm = llvm_handle.to_value(),
.type = function_type,
.bb = .{
.function = .{
.current_basic_block = entry_block,
.calling_convention = calling_convention,
.current_scope = current_scope,
},
},
};
global.* = .{
.value = value,
.name = global_name,
};
module.current_function = global;
defer module.current_function = null;
const argument_variables = global.value.bb.function.arguments.add_many(argument_count);
for (argument_variables, arguments) |*argument_variable, *argument| {
const argument_alloca = module.llvm.builder.create_alloca(argument.type.llvm.handle, argument.name);
const argument_value = module.values.add();
argument_value.* = .{
.llvm = argument_alloca,
.type = argument.type,
.bb = .argument,
if (converter.consume_character_if_match(';')) {
const value = module.values.add();
value.* = .{
.llvm = llvm_handle.to_value(),
.type = function_type,
.bb = .external_function,
};
argument_variable.* = .{
.value = argument_value,
.name = argument.name,
global.* = .{
.value = value,
.name = global_name,
};
}
} else {
const entry_block = module.llvm.context.create_basic_block("entry", llvm_handle);
module.llvm.builder.position_at_end(entry_block);
var llvm_argument_buffer: [argument_buffer.len]*llvm.Argument = undefined;
llvm_handle.get_arguments(&llvm_argument_buffer);
const llvm_arguments = llvm_argument_buffer[0..argument_count];
if (argument_count > 0) {
switch (calling_convention) {
.unknown => {
for (argument_variables, llvm_arguments) |*argument_variable, llvm_argument| {
_ = module.llvm.builder.create_store(llvm_argument.to_value(), argument_variable.value.llvm);
}
const value = module.values.add();
value.* = .{
.llvm = llvm_handle.to_value(),
.type = function_type,
.bb = .{
.function = .{
.current_basic_block = entry_block,
.calling_convention = calling_convention,
.current_scope = current_scope,
},
},
.c => @trap(),
};
global.* = .{
.value = value,
.name = global_name,
};
module.current_function = global;
defer module.current_function = null;
const argument_variables = global.value.bb.function.arguments.add_many(argument_count);
for (argument_variables, arguments) |*argument_variable, *argument| {
const argument_alloca = module.llvm.builder.create_alloca(argument.type.llvm.handle, argument.name);
const argument_value = module.values.add();
argument_value.* = .{
.llvm = argument_alloca,
.type = argument.type,
.bb = .argument,
};
argument_variable.* = .{
.value = argument_value,
.name = argument.name,
};
}
if (module.llvm.di_builder) |di_builder| {
for (argument_variables, arguments, 0..) |argument_variable, argument, argument_number| {
const always_preserve = true;
const flags = llvm.DI.Flags{};
const parameter_variable = di_builder.create_parameter_variable(global.value.bb.function.current_scope, argument_variable.name, @intCast(argument_number + 1), module.llvm.file, argument.line, argument.type.llvm.debug, always_preserve, flags);
const inlined_at: ?*llvm.DI.Metadata = null; // TODO
const debug_location = llvm.DI.create_debug_location(module.llvm.context, argument.line, argument.column, global.value.bb.function.current_scope, inlined_at);
_ = di_builder.insert_declare_record_at_end(argument_variable.value.llvm, parameter_variable, di_builder.null_expression(), debug_location, global.value.bb.function.current_basic_block);
var llvm_argument_buffer: [argument_buffer.len]*llvm.Argument = undefined;
llvm_handle.get_arguments(&llvm_argument_buffer);
const llvm_arguments = llvm_argument_buffer[0..argument_count];
if (argument_count > 0) {
switch (calling_convention) {
.unknown => {
for (argument_variables, llvm_arguments) |*argument_variable, llvm_argument| {
_ = module.llvm.builder.create_store(llvm_argument.to_value(), argument_variable.value.llvm);
}
},
.c => @trap(),
}
if (module.llvm.di_builder) |di_builder| {
for (argument_variables, arguments, 0..) |argument_variable, argument, argument_number| {
const always_preserve = true;
const flags = llvm.DI.Flags{};
const parameter_variable = di_builder.create_parameter_variable(global.value.bb.function.current_scope, argument_variable.name, @intCast(argument_number + 1), module.llvm.file, argument.line, argument.type.llvm.debug, always_preserve, flags);
const inlined_at: ?*llvm.DI.Metadata = null; // TODO
const debug_location = llvm.DI.create_debug_location(module.llvm.context, argument.line, argument.column, global.value.bb.function.current_scope, inlined_at);
_ = di_builder.insert_declare_record_at_end(argument_variable.value.llvm, parameter_variable, di_builder.null_expression(), debug_location, global.value.bb.function.current_basic_block);
}
}
}
converter.parse_block(module);
if (lib.optimization_mode == .Debug and module.llvm.di_builder == null) {
const verify_result = llvm_handle.verify();
if (!verify_result.success) {
os.abort();
}
}
}
converter.parse_block(module);
if (module.llvm.di_builder) |di_builder| {
di_builder.finalize_subprogram(llvm_handle.get_subprogram());
}
if (lib.optimization_mode == .Debug and module.llvm.di_builder == null) {
} else if (lib.optimization_mode == .Debug and global.value.bb == .function) {
const verify_result = llvm_handle.verify();
if (!verify_result.success) {
os.abort();

View File

@ -86,20 +86,20 @@ ByVal = struct
[extern] run_c_tests = fn [cc(c)] () void;
[extern] c_u8 = fn [cc(.c)] (x: u8) void;
[extern] c_u16 = fn [cc(.c)] (x: u16) void;
[extern] c_u32 = fn [cc(.c)] (x: u32) void;
[extern] c_u64 = fn [cc(.c)] (x: u64) void;
[extern] c_u8 = fn [cc(c)] (x: u8) void;
[extern] c_u16 = fn [cc(c)] (x: u16) void;
[extern] c_u32 = fn [cc(c)] (x: u32) void;
[extern] c_u64 = fn [cc(c)] (x: u64) void;
[extern] c_s8 = fn [cc(.c)] (x: s8) void;
[extern] c_s16 = fn [cc(.c)] (x: s16) void;
[extern] c_s32 = fn [cc(.c)] (x: s32) void;
[extern] c_s64 = fn [cc(.c)] (x: s64) void;
[extern] c_s8 = fn [cc(c)] (x: s8) void;
[extern] c_s16 = fn [cc(c)] (x: s16) void;
[extern] c_s32 = fn [cc(c)] (x: s32) void;
[extern] c_s64 = fn [cc(c)] (x: s64) void;
[extern] c_bool = fn [cc(.c)] (x: u8) void;
[extern] c_bool = fn [cc(c)] (x: u8) void;
[extern] c_five_integers = fn [cc(.c)] (a: s32, b: s32, c: s32, d: s32, e: s32) void;
[extern] c_ret_struct_u64_u64 = fn [cc(.c)] () Struct_u64_u64;
[extern] c_five_integers = fn [cc(c)] (a: s32, b: s32, c: s32, d: s32, e: s32) void;
[extern] c_ret_struct_u64_u64 = fn [cc(c)] () Struct_u64_u64;
[extern] c_struct_u64_u64_0 = fn [cc(c)] (a: Struct_u64_u64) void;
[extern] c_struct_u64_u64_1 = fn [cc(c)] (a: u64, b: Struct_u64_u64) void;
@ -111,33 +111,33 @@ ByVal = struct
[extern] c_struct_u64_u64_7 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, h: Struct_u64_u64) void;
[extern] c_struct_u64_u64_8 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, h: u64, i: Struct_u64_u64) void;
[extern] c_big_struct = fn [cc(.c)] (x: BigStruct) void;
[extern] c_small_struct_ints = fn [cc(.c)] (x: SmallStructInts) void;
[extern] c_ret_small_struct_ints = fn [cc(.c)] () SmallStructInts;
[extern] c_med_struct_ints = fn [cc(.c)] (x: MedStructInts) void;
[extern] c_ret_med_struct_ints = fn [cc(.c)] () MedStructInts;
[extern] c_small_packed_struct = fn [cc(.c)] (x: SmallPackedStruct) void;
[extern] c_ret_small_packed_struct = fn [cc(.c)] () SmallPackedStruct;
[extern] c_split_struct_ints = fn [cc(.c)] (x: SplitStructInt) void;
[extern] c_big_struct_both = fn [cc(.c)] (x: BigStruct) BigStruct;
[extern] c_multiple_struct_ints = fn [cc(.c)] (a: Rect, b: Rect) void;
[extern] c_big_struct = fn [cc(c)] (x: BigStruct) void;
[extern] c_small_struct_ints = fn [cc(c)] (x: SmallStructInts) void;
[extern] c_ret_small_struct_ints = fn [cc(c)] () SmallStructInts;
[extern] c_med_struct_ints = fn [cc(c)] (x: MedStructInts) void;
[extern] c_ret_med_struct_ints = fn [cc(c)] () MedStructInts;
[extern] c_small_packed_struct = fn [cc(c)] (x: SmallPackedStruct) void;
[extern] c_ret_small_packed_struct = fn [cc(c)] () SmallPackedStruct;
[extern] c_split_struct_ints = fn [cc(c)] (x: SplitStructInt) void;
[extern] c_big_struct_both = fn [cc(c)] (x: BigStruct) BigStruct;
[extern] c_multiple_struct_ints = fn [cc(c)] (a: Rect, b: Rect) void;
[extern] c_ret_bool = fn [cc(.c)] () u8;
[extern] c_ret_bool = fn [cc(c)] () u8;
[extern] c_ret_u8 = fn [cc(.c)] () u8;
[extern] c_ret_u16 = fn [cc(.c)] () u16;
[extern] c_ret_u32 = fn [cc(.c)] () u32;
[extern] c_ret_u64 = fn [cc(.c)] () u64;
[extern] c_ret_u8 = fn [cc(c)] () u8;
[extern] c_ret_u16 = fn [cc(c)] () u16;
[extern] c_ret_u32 = fn [cc(c)] () u32;
[extern] c_ret_u64 = fn [cc(c)] () u64;
[extern] c_ret_s8 = fn [cc(.c)] () s8;
[extern] c_ret_s16 = fn [cc(.c)] () s16;
[extern] c_ret_s32 = fn [cc(.c)] () s32;
[extern] c_ret_s64 = fn [cc(.c)] () s64;
[extern] c_ret_s8 = fn [cc(c)] () s8;
[extern] c_ret_s16 = fn [cc(c)] () s16;
[extern] c_ret_s32 = fn [cc(c)] () s32;
[extern] c_ret_s64 = fn [cc(c)] () s64;
[extern] c_struct_with_array = fn [cc(.c)] (x: StructWithArray) void;
[extern] c_ret_struct_with_array = fn [cc(.c)] () StructWithArray;
[extern] c_struct_with_array = fn [cc(c)] (x: StructWithArray) void;
[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;
[export] require = fn [cc(c)] (ok: u8)
@ -174,8 +174,8 @@ ByVal = struct
c_five_integers(12, 34, 56, 78, 90);
>s = c_ret_struct_u64_u64();
#require(s.a == 21);
#require(s.b == 22);
require(s.a == 21);
require(s.b == 22);
c_struct_u64_u64_0({ .a = 23, .b = 24, });
c_struct_u64_u64_1(0, { .a = 25, .b = 26, });
c_struct_u64_u64_2(0, 1, { .a = 27, .b = 28, });
@ -203,10 +203,10 @@ ByVal = struct
};
c_small_struct_ints(small);
>small2 = c_ret_small_struct_ints();
#require(small2.a == 1);
#require(small2.b == 2);
#require(small2.c == 3);
#require(small2.d == 4);
require(small2.a == 1);
require(small2.b == 2);
require(small2.c == 3);
require(small2.d == 4);
>med: MedStructInts = {
.x = 1,
@ -215,17 +215,17 @@ ByVal = struct
};
c_med_struct_ints(med);
>med2 = c_ret_med_struct_ints();
#require(med2.x == 1);
#require(med2.y == 2);
#require(med2.z == 3);
require(med2.x == 1);
require(med2.y == 2);
require(med2.z == 3);
>p: SmallPackedStruct = { .a = 0, .b = 1, .c = 2, .d = 3, };
c_small_packed_struct(p);
>p2 = c_ret_small_packed_struct();
#require(p2.a == 0);
#require(p2.b == 1);
#require(p2.c == 2);
#require(p2.d == 3);
require(p2.a == 0);
require(p2.b == 1);
require(p2.c == 2);
require(p2.d == 3);
>split: SplitStructInt = {
.a = 1234,
@ -242,11 +242,11 @@ ByVal = struct
.e = 5,
};
>big2 = c_big_struct_both(big);
#require(big2.a == 10);
#require(big2.b == 11);
#require(big2.c == 12);
#require(big2.d == 13);
#require(big2.e == 14);
require(big2.a == 10);
require(big2.b == 11);
require(big2.c == 12);
require(big2.d == 13);
require(big2.e == 14);
>r1: Rect = {
.left = 1,
@ -262,26 +262,26 @@ ByVal = struct
};
c_multiple_struct_ints(r1, r2);
#require(c_ret_bool() == 1);
require(c_ret_bool() == 1);
#require(c_ret_u8() == 0xff);
#require(c_ret_u16() == 0xffff);
#require(c_ret_u32() == 0xffffffff);
#require(c_ret_u64() == 0xffffffffffffffff);
require(c_ret_u8() == 0xff);
require(c_ret_u16() == 0xffff);
require(c_ret_u32() == 0xffffffff);
require(c_ret_u64() == 0xffffffffffffffff);
#require(c_ret_s8() == -1);
#require(c_ret_s16() == -1);
#require(c_ret_s32() == -1);
#require(c_ret_s64() == -1);
require(c_ret_s8() == -1);
require(c_ret_s16() == -1);
require(c_ret_s32() == -1);
require(c_ret_s64() == -1);
c_struct_with_array({ .a = 1, .padding = undefined, .b = 2, });
>x = c_ret_struct_with_array();
#require(x.a == 4);
#require(x.b == 155);
require(x.a == 4);
require(x.b == 155);
>res = c_modify_by_ref_param({ .val = 1, .arr = undefined, });
#require(res.val == 42);
require(res.val == 42);
>function_pointer = c_func_ptr_byval&;
function_pointer(1, 2, { .origin = { .x = 9, .y = 10, .z = 11, }, .size = { .width = 12, .height = 13, .depth = 14, }, }, 3, 4, 5);
@ -290,61 +290,61 @@ ByVal = struct
[export] bb_u8 = fn [cc(c)] (x: u8) void
{
#require(x == 0xff);
require(x == 0xff);
}
[export] bb_u16 = fn [cc(c)] (x: u16) void
{
#require(x == 0xfffe);
require(x == 0xfffe);
}
[export] bb_u32 = fn [cc(c)] (x: u32) void
{
#require(x == 0xfffffffd);
require(x == 0xfffffffd);
}
[export] bb_u64 = fn [cc(c)] (x: u64) void
{
#require(x == 0xfffffffffffffffc);
require(x == 0xfffffffffffffffc);
}
[export] bb_s8 = fn [cc(c)] (x: s8) void
{
#require(x == -1);
require(x == -1);
}
[export] bb_s16 = fn [cc(c)] (x: s16) void
{
#require(x == -2);
require(x == -2);
}
[export] bb_s32 = fn [cc(c)] (x: s32) void
{
#require(x == -3);
require(x == -3);
}
[export] bb_s64 = fn [cc(c)] (x: s64) void
{
#require(x == -4);
require(x == -4);
}
[export] bb_ptr = fn [cc(c)] (x: *u8) void
{
#require(#int_from_pointer(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
{
#require(a == 12);
#require(b == 34);
#require(c == 56);
#require(d == 78);
#require(e == 90);
require(a == 12);
require(b == 34);
require(c == 56);
require(d == 78);
require(e == 90);
}
[export] bb_bool = fn [cc(c)] (x: u8) void
{
#require(x);
require(x);
}
[export] bb_ret_struct_u64_u64 = fn [cc(c)] () Struct_u64_u64
@ -354,89 +354,89 @@ ByVal = struct
[export] bb_struct_u64_u64_0 = fn [cc(c)] (s: Struct_u64_u64) void
{
#require(s.a == 3);
#require(s.b == 4);
require(s.a == 3);
require(s.b == 4);
}
[export] bb_struct_u64_u64_1 = fn [cc(c)] (_: u64, s: Struct_u64_u64) void
{
#require(s.a == 5);
#require(s.b == 6);
require(s.a == 5);
require(s.b == 6);
}
[export] bb_struct_u64_u64_2 = fn [cc(c)] (_: u64, _: u64, s: Struct_u64_u64) void
{
#require(s.a == 7);
#require(s.b == 8);
require(s.a == 7);
require(s.b == 8);
}
[export] bb_struct_u64_u64_3 = fn [cc(c)] (_: u64, _: u64, _: u64, s: Struct_u64_u64) void
{
#require(s.a == 9);
#require(s.b == 10);
require(s.a == 9);
require(s.b == 10);
}
[export] bb_struct_u64_u64_4 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
{
#require(s.a == 11);
#require(s.b == 12);
require(s.a == 11);
require(s.b == 12);
}
[export] bb_struct_u64_u64_5 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
{
#require(s.a == 13);
#require(s.b == 14);
require(s.a == 13);
require(s.b == 14);
}
[export] bb_struct_u64_u64_6 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
{
#require(s.a == 15);
#require(s.b == 16);
require(s.a == 15);
require(s.b == 16);
}
[export] bb_struct_u64_u64_7 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
{
#require(s.a == 17);
#require(s.b == 18);
require(s.a == 17);
require(s.b == 18);
}
[export] bb_struct_u64_u64_8 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
{
#require(s.a == 19);
#require(s.b == 20);
require(s.a == 19);
require(s.b == 20);
}
[export] bb_big_struct = fn [cc(c)] (x: BigStruct) void
{
#require(x.a == 1);
#require(x.b == 2);
#require(x.c == 3);
#require(x.d == 4);
#require(x.e == 5);
require(x.a == 1);
require(x.b == 2);
require(x.c == 3);
require(x.d == 4);
require(x.e == 5);
}
[export] bb_small_packed_struct = fn [cc(c)] (x: SmallPackedStruct) void
{
#require(x.a == 0);
#require(x.b == 1);
#require(x.c == 2);
#require(x.d == 3);
require(x.a == 0);
require(x.b == 1);
require(x.c == 2);
require(x.d == 3);
}
[export] bb_split_struct_ints = fn [cc(c)] (x: SplitStructInt) void
{
#require(x.a == 1234);
#require(x.b == 100);
#require(x.c == 1337);
require(x.a == 1234);
require(x.b == 100);
require(x.c == 1337);
}
[export] bb_big_struct_both = fn [cc(c)] (x: BigStruct) BigStruct
{
#require(x.a == 30);
#require(x.b == 31);
#require(x.c == 32);
#require(x.d == 33);
#require(x.e == 34);
require(x.a == 30);
require(x.b == 31);
require(x.c == 32);
require(x.d == 33);
require(x.e == 34);
>s: BigStruct = {
.a = 20,
.b = 21,
@ -513,27 +513,27 @@ ByVal = struct
[export] bb_multiple_struct_ints = fn [cc(c)] (x: Rect, y: Rect) void
{
#require(x.left == 1);
#require(x.right == 21);
#require(x.top == 16);
#require(x.bottom == 4);
#require(y.left == 178);
#require(y.right == 189);
#require(y.top == 21);
#require(y.bottom == 15);
require(x.left == 1);
require(x.right == 21);
require(x.top == 16);
require(x.bottom == 4);
require(y.left == 178);
require(y.right == 189);
require(y.top == 21);
require(y.bottom == 15);
}
[export] bb_small_struct_ints = fn [cc(c)] (x: SmallStructInts) void
{
#require(x.a == 1);
#require(x.b == 2);
#require(x.c == 3);
#require(x.d == 4);
require(x.a == 1);
require(x.b == 2);
require(x.c == 3);
require(x.d == 4);
}
[export] bb_med_struct_ints = fn [cc(c)] (s: MedStructInts) void
{
#require(s.x == 1);
#require(s.y == 2);
#require(s.z == 3);
require(s.x == 1);
require(s.y == 2);
require(s.z == 3);
}