Extern function
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 41s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 40s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 48s
CI / ci (Debug, ubuntu-latest) (push) Successful in 1m8s

This commit is contained in:
David Gonzalez Martin 2025-04-10 07:30:28 -06:00
parent 93805ebe9f
commit 1febc390a8
2 changed files with 410 additions and 401 deletions

View File

@ -505,6 +505,7 @@ pub const Call = struct {
pub const Value = struct { pub const Value = struct {
bb: union(enum) { bb: union(enum) {
external_function,
function: Function, function: Function,
constant_integer: ConstantInteger, constant_integer: ConstantInteger,
unary: Unary, unary: Unary,
@ -1053,8 +1054,7 @@ pub const Module = struct {
const ty = module.integer_type(bit_count, signedness); const ty = module.integer_type(bit_count, signedness);
return ty; return ty;
} else if (lib.string.equal(identifier, "noreturn")) { } else if (lib.string.equal(identifier, "noreturn")) {
@trap(); return module.noreturn_type;
// return module.noreturn_type;
} else { } else {
const ty = module.types.find_by_name(identifier) orelse @trap(); const ty = module.types.find_by_name(identifier) orelse @trap();
return ty; return ty;
@ -2262,8 +2262,7 @@ pub const Module = struct {
storage.bb.function.main_block = module.parse_block(); storage.bb.function.main_block = module.parse_block();
} else { } else {
// TODO: initialize value.bb storage.bb = .external_function;
@trap();
} }
}, },
else => @trap(), else => @trap(),
@ -2355,10 +2354,9 @@ pub const Module = struct {
for (module.globals.get_slice()) |*global| { for (module.globals.get_slice()) |*global| {
switch (global.variable.storage.?.bb) { switch (global.variable.storage.?.bb) {
.function => { .function, .external_function => {
const function_type = &global.variable.storage.?.type.?.bb.pointer.type.bb.function; const function_type = &global.variable.storage.?.type.?.bb.pointer.type.bb.function;
const argument_variables = global.variable.storage.?.bb.function.arguments; function_type.argument_abis = module.arena.allocate(Abi.Information, function_type.semantic_argument_types.len);
function_type.argument_abis = module.arena.allocate(Abi.Information, argument_variables.len);
const resolved_calling_convention = function_type.calling_convention.resolve(module.target); const resolved_calling_convention = function_type.calling_convention.resolve(module.target);
const is_reg_call = resolved_calling_convention == .system_v and false; // TODO: regcall calling_convention const is_reg_call = resolved_calling_convention == .system_v and false; // TODO: regcall calling_convention
@ -2366,6 +2364,7 @@ pub const Module = struct {
var llvm_abi_argument_type_buffer: [64]*llvm.Type = undefined; var llvm_abi_argument_type_buffer: [64]*llvm.Type = undefined;
var abi_argument_type_buffer: [64]*Type = undefined; var abi_argument_type_buffer: [64]*Type = undefined;
var abi_argument_type_count: u16 = 0; var abi_argument_type_count: u16 = 0;
switch (resolved_calling_convention) { switch (resolved_calling_convention) {
.system_v => { .system_v => {
function_type.available_registers = switch (resolved_calling_convention) { function_type.available_registers = switch (resolved_calling_convention) {
@ -2417,6 +2416,7 @@ pub const Module = struct {
@trap(); @trap();
}, },
} }
const llvm_abi_argument_types = llvm_abi_argument_type_buffer[0..abi_argument_type_count]; const llvm_abi_argument_types = llvm_abi_argument_type_buffer[0..abi_argument_type_count];
const llvm_function_type = llvm.Type.Function.get(function_type.abi_return_type.resolve(module).handle, llvm_abi_argument_types, function_type.is_var_args); const llvm_function_type = llvm.Type.Function.get(function_type.abi_return_type.resolve(module).handle, llvm_abi_argument_types, function_type.is_var_args);
@ -2459,7 +2459,10 @@ pub const Module = struct {
.abi_argument_types = function_type.abi_argument_types, .abi_argument_types = function_type.abi_argument_types,
.argument_type_abis = function_type.argument_abis, .argument_type_abis = function_type.argument_abis,
.return_type_abi = function_type.return_abi, .return_type_abi = function_type.return_abi,
.attributes = global.variable.storage.?.bb.function.attributes, .attributes = switch (global.variable.storage.?.bb) {
.function => |function| function.attributes,
else => .{},
},
.call_site = false, .call_site = false,
}); });
@ -2474,6 +2477,7 @@ pub const Module = struct {
const flags = llvm.DI.Flags{}; const flags = llvm.DI.Flags{};
const is_definition = switch (global.variable.storage.?.bb) { const is_definition = switch (global.variable.storage.?.bb) {
.function => true, .function => true,
.external_function => false,
else => @trap(), else => @trap(),
}; };
const name = global.variable.name; const name = global.variable.name;
@ -2483,6 +2487,8 @@ pub const Module = struct {
break :blk @ptrCast(subprogram); break :blk @ptrCast(subprogram);
} else undefined; } else undefined;
if (global.variable.storage.?.bb == .function) {
global.variable.storage.?.bb.function.scope.llvm = function_scope; global.variable.storage.?.bb.function.scope.llvm = function_scope;
const entry_block = module.llvm.context.create_basic_block("entry", llvm_function_value); const entry_block = module.llvm.context.create_basic_block("entry", llvm_function_value);
@ -2518,7 +2524,7 @@ pub const Module = struct {
}, },
} }
// const argument_variables = global.value.bb.function.arguments.add_many(semantic_argument_count); const argument_variables = global.variable.storage.?.bb.function.arguments;
for ( for (
//semantic_arguments, //semantic_arguments,
function_type.argument_abis, argument_variables, 0..) | function_type.argument_abis, argument_variables, 0..) |
@ -2776,6 +2782,7 @@ pub const Module = struct {
module.llvm.builder.create_ret_void(); module.llvm.builder.create_ret_void();
} }
} }
}
if (lib.optimization_mode == .Debug) { if (lib.optimization_mode == .Debug) {
const verify_result = llvm_function_value.verify(); const verify_result = llvm_function_value.verify();
@ -3467,7 +3474,7 @@ pub const Module = struct {
if (variable.type != expected_type) { if (variable.type != expected_type) {
module.report_error(); module.report_error();
} }
} },
}, },
.intrinsic => |intrinsic| switch (intrinsic) { .intrinsic => |intrinsic| switch (intrinsic) {
.extend => |extended_value| { .extend => |extended_value| {
@ -3533,7 +3540,9 @@ pub const Module = struct {
module.report_error(); module.report_error();
} }
for (call.arguments, call.function_type.bb.function.semantic_argument_types) |argument, argument_type| { for (call.arguments, call.function_type.bb.function.semantic_argument_types) |argument, argument_type| {
module.analyze_value_type(function, argument, .{ .type = argument_type, }); module.analyze_value_type(function, argument, .{
.type = argument_type,
});
} }
if (call.function_type.bb.function.semantic_return_type != expected_type) { if (call.function_type.bb.function.semantic_return_type != expected_type) {
@ -4408,8 +4417,7 @@ pub const Abi = struct {
result[current_index] = .memory; result[current_index] = .memory;
switch (ty.bb) { switch (ty.bb) {
.void => result[current_index] = .none, .void, .noreturn => result[current_index] = .none,
// .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| {

View File

@ -200,4 +200,5 @@ const names = &[_][]const u8{
"local_type_inference", "local_type_inference",
"global", "global",
"function_pointer", "function_pointer",
"extern",
}; };