Roughly link LLVM for self-hosted compiler
All checks were successful
All checks were successful
This commit is contained in:
parent
d327813595
commit
a6315a388f
@ -94,7 +94,9 @@ fn void compile(Arena* arena, Options options)
|
||||
.path = options.path,
|
||||
.executable = options.executable,
|
||||
.objects = options.objects,
|
||||
.libraries = options.libraries,
|
||||
.library_directories = options.library_directories,
|
||||
.library_names = options.library_names,
|
||||
.library_paths = options.library_paths,
|
||||
.target = options.target,
|
||||
.build_mode = options.build_mode,
|
||||
.has_debug_info = options.has_debug_info,
|
||||
@ -179,17 +181,80 @@ fn String compile_file(Arena* arena, Compile options)
|
||||
String c_abi_libraries[] = {
|
||||
string_literal("build/libc_abi.a"),
|
||||
};
|
||||
Slice<String> library_slice = {};
|
||||
Slice<String> library_names = {};
|
||||
Slice<String> library_paths = {};
|
||||
String library_buffer[256];
|
||||
|
||||
Slice<String> library_directories = {};
|
||||
String library_directory = {};
|
||||
|
||||
if (is_compiler)
|
||||
{
|
||||
// ArgBuilder builder = {};
|
||||
// auto arguments = builder.flush();
|
||||
// os_execute(arena, arguments, environment, {});
|
||||
ArgBuilder builder = {};
|
||||
String llvm_config_parts[] = {
|
||||
string_literal(CMAKE_PREFIX_PATH),
|
||||
string_literal("/bin/llvm-config"),
|
||||
};
|
||||
builder.add(arena, arena_join_string(arena, array_to_slice(llvm_config_parts)));
|
||||
builder.add("--libdir");
|
||||
builder.add("--libs");
|
||||
auto arguments = builder.flush();
|
||||
auto llvm_config = os_execute(arena, arguments, environment, {
|
||||
.policies = { ExecuteStandardStreamPolicy::pipe, ExecuteStandardStreamPolicy::ignore },
|
||||
});
|
||||
auto success = llvm_config.termination_kind == TerminationKind::exit && llvm_config.termination_code == 0;
|
||||
if (!success)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
auto stream = llvm_config.streams[0];
|
||||
auto line = string_first_character(stream, '\n');
|
||||
if (line == string_no_match)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
library_directory = stream(0, line);
|
||||
library_directories = { &library_directory, 1 };
|
||||
|
||||
stream = stream(line + 1);
|
||||
|
||||
line = string_first_character(stream, '\n');
|
||||
if (line == string_no_match)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
if (line != stream.length - 1)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
auto library_list = stream(0, line);
|
||||
u64 library_count = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
auto space = string_first_character(library_list, ' ');
|
||||
if (space == string_no_match)
|
||||
{
|
||||
auto library_argument = library_list(2);
|
||||
library_buffer[library_count] = library_argument;
|
||||
library_count += 1;
|
||||
break;
|
||||
}
|
||||
// Omit the first two characters: "-l"
|
||||
auto library_argument = library_list(2, space);
|
||||
library_buffer[library_count] = library_argument;
|
||||
library_count += 1;
|
||||
library_list = library_list(space + 1);
|
||||
}
|
||||
|
||||
library_names = { library_buffer, library_count };
|
||||
}
|
||||
else if (base_name.equal(string_literal("c_abi")))
|
||||
{
|
||||
library_slice = array_to_slice(c_abi_libraries);
|
||||
library_paths = array_to_slice(c_abi_libraries);
|
||||
}
|
||||
|
||||
compile(arena, {
|
||||
@ -198,10 +263,12 @@ fn String compile_file(Arena* arena, Compile options)
|
||||
.executable = output_executable_path,
|
||||
.name = base_name,
|
||||
.objects = object_slice,
|
||||
.libraries = library_slice,
|
||||
.library_paths = library_paths,
|
||||
.library_names = library_names,
|
||||
.library_directories = library_directories,
|
||||
.target = {
|
||||
.cpu = CPUArchitecture::x86_64,
|
||||
.os = OperatingSystem::linux_,
|
||||
.cpu = CPUArchitecture::x86_64,
|
||||
.os = OperatingSystem::linux_,
|
||||
},
|
||||
.build_mode = options.build_mode,
|
||||
.has_debug_info = options.has_debug_info,
|
||||
|
@ -1213,8 +1213,10 @@ struct Module
|
||||
String name;
|
||||
String path;
|
||||
String executable;
|
||||
Slice<String>objects;
|
||||
Slice<String>libraries;
|
||||
Slice<String> objects;
|
||||
Slice<String> library_directories;
|
||||
Slice<String> library_names;
|
||||
Slice<String> library_paths;
|
||||
|
||||
Target target;
|
||||
BuildMode build_mode;
|
||||
@ -1283,7 +1285,9 @@ struct Options
|
||||
String executable;
|
||||
String name;
|
||||
Slice<String> objects;
|
||||
Slice<String> libraries;
|
||||
Slice<String> library_paths;
|
||||
Slice<String> library_names;
|
||||
Slice<String> library_directories;
|
||||
Target target;
|
||||
BuildMode build_mode;
|
||||
bool has_debug_info;
|
||||
@ -1852,6 +1856,16 @@ struct ArgBuilder
|
||||
argument_count += 1;
|
||||
}
|
||||
|
||||
void add(Arena* arena, String arg)
|
||||
{
|
||||
if (arg.pointer[arg.length] != 0)
|
||||
{
|
||||
arg = arena_duplicate_string(arena, arg);
|
||||
}
|
||||
|
||||
add((const char*)arg.pointer);
|
||||
}
|
||||
|
||||
Slice<char* const> flush()
|
||||
{
|
||||
assert(argument_count < array_length(args));
|
||||
|
@ -8325,16 +8325,33 @@ fn void link(Module* module)
|
||||
builder.add("-o");
|
||||
assert(module->executable.pointer[module->executable.length] == 0);
|
||||
builder.add((char*)module->executable.pointer);
|
||||
|
||||
for (String object: module->objects)
|
||||
{
|
||||
assert(object.pointer[object.length] == 0);
|
||||
builder.add((char*)object.pointer);
|
||||
builder.add(arena, object);
|
||||
}
|
||||
|
||||
for (String library: module->libraries)
|
||||
for (String library_directory: module->library_directories)
|
||||
{
|
||||
assert(library.pointer[library.length] == 0);
|
||||
builder.add((char*)library.pointer);
|
||||
String parts[] = {
|
||||
string_literal("-L"),
|
||||
library_directory,
|
||||
};
|
||||
builder.add(arena, arena_join_string(arena, array_to_slice(parts)));
|
||||
}
|
||||
|
||||
for (String library_path: module->library_paths)
|
||||
{
|
||||
builder.add(arena, library_path);
|
||||
}
|
||||
|
||||
for (String library_name: module->library_names)
|
||||
{
|
||||
String parts[] = {
|
||||
string_literal("-l"),
|
||||
library_name,
|
||||
};
|
||||
builder.add(arena, arena_join_string(arena, array_to_slice(parts)));
|
||||
}
|
||||
|
||||
String candidate_library_paths[] = {
|
||||
|
23
src/lib.cpp
23
src/lib.cpp
@ -37,6 +37,7 @@ extern "C" s32 fork();
|
||||
extern "C" s32 dup2(s32, s32);
|
||||
extern "C" s32 execve(const char* path_name, const char* const argv[], char* const envp[]);
|
||||
extern "C" s32 waitpid(s32 pid, int* wstatus, int options);
|
||||
extern "C" s32 pipe(int fd[2]);
|
||||
|
||||
u64 os_file_size(s32 fd)
|
||||
{
|
||||
@ -75,6 +76,7 @@ fn bool IFSIGNALED(u32 s)
|
||||
{
|
||||
return (s & 0xffff) - 1 < 0xff;
|
||||
}
|
||||
|
||||
Execution os_execute(Arena* arena, Slice<char* const> arguments, Slice<char* const> environment, ExecuteOptions options)
|
||||
{
|
||||
unused(arena);
|
||||
@ -90,7 +92,7 @@ Execution os_execute(Arena* arena, Slice<char* const> arguments, Slice<char* con
|
||||
}
|
||||
else if (options.policies[0] == ExecuteStandardStreamPolicy::ignore || options.policies[1] == ExecuteStandardStreamPolicy::ignore)
|
||||
{
|
||||
trap();
|
||||
null_file_descriptor = open("/dev/null", { .access_mode = OPEN::AccessMode::write_only });
|
||||
}
|
||||
|
||||
int pipes[standard_stream_count][2];
|
||||
@ -99,7 +101,10 @@ Execution os_execute(Arena* arena, Slice<char* const> arguments, Slice<char* con
|
||||
{
|
||||
if (options.policies[i] == ExecuteStandardStreamPolicy::pipe)
|
||||
{
|
||||
trap();
|
||||
if (pipe(pipes[i]) == -1)
|
||||
{
|
||||
trap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,16 +159,26 @@ Execution os_execute(Arena* arena, Slice<char* const> arguments, Slice<char* con
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: better allocation strategy
|
||||
u64 allocation_size = 1024 * 1024;
|
||||
Slice<u8> allocation = {};
|
||||
if (options.policies[0] == ExecuteStandardStreamPolicy::pipe || options.policies[1] == ExecuteStandardStreamPolicy::pipe)
|
||||
{
|
||||
trap();
|
||||
allocation = arena_allocate<u8>(arena, allocation_size * ((options.policies[0] == ExecuteStandardStreamPolicy::pipe) + (options.policies[1] == ExecuteStandardStreamPolicy::pipe)));
|
||||
}
|
||||
|
||||
u64 offset = 0;
|
||||
for (u64 i = 0; i < standard_stream_count; i += 1)
|
||||
{
|
||||
if (options.policies[i] == ExecuteStandardStreamPolicy::pipe)
|
||||
{
|
||||
trap();
|
||||
auto buffer = allocation(offset)(0, allocation_size);
|
||||
auto byte_count = read(pipes[i][0], buffer.pointer, buffer.length);
|
||||
assert(byte_count >= 0);
|
||||
execution.streams[i] = buffer(0, byte_count);
|
||||
close(pipes[i][0]);
|
||||
|
||||
offset += allocation_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,11 @@ fn void* arena_allocate_bytes(Arena* arena, u64 size, u64 alignment)
|
||||
|
||||
if (aligned_size_after > arena->os_position)
|
||||
{
|
||||
unreachable();
|
||||
auto target_commited_size = align_forward(aligned_size_after, arena->granularity);
|
||||
auto size_to_commit = target_commited_size - arena->os_position;
|
||||
auto commit_pointer = ((u8*)arena) + arena->os_position;
|
||||
os_commit(commit_pointer, size_to_commit, { .read = 1, .write = 1 });
|
||||
arena->os_position = target_commited_size;
|
||||
}
|
||||
|
||||
result = (u8*)arena + aligned_offset;
|
||||
@ -709,8 +713,7 @@ enum class TerminationKind : u8
|
||||
|
||||
struct Execution
|
||||
{
|
||||
String stdout;
|
||||
String stderr;
|
||||
String streams[2];
|
||||
TerminationKind termination_kind;
|
||||
u32 termination_code;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user