Skip to content

Commit 14d02e4

Browse files
committed
Add support for the llvm: use scheme
1 parent 98b5cff commit 14d02e4

File tree

7 files changed

+96
-4
lines changed

7 files changed

+96
-4
lines changed

src/libponyc/codegen/genexe.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ bool genexe(compile_t* c, ast_t* program)
606606
return false;
607607
}
608608

609-
const char* file_o = genobj(c);
609+
const char* file_o = genobj(c, program);
610610

611611
if(file_o == NULL)
612612
return false;

src/libponyc/codegen/genlib.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ bool genlib(compile_t* c, ast_t* program)
196196
return false;
197197
}
198198

199-
const char* file_o = genobj(c);
199+
const char* file_o = genobj(c, program);
200200

201201
if(file_o == NULL)
202202
return false;

src/libponyc/codegen/genobj.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#include "genobj.h"
2+
#include "../pkg/program.h"
23
#include <llvm-c/BitWriter.h>
4+
#include <llvm-c/IRReader.h>
5+
#include <llvm-c/Linker.h>
36

4-
const char* genobj(compile_t* c)
7+
const char* genobj(compile_t* c, ast_t* program)
58
{
69
errors_t* errors = c->opt->check.errors;
710

@@ -48,6 +51,38 @@ const char* genobj(compile_t* c)
4851
return file_o;
4952
}
5053

54+
for(strlist_t* p = program_llvm_irs(program); p != NULL ; p = strlist_next(p))
55+
{
56+
const char* llvmir = strlist_data(p);
57+
58+
if(c->opt->verbosity >= VERBOSITY_ALL)
59+
fprintf(stderr, "Reading llvm: %s\n", llvmir);
60+
61+
char* err;
62+
63+
LLVMMemoryBufferRef buf;
64+
if(LLVMCreateMemoryBufferWithContentsOfFile(llvmir, &buf, &err) != 0)
65+
{
66+
errorf(errors, NULL, "couldn't find LLVMIR at %s: %s", llvmir, err);
67+
LLVMDisposeMessage(err);
68+
return NULL;
69+
}
70+
71+
LLVMModuleRef mod;
72+
if (LLVMParseIRInContext(c->context, buf, &mod, &err) != 0)
73+
{
74+
errorf(errors, NULL, "couldn't parse LLVMIR at %s: %s", llvmir, err);
75+
LLVMDisposeMessage(err);
76+
return NULL;
77+
}
78+
79+
if (LLVMLinkModules2(c->module, mod) != 0)
80+
{
81+
errorf(errors, NULL, "failed to link: %s", llvmir);
82+
return NULL;
83+
}
84+
}
85+
5186
LLVMCodeGenFileType fmt;
5287
const char* file_o;
5388

src/libponyc/codegen/genobj.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
PONY_EXTERN_C_BEGIN
88

9-
const char* genobj(compile_t* c);
9+
const char* genobj(compile_t* c, ast_t* program);
1010

1111
PONY_EXTERN_C_END
1212

src/libponyc/pkg/program.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ typedef struct program_t
1616
uint32_t next_package_id;
1717
strlist_t* libpaths;
1818
strlist_t* libs;
19+
strlist_t* llvm_irs;
1920
size_t lib_args_size;
2021
size_t lib_args_alloced;
2122
char* lib_args;
@@ -142,6 +143,41 @@ bool use_library(ast_t* use, const char* locator, ast_t* name,
142143
return true;
143144
}
144145

146+
/// Process a "llvm:" scheme use command.
147+
bool use_llvm(ast_t* use, const char* locator, ast_t* name,
148+
pass_opt_t* options)
149+
{
150+
(void)name;
151+
(void)options;
152+
153+
char absolute[FILENAME_MAX];
154+
const char* prefix = NULL;
155+
156+
if(!is_path_absolute(locator)) {
157+
ast_t* pkg_ast = ast_nearest(use, TK_PACKAGE);
158+
prefix = package_path(pkg_ast);
159+
}
160+
161+
path_cat(prefix, locator, absolute);
162+
163+
size_t len = strlen(absolute);
164+
char* allocated = (char*)ponyint_pool_alloc_size(len + 4); // ".ll\0"
165+
memcpy(allocated, absolute, len);
166+
allocated[len] = '.';
167+
allocated[len + 1] = 'l';
168+
allocated[len + 2] = 'l';
169+
allocated[len + 3] = '\0';
170+
const char* libname = stringtab_consume(allocated, len + 4);
171+
172+
if(libname == NULL)
173+
return false;
174+
175+
ast_t* p = ast_nearest(use, TK_PROGRAM);
176+
program_t* prog = (program_t*)ast_data(p);
177+
178+
prog->llvm_irs = strlist_append(prog->llvm_irs, libname);
179+
return true;
180+
}
145181

146182
/// Process a "path:" scheme use command.
147183
bool use_path(ast_t* use, const char* locator, ast_t* name,
@@ -173,6 +209,16 @@ bool use_path(ast_t* use, const char* locator, ast_t* name,
173209
return true;
174210
}
175211

212+
strlist_t* program_llvm_irs(ast_t* program)
213+
{
214+
pony_assert(program != NULL);
215+
pony_assert(ast_id(program) == TK_PROGRAM);
216+
217+
program_t* data = (program_t*)ast_data(program);
218+
pony_assert(data != NULL);
219+
220+
return data->llvm_irs;
221+
}
176222

177223
void program_lib_build_args(ast_t* program, pass_opt_t* opt,
178224
const char* path_preamble, const char* rpath_preamble,

src/libponyc/pkg/program.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,24 @@ void program_free(program_t* program);
1919
/// The actual AST node passed in may be anywhere in the tree.
2020
uint32_t program_assign_pkg_id(ast_t* ast);
2121

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

27+
/// Process an "llvm:" scheme use command.
28+
bool use_llvm(ast_t* use, const char* locator, ast_t* name,
29+
pass_opt_t* options);
30+
2631
/// Process a "path:" scheme use command.
2732
bool use_path(ast_t* use, const char* locator, ast_t* name,
2833
pass_opt_t* options);
2934

35+
/** Assert that the provided ast_t* and the required field
36+
* llvm_irs are not NULL before returning the field
37+
*/
38+
strlist_t* program_llvm_irs(ast_t* program);
39+
3040
/** Build the required linker arguments based on the libraries we're using.
3141
* Once this has been called no more calls to use_library() are permitted.
3242
*/

src/libponyc/pkg/use.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static __pony_thread_local use_scheme_t handlers[] =
3434
{"package:", 8, true, false, use_package},
3535
{"lib:", 4, false, true, use_library},
3636
{"path:", 5, false, true, use_path},
37+
{"llvm:", 5, false, true, use_llvm},
3738

3839
{"test:", 5, false, false, NULL}, // For testing
3940
{NULL, 0, false, false, NULL} // Terminator

0 commit comments

Comments
 (0)