Skip to content

Commit

Permalink
Add support for the llvm: use scheme
Browse files Browse the repository at this point in the history
  • Loading branch information
redvers committed Jun 8, 2022
1 parent 7b07d4d commit dedfe2e
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/libponyc/codegen/genexe.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ bool genexe(compile_t* c, ast_t* program)
return false;
}

const char* file_o = genobj(c);
const char* file_o = genobj(c, program);

if(file_o == NULL)
return false;
Expand Down
37 changes: 36 additions & 1 deletion src/libponyc/codegen/genobj.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#include "genobj.h"
#include "../pkg/program.h"
#include <llvm-c/BitWriter.h>
#include <llvm-c/IRReader.h>
#include <llvm-c/Linker.h>

const char* genobj(compile_t* c)
const char* genobj(compile_t* c, ast_t* program)
{
errors_t* errors = c->opt->check.errors;

Expand Down Expand Up @@ -48,6 +51,38 @@ const char* genobj(compile_t* c)
return file_o;
}

for(strlist_t* p = program_llvm_irs(program); p != NULL ; p = strlist_next(p))
{
const char* llvmir = strlist_data(p);

if(c->opt->verbosity >= VERBOSITY_ALL)
fprintf(stderr, "Reading llvm: %s\n", llvmir);

char* err;

LLVMMemoryBufferRef buf;
if(LLVMCreateMemoryBufferWithContentsOfFile(llvmir, &buf, &err) != 0)
{
errorf(errors, NULL, "couldn't find LLVMIR at %s: %s", llvmir, err);
LLVMDisposeMessage(err);
return NULL;
}

LLVMModuleRef mod;
if (LLVMParseIRInContext(c->context, buf, &mod, &err) != 0)
{
errorf(errors, NULL, "couldn't parse LLVMIR at %s: %s", llvmir, err);
LLVMDisposeMessage(err);
return NULL;
}

if (LLVMLinkModules2(c->module, mod) != 0)
{
errorf(errors, NULL, "failed to link: %s", llvmir);
return NULL;
}
}

LLVMCodeGenFileType fmt;
const char* file_o;

Expand Down
2 changes: 1 addition & 1 deletion src/libponyc/codegen/genobj.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

PONY_EXTERN_C_BEGIN

const char* genobj(compile_t* c);
const char* genobj(compile_t* c, ast_t* program);

PONY_EXTERN_C_END

Expand Down
46 changes: 46 additions & 0 deletions src/libponyc/pkg/program.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ typedef struct program_t
uint32_t next_package_id;
strlist_t* libpaths;
strlist_t* libs;
strlist_t* llvm_irs;
size_t lib_args_size;
size_t lib_args_alloced;
char* lib_args;
Expand Down Expand Up @@ -142,6 +143,41 @@ bool use_library(ast_t* use, const char* locator, ast_t* name,
return true;
}

/// Process a "llvm:" scheme use command.
bool use_llvm(ast_t* use, const char* locator, ast_t* name,
pass_opt_t* options)
{
(void)name;
(void)options;

char absolute[FILENAME_MAX];
const char* prefix = NULL;

if(!is_path_absolute(locator)) {
ast_t* pkg_ast = ast_nearest(use, TK_PACKAGE);
prefix = package_path(pkg_ast);
}

path_cat(prefix, locator, absolute);

size_t len = strlen(absolute);
char* allocated = (char*)ponyint_pool_alloc_size(len + 4); // ".ll\0"
memcpy(allocated, absolute, len);
allocated[len] = '.';
allocated[len + 1] = 'l';
allocated[len + 2] = 'l';
allocated[len + 3] = '\0';
const char* libname = stringtab_consume(allocated, len + 4);

if(libname == NULL)
return false;

ast_t* p = ast_nearest(use, TK_PROGRAM);
program_t* prog = (program_t*)ast_data(p);

prog->llvm_irs = strlist_append(prog->llvm_irs, libname);
return true;
}

/// Process a "path:" scheme use command.
bool use_path(ast_t* use, const char* locator, ast_t* name,
Expand Down Expand Up @@ -173,6 +209,16 @@ bool use_path(ast_t* use, const char* locator, ast_t* name,
return true;
}

strlist_t* program_llvm_irs(ast_t* program)
{
pony_assert(program != NULL);
pony_assert(ast_id(program) == TK_PROGRAM);

program_t* data = (program_t*)ast_data(program);
pony_assert(data != NULL);

return data->llvm_irs;
}

void program_lib_build_args(ast_t* program, pass_opt_t* opt,
const char* path_preamble, const char* rpath_preamble,
Expand Down
10 changes: 10 additions & 0 deletions src/libponyc/pkg/program.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,24 @@ void program_free(program_t* program);
/// The actual AST node passed in may be anywhere in the tree.
uint32_t program_assign_pkg_id(ast_t* ast);


/// Process a "lib:" scheme use command.
bool use_library(ast_t* use, const char* locator, ast_t* name,
pass_opt_t* options);

/// Process an "llvm:" scheme use command.
bool use_llvm(ast_t* use, const char* locator, ast_t* name,
pass_opt_t* options);

/// Process a "path:" scheme use command.
bool use_path(ast_t* use, const char* locator, ast_t* name,
pass_opt_t* options);

/** Assert that the provided ast_t* and the required field
* llvm_irs are not NULL before returning the field
*/
strlist_t* program_llvm_irs(ast_t* program);

/** Build the required linker arguments based on the libraries we're using.
* Once this has been called no more calls to use_library() are permitted.
*/
Expand Down
1 change: 1 addition & 0 deletions src/libponyc/pkg/use.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ static __pony_thread_local use_scheme_t handlers[] =
{"package:", 8, true, false, use_package},
{"lib:", 4, false, true, use_library},
{"path:", 5, false, true, use_path},
{"llvm:", 5, false, true, use_llvm},

{"test:", 5, false, false, NULL}, // For testing
{NULL, 0, false, false, NULL} // Terminator
Expand Down

0 comments on commit dedfe2e

Please sign in to comment.