@@ -44,8 +44,9 @@ namespace {
4444class PelotonMemoryManager : public llvm ::SectionMemoryManager {
4545 public:
4646 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) {}
4950
5051#if LLVM_VERSION_GE(4, 0)
5152#define RET_TYPE llvm::JITSymbol
@@ -56,8 +57,6 @@ class PelotonMemoryManager : public llvm::SectionMemoryManager {
5657#define BUILD_RET_TYPE (addr ) \
5758 (RET_TYPE{(uint64_t )addr, llvm::JITSymbolFlags::Exported})
5859#endif
59-
60- // / Find the address of the function with the given name
6160 RET_TYPE findSymbol (const std::string &name) override {
6261 LOG_TRACE (" Looking up symbol '%s' ..." , name.c_str ());
6362 if (auto *builtin = LookupSymbol (name)) {
@@ -68,23 +67,22 @@ class PelotonMemoryManager : public llvm::SectionMemoryManager {
6867 LOG_TRACE (" --> Not builtin, use fallback resolution ..." );
6968 return llvm::SectionMemoryManager::findSymbol (name);
7069 }
71-
7270#undef RET_TYPE
7371#undef BUILD_RET_TYPE
7472
7573 private:
7674 void *LookupSymbol (const std::string &name) const {
7775 // 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 ;
8179 }
8280
8381 // Check for a builtin with the leading '_' removed
8482 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 ;
8886 }
8987 }
9088
@@ -94,7 +92,9 @@ class PelotonMemoryManager : public llvm::SectionMemoryManager {
9492
9593 private:
9694 // 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_;
9898};
9999
100100// //////////////////////////////////////////////////////////////////////////////
@@ -177,7 +177,8 @@ CodeContext::CodeContext()
177177 func_(nullptr ),
178178 udf_func_ptr_(nullptr ),
179179 pass_manager_(nullptr ),
180- engine_(nullptr ) {
180+ engine_(nullptr ),
181+ is_verified_(false ) {
181182 // Initialize JIT stuff
182183 llvm::InitializeNativeTarget ();
183184 llvm::InitializeNativeTargetAsmPrinter ();
@@ -200,8 +201,7 @@ CodeContext::CodeContext()
200201 engine_.reset (
201202 llvm::EngineBuilder (std::move (m))
202203 .setEngineKind (llvm::EngineKind::JIT)
203- .setMCJITMemoryManager (
204- llvm::make_unique<PelotonMemoryManager>(function_symbols_))
204+ .setMCJITMemoryManager (llvm::make_unique<PelotonMemoryManager>(builtins_))
205205 .setMCPU (llvm::sys::getHostCPUName ())
206206 .setErrorStr (&err_str_)
207207 .create ());
@@ -223,6 +223,7 @@ CodeContext::CodeContext()
223223 int32_type_ = llvm::Type::getInt32Ty (*context_);
224224 int64_type_ = llvm::Type::getInt64Ty (*context_);
225225 double_type_ = llvm::Type::getDoubleTy (*context_);
226+ float_type_ = llvm::Type::getFloatTy (*context_);
226227 void_type_ = llvm::Type::getVoidTy (*context_);
227228 void_ptr_type_ = llvm::Type::getInt8PtrTy (*context_);
228229 char_ptr_type_ = llvm::Type::getInt8PtrTy (*context_);
@@ -251,14 +252,13 @@ void CodeContext::RegisterExternalFunction(llvm::Function *func_decl,
251252 PELOTON_ASSERT (func_impl != nullptr && " The function pointer cannot be NULL" );
252253 functions_.emplace_back (func_decl, func_impl);
253254
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);
256256}
257257
258258void CodeContext::RegisterBuiltin (llvm::Function *func_decl,
259259 CodeContext::FuncPtr func_impl) {
260260 const auto name = func_decl->getName ();
261- if (LookupBuiltin (name) != nullptr ) {
261+ if (LookupBuiltin (name). first != nullptr ) {
262262 LOG_DEBUG (" Builtin '%s' already registered, skipping ..." , name.data ());
263263 return ;
264264 }
@@ -268,44 +268,58 @@ void CodeContext::RegisterBuiltin(llvm::Function *func_decl,
268268 func_decl->isDeclaration () &&
269269 " You cannot provide a function definition for a builtin function" );
270270
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);
276273}
277274
278- llvm::Function *CodeContext::LookupBuiltin (const std::string &name) const {
275+ std::pair< llvm::Function *, CodeContext::FuncPtr> CodeContext::LookupBuiltin (const std::string &name) const {
279276 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 );
281278}
282279
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 () {
285282 // Verify the module is okay
286283 llvm::raw_ostream &errors = llvm::errs ();
287284 if (llvm::verifyModule (*module_, &errors)) {
288- // There is an error in the module that failed compilation .
285+ // There is an error in the module.
289286 // Dump the crappy IR to the log ...
290287 LOG_ERROR (" ERROR IN MODULE:\n %s\n " , GetIR ().c_str ());
291- return false ;
288+
289+ throw Exception (" The generated LLVM code contains errors. " );
292290 }
293291
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+
294301 // Run the optimization passes over each function in this module
295302 pass_manager_->doInitialization ();
296303 for (auto &func_iter : functions_) {
297304 pass_manager_->run (*func_iter.first );
298305 }
299306 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 ();
300313
314+ // Print some IR stats
301315 if (settings::SettingsManager::GetBool (settings::SettingId::print_ir_stats)) {
302316 char name[] = " inst count" ;
303317 InstructionCounts inst_count (*name);
304318 inst_count.runOnModule (GetModule ());
305319 inst_count.DumpStats ();
306320 }
307321
308- // Functions and module have been optimized, now JIT compile the module
322+ // JIT compile the module
309323 engine_->finalizeObject ();
310324
311325 // Pull out the compiled function implementations
@@ -314,14 +328,34 @@ bool CodeContext::Compile() {
314328 }
315329
316330 // Log the module
331+ LOG_TRACE (" %s\n " , GetIR ().c_str ());
317332 if (settings::SettingsManager::GetBool (settings::SettingId::dump_ir)) {
318333 LOG_DEBUG (" %s\n " , GetIR ().c_str ());
319334 }
335+ }
320336
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);
323356}
324357
358+ // TODO(marcel) same as LookupBuiltin?
325359CodeContext::FuncPtr CodeContext::GetRawFunctionPointer (
326360 llvm::Function *fn) const {
327361 for (const auto &iter : functions_) {
@@ -334,6 +368,7 @@ CodeContext::FuncPtr CodeContext::GetRawFunctionPointer(
334368 return nullptr ;
335369}
336370
371+ // / Get the module's layout
337372const llvm::DataLayout &CodeContext::GetDataLayout () const {
338373 return module_->getDataLayout ();
339374}
0 commit comments