codegen.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. #include "codegen.h"
  2. Y_PRAGMA_DIAGNOSTIC_PUSH
  3. Y_PRAGMA("GCC diagnostic ignored \"-Wbitwise-instead-of-logical\"")
  4. #include "codegen_llvm_deps.h" // Y_IGNORE
  5. Y_PRAGMA_DIAGNOSTIC_POP
  6. #include <contrib/libs/re2/re2/re2.h>
  7. #include <util/generic/maybe.h>
  8. #include <util/generic/singleton.h>
  9. #include <util/generic/hash_set.h>
  10. #include <util/generic/hash.h>
  11. #include <util/generic/yexception.h>
  12. #include <util/generic/strbuf.h>
  13. #include <util/generic/string.h>
  14. #include <util/stream/format.h>
  15. #include <util/system/defaults.h>
  16. #include <util/system/platform.h>
  17. #include <util/datetime/base.h>
  18. typedef struct __emutls_control {
  19. size_t size; /* size of the object in bytes */
  20. size_t align; /* alignment of the object in bytes */
  21. union {
  22. uintptr_t index; /* data[index-1] is the object address */
  23. void* address; /* object address, when in single thread env */
  24. } object;
  25. void* value; /* null or non-zero initial value for the object */
  26. } __emutls_control;
  27. #if defined(_msan_enabled_)
  28. extern "C" void* __emutls_get_address(__emutls_control* control);
  29. #endif
  30. class TTlsManager {
  31. public:
  32. void* Add(const TString& name, size_t size, size_t align) {
  33. //Cerr << "name: " << name << ", size: " << size << ", align: " << align << "\n";
  34. auto pair = Tls_.insert(std::make_pair(name, __emutls_control()));
  35. if (pair.second) {
  36. Zero(pair.first->second);
  37. pair.first->second.size = size;
  38. pair.first->second.align = align;
  39. }
  40. return &pair.first->second;
  41. }
  42. private:
  43. THashMap<TString, __emutls_control> Tls_;
  44. };
  45. #if !defined(_win_) || defined(__clang__)
  46. extern "C" void __divti3();
  47. extern "C" void __fixdfti();
  48. extern "C" void __fixsfti();
  49. extern "C" void __fixunsdfti();
  50. extern "C" void __floattidf();
  51. extern "C" void __floattisf();
  52. extern "C" void __floatuntidf();
  53. extern "C" void __floatuntisf();
  54. extern "C" void __modti3();
  55. extern "C" void __muloti4();
  56. extern "C" void __udivti3();
  57. extern "C" void __umodti3();
  58. #else
  59. #include <yql/essentials/public/decimal/yql_decimal.h>
  60. #define CRT_HAS_128BIT
  61. #define INT_LIB_H
  62. #define COMPILER_RT_ABI
  63. typedef NYql::NDecimal::TInt128 ti_int;
  64. typedef NYql::NDecimal::TUint128 tu_int;
  65. typedef int si_int;
  66. typedef unsigned su_int;
  67. typedef long long di_int;
  68. typedef unsigned long long du_int;
  69. typedef union
  70. {
  71. tu_int all;
  72. struct
  73. {
  74. du_int low;
  75. du_int high;
  76. }s;
  77. } utwords;
  78. typedef union
  79. {
  80. ti_int all;
  81. struct
  82. {
  83. du_int low;
  84. di_int high;
  85. }s;
  86. } twords;
  87. typedef union
  88. {
  89. du_int all;
  90. struct
  91. {
  92. su_int low;
  93. su_int high;
  94. }s;
  95. } udwords;
  96. typedef union
  97. {
  98. su_int u;
  99. float f;
  100. } float_bits;
  101. typedef union
  102. {
  103. udwords u;
  104. double f;
  105. } double_bits;
  106. int __builtin_ctzll(ui64 value) {
  107. DWORD trailing_zero = 0;
  108. if (_BitScanForward64(&trailing_zero, value)) {
  109. return trailing_zero;
  110. } else {
  111. return 64;
  112. }
  113. }
  114. int __builtin_clzll(ui64 value) {
  115. DWORD leading_zero = 0;
  116. if (_BitScanReverse64(&leading_zero, value)) {
  117. return 63 - leading_zero;
  118. } else {
  119. return 64;
  120. }
  121. }
  122. #define __divti3 __divti3impl
  123. #define __udivmodti4 __udivmodti4impl
  124. #define __modti3 __modti3impl
  125. #define __clzti2 __clzti2impl
  126. #define __floattisf __floattisfimpl
  127. #define __floattidf __floattidfimpl
  128. #include <contrib/libs/cxxsupp/builtins/udivmodti4.c>
  129. #include <contrib/libs/cxxsupp/builtins/divti3.c>
  130. #include <contrib/libs/cxxsupp/builtins/modti3.c>
  131. #include <contrib/libs/cxxsupp/builtins/clzti2.c>
  132. #include <contrib/libs/cxxsupp/builtins/floattisf.c>
  133. #include <contrib/libs/cxxsupp/builtins/floattidf.c>
  134. #include <intrin.h>
  135. #include <xmmintrin.h>
  136. // Return value in XMM0
  137. __m128 __vectorcall __divti3abi(ti_int* x, ti_int* y) {
  138. __m128 ret;
  139. auto z = __divti3(*x, *y);
  140. memcpy(&ret, &z, sizeof(ti_int));
  141. return ret;
  142. }
  143. // Return value in XMM0
  144. __m128 __vectorcall __modti3abi(ti_int* x, ti_int* y) {
  145. __m128 ret;
  146. auto z = __modti3(*x, *y);
  147. memcpy(&ret, &z, sizeof(ti_int));
  148. return ret;
  149. }
  150. float __floattisfabi(du_int x, du_int y) {
  151. utwords t;
  152. t.s.low = x;
  153. t.s.high = y;
  154. return __floattisf(t.all);
  155. }
  156. double __floattidfabi(du_int x, du_int y) {
  157. utwords t;
  158. t.s.low = x;
  159. t.s.high = y;
  160. return __floattidf(t.all);
  161. }
  162. #endif
  163. namespace NYql {
  164. namespace NCodegen {
  165. namespace {
  166. void FatalErrorHandler(void* user_data,
  167. #if LLVM_VERSION_MAJOR == 12
  168. const std::string& reason
  169. #else
  170. const char* reason
  171. #endif
  172. , bool gen_crash_diag) {
  173. Y_UNUSED(user_data);
  174. Y_UNUSED(gen_crash_diag);
  175. ythrow yexception() << "LLVM fatal error: " << reason;
  176. }
  177. void AddAddressSanitizerPasses(const llvm::PassManagerBuilder& builder, llvm::legacy::PassManagerBase& pm) {
  178. Y_UNUSED(builder);
  179. pm.add(llvm::createAddressSanitizerFunctionPass());
  180. pm.add(llvm::createModuleAddressSanitizerLegacyPassPass());
  181. }
  182. void AddMemorySanitizerPass(const llvm::PassManagerBuilder& builder, llvm::legacy::PassManagerBase& pm) {
  183. Y_UNUSED(builder);
  184. pm.add(llvm::createMemorySanitizerLegacyPassPass());
  185. }
  186. void AddThreadSanitizerPass(const llvm::PassManagerBuilder& builder, llvm::legacy::PassManagerBase& pm) {
  187. Y_UNUSED(builder);
  188. pm.add(llvm::createThreadSanitizerLegacyPassPass());
  189. }
  190. struct TCodegenInit {
  191. TCodegenInit() {
  192. llvm::InitializeNativeTarget();
  193. llvm::InitializeNativeTargetAsmPrinter();
  194. llvm::InitializeNativeTargetAsmParser();
  195. llvm::InitializeNativeTargetDisassembler();
  196. llvm::install_fatal_error_handler(&FatalErrorHandler, nullptr);
  197. }
  198. };
  199. bool CompareFuncOffsets(const std::pair<ui64, llvm::Function*>& lhs,
  200. const std::pair<ui64, llvm::Function*>& rhs) {
  201. return lhs.first < rhs.first;
  202. }
  203. }
  204. bool ICodegen::IsCodegenAvailable() {
  205. return true;
  206. }
  207. class TCodegen : public ICodegen, private llvm::JITEventListener {
  208. public:
  209. TCodegen(ETarget target, ESanitize sanitize)
  210. : Target_(target), Sanitize_(sanitize)
  211. , EffectiveTarget_(Target_), EffectiveSanitize_(Sanitize_)
  212. {
  213. Singleton<TCodegenInit>();
  214. Context_.setDiagnosticHandlerCallBack(&DiagnosticHandler, this);
  215. std::unique_ptr<llvm::Module> module(new llvm::Module("yql", Context_));
  216. Module_ = module.get();
  217. std::string triple;
  218. if (EffectiveTarget_ == ETarget::Native && EffectiveSanitize_ == ESanitize::Auto) {
  219. #if defined(_asan_enabled_)
  220. EffectiveSanitize_ = ESanitize::Asan;
  221. #elif defined(_tsan_enabled_)
  222. EffectiveSanitize_ = ESanitize::Tsan;
  223. #elif defined(_msan_enabled_)
  224. EffectiveSanitize_ = ESanitize::Msan;
  225. #endif
  226. }
  227. if (EffectiveTarget_ == ETarget::CurrentOS || EffectiveTarget_ == ETarget::Native) {
  228. #if defined(_linux_)
  229. EffectiveTarget_ = ETarget::Linux;
  230. #elif defined(_darwin_)
  231. EffectiveTarget_ = ETarget::Darwin;
  232. #elif defined(_win_)
  233. EffectiveTarget_ = ETarget::Windows;
  234. #else
  235. #error Unsupported OS
  236. #endif
  237. }
  238. switch (EffectiveTarget_) {
  239. case ETarget::Linux:
  240. triple = "x86_64-unknown-linux-gnu";
  241. break;
  242. case ETarget::Darwin:
  243. triple = "x86_64-apple-darwin";
  244. break;
  245. case ETarget::Windows:
  246. triple = "x86_64-unknown-windows-msvc";
  247. break;
  248. default:
  249. ythrow yexception() << "Failed to select target";
  250. }
  251. Triple_ = llvm::Triple::normalize(triple);
  252. Module_->setTargetTriple(Triple_);
  253. Module_->addModuleFlag(llvm::Module::Warning, "Dwarf Version", llvm::dwarf::DWARF_VERSION);
  254. Module_->addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION);
  255. llvm::TargetOptions targetOptions;
  256. targetOptions.EnableFastISel = true;
  257. // init manually, this field was lost in llvm::TargetOptions ctor :/
  258. // make coverity happy
  259. #if LLVM_VERSION_MAJOR == 12
  260. targetOptions.StackProtectorGuardOffset = 0;
  261. #endif
  262. std::string what;
  263. auto&& engineBuilder = llvm::EngineBuilder(std::move(module));
  264. engineBuilder
  265. .setEngineKind(llvm::EngineKind::JIT)
  266. .setOptLevel(llvm::CodeGenOpt::Default)
  267. .setErrorStr(&what)
  268. .setTargetOptions(targetOptions);
  269. if (Target_ == ETarget::Native) {
  270. auto hostCpu = llvm::sys::getHostCPUName();
  271. engineBuilder.setMCPU(hostCpu);
  272. }
  273. Engine_.reset(engineBuilder.create());
  274. if (!Engine_)
  275. ythrow yexception() << "Failed to construct ExecutionEngine: " << what;
  276. Module_->setDataLayout(Engine_->getDataLayout().getStringRepresentation());
  277. Engine_->RegisterJITEventListener(this);
  278. }
  279. void TogglePerfJITEventListener() override {
  280. #ifdef __linux__
  281. PerfListener_ = llvm::JITEventListener::createPerfJITEventListener();
  282. Engine_->RegisterJITEventListener(PerfListener_);
  283. #endif
  284. }
  285. ~TCodegen() {
  286. #ifdef __linux__
  287. if (PerfListener_) {
  288. Engine_->UnregisterJITEventListener(PerfListener_);
  289. }
  290. #endif
  291. Engine_->UnregisterJITEventListener(this);
  292. }
  293. ETarget GetEffectiveTarget() const override {
  294. return EffectiveTarget_;
  295. }
  296. llvm::LLVMContext& GetContext() override {
  297. return Context_;
  298. }
  299. llvm::Module& GetModule() override {
  300. return *Module_;
  301. }
  302. llvm::ExecutionEngine& GetEngine() override {
  303. return *Engine_;
  304. }
  305. void Verify() override {
  306. std::string what;
  307. llvm::raw_string_ostream os(what);
  308. if (llvm::verifyModule(*Module_, &os)) {
  309. ythrow yexception() << "Verification error: " << what;
  310. }
  311. }
  312. void GetStats(TCodegenStats& stats) override {
  313. TCodegenStats ret;
  314. for (auto& func : Module_->functions()) {
  315. if (func.isDeclaration()) {
  316. continue;
  317. }
  318. ui64 instructions = func.getInstructionCount();
  319. ret.TotalInstructions += instructions;
  320. ret.MaxFunctionInstructions = Max(ret.MaxFunctionInstructions, instructions);
  321. ++ret.TotalFunctions;
  322. }
  323. stats = ret;
  324. }
  325. void ExportSymbol(llvm::Function* function) override {
  326. if (!ExportedSymbols) {
  327. ExportedSymbols.ConstructInPlace();
  328. }
  329. auto name = function->getName();
  330. ExportedSymbols->emplace(TString(name.data(), name.size()));
  331. }
  332. void Compile(const TStringBuf compileOpts, TCompileStats* compileStats) override {
  333. bool dumpTimers = compileOpts.Contains("time-passes");
  334. bool disableOpt = compileOpts.Contains("disable-opt");
  335. #ifndef NDEBUG
  336. disableOpt = true;
  337. #endif
  338. #if defined(_msan_enabled_)
  339. ReverseGlobalMapping_[(const void*)&__emutls_get_address] = "__emutls_get_address";
  340. #endif
  341. #if defined(_win_) && !defined(__clang__)
  342. AddGlobalMapping("__security_check_cookie", (const void*)&__security_check_cookie);
  343. AddGlobalMapping("__security_cookie", (const void*)&__security_cookie);
  344. AddGlobalMapping("__divti3", (const void*)&__divti3abi);
  345. AddGlobalMapping("__modti3", (const void*)&__modti3abi);
  346. AddGlobalMapping("__floattisf", (const void*)&__floattisfabi);
  347. AddGlobalMapping("__floattidf", (const void*)&__floattidfabi);
  348. #else
  349. AddGlobalMapping("__divti3", (const void*)&__divti3);
  350. AddGlobalMapping("__fixdfti", (const void*)&__fixdfti);
  351. AddGlobalMapping("__fixsfti", (const void*)&__fixsfti);
  352. AddGlobalMapping("__fixunsdfti", (const void*)&__fixunsdfti);
  353. AddGlobalMapping("__floattidf", (const void*)&__floattidf);
  354. AddGlobalMapping("__floattisf", (const void*)&__floattisf);
  355. AddGlobalMapping("__floatuntidf", (const void*)&__floatuntidf);
  356. AddGlobalMapping("__floatuntisf", (const void*)&__floatuntisf);
  357. AddGlobalMapping("__modti3", (const void*)&__modti3);
  358. AddGlobalMapping("__muloti4", (const void*)&__muloti4);
  359. AddGlobalMapping("__udivti3", (const void*)&__udivti3);
  360. AddGlobalMapping("__umodti3", (const void*)&__umodti3);
  361. #endif
  362. for (auto& function : Module_->getFunctionList()) {
  363. function.addFnAttr("target-cpu", "x86-64");
  364. function.addFnAttr("target-features", "+sse,+sse2");
  365. }
  366. if (dumpTimers) {
  367. llvm::TimePassesIsEnabled = true;
  368. }
  369. std::unique_ptr<llvm::legacy::PassManager> modulePassManager;
  370. std::unique_ptr<llvm::legacy::FunctionPassManager> functionPassManager;
  371. if (ExportedSymbols) {
  372. modulePassManager = std::make_unique<llvm::legacy::PassManager>();
  373. modulePassManager->add(llvm::createInternalizePass([&](const llvm::GlobalValue& gv) -> bool {
  374. auto name = TString(gv.getName().str());
  375. return ExportedSymbols->contains(name);
  376. }));
  377. modulePassManager->add(llvm::createGlobalDCEPass());
  378. modulePassManager->run(*Module_);
  379. }
  380. llvm::PassManagerBuilder passManagerBuilder;
  381. passManagerBuilder.OptLevel = disableOpt ? 0 : 2;
  382. passManagerBuilder.SizeLevel = 0;
  383. passManagerBuilder.Inliner = llvm::createFunctionInliningPass();
  384. if (EffectiveSanitize_ == ESanitize::Asan) {
  385. passManagerBuilder.addExtension(llvm::PassManagerBuilder::EP_OptimizerLast,
  386. AddAddressSanitizerPasses);
  387. passManagerBuilder.addExtension(llvm::PassManagerBuilder::EP_EnabledOnOptLevel0,
  388. AddAddressSanitizerPasses);
  389. }
  390. if (EffectiveSanitize_ == ESanitize::Msan) {
  391. passManagerBuilder.addExtension(llvm::PassManagerBuilder::EP_OptimizerLast,
  392. AddMemorySanitizerPass);
  393. passManagerBuilder.addExtension(llvm::PassManagerBuilder::EP_EnabledOnOptLevel0,
  394. AddMemorySanitizerPass);
  395. }
  396. if (EffectiveSanitize_ == ESanitize::Tsan) {
  397. passManagerBuilder.addExtension(llvm::PassManagerBuilder::EP_OptimizerLast,
  398. AddThreadSanitizerPass);
  399. passManagerBuilder.addExtension(llvm::PassManagerBuilder::EP_EnabledOnOptLevel0,
  400. AddThreadSanitizerPass);
  401. }
  402. functionPassManager = std::make_unique<llvm::legacy::FunctionPassManager>(Module_);
  403. modulePassManager = std::make_unique<llvm::legacy::PassManager>();
  404. passManagerBuilder.populateModulePassManager(*modulePassManager);
  405. passManagerBuilder.populateFunctionPassManager(*functionPassManager);
  406. auto functionPassStart = Now();
  407. functionPassManager->doInitialization();
  408. for (auto it = Module_->begin(), jt = Module_->end(); it != jt; ++it) {
  409. if (!it->isDeclaration()) {
  410. functionPassManager->run(*it);
  411. }
  412. }
  413. functionPassManager->doFinalization();
  414. if (compileStats) {
  415. compileStats->FunctionPassTime = (Now() - functionPassStart).MilliSeconds();
  416. }
  417. auto modulePassStart = Now();
  418. modulePassManager->run(*Module_);
  419. if (compileStats) {
  420. compileStats->ModulePassTime = (Now() - modulePassStart).MilliSeconds();
  421. }
  422. AllocateTls();
  423. auto finalizeStart = Now();
  424. Engine_->finalizeObject();
  425. if (compileStats) {
  426. compileStats->FinalizeTime = (Now() - finalizeStart).MilliSeconds();
  427. }
  428. for (const auto& secEntry : CodeSections_) {
  429. for (auto& func : Module_->functions()) {
  430. if (func.isDeclaration()) {
  431. continue;
  432. }
  433. auto addr = (ui64)Engine_->getPointerToFunction(&func);
  434. if (addr < secEntry.second || addr >= secEntry.second + secEntry.first.getSize()) {
  435. continue;
  436. }
  437. SortedFuncs_.emplace_back(addr, &func);
  438. }
  439. SortedFuncs_.emplace_back(secEntry.second + secEntry.first.getSize(), nullptr);
  440. }
  441. std::sort(SortedFuncs_.begin(), SortedFuncs_.end(), CompareFuncOffsets);
  442. if (dumpTimers) {
  443. llvm::TimerGroup::printAll(llvm::errs());
  444. llvm::TimePassesIsEnabled = false;
  445. }
  446. if (compileStats) {
  447. compileStats->TotalObjectSize = TotalObjectSize;
  448. }
  449. }
  450. void* GetPointerToFunction(llvm::Function* function) override {
  451. return Engine_->getPointerToFunction(function);
  452. }
  453. ui64 GetFunctionCodeSize(llvm::Function* function) override {
  454. auto addr = (ui64)Engine_->getPointerToFunction(function);
  455. auto it = std::upper_bound(SortedFuncs_.begin(), SortedFuncs_.end(), std::make_pair(addr, nullptr), CompareFuncOffsets);
  456. return it->first - addr;
  457. }
  458. void ShowGeneratedFunctions(IOutputStream* out) override {
  459. *out << "--- functions begin ---\n";
  460. for (const auto& secEntry : CodeSections_) {
  461. auto expName = secEntry.first.getName();
  462. auto name = expName.get();
  463. auto sectionName = TStringBuf(name.data(), name.size());
  464. *out << "section: " << sectionName << ", addr: " << (void*)secEntry.second << ", size: " << secEntry.first.getSize() << "\n";
  465. }
  466. for (const auto& funcEntry : SortedFuncs_) {
  467. if (!funcEntry.second) {
  468. continue;
  469. }
  470. const auto& name = funcEntry.second->getName();
  471. auto funcName = TStringBuf(name.data(), name.size());
  472. auto codeSize = GetFunctionCodeSize(funcEntry.second);
  473. *out << "function: " << funcName << ", addr: " << (void*)funcEntry.first << ", size: " <<
  474. codeSize << "\n";
  475. Disassemble(out, (const unsigned char*)funcEntry.first, codeSize);
  476. }
  477. *out << "--- functions end ---\n";
  478. }
  479. void Disassemble(IOutputStream* out, const unsigned char* buf, size_t size) {
  480. InitRegexps();
  481. auto dis = LLVMCreateDisasm(Triple_.c_str(), nullptr, 0, nullptr, nullptr);
  482. if (!dis) {
  483. ythrow yexception() << "Cannot create disassembler";
  484. }
  485. std::unique_ptr<void, void(*)(void*)> delDis(dis, LLVMDisasmDispose);
  486. LLVMSetDisasmOptions(dis, LLVMDisassembler_Option_AsmPrinterVariant);
  487. char outline[1024];
  488. size_t pos = 0;
  489. while (pos < size) {
  490. size_t l = LLVMDisasmInstruction(dis, (uint8_t*)buf + pos, size - pos, 0, outline, sizeof(outline));
  491. if (!l) {
  492. *out << " " << LeftPad(pos, 4, '0') << "\t???";
  493. ++pos;
  494. } else {
  495. *out << " " << LeftPad(pos, 4, '0') << outline;
  496. TStringBuf s(outline);
  497. const re2::StringPiece piece(s.data(), s.size());
  498. std::array<re2::StringPiece, 2> captures;
  499. if (Patterns_->Imm_.Match(piece, 0, s.size(), re2::RE2::UNANCHORED, captures.data(), captures.size())) {
  500. auto numBuf = TStringBuf(captures[1].data(), captures[1].size());
  501. ui64 addr = FromString<ui64>(numBuf);
  502. auto it = ReverseGlobalMapping_.find((void*)addr);
  503. if (it != ReverseGlobalMapping_.end()) {
  504. *out << " ; &" << it->second;
  505. }
  506. } else if (Patterns_->Jump_.Match(piece, 0, s.size(), re2::RE2::UNANCHORED, captures.data(), captures.size())) {
  507. auto numBuf = TStringBuf(captures[1].data(), captures[1].size());
  508. i64 offset = FromString<i64>(numBuf);
  509. *out << " ; -> " << pos + l + offset;
  510. }
  511. pos += l;
  512. }
  513. *out << '\n';
  514. }
  515. }
  516. void LoadBitCode(TStringBuf bitcode, TStringBuf uniqId) override {
  517. if (uniqId && LoadedModules_.contains(uniqId)) {
  518. return;
  519. }
  520. llvm::SMDiagnostic error;
  521. auto buffer = llvm::MemoryBuffer::getMemBuffer(
  522. llvm::StringRef(bitcode.data(), bitcode.size()));
  523. std::unique_ptr<llvm::Module> module = llvm::parseIR(buffer->getMemBufferRef(), error, Context_);
  524. if (!module) {
  525. std::string what;
  526. llvm::raw_string_ostream os(what);
  527. error.print("error after ParseIR()", os);
  528. ythrow yexception() << what;
  529. }
  530. module->setTargetTriple(Triple_);
  531. module->setDataLayout(Engine_->getDataLayout().getStringRepresentation());
  532. if (uniqId) {
  533. module->setModuleIdentifier(llvm::StringRef(uniqId.data(), uniqId.size()));
  534. }
  535. if (llvm::Linker::linkModules(*Module_, std::move(module))) {
  536. TString err;
  537. err.append("LLVM: error linking module");
  538. if (uniqId) {
  539. err.append(' ').append(uniqId);
  540. }
  541. if (Diagnostic_.size()) {
  542. err.append(": ").append(Diagnostic_.c_str(), Diagnostic_.size());
  543. }
  544. ythrow yexception() << err;
  545. }
  546. if (uniqId) {
  547. LoadedModules_.emplace(uniqId);
  548. }
  549. }
  550. void AddGlobalMapping(TStringBuf name, const void* address) override {
  551. ReverseGlobalMapping_[address] = TString(name);
  552. Engine_->updateGlobalMapping(llvm::StringRef(name.data(), name.size()), (uint64_t)address);
  553. }
  554. void notifyObjectLoaded(ObjectKey key, const llvm::object::ObjectFile &obj,
  555. const llvm::RuntimeDyld::LoadedObjectInfo &loi) override
  556. {
  557. Y_UNUSED(key);
  558. TotalObjectSize += obj.getData().size();
  559. for (const auto& section : obj.sections()) {
  560. //auto nameExp = section.getName();
  561. //auto name = nameExp.get();
  562. //auto nameStr = TStringBuf(name.data(), name.size());
  563. //Cerr << nameStr << "\n";
  564. if (section.isText()) {
  565. CodeSections_.emplace_back(section, loi.getSectionLoadAddress(section));
  566. }
  567. }
  568. }
  569. private:
  570. void OnDiagnosticInfo(const llvm::DiagnosticInfo &info) {
  571. llvm::raw_string_ostream ostream(Diagnostic_);
  572. llvm::DiagnosticPrinterRawOStream printer(ostream);
  573. info.print(printer);
  574. }
  575. static void DiagnosticHandler(const llvm::DiagnosticInfo &info, void* context) {
  576. return static_cast<TCodegen*>(context)->OnDiagnosticInfo(info);
  577. }
  578. void AllocateTls() {
  579. for (const auto& glob : Module_->globals()) {
  580. auto nameRef = glob.getName();
  581. if (glob.isThreadLocal()) {
  582. llvm::Type* type = glob.getValueType();
  583. const llvm::DataLayout& dataLayout = Module_->getDataLayout();
  584. auto size = dataLayout.getTypeStoreSize(type);
  585. auto align = glob.getAlignment();
  586. if (!align) {
  587. // When LLVM IL declares a variable without alignment, use
  588. // the ABI default alignment for the type.
  589. align = dataLayout.getABITypeAlignment(type);
  590. }
  591. TStringBuf name(nameRef.data(), nameRef.size());
  592. TString fullName = TString("__emutls_v.") + name;
  593. auto ctl = TlsManager_.Add(fullName, size, align);
  594. Engine_->updateGlobalMapping(llvm::StringRef(fullName.data(), fullName.size()), (uint64_t)ctl);
  595. ReverseGlobalMapping_[&ctl] = fullName;
  596. }
  597. }
  598. }
  599. struct TPatterns {
  600. TPatterns()
  601. : Imm_(re2::StringPiece("\\s*movabs\\s+[0-9a-z]+\\s*,\\s*(\\d+)\\s*"))
  602. , Jump_(re2::StringPiece("\\s*(?:j[a-z]+)\\s*(-?\\d+)\\s*"))
  603. {}
  604. re2::RE2 Imm_;
  605. re2::RE2 Jump_;
  606. };
  607. void InitRegexps() {
  608. if (!Patterns_) {
  609. Patterns_.ConstructInPlace();
  610. }
  611. }
  612. const ETarget Target_;
  613. const ESanitize Sanitize_;
  614. ETarget EffectiveTarget_;
  615. ESanitize EffectiveSanitize_;
  616. llvm::LLVMContext Context_;
  617. std::string Diagnostic_;
  618. std::string Triple_;
  619. llvm::Module* Module_;
  620. #ifdef __linux__
  621. llvm::JITEventListener* PerfListener_ = nullptr;
  622. #endif
  623. std::unique_ptr<llvm::ExecutionEngine> Engine_;
  624. std::vector<std::pair<llvm::object::SectionRef, ui64>> CodeSections_;
  625. ui64 TotalObjectSize = 0;
  626. std::vector<std::pair<ui64, llvm::Function*>> SortedFuncs_;
  627. TMaybe<THashSet<TString>> ExportedSymbols;
  628. THashMap<const void*, TString> ReverseGlobalMapping_;
  629. TMaybe<TPatterns> Patterns_;
  630. TTlsManager TlsManager_;
  631. THashSet<TString> LoadedModules_;
  632. };
  633. ICodegen::TPtr
  634. ICodegen::Make(ETarget target, ESanitize sanitize) {
  635. return std::make_unique<TCodegen>(target, sanitize);
  636. }
  637. ICodegen::TSharedPtr
  638. ICodegen::MakeShared(ETarget target, ESanitize sanitize) {
  639. return std::make_shared<TCodegen>(target, sanitize);
  640. }
  641. }
  642. }