From 7094d5937254fe1d08a96f54aa548dbd3b67889f Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Fri, 10 May 2024 14:27:41 -0600 Subject: [PATCH] parse bitcode --- bootstrap/backend/llvm_bindings.zig | 3 + bootstrap/compiler.zig | 353 +++++++++++++++------------- bootstrap/library.zig | 3 +- retest/standalone/first/main.nat | 4 +- src/llvm/llvm.cpp | 10 +- 5 files changed, 191 insertions(+), 182 deletions(-) diff --git a/bootstrap/backend/llvm_bindings.zig b/bootstrap/backend/llvm_bindings.zig index 4171280..5e438e9 100644 --- a/bootstrap/backend/llvm_bindings.zig +++ b/bootstrap/backend/llvm_bindings.zig @@ -157,6 +157,9 @@ pub extern fn NativityLLVMModuleSetTargetMachineDataLayout(module: *LLVM.Module, pub extern fn NativityLLVMModuleSetTargetTriple(module: *LLVM.Module, target_triple_ptr: [*]const u8, target_triple_len: usize) void; pub extern fn NativityLLVMTypeAssertEqual(a: *LLVM.Type, b: *LLVM.Type) void; +pub extern fn LLVMCreateMemoryBufferWithMemoryRange(InputData: [*]const u8, InputDataLength: usize, BufferName: ?[*:0]const u8, RequiresNullTerminator: c_int) *LLVM.MemoryBuffer; +pub extern fn LLVMParseBitcodeInContext2(context: *LLVM.Context, memory_buffer: *LLVM.MemoryBuffer, out_module: **LLVM.Module) c_int; + pub extern fn LLVMInitializeAArch64TargetInfo() void; pub extern fn LLVMInitializeAMDGPUTargetInfo() void; pub extern fn LLVMInitializeARMTargetInfo() void; diff --git a/bootstrap/compiler.zig b/bootstrap/compiler.zig index b6cca54..f8cc28a 100644 --- a/bootstrap/compiler.zig +++ b/bootstrap/compiler.zig @@ -886,72 +886,72 @@ pub fn make() void { } // TODO: Prune - // if (do_codegen) { - // for (threads) |*thread| { - // thread.add_thread_work(Job{ - // .id = switch (codegen_backend) { - // .llvm => .llvm_codegen_thread_module, - // }, - // }); - // } - // - // while (true) { - // var to_do: u64 = 0; - // for (threads) |*thread| { - // const jobs_to_do = thread.task_system.job.to_do - thread.task_system.job.completed; - // const asks_to_do = thread.task_system.ask.to_do - thread.task_system.ask.completed; - // assert(asks_to_do == 0); - // - // to_do += jobs_to_do; - // } - // - // if (to_do == 0) { - // break; - // } - // } - // - // var modules_present = PinnedArray(usize){}; - // for (threads, 0..) |*thread, i| { - // if (thread.functions.length > 0) { - // _ = modules_present.append(i); - // } - // } - // - // switch (modules_present.length) { - // 0 => unreachable, - // 1 => unreachable, - // 2 => { - // const first = modules_present.slice()[0]; - // const second = modules_present.slice()[1]; - // const destination = threads[first].llvm.module; - // { - // var message: []const u8 = undefined; - // destination.toString(&message.ptr, &message.len); - // std.debug.print("{s}\n", .{message}); - // } - // const source = threads[second].llvm.module; - // { - // var message: []const u8 = undefined; - // source.toString(&message.ptr, &message.len); - // std.debug.print("{s}\n", .{message}); - // } - // - // if (!destination.link(source, .{ - // .override_from_source = true, - // .link_only_needed = false, - // })) { - // exit(1); - // } - // - // var message: []const u8 = undefined; - // destination.toString(&message.ptr, &message.len); - // std.debug.print("============\n===========\n{s}\n", .{message}); - // }, - // else => unreachable, - // } - // } + if (do_codegen) { + for (threads) |*thread| { + thread.add_thread_work(Job{ + .id = switch (codegen_backend) { + .llvm => .llvm_codegen_thread_module, + }, + }); + } - // while (true) {} + while (true) { + var to_do: u64 = 0; + for (threads) |*thread| { + const jobs_to_do = thread.task_system.job.to_do - thread.task_system.job.completed; + const asks_to_do = thread.task_system.ask.to_do - thread.task_system.ask.completed; + assert(asks_to_do == 0); + + to_do += jobs_to_do; + } + + if (to_do == 0) { + break; + } + } + + var modules_present = PinnedArray(usize){}; + for (threads, 0..) |*thread, i| { + if (thread.functions.length > 0) { + _ = modules_present.append(i); + } + } + + switch (modules_present.length) { + 0 => unreachable, + 1 => {}, + 2 => { + // const first = modules_present.slice()[0]; + // const second = modules_present.slice()[1]; + // const destination = threads[first].llvm.module; + // { + // var message: []const u8 = undefined; + // destination.toString(&message.ptr, &message.len); + // std.debug.print("{s}\n", .{message}); + // } + // const source = threads[second].llvm.module; + // { + // var message: []const u8 = undefined; + // source.toString(&message.ptr, &message.len); + // std.debug.print("{s}\n", .{message}); + // } + // + // if (!destination.link(source, .{ + // .override_from_source = true, + // .link_only_needed = false, + // })) { + // exit(1); + // } + // + // var message: []const u8 = undefined; + // destination.toString(&message.ptr, &message.len); + // std.debug.print("============\n===========\n{s}\n", .{message}); + }, + else => unreachable, + } + } + + while (true) {} } fn intern_identifier(pool: *PinnedHashMap(u32, []const u8), identifier: []const u8) u32 { @@ -1252,109 +1252,113 @@ fn thread_callback(thread_index: u32) void { }, .llvm_codegen_thread_module => { if (thread.functions.length > 0) { - const debug_info = true; - - const ExternalRef = struct{ - gsr: GlobalSymbolReference, - thread: u16, - }; - var external_hashmap = PinnedHashMap(ExternalRef, *LLVM.Value.Constant.Function){}; - - for (thread.external_functions.slice()) |*nat_function| { - _ = llvm_get_function(thread, nat_function, true); - } - - _ = &external_hashmap; // autofix - for (thread.functions.slice()) |*nat_function| { - _ = llvm_get_function(thread, &nat_function.declaration, false); - } - - for (thread.functions.slice()) |*nat_function| { - const function = nat_function.declaration.llvm.?; - const nat_entry_basic_block = thread.basic_blocks.get(nat_function.entry_block); - assert(nat_entry_basic_block.predecessors.length == 0); - const entry_block_name = "entry_block_name"; - const entry_block = thread.llvm.context.createBasicBlock(entry_block_name, entry_block_name.len, function, null); - thread.llvm.builder.setInsertPoint(entry_block); - - for (nat_entry_basic_block.instructions.slice()) |instruction| { - const value: *LLVM.Value = switch (instruction.id) { - .ret => block: { - const return_instruction = thread.returns.get(@enumFromInt(instruction.index)); - const return_value = llvm_get_value(thread, return_instruction.value); - const ret = thread.llvm.builder.createRet(return_value); - break :block ret.toValue(); - }, - .call => block: { - const call = thread.calls.get(@enumFromInt(instruction.index)); - const callee = if (call.value.sema.thread == thread.get_index()) switch (call.value.sema.id) { - .global_symbol => blk: { - const global_symbol: GlobalSymbolReference = @bitCast(call.value.sema.index); - break :blk switch (global_symbol.id) { - .function_declaration => b: { - const external_function = thread.external_functions.slice()[global_symbol.index]; - break :b external_function.llvm.?; - }, - else => |t| @panic(@tagName(t)), - }; - }, - else => |t| @panic(@tagName(t)), - } else exit(1); - const function_type = callee.getType(); - - const arguments: []const *LLVM.Value = &.{}; - const call_i = thread.llvm.builder.createCall(function_type, callee.toValue(), arguments.ptr, arguments.len, "", "".len, null); - break :block call_i.toValue(); - }, - else => |t| @panic(@tagName(t)), - }; - - instruction.llvm = value; - } - - if (debug_info) { - const file_index = nat_function.declaration.file; - const llvm_file = thread.debug_info_file_map.get_pointer(file_index).?; - const subprogram = function.getSubprogram(); - llvm_file.builder.finalizeSubprogram(subprogram, function); - } - - const verify_function = true; - if (verify_function) { - var message: []const u8 = undefined; - const verification_success = function.verify(&message.ptr, &message.len); - if (!verification_success) { - var function_msg: []const u8 = undefined; - function.toString(&function_msg.ptr, &function_msg.len); - write(function_msg); - write("\n"); - exit_with_error(message); - } - } - } - - if (debug_info) { - const file_index = thread.functions.slice()[0].declaration.file; - const llvm_file = thread.debug_info_file_map.get_pointer(file_index).?; - llvm_file.builder.finalize(); - } - - const verify_module = true; - if (verify_module) { - var verification_message: []const u8 = undefined; - const verification_success = thread.llvm.module.verify(&verification_message.ptr, &verification_message.len); - if (!verification_success) { - const print_module = true; - if (print_module) { - var module_content: []const u8 = undefined; - thread.llvm.module.toString(&module_content.ptr, &module_content.len); - write(module_content); - write("\n"); - } - - exit_with_error(verification_message); - } - } + const context = LLVM.Context.create(); + const result = context.parse_bitcode("foo"); + _ = result; // autofix + exit(0); + // const debug_info = true; + // + // const ExternalRef = struct{ + // gsr: GlobalSymbolReference, + // thread: u16, + // }; + // var external_hashmap = PinnedHashMap(ExternalRef, *LLVM.Value.Constant.Function){}; + // + // for (thread.external_functions.slice()) |*nat_function| { + // _ = llvm_get_function(thread, nat_function, true); + // } + // + // _ = &external_hashmap; // autofix + // for (thread.functions.slice()) |*nat_function| { + // _ = llvm_get_function(thread, &nat_function.declaration, false); + // } + // + // for (thread.functions.slice()) |*nat_function| { + // const function = nat_function.declaration.llvm.?; + // const nat_entry_basic_block = thread.basic_blocks.get(nat_function.entry_block); + // assert(nat_entry_basic_block.predecessors.length == 0); + // const entry_block_name = "entry_block_name"; + // const entry_block = thread.llvm.context.createBasicBlock(entry_block_name, entry_block_name.len, function, null); + // thread.llvm.builder.setInsertPoint(entry_block); + // + // for (nat_entry_basic_block.instructions.slice()) |instruction| { + // const value: *LLVM.Value = switch (instruction.id) { + // .ret => block: { + // const return_instruction = thread.returns.get(@enumFromInt(instruction.index)); + // const return_value = llvm_get_value(thread, return_instruction.value); + // const ret = thread.llvm.builder.createRet(return_value); + // break :block ret.toValue(); + // }, + // .call => block: { + // const call = thread.calls.get(@enumFromInt(instruction.index)); + // const callee = if (call.value.sema.thread == thread.get_index()) switch (call.value.sema.id) { + // .global_symbol => blk: { + // const global_symbol: GlobalSymbolReference = @bitCast(call.value.sema.index); + // break :blk switch (global_symbol.id) { + // .function_declaration => b: { + // const external_function = thread.external_functions.slice()[global_symbol.index]; + // break :b external_function.llvm.?; + // }, + // else => |t| @panic(@tagName(t)), + // }; + // }, + // else => |t| @panic(@tagName(t)), + // } else exit(1); + // const function_type = callee.getType(); + // + // const arguments: []const *LLVM.Value = &.{}; + // const call_i = thread.llvm.builder.createCall(function_type, callee.toValue(), arguments.ptr, arguments.len, "", "".len, null); + // break :block call_i.toValue(); + // }, + // else => |t| @panic(@tagName(t)), + // }; + // + // instruction.llvm = value; + // } + // + // if (debug_info) { + // const file_index = nat_function.declaration.file; + // const llvm_file = thread.debug_info_file_map.get_pointer(file_index).?; + // const subprogram = function.getSubprogram(); + // llvm_file.builder.finalizeSubprogram(subprogram, function); + // } + // + // const verify_function = true; + // if (verify_function) { + // var message: []const u8 = undefined; + // const verification_success = function.verify(&message.ptr, &message.len); + // if (!verification_success) { + // var function_msg: []const u8 = undefined; + // function.toString(&function_msg.ptr, &function_msg.len); + // write(function_msg); + // write("\n"); + // exit_with_error(message); + // } + // } + // } + // + // if (debug_info) { + // const file_index = thread.functions.slice()[0].declaration.file; + // const llvm_file = thread.debug_info_file_map.get_pointer(file_index).?; + // llvm_file.builder.finalize(); + // } + // + // const verify_module = true; + // if (verify_module) { + // var verification_message: []const u8 = undefined; + // const verification_success = thread.llvm.module.verify(&verification_message.ptr, &verification_message.len); + // if (!verification_success) { + // const print_module = true; + // if (print_module) { + // var module_content: []const u8 = undefined; + // thread.llvm.module.toString(&module_content.ptr, &module_content.len); + // write(module_content); + // write("\n"); + // } + // + // exit_with_error(verification_message); + // } + // } } }, } @@ -1939,6 +1943,17 @@ pub const LLVM = struct { const getAttributeFromString = bindings.NativityLLVMContextGetAttributeFromString; const getAttributeFromType = bindings.NativityLLVMContextGetAttributeFromType; const getAttributeSet = bindings.NativityLLVMContextGetAttributeSet; + + + pub fn parse_bitcode(context: *LLVM.Context, bytes: []const u8) ?*LLVM.Module { + const memory_buffer = bindings.LLVMCreateMemoryBufferWithMemoryRange(bytes.ptr, bytes.len, null, 0); + var out_module: *LLVM.Module = undefined; + if (bindings.LLVMParseBitcodeInContext2(context, memory_buffer, &out_module) != 0) { + return out_module; + } else { + return null; + } + } }; pub const Module = opaque { @@ -2579,6 +2594,8 @@ pub const LLVM = struct { }; + pub const MemoryBuffer = opaque{}; + pub const Value = opaque { const setName = bindings.NativityLLVMValueSetName; const getType = bindings.NativityLLVMValueGetType; diff --git a/bootstrap/library.zig b/bootstrap/library.zig index 1739a2a..eefdc51 100644 --- a/bootstrap/library.zig +++ b/bootstrap/library.zig @@ -153,9 +153,8 @@ pub fn DynamicBoundedArray(comptime T: type) type { const pinned_array_page_size = 2 * 1024 * 1024; const pinned_array_max_size = std.math.maxInt(u32) - pinned_array_page_size; -const pinned_array_default_granularity = pinned_array_page_size; -const small_granularity = 0x1000; +const small_granularity = std.mem.page_size; const large_granularity = 2 * 1024 * 1024; // This must be used with big arrays, which are not resizeable (can't be cleared) pub fn PinnedArray(comptime T: type) type { diff --git a/retest/standalone/first/main.nat b/retest/standalone/first/main.nat index 45970a5..672fa11 100644 --- a/retest/standalone/first/main.nat +++ b/retest/standalone/first/main.nat @@ -1,6 +1,4 @@ -import "file.nat"; - fn [cc(.c)] main [export]() s32 { - return file.foo(); + return 0; } diff --git a/src/llvm/llvm.cpp b/src/llvm/llvm.cpp index d11ee1e..a110592 100644 --- a/src/llvm/llvm.cpp +++ b/src/llvm/llvm.cpp @@ -4,6 +4,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/Bitcode/BitcodeReader.h" #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" @@ -22,8 +23,6 @@ using namespace llvm; -using llvm::orc::ThreadSafeContext; -using llvm::orc::ThreadSafeModule; extern "C" LLVMContext* NativityLLVMCreateContext() { @@ -1077,13 +1076,6 @@ extern "C" CallInst* NativityLLVMBuilderCreateMemcpy(IRBuilder<>& builder, Value return memcpy; } -extern "C" bool NativityLLVMLinkModules(Module& destination, Module* source) -{ - auto src = std::unique_ptr(source); - bool result = Linker::linkModules(destination, std::move(src)); - // Invert the condition because LLVM boolean concept is lame - return !result; -} extern "C" void NativityLLVMTypeAssertEqual(Type* a, Type* b) { assert(a == b);