@@ -44,8 +44,9 @@ namespace {
44
44
class PelotonMemoryManager : public llvm ::SectionMemoryManager {
45
45
public:
46
46
explicit PelotonMemoryManager (
47
- const std::unordered_map<std::string, CodeContext::FuncPtr> &symbols)
48
- : symbols_(symbols) {}
47
+ const std::unordered_map<std::string,
48
+ std::pair<llvm::Function *, CodeContext::FuncPtr>> &builtins)
49
+ : builtins_(builtins) {}
49
50
50
51
#if LLVM_VERSION_GE(4, 0)
51
52
#define RET_TYPE llvm::JITSymbol
@@ -56,8 +57,6 @@ class PelotonMemoryManager : public llvm::SectionMemoryManager {
56
57
#define BUILD_RET_TYPE (addr ) \
57
58
(RET_TYPE{(uint64_t )addr, llvm::JITSymbolFlags::Exported})
58
59
#endif
59
-
60
- // / Find the address of the function with the given name
61
60
RET_TYPE findSymbol (const std::string &name) override {
62
61
LOG_TRACE (" Looking up symbol '%s' ..." , name.c_str ());
63
62
if (auto *builtin = LookupSymbol (name)) {
@@ -68,23 +67,22 @@ class PelotonMemoryManager : public llvm::SectionMemoryManager {
68
67
LOG_TRACE (" --> Not builtin, use fallback resolution ..." );
69
68
return llvm::SectionMemoryManager::findSymbol (name);
70
69
}
71
-
72
70
#undef RET_TYPE
73
71
#undef BUILD_RET_TYPE
74
72
75
73
private:
76
74
void *LookupSymbol (const std::string &name) const {
77
75
// Check for a builtin with the exact name
78
- auto symbol_iter = symbols_ .find (name);
79
- if (symbol_iter != symbols_ .end ()) {
80
- return symbol_iter->second ;
76
+ auto symbol_iter = builtins_ .find (name);
77
+ if (symbol_iter != builtins_ .end ()) {
78
+ return symbol_iter->second . second ;
81
79
}
82
80
83
81
// Check for a builtin with the leading '_' removed
84
82
if (!name.empty () && name[0 ] == ' _' ) {
85
- symbol_iter = symbols_ .find (name.substr (1 ));
86
- if (symbol_iter != symbols_ .end ()) {
87
- return symbol_iter->second ;
83
+ symbol_iter = builtins_ .find (name.substr (1 ));
84
+ if (symbol_iter != builtins_ .end ()) {
85
+ return symbol_iter->second . second ;
88
86
}
89
87
}
90
88
@@ -94,7 +92,9 @@ class PelotonMemoryManager : public llvm::SectionMemoryManager {
94
92
95
93
private:
96
94
// The code context
97
- const std::unordered_map<std::string, CodeContext::FuncPtr> &symbols_;
95
+ const std::unordered_map<std::string,
96
+ std::pair<llvm::Function *, CodeContext::FuncPtr>>
97
+ &builtins_;
98
98
};
99
99
100
100
// //////////////////////////////////////////////////////////////////////////////
@@ -177,7 +177,8 @@ CodeContext::CodeContext()
177
177
func_(nullptr ),
178
178
udf_func_ptr_(nullptr ),
179
179
pass_manager_(nullptr ),
180
- engine_(nullptr ) {
180
+ engine_(nullptr ),
181
+ is_verified_(false ) {
181
182
// Initialize JIT stuff
182
183
llvm::InitializeNativeTarget ();
183
184
llvm::InitializeNativeTargetAsmPrinter ();
@@ -200,8 +201,7 @@ CodeContext::CodeContext()
200
201
engine_.reset (
201
202
llvm::EngineBuilder (std::move (m))
202
203
.setEngineKind (llvm::EngineKind::JIT)
203
- .setMCJITMemoryManager (
204
- llvm::make_unique<PelotonMemoryManager>(function_symbols_))
204
+ .setMCJITMemoryManager (llvm::make_unique<PelotonMemoryManager>(builtins_))
205
205
.setMCPU (llvm::sys::getHostCPUName ())
206
206
.setErrorStr (&err_str_)
207
207
.create ());
@@ -223,6 +223,7 @@ CodeContext::CodeContext()
223
223
int32_type_ = llvm::Type::getInt32Ty (*context_);
224
224
int64_type_ = llvm::Type::getInt64Ty (*context_);
225
225
double_type_ = llvm::Type::getDoubleTy (*context_);
226
+ float_type_ = llvm::Type::getFloatTy (*context_);
226
227
void_type_ = llvm::Type::getVoidTy (*context_);
227
228
void_ptr_type_ = llvm::Type::getInt8PtrTy (*context_);
228
229
char_ptr_type_ = llvm::Type::getInt8PtrTy (*context_);
@@ -251,14 +252,13 @@ void CodeContext::RegisterExternalFunction(llvm::Function *func_decl,
251
252
PELOTON_ASSERT (func_impl != nullptr && " The function pointer cannot be NULL" );
252
253
functions_.emplace_back (func_decl, func_impl);
253
254
254
- // Register the builtin symbol by name
255
- function_symbols_[func_decl->getName ()] = func_impl;
255
+ builtins_[func_decl->getName ()] = std::make_pair (func_decl, func_impl);
256
256
}
257
257
258
258
void CodeContext::RegisterBuiltin (llvm::Function *func_decl,
259
259
CodeContext::FuncPtr func_impl) {
260
260
const auto name = func_decl->getName ();
261
- if (LookupBuiltin (name) != nullptr ) {
261
+ if (LookupBuiltin (name). first != nullptr ) {
262
262
LOG_DEBUG (" Builtin '%s' already registered, skipping ..." , name.data ());
263
263
return ;
264
264
}
@@ -268,44 +268,58 @@ void CodeContext::RegisterBuiltin(llvm::Function *func_decl,
268
268
func_decl->isDeclaration () &&
269
269
" You cannot provide a function definition for a builtin function" );
270
270
271
- // Register the builtin function
272
- builtins_[name] = func_decl;
273
-
274
- // Register the builtin symbol by name
275
- function_symbols_[name] = func_impl;
271
+ // Register the builtin function with type and implementation
272
+ builtins_[name] = std::make_pair (func_decl, func_impl);
276
273
}
277
274
278
- llvm::Function *CodeContext::LookupBuiltin (const std::string &name) const {
275
+ std::pair< llvm::Function *, CodeContext::FuncPtr> CodeContext::LookupBuiltin (const std::string &name) const {
279
276
auto iter = builtins_.find (name);
280
- return (iter == builtins_.end () ? nullptr : iter->second );
277
+ return (iter == builtins_.end () ? std::make_pair<llvm::Function *, CodeContext::FuncPtr>( nullptr , nullptr ) : iter->second );
281
278
}
282
279
283
- // / Optimize and JIT compile all the functions that were created in this context
284
- bool CodeContext::Compile () {
280
+ // / Verify all the functions that were created in this context
281
+ void CodeContext::Verify () {
285
282
// Verify the module is okay
286
283
llvm::raw_ostream &errors = llvm::errs ();
287
284
if (llvm::verifyModule (*module_, &errors)) {
288
- // There is an error in the module that failed compilation .
285
+ // There is an error in the module.
289
286
// Dump the crappy IR to the log ...
290
287
LOG_ERROR (" ERROR IN MODULE:\n %s\n " , GetIR ().c_str ());
291
- return false ;
288
+
289
+ throw Exception (" The generated LLVM code contains errors. " );
292
290
}
293
291
292
+ // All is well
293
+ is_verified_ = true ;
294
+ }
295
+
296
+ // / Optimize all the functions that were created in this context
297
+ void CodeContext::Optimize () {
298
+ // make sure the code is verified
299
+ if (!is_verified_) Verify ();
300
+
294
301
// Run the optimization passes over each function in this module
295
302
pass_manager_->doInitialization ();
296
303
for (auto &func_iter : functions_) {
297
304
pass_manager_->run (*func_iter.first );
298
305
}
299
306
pass_manager_->doFinalization ();
307
+ }
308
+
309
+ // / JIT compile all the functions that were created in this context
310
+ void CodeContext::Compile () {
311
+ // make sure the code is verified
312
+ if (!is_verified_) Verify ();
300
313
314
+ // Print some IR stats
301
315
if (settings::SettingsManager::GetBool (settings::SettingId::print_ir_stats)) {
302
316
char name[] = " inst count" ;
303
317
InstructionCounts inst_count (*name);
304
318
inst_count.runOnModule (GetModule ());
305
319
inst_count.DumpStats ();
306
320
}
307
321
308
- // Functions and module have been optimized, now JIT compile the module
322
+ // JIT compile the module
309
323
engine_->finalizeObject ();
310
324
311
325
// Pull out the compiled function implementations
@@ -314,14 +328,34 @@ bool CodeContext::Compile() {
314
328
}
315
329
316
330
// Log the module
331
+ LOG_TRACE (" %s\n " , GetIR ().c_str ());
317
332
if (settings::SettingsManager::GetBool (settings::SettingId::dump_ir)) {
318
333
LOG_DEBUG (" %s\n " , GetIR ().c_str ());
319
334
}
335
+ }
320
336
321
- // All is well
322
- return true ;
337
+ size_t CodeContext::GetTypeSize (llvm::Type *type) const {
338
+ auto size = GetDataLayout ().getTypeSizeInBits (type) / 8 ;
339
+ return size != 0 ? size : 1 ;
340
+ }
341
+
342
+ size_t CodeContext::GetTypeSizeInBits (llvm::Type *type) const {
343
+ return GetDataLayout ().getTypeSizeInBits (type);
344
+ }
345
+
346
+ size_t CodeContext::GetTypeAllocSize (llvm::Type *type) const {
347
+ return GetDataLayout ().getTypeAllocSize (type);
348
+ }
349
+
350
+ size_t CodeContext::GetTypeAllocSizeInBits (llvm::Type *type) const {
351
+ return GetDataLayout ().getTypeAllocSizeInBits (type);
352
+ }
353
+
354
+ size_t CodeContext::GetStructElementOffset (llvm::StructType *type, size_t index) const {
355
+ return GetDataLayout ().getStructLayout (type)->getElementOffset (index);
323
356
}
324
357
358
+ // TODO(marcel) same as LookupBuiltin?
325
359
CodeContext::FuncPtr CodeContext::GetRawFunctionPointer (
326
360
llvm::Function *fn) const {
327
361
for (const auto &iter : functions_) {
@@ -334,6 +368,7 @@ CodeContext::FuncPtr CodeContext::GetRawFunctionPointer(
334
368
return nullptr ;
335
369
}
336
370
371
+ // / Get the module's layout
337
372
const llvm::DataLayout &CodeContext::GetDataLayout () const {
338
373
return module_->getDataLayout ();
339
374
}
0 commit comments