parse bitcode

This commit is contained in:
David Gonzalez Martin 2024-05-10 14:27:41 -06:00
parent a379ba9cf1
commit 7094d59372
5 changed files with 191 additions and 182 deletions

View File

@ -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 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 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 LLVMInitializeAArch64TargetInfo() void;
pub extern fn LLVMInitializeAMDGPUTargetInfo() void; pub extern fn LLVMInitializeAMDGPUTargetInfo() void;
pub extern fn LLVMInitializeARMTargetInfo() void; pub extern fn LLVMInitializeARMTargetInfo() void;

View File

@ -886,72 +886,72 @@ pub fn make() void {
} }
// TODO: Prune // TODO: Prune
// if (do_codegen) { if (do_codegen) {
// for (threads) |*thread| { for (threads) |*thread| {
// thread.add_thread_work(Job{ thread.add_thread_work(Job{
// .id = switch (codegen_backend) { .id = switch (codegen_backend) {
// .llvm => .llvm_codegen_thread_module, .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,
// }
// }
// 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 { 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 => { .llvm_codegen_thread_module => {
if (thread.functions.length > 0) { if (thread.functions.length > 0) {
const debug_info = true; const context = LLVM.Context.create();
const result = context.parse_bitcode("foo");
const ExternalRef = struct{ _ = result; // autofix
gsr: GlobalSymbolReference, exit(0);
thread: u16, // const debug_info = true;
}; //
var external_hashmap = PinnedHashMap(ExternalRef, *LLVM.Value.Constant.Function){}; // const ExternalRef = struct{
// gsr: GlobalSymbolReference,
for (thread.external_functions.slice()) |*nat_function| { // thread: u16,
_ = llvm_get_function(thread, nat_function, true); // };
} // var external_hashmap = PinnedHashMap(ExternalRef, *LLVM.Value.Constant.Function){};
//
_ = &external_hashmap; // autofix // for (thread.external_functions.slice()) |*nat_function| {
for (thread.functions.slice()) |*nat_function| { // _ = llvm_get_function(thread, nat_function, true);
_ = llvm_get_function(thread, &nat_function.declaration, false); // }
} //
// _ = &external_hashmap; // autofix
for (thread.functions.slice()) |*nat_function| { // for (thread.functions.slice()) |*nat_function| {
const function = nat_function.declaration.llvm.?; // _ = llvm_get_function(thread, &nat_function.declaration, false);
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"; // for (thread.functions.slice()) |*nat_function| {
const entry_block = thread.llvm.context.createBasicBlock(entry_block_name, entry_block_name.len, function, null); // const function = nat_function.declaration.llvm.?;
thread.llvm.builder.setInsertPoint(entry_block); // const nat_entry_basic_block = thread.basic_blocks.get(nat_function.entry_block);
// assert(nat_entry_basic_block.predecessors.length == 0);
for (nat_entry_basic_block.instructions.slice()) |instruction| { // const entry_block_name = "entry_block_name";
const value: *LLVM.Value = switch (instruction.id) { // const entry_block = thread.llvm.context.createBasicBlock(entry_block_name, entry_block_name.len, function, null);
.ret => block: { // thread.llvm.builder.setInsertPoint(entry_block);
const return_instruction = thread.returns.get(@enumFromInt(instruction.index)); //
const return_value = llvm_get_value(thread, return_instruction.value); // for (nat_entry_basic_block.instructions.slice()) |instruction| {
const ret = thread.llvm.builder.createRet(return_value); // const value: *LLVM.Value = switch (instruction.id) {
break :block ret.toValue(); // .ret => block: {
}, // const return_instruction = thread.returns.get(@enumFromInt(instruction.index));
.call => block: { // const return_value = llvm_get_value(thread, return_instruction.value);
const call = thread.calls.get(@enumFromInt(instruction.index)); // const ret = thread.llvm.builder.createRet(return_value);
const callee = if (call.value.sema.thread == thread.get_index()) switch (call.value.sema.id) { // break :block ret.toValue();
.global_symbol => blk: { // },
const global_symbol: GlobalSymbolReference = @bitCast(call.value.sema.index); // .call => block: {
break :blk switch (global_symbol.id) { // const call = thread.calls.get(@enumFromInt(instruction.index));
.function_declaration => b: { // const callee = if (call.value.sema.thread == thread.get_index()) switch (call.value.sema.id) {
const external_function = thread.external_functions.slice()[global_symbol.index]; // .global_symbol => blk: {
break :b external_function.llvm.?; // const global_symbol: GlobalSymbolReference = @bitCast(call.value.sema.index);
}, // break :blk switch (global_symbol.id) {
else => |t| @panic(@tagName(t)), // .function_declaration => b: {
}; // const external_function = thread.external_functions.slice()[global_symbol.index];
}, // break :b external_function.llvm.?;
else => |t| @panic(@tagName(t)), // },
} else exit(1); // else => |t| @panic(@tagName(t)),
const function_type = callee.getType(); // };
// },
const arguments: []const *LLVM.Value = &.{}; // else => |t| @panic(@tagName(t)),
const call_i = thread.llvm.builder.createCall(function_type, callee.toValue(), arguments.ptr, arguments.len, "", "".len, null); // } else exit(1);
break :block call_i.toValue(); // const function_type = callee.getType();
}, //
else => |t| @panic(@tagName(t)), // 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();
instruction.llvm = value; // },
} // else => |t| @panic(@tagName(t)),
// };
if (debug_info) { //
const file_index = nat_function.declaration.file; // instruction.llvm = value;
const llvm_file = thread.debug_info_file_map.get_pointer(file_index).?; // }
const subprogram = function.getSubprogram(); //
llvm_file.builder.finalizeSubprogram(subprogram, function); // if (debug_info) {
} // const file_index = nat_function.declaration.file;
// const llvm_file = thread.debug_info_file_map.get_pointer(file_index).?;
const verify_function = true; // const subprogram = function.getSubprogram();
if (verify_function) { // llvm_file.builder.finalizeSubprogram(subprogram, function);
var message: []const u8 = undefined; // }
const verification_success = function.verify(&message.ptr, &message.len); //
if (!verification_success) { // const verify_function = true;
var function_msg: []const u8 = undefined; // if (verify_function) {
function.toString(&function_msg.ptr, &function_msg.len); // var message: []const u8 = undefined;
write(function_msg); // const verification_success = function.verify(&message.ptr, &message.len);
write("\n"); // if (!verification_success) {
exit_with_error(message); // 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(); //
} // if (debug_info) {
// const file_index = thread.functions.slice()[0].declaration.file;
const verify_module = true; // const llvm_file = thread.debug_info_file_map.get_pointer(file_index).?;
if (verify_module) { // llvm_file.builder.finalize();
var verification_message: []const u8 = undefined; // }
const verification_success = thread.llvm.module.verify(&verification_message.ptr, &verification_message.len); //
if (!verification_success) { // const verify_module = true;
const print_module = true; // if (verify_module) {
if (print_module) { // var verification_message: []const u8 = undefined;
var module_content: []const u8 = undefined; // const verification_success = thread.llvm.module.verify(&verification_message.ptr, &verification_message.len);
thread.llvm.module.toString(&module_content.ptr, &module_content.len); // if (!verification_success) {
write(module_content); // const print_module = true;
write("\n"); // if (print_module) {
} // var module_content: []const u8 = undefined;
// thread.llvm.module.toString(&module_content.ptr, &module_content.len);
exit_with_error(verification_message); // write(module_content);
} // write("\n");
} // }
//
// exit_with_error(verification_message);
// }
// }
} }
}, },
} }
@ -1939,6 +1943,17 @@ pub const LLVM = struct {
const getAttributeFromString = bindings.NativityLLVMContextGetAttributeFromString; const getAttributeFromString = bindings.NativityLLVMContextGetAttributeFromString;
const getAttributeFromType = bindings.NativityLLVMContextGetAttributeFromType; const getAttributeFromType = bindings.NativityLLVMContextGetAttributeFromType;
const getAttributeSet = bindings.NativityLLVMContextGetAttributeSet; 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 { pub const Module = opaque {
@ -2579,6 +2594,8 @@ pub const LLVM = struct {
}; };
pub const MemoryBuffer = opaque{};
pub const Value = opaque { pub const Value = opaque {
const setName = bindings.NativityLLVMValueSetName; const setName = bindings.NativityLLVMValueSetName;
const getType = bindings.NativityLLVMValueGetType; const getType = bindings.NativityLLVMValueGetType;

View File

@ -153,9 +153,8 @@ pub fn DynamicBoundedArray(comptime T: type) type {
const pinned_array_page_size = 2 * 1024 * 1024; const pinned_array_page_size = 2 * 1024 * 1024;
const pinned_array_max_size = std.math.maxInt(u32) - pinned_array_page_size; 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; const large_granularity = 2 * 1024 * 1024;
// This must be used with big arrays, which are not resizeable (can't be cleared) // This must be used with big arrays, which are not resizeable (can't be cleared)
pub fn PinnedArray(comptime T: type) type { pub fn PinnedArray(comptime T: type) type {

View File

@ -1,6 +1,4 @@
import "file.nat";
fn [cc(.c)] main [export]() s32 fn [cc(.c)] main [export]() s32
{ {
return file.foo(); return 0;
} }

View File

@ -4,6 +4,7 @@
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h" #include "llvm/IR/Verifier.h"
#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DIBuilder.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
@ -22,8 +23,6 @@
using namespace llvm; using namespace llvm;
using llvm::orc::ThreadSafeContext;
using llvm::orc::ThreadSafeModule;
extern "C" LLVMContext* NativityLLVMCreateContext() extern "C" LLVMContext* NativityLLVMCreateContext()
{ {
@ -1077,13 +1076,6 @@ extern "C" CallInst* NativityLLVMBuilderCreateMemcpy(IRBuilder<>& builder, Value
return memcpy; return memcpy;
} }
extern "C" bool NativityLLVMLinkModules(Module& destination, Module* source)
{
auto src = std::unique_ptr<Module>(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) extern "C" void NativityLLVMTypeAssertEqual(Type* a, Type* b)
{ {
assert(a == b); assert(a == b);