Merge pull request #236 from birth-software/start-preparing-for-c
Start preparing for C compilation
This commit is contained in:
commit
5347b1f0e9
@ -1,6 +1,7 @@
|
||||
const compiler = @import("../compiler.zig");
|
||||
const LLVM = compiler.LLVM;
|
||||
|
||||
pub extern fn NativityLLVMInitializeAll() void;
|
||||
pub extern fn NativityLLVMCreateContext() *LLVM.Context;
|
||||
pub extern fn NativityLLVMCreateModule(module_name_ptr: [*]const u8, module_name_len: usize, context: *LLVM.Context) *LLVM.Module;
|
||||
pub extern fn NativityLLVMCreateBuilder(context: *LLVM.Context) *LLVM.Builder;
|
||||
|
@ -3069,6 +3069,7 @@ const Job = packed struct(u64) {
|
||||
llvm_optimize,
|
||||
llvm_emit_object,
|
||||
llvm_notify_object_done,
|
||||
compile_c_source_file,
|
||||
};
|
||||
};
|
||||
|
||||
@ -3322,6 +3323,7 @@ const Unit = struct {
|
||||
main_source_file_path: []const u8,
|
||||
executable_path: []const u8,
|
||||
object_path: []const u8,
|
||||
c_source_files: []const []const u8,
|
||||
target: Target,
|
||||
optimization: Optimization,
|
||||
generate_debug_information: bool,
|
||||
@ -3336,6 +3338,9 @@ const Unit = struct {
|
||||
.descriptor = descriptor,
|
||||
};
|
||||
|
||||
if (descriptor.c_source_files.len > 0) {
|
||||
LLVM.initializeAll();
|
||||
} else {
|
||||
switch (unit.descriptor.target.arch) {
|
||||
inline else => |a| {
|
||||
const arch = @field(LLVM, @tagName(a));
|
||||
@ -3346,24 +3351,37 @@ const Unit = struct {
|
||||
arch.initializeAsmParser();
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const main_source_file_absolute = instance.path_from_cwd(instance.arena, unit.descriptor.main_source_file_path);
|
||||
const new_file_index = add_file(main_source_file_absolute, &.{});
|
||||
instance.threads[0].task_system.program_state = .analysis;
|
||||
instance.threads[0].add_thread_work(Job{
|
||||
var last_assigned_thread_index: u32 = 0;
|
||||
instance.threads[last_assigned_thread_index].task_system.program_state = .analysis;
|
||||
instance.threads[last_assigned_thread_index].add_thread_work(Job{
|
||||
.offset = new_file_index,
|
||||
.count = 1,
|
||||
.id = .analyze_file,
|
||||
});
|
||||
control_thread(unit);
|
||||
last_assigned_thread_index += 1;
|
||||
|
||||
for (descriptor.c_source_files, 0..) |_, index| {
|
||||
const thread_index = last_assigned_thread_index % instance.threads.len;
|
||||
instance.threads[thread_index].add_thread_work(Job{
|
||||
.offset = @intCast(index),
|
||||
.count = 1,
|
||||
.id = .compile_c_source_file,
|
||||
});
|
||||
last_assigned_thread_index += 1;
|
||||
}
|
||||
|
||||
control_thread(unit, last_assigned_thread_index);
|
||||
|
||||
return unit;
|
||||
}
|
||||
};
|
||||
|
||||
fn control_thread(unit: *Unit) void {
|
||||
var last_assigned_thread_index: u32 = 1;
|
||||
fn control_thread(unit: *Unit, lati: u32) void {
|
||||
var last_assigned_thread_index: u32 = lati;
|
||||
var first_ir_done = false;
|
||||
var total_is_done: bool = false;
|
||||
var iterations_without_work_done: u32 = 0;
|
||||
@ -3613,6 +3631,7 @@ fn command_exe(arguments: []const []const u8) void {
|
||||
.main_source_file_path = main_source_file_path,
|
||||
.object_path = object_path,
|
||||
.executable_path = executable_path,
|
||||
.c_source_files = &.{},
|
||||
.optimization = optimization,
|
||||
.generate_debug_information = generate_debug_information,
|
||||
.codegen_backend = .{
|
||||
@ -6650,6 +6669,7 @@ fn get_array_type(thread: *Thread, descriptor: Type.Array.Descriptor) *Type {
|
||||
|
||||
pub const LLVM = struct {
|
||||
const bindings = @import("backend/llvm_bindings.zig");
|
||||
pub const initializeAll = bindings.NativityLLVMInitializeAll;
|
||||
pub const x86_64 = struct {
|
||||
pub const initializeTarget = bindings.LLVMInitializeX86Target;
|
||||
pub const initializeTargetInfo = bindings.LLVMInitializeX86TargetInfo;
|
||||
|
@ -31,32 +31,35 @@ fn collectDirectoryDirEntries(allocator: Allocator, path: []const u8) ![]const [
|
||||
|
||||
const bootstrap_relative_path = "zig-out/bin/nat";
|
||||
|
||||
fn runStandalone(allocator: Allocator, args: struct {
|
||||
directory_path: []const u8,
|
||||
group_name: []const u8,
|
||||
self_hosted: bool,
|
||||
is_test: bool,
|
||||
compiler_path: []const u8,
|
||||
const Run = struct{
|
||||
compilation_run: usize = 0,
|
||||
compilation_failure: usize = 0,
|
||||
test_run: usize = 0,
|
||||
test_failure: usize = 0,
|
||||
|
||||
fn add(run: *Run, other: Run) void {
|
||||
run.compilation_run += other.compilation_run;
|
||||
run.compilation_failure += other.compilation_failure;
|
||||
run.test_run += other.test_run;
|
||||
run.test_failure += other.test_failure;
|
||||
}
|
||||
};
|
||||
|
||||
fn compiler_run(allocator: Allocator, args: struct{
|
||||
test_name: []const u8,
|
||||
repetitions: usize,
|
||||
}) !void {
|
||||
const test_names = try collectDirectoryDirEntries(allocator, args.directory_path);
|
||||
std.debug.assert(args.repetitions > 0);
|
||||
extra_arguments: []const []const u8,
|
||||
source_file_path: []const u8,
|
||||
compiler_path: []const u8,
|
||||
is_test: bool,
|
||||
self_hosted: bool,
|
||||
}) !Run {
|
||||
std.debug.print("{s} [repetitions={}] {s}", .{args.test_name, args.repetitions, if (args.repetitions > 1) "\n\n" else ""});
|
||||
var run = Run{};
|
||||
|
||||
const total_compilation_count = test_names.len;
|
||||
var ran_compilation_count: usize = 0;
|
||||
var failed_compilation_count: usize = 0;
|
||||
|
||||
var ran_test_count: usize = 0;
|
||||
var failed_test_count: usize = 0;
|
||||
const total_test_count = test_names.len;
|
||||
|
||||
std.debug.print("\n[{s} START]\n\n", .{args.group_name});
|
||||
|
||||
for (test_names) |test_name| {
|
||||
std.debug.print("{s} [repetitions={}]{s}", .{test_name, args.repetitions, if (args.repetitions > 1) "\n\n" else ""});
|
||||
for (0..args.repetitions) |_| {
|
||||
const source_file_path = try std.mem.concat(allocator, u8, &.{ args.directory_path, "/", test_name, "/main.nat" });
|
||||
const argv: []const []const u8 = &.{ args.compiler_path, if (args.is_test) "test" else "exe", "-main_source_file", source_file_path };
|
||||
const base_argv: []const []const u8 = &.{ args.compiler_path, if (args.is_test) "test" else "exe", "-main_source_file", args.source_file_path };
|
||||
const argv = try std.mem.concat(allocator, []const u8, &.{base_argv, args.extra_arguments});
|
||||
// if (std.mem.eql(u8, args.compiler_path, "nat/compiler_lightly_optimize_for_speed")) @breakpoint();
|
||||
const compile_run = try std.process.Child.run(.{
|
||||
.allocator = allocator,
|
||||
@ -64,7 +67,7 @@ fn runStandalone(allocator: Allocator, args: struct {
|
||||
.argv = argv,
|
||||
.max_output_bytes = std.math.maxInt(u64),
|
||||
});
|
||||
ran_compilation_count += 1;
|
||||
run.compilation_run += 1;
|
||||
|
||||
const compilation_result: TestError!bool = switch (compile_run.term) {
|
||||
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
||||
@ -74,7 +77,7 @@ fn runStandalone(allocator: Allocator, args: struct {
|
||||
};
|
||||
|
||||
const compilation_success = compilation_result catch b: {
|
||||
failed_compilation_count += 1;
|
||||
run.compilation_failure += 1;
|
||||
break :b false;
|
||||
};
|
||||
|
||||
@ -87,13 +90,13 @@ fn runStandalone(allocator: Allocator, args: struct {
|
||||
}
|
||||
|
||||
if (compilation_success and !args.self_hosted) {
|
||||
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name });
|
||||
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", args.test_name });
|
||||
const test_run = try std.process.Child.run(.{
|
||||
.allocator = allocator,
|
||||
.argv = &.{test_path},
|
||||
.max_output_bytes = std.math.maxInt(u64),
|
||||
});
|
||||
ran_test_count += 1;
|
||||
run.test_run += 1;
|
||||
const test_result: TestError!bool = switch (test_run.term) {
|
||||
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
||||
.Signal => error.signaled,
|
||||
@ -102,9 +105,10 @@ fn runStandalone(allocator: Allocator, args: struct {
|
||||
};
|
||||
|
||||
const test_success = test_result catch b: {
|
||||
failed_test_count += 1;
|
||||
break :b false;
|
||||
};
|
||||
run.test_failure += @intFromBool(!test_success);
|
||||
|
||||
std.debug.print("[TEST {s}]\n", .{if (test_success) "\x1b[32mOK\x1b[0m" else "\x1b[31mFAILED\x1b[0m"});
|
||||
if (test_run.stdout.len > 0) {
|
||||
std.debug.print("STDOUT:\n\n{s}\n\n", .{test_run.stdout});
|
||||
@ -116,16 +120,56 @@ fn runStandalone(allocator: Allocator, args: struct {
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
}
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
std.debug.print("\n{s} COMPILATIONS: {}. FAILED: {}\n", .{ args.group_name, total_compilation_count, failed_compilation_count });
|
||||
std.debug.print("{s} TESTS: {}. RAN: {}. FAILED: {}\n", .{ args.group_name, total_test_count, ran_test_count, failed_test_count });
|
||||
fn group_start(group: []const u8, test_count: usize) void {
|
||||
std.debug.print("\n[{s} START ({} tests queued)]\n\n", .{group, test_count});
|
||||
}
|
||||
|
||||
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
||||
fn group_end(group: []const u8, test_count: usize, run: Run) !void {
|
||||
std.debug.print("\n{s} COMPILATIONS: {}. FAILED: {}\n", .{ group, test_count, run.compilation_failure });
|
||||
std.debug.print("{s} TESTS: {}. RAN: {}. FAILED: {}\n", .{ group, test_count, run.test_run, run.test_failure });
|
||||
std.debug.print("\n[{s} END]\n\n", .{group});
|
||||
|
||||
if (run.compilation_failure > 0 or run.test_failure > 0) {
|
||||
return error.fail;
|
||||
}
|
||||
}
|
||||
|
||||
fn runStandalone(allocator: Allocator, args: struct {
|
||||
directory_path: []const u8,
|
||||
group_name: []const u8,
|
||||
self_hosted: bool,
|
||||
is_test: bool,
|
||||
compiler_path: []const u8,
|
||||
repetitions: usize,
|
||||
}) !void {
|
||||
const test_names = try collectDirectoryDirEntries(allocator, args.directory_path);
|
||||
std.debug.assert(args.repetitions > 0);
|
||||
|
||||
var total_run = Run{};
|
||||
|
||||
group_start(args.group_name, test_names.len * args.repetitions);
|
||||
|
||||
for (test_names) |test_name| {
|
||||
const source_file_path = try std.mem.concat(allocator, u8, &.{ args.directory_path, "/", test_name, "/main.nat" });
|
||||
const run = try compiler_run(allocator, .{
|
||||
.compiler_path = args.compiler_path,
|
||||
.source_file_path = source_file_path,
|
||||
.test_name = test_name,
|
||||
.repetitions = args.repetitions,
|
||||
.extra_arguments = &.{},
|
||||
.is_test = args.is_test,
|
||||
.self_hosted = args.self_hosted,
|
||||
});
|
||||
total_run.add(run);
|
||||
}
|
||||
|
||||
try group_end(args.group_name, test_names.len * args.repetitions, total_run);
|
||||
}
|
||||
|
||||
fn runBuildTests(allocator: Allocator, args: struct {
|
||||
self_hosted: bool,
|
||||
compiler_path: []const u8,
|
||||
@ -583,6 +627,22 @@ fn run_test_suite(allocator: Allocator, args: struct {
|
||||
return errors;
|
||||
}
|
||||
|
||||
fn c_abi_tests(allocator: Allocator) !void {
|
||||
const test_count = 1;
|
||||
const group = "C ABI";
|
||||
group_start(group, test_count);
|
||||
const run = try compiler_run(allocator, .{
|
||||
.test_name = "c_abi",
|
||||
.repetitions = 1,
|
||||
.extra_arguments = &.{},
|
||||
.source_file_path = "retest/c_abi/main.nat",
|
||||
.compiler_path = bootstrap_relative_path,
|
||||
.is_test = false,
|
||||
.self_hosted = false,
|
||||
});
|
||||
try group_end(group, test_count, run);
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
const allocator = arena.allocator();
|
||||
@ -596,6 +656,8 @@ pub fn main() !void {
|
||||
.repetitions = 1,
|
||||
});
|
||||
|
||||
try c_abi_tests(allocator);
|
||||
|
||||
// var errors = run_test_suite(allocator, .{
|
||||
// .self_hosted = false,
|
||||
// .compiler_path = bootstrap_relative_path,
|
||||
|
4
retest/c_abi/main.nat
Normal file
4
retest/c_abi/main.nat
Normal file
@ -0,0 +1,4 @@
|
||||
fn[cc(.c)] main[export]() s32
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -25,6 +25,15 @@ using namespace llvm;
|
||||
using llvm::orc::ThreadSafeContext;
|
||||
using llvm::orc::ThreadSafeModule;
|
||||
|
||||
extern "C" void NativityLLVMInitializeAll()
|
||||
{
|
||||
InitializeAllTargetInfos();
|
||||
InitializeAllTargets();
|
||||
InitializeAllTargetMCs();
|
||||
InitializeAllAsmParsers();
|
||||
InitializeAllAsmPrinters();
|
||||
}
|
||||
|
||||
extern "C" LLVMContext* NativityLLVMCreateContext()
|
||||
{
|
||||
auto* context = new LLVMContext();
|
||||
@ -940,14 +949,6 @@ extern "C" void NativityLLVMCallSetCallingConvention(CallBase& call_instruction,
|
||||
call_instruction.setCallingConv(calling_convention);
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMInitializeCodeGeneration()
|
||||
{
|
||||
InitializeAllTargetInfos();
|
||||
InitializeAllTargets();
|
||||
InitializeAllTargetMCs();
|
||||
InitializeAllAsmParsers();
|
||||
InitializeAllAsmPrinters();
|
||||
}
|
||||
|
||||
extern "C" const Target* NativityLLVMGetTarget(const char* target_triple_ptr, size_t target_triple_len, const char** message_ptr, size_t* message_len)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user