15 #include <llvm-c/Core.h>
16 #include <llvm-c/Target.h>
17 #include <llvm-c/TargetMachine.h>
18 #include <llvm-c/Analysis.h>
27 static LLVMContextRef gContext = NULL;
28 static char *gTargetTriple = NULL;
29 static LLVMTargetRef gTarget = NULL;
30 static LLVMTargetMachineRef gMachine = NULL;
31 static LLVMTargetDataRef gDataLayout = NULL;
35 static const diagnostic_t *get_diagnostic_level(LLVMDiagnosticSeverity severity)
39 case LLVMDSError:
return &kEvent_LLVMFatalEvent;
40 case LLVMDSWarning:
return &kEvent_LLVMWarnEvent;
41 case LLVMDSRemark:
return &kEvent_LLVMRemarkEvent;
42 case LLVMDSNote:
return &kEvent_LLVMNoteEvent;
45 return &kEvent_LLVMFatalEvent;
48 static void llvm_report_callback(LLVMDiagnosticInfoRef info,
void *ctx)
52 char *message = LLVMGetDiagInfoDescription(info);
53 const diagnostic_t *
event = get_diagnostic_level(LLVMGetDiagInfoSeverity(info));
56 msg_notify(self->logger, event, node,
"%s", message);
58 LLVMDisposeMessage(message);
63 LLVMInitializeAllTargetInfos();
64 LLVMInitializeAllTargets();
65 LLVMInitializeAllTargetMCs();
66 LLVMInitializeAllAsmPrinters();
67 LLVMInitializeAllAsmParsers();
69 gContext = LLVMContextCreate();
71 CT_PANIC(
"Failed to create LLVM context");
73 LLVMContextSetDiagnosticHandler(gContext, llvm_report_callback, runtime);
75 gTargetTriple = LLVMGetDefaultTargetTriple();
78 if (LLVMGetTargetFromTriple(gTargetTriple, &gTarget, &error))
79 CT_PANIC(
"Failed to get target %s: %s", gTargetTriple, error);
81 gMachine = LLVMCreateTargetMachine(gTarget, gTargetTriple,
"generic",
"", LLVMCodeGenLevelDefault, LLVMRelocStatic, LLVMCodeModelDefault);
83 gDataLayout = LLVMCreateTargetDataLayout(gMachine);
91 LLVMDisposeTargetData(gDataLayout);
92 LLVMDisposeTargetMachine(gMachine);
93 LLVMDisposeMessage(gTargetTriple);
94 LLVMContextDispose(gContext);
103 static LLVMTypeRef get_llvm_digit_type(LLVMContextRef ctx,
ssa_type_digit_t digit)
110 case eDigit8:
case eDigitChar:
111 case eDigitLeast8:
case eDigitFast8:
112 return LLVMInt8TypeInContext(ctx);
113 case eDigit16:
case eDigitShort:
115 return LLVMInt16TypeInContext(ctx);
116 case eDigit32:
case eDigitInt:
117 case eDigitLong:
case eDigitLeast32:
118 case eDigitFast16:
case eDigitFast32:
119 return LLVMInt32TypeInContext(ctx);
120 case eDigit64:
case eDigitLongLong:
121 case eDigitLeast64:
case eDigitFast64:
122 case eDigitMax:
case eDigitSize:
case eDigitPtr:
123 return LLVMInt64TypeInContext(ctx);
127 return LLVMHalfTypeInContext(ctx);
129 return LLVMFloatTypeInContext(ctx);
131 return LLVMDoubleTypeInContext(ctx);
140 LLVMTypeRef inner = get_llvm_type(
self, ptr.
pointer);
143 return LLVMPointerType(inner, 0);
146 return LLVMArrayType2(inner, ptr.
length);
152 LLVMTypeRef *params =
ARENA_MALLOC(len *
sizeof(LLVMTypeRef),
"llvm_closure_params", NULL, self->arena);
153 for (
size_t i = 0; i < len; i++)
156 params[i] = get_llvm_type(
self, param);
159 LLVMTypeRef ret = get_llvm_type(
self, closure.
result);
161 return LLVMFunctionType(ret, params, len, closure.
variadic);
172 LLVMTypeRef *fields =
ARENA_MALLOC(len *
sizeof(LLVMTypeRef),
"llvm_struct_fields", NULL, self->arena);
173 for (
size_t i = 0; i < len; i++)
176 fields[i] = get_llvm_type(
self, field->
type);
180 return LLVMStructTypeInContext(gContext, fields, len,
false);
188 for (
size_t i = 0; i < len; i++)
191 LLVMTypeRef type = get_llvm_type(
self, field->
type);
192 size_t size = LLVMStoreSizeOfType(gDataLayout, type);
197 return LLVMArrayType2(LLVMInt8TypeInContext(gContext), largest);
206 return LLVMVoidTypeInContext(gContext);
208 return LLVMInt1TypeInContext(gContext);
210 return get_llvm_digit_type(gContext, type->
digit);
212 return get_llvm_closure_type(
self, type->
closure);
214 return LLVMPointerType(get_llvm_pointer_type(
self, type->
pointer), 0);
216 return get_llvm_enum_type(
self, type->
sum);
218 return LLVMPointerTypeInContext(gContext, 0);
220 return get_llvm_struct_type(
self, type->
record);
222 return get_llvm_union_type(
self, type->
record);
231 LLVMTypeRef ref =
map_get(self->types, type);
235 ref = get_llvm_type_inner(
self, type);
236 map_set(self->types, type, ref);
241 static LLVMValueRef get_digit_value(LLVMTypeRef type,
const mpz_t value,
ssa_type_digit_t digit)
243 return LLVMConstIntOfString(type, mpz_get_str(NULL, 10, value), digit.
sign == eSignSigned);
246 static LLVMValueRef get_llvm_value(LLVMTypeRef type,
const ssa_value_t *value)
249 return LLVMGetUndef(type);
254 return get_digit_value(type, value->digit_value, value->
type->
digit);
256 return LLVMConstInt(type, value->bool_value,
false);
257 case eTypeOpaque:
case eTypePointer:
258 return LLVMConstPointerNull(type);
267 LLVMModuleRef modref = LLVMModuleCreateWithNameInContext(mod->
name, gContext);
268 LLVMSetModuleDataLayout(modref, gDataLayout);
269 LLVMSetTarget(modref, gTargetTriple);
272 for (
size_t i = 0; i < vars; i++)
276 LLVMTypeRef type = get_llvm_type(
self, global->
type);
278 if (storage.
size > 1)
279 type = LLVMArrayType2(type, storage.
size);
281 LLVMValueRef ref = LLVMAddGlobal(modref, type, global->
name);
282 LLVMSetGlobalConstant(ref, storage.
quals & eQualConst);
284 if (global->
value != NULL)
286 LLVMValueRef init = get_llvm_value(type, global->
value);
287 LLVMSetInitializer(ref, init);
292 if (LLVMVerifyModule(modref, LLVMReturnStatusAction, &message))
293 CT_NEVER(
"Failed to verify module %s: %s", mod->
name, message);
295 LLVMDisposeMessage(message);
312 for (
size_t i = 0; i < len; i++)
315 llvm_build_module(&info, mod);
STA_DECL const char * ssa_type_name(ssa_kind_t kind)
CT_BROKER_API const node_t * broker_get_node(broker_t *broker)
CT_STD_API void map_set(map_t *map, const void *key, void *value)
set a key-value pair in a map
CT_NODISCARD CT_STD_API map_t * map_new(size_t size, hash_info_t info, arena_t *arena)
create a new map on the heap
CT_NODISCARD CT_PUREFN CT_STD_API void * map_get(const map_t *map, const void *key)
get a value from a map
#define CT_UNUSED(x)
mark a variable as unused
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
CT_NOTIFY_API event_builder_t msg_notify(INOUT_NOTNULL logger_t *logs, const diagnostic_t *diagnostic, const node_t *node, STA_FORMAT_STRING const char *fmt,...)
notify the logger of a new message
#define CT_NEVER(...)
assert that a code path is never reached
#define CT_PANIC(...)
panic with a message and optional format arguments
CT_TREE_API const char * digit_name(digit_t digit)
get the pretty name of a digit
CT_STD_API const hash_info_t kTypeInfoPtr
type information for a generic pointer this operates on the pointer itself and not the data it points...
CT_NODISCARD CT_PUREFN CT_STD_API size_t typevec_len(const typevec_t *vec)
get the length of a vector
CT_NODISCARD CT_PUREFN CT_STD_API void * typevec_offset(const typevec_t *vec, size_t index)
get a pointer to the value at the given index
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_get(const vector_t *vector, size_t index)
get a value from a vector
CT_NODISCARD CT_STD_API vector_t * vector_new(size_t size, arena_t *arena)
create a new vector with an initial capacity
CT_NODISCARD CT_PUREFN CT_STD_API size_t vector_len(const vector_t *vector)
get the length of a vector
a position in a source file
vector_t * globals
vector<ssa_symbol_t> all globals declared/imported/exported by this module
ssa underlying storage type
size_t size
the number of elements in the storage
tree_quals_t quals
the qualifiers of the storage
const ssa_type_t * type
the public facing type of this symbol
ssa_storage_t storage
the backing storage for this symbol
const ssa_value_t * value
the value of this symbol, must always be set for globals
const char * name
internal name
const ssa_type_t * result
const ssa_type_t * pointer
ssa_type_closure_t closure
ssa_type_pointer_t pointer
bool init
whether this value has been initialized
a generic vector of pointers
void llvm_destroy(target_runtime_t *runtime)
emit_result_t llvm_ssa(target_runtime_t *runtime, const ssa_result_t *ssa, target_emit_t *emit)
void llvm_create(target_runtime_t *runtime)