55// This file is distributed under the BSD-style LDC license. See the LICENSE
66// file for details.
77//
8+ // This module is compiled into both the compiler and the JIT runtime library
9+ // (with predefined IN_JITRT).
10+ //
811// ===----------------------------------------------------------------------===//
912
13+ #ifdef IN_JITRT
14+ #include " runtime/jit-rt/cpp-so/optimizer.h"
15+ #include " runtime/jit-rt/cpp-so/valueparser.h"
16+ #include " runtime/jit-rt/cpp-so/utils.h"
17+ #endif
18+
1019#include " gen/optimizer.h"
1120
21+ #ifndef IN_JITRT
1222#include " dmd/errors.h"
1323#include " gen/logger.h"
24+ #endif
25+
1426#include " gen/passes/GarbageCollect2Stack.h"
1527#include " gen/passes/StripExternals.h"
1628#include " gen/passes/SimplifyDRuntimeCalls.h"
1729#include " gen/passes/Passes.h"
30+
31+ #ifndef IN_JITRT
1832#include " driver/cl_options.h"
1933#include " driver/cl_options_instrumentation.h"
2034#include " driver/cl_options_sanitizers.h"
2135#include " driver/plugins.h"
2236#include " driver/targetmachine.h"
37+ #endif
38+
2339#if LDC_LLVM_VER < 1700
2440#include " llvm/ADT/Triple.h"
2541#else
5571#include " llvm/Transforms/Scalar/Reassociate.h"
5672#include " llvm/Transforms/Instrumentation/SanitizerCoverage.h"
5773
58- extern llvm::TargetMachine *gTargetMachine ;
5974using namespace llvm ;
6075
6176static cl::opt<signed char > optimizeLevel (
@@ -96,6 +111,7 @@ static cl::opt<bool> disableGCToStack(
96111 " disable-gc2stack" , cl::ZeroOrMore,
97112 cl::desc (" Disable promotion of GC allocations to stack memory" ));
98113
114+ #ifndef IN_JITRT
99115static cl::opt<cl::boolOrDefault, false , opts::FlagParser<cl::boolOrDefault>>
100116 enableInlining (
101117 " inlining" , cl::ZeroOrMore,
@@ -105,6 +121,7 @@ static cl::opt<cl::boolOrDefault, false, opts::FlagParser<cl::boolOrDefault>>
105121 enableCrossModuleInlining (
106122 " cross-module-inlining" , cl::ZeroOrMore, cl::Hidden,
107123 cl::desc (" (*) Enable cross-module function inlining (default disabled)" ));
124+ #endif
108125
109126static cl::opt<bool > stripDebug (
110127 " strip-debug" , cl::ZeroOrMore,
@@ -135,12 +152,20 @@ static unsigned sizeLevel() { return optimizeLevel < 0 ? -optimizeLevel : 0; }
135152
136153// Determines whether or not to run the normal, full inlining pass.
137154bool willInline () {
155+ #ifdef IN_JITRT
156+ return false ;
157+ #else
138158 return enableInlining == cl::BOU_TRUE ||
139159 (enableInlining == cl::BOU_UNSET && optLevel () > 1 );
160+ #endif
140161}
141162
142163bool willCrossModuleInline () {
164+ #ifdef IN_JITRT
165+ return false ;
166+ #else
143167 return enableCrossModuleInlining == llvm::cl::BOU_TRUE && willInline ();
168+ #endif
144169}
145170
146171bool isOptimizationEnabled () { return optimizeLevel != 0 ; }
@@ -180,6 +205,7 @@ static OptimizationLevel getOptimizationLevel(){
180205 return OptimizationLevel::O0;
181206}
182207
208+ #ifndef IN_JITRT
183209static void addAddressSanitizerPasses (ModulePassManager &mpm,
184210 OptimizationLevel level ) {
185211 AddressSanitizerOptions aso;
@@ -262,6 +288,7 @@ static void addPGOPasses(ModulePassManager &mpm,
262288 }
263289 }
264290}
291+ #endif // !IN_JITRT
265292
266293static void addStripExternalsPass (ModulePassManager &mpm,
267294 OptimizationLevel level ) {
@@ -296,7 +323,7 @@ static void addGarbageCollect2StackPass(ModulePassManager &mpm,
296323 }
297324}
298325
299-
326+ # ifndef IN_JITRT
300327static llvm::Optional<PGOOptions> getPGOOptions () {
301328 // FIXME: Do we have these anywhere?
302329 bool debugInfoForProfiling = false ;
@@ -341,6 +368,7 @@ static llvm::Optional<PGOOptions> getPGOOptions() {
341368 return std::nullopt ;
342369#endif
343370}
371+ #endif // !IN_JITRT
344372
345373static PipelineTuningOptions getPipelineTuningOptions (unsigned optLevelVal, unsigned sizeLevelVal) {
346374 PipelineTuningOptions pto;
@@ -373,7 +401,7 @@ static PipelineTuningOptions getPipelineTuningOptions(unsigned optLevelVal, unsi
373401 * PassManagerBuilder.
374402 */
375403// Run optimization passes using the new pass manager
376- void runOptimizationPasses (llvm::Module *M) {
404+ void runOptimizationPasses (llvm::Module *M, llvm::TargetMachine *TM ) {
377405 // Create a ModulePassManager to hold and optimize the collection of
378406 // per-module passes we are about to build.
379407
@@ -415,8 +443,12 @@ void runOptimizationPasses(llvm::Module *M) {
415443 si.registerCallbacks (pic, &mam);
416444#endif
417445
418- PassBuilder pb (gTargetMachine , getPipelineTuningOptions (optLevelVal, sizeLevelVal),
446+ PassBuilder pb (TM, getPipelineTuningOptions (optLevelVal, sizeLevelVal),
447+ #ifdef IN_JITRT
448+ {}, &pic);
449+ #else
419450 getPGOOptions (), &pic);
451+ #endif
420452
421453 // register the target library analysis directly because clang does :)
422454 auto tlii = createTLII (*M);
@@ -433,6 +465,7 @@ void runOptimizationPasses(llvm::Module *M) {
433465
434466 // TODO: port over strip-debuginfos pass for -strip-debug
435467
468+ #ifndef IN_JITRT
436469 pb.registerPipelineStartEPCallback (addPGOPasses);
437470
438471 if (opts::isSanitizerEnabled (opts::AddressSanitizer)) {
@@ -455,6 +488,7 @@ void runOptimizationPasses(llvm::Module *M) {
455488 if (opts::isSanitizerEnabled (opts::CoverageSanitizer)) {
456489 pb.registerOptimizerLastEPCallback (addSanitizerCoveragePass);
457490 }
491+ #endif // !IN_JITRT
458492
459493 if (!disableLangSpecificPasses) {
460494 if (!disableSimplifyDruntimeCalls) {
@@ -474,7 +508,9 @@ void runOptimizationPasses(llvm::Module *M) {
474508
475509 pb.registerOptimizerLastEPCallback (addStripExternalsPass);
476510
511+ #ifndef IN_JITRT
477512 registerAllPluginsWithPassBuilder (pb);
513+ #endif
478514
479515 pb.registerModuleAnalyses (mam);
480516 pb.registerCGSCCAnalyses (cgam);
@@ -486,6 +522,9 @@ void runOptimizationPasses(llvm::Module *M) {
486522 OptimizationLevel level = getOptimizationLevel ();
487523
488524 if (optLevelVal == 0 ) {
525+ #ifdef IN_JITRT
526+ mpm = pb.buildO0DefaultPipeline (level, false );
527+ #else
489528 mpm = pb.buildO0DefaultPipeline (level, opts::isUsingLTO ());
490529#if LDC_LLVM_VER >= 1700
491530 } else if (opts::ltoFatObjects && opts::isUsingLTO ()) {
@@ -498,6 +537,7 @@ void runOptimizationPasses(llvm::Module *M) {
498537 mpm = pb.buildThinLTOPreLinkDefaultPipeline (level);
499538 } else if (opts::isUsingLTO ()) {
500539 mpm = pb.buildLTOPreLinkDefaultPipeline (level);
540+ #endif // !IN_JITRT
501541 } else {
502542 mpm = pb.buildPerModuleDefaultPipeline (level);
503543 }
@@ -508,7 +548,8 @@ void runOptimizationPasses(llvm::Module *M) {
508548// //////////////////////////////////////////////////////////////////////////////
509549// This function runs optimization passes based on command line arguments.
510550// Returns true if any optimization passes were invoked.
511- bool ldc_optimize_module (llvm::Module *M) {
551+ bool ldc_optimize_module (llvm::Module *M, llvm::TargetMachine *TM) {
552+ #ifndef IN_JITRT
512553 // Dont optimise spirv modules because turning GEPs into extracts triggers
513554 // asserts in the IR -> SPIR-V translation pass. SPIRV doesn't have a target
514555 // machine, so any optimisation passes that rely on it to provide analysis,
@@ -518,8 +559,9 @@ bool ldc_optimize_module(llvm::Module *M) {
518559 // TODO: run rudimentary optimisations to improve IR debuggability.
519560 if (getComputeTargetType (M) == ComputeBackend::SPIRV)
520561 return false ;
562+ #endif
521563
522- runOptimizationPasses (M);
564+ runOptimizationPasses (M, TM );
523565
524566 // Verify the resulting module.
525567 if (!noVerify) {
@@ -530,18 +572,38 @@ bool ldc_optimize_module(llvm::Module *M) {
530572 return true ;
531573}
532574
575+ #ifdef IN_JITRT
576+ void optimizeModule (const OptimizerSettings &settings, llvm::Module *M,
577+ llvm::TargetMachine *TM) {
578+ if (settings.sizeLevel > 0 ) {
579+ optimizeLevel = -settings.sizeLevel ;
580+ } else {
581+ optimizeLevel = settings.optLevel ;
582+ }
583+
584+ ldc_optimize_module (M, TM);
585+ }
586+ #endif // IN_JITRT
533587
534588// Verifies the module.
535589void verifyModule (llvm::Module *m) {
590+ #ifndef IN_JITRT
536591 Logger::println (" Verifying module..." );
537592 LOG_SCOPE;
593+ #endif
538594 std::string ErrorStr;
539595 raw_string_ostream OS (ErrorStr);
540596 if (llvm::verifyModule (*m, &OS)) {
597+ #ifndef IN_JITRT
541598 error (Loc (), " %s" , ErrorStr.c_str ());
542599 fatal ();
600+ #else
601+ assert (false && " Verification failed!" );
602+ #endif
543603 }
604+ #ifndef IN_JITRT
544605 Logger::println (" Verification passed!" );
606+ #endif
545607}
546608
547609// Output to `hash_os` all optimization settings that influence object code
@@ -559,3 +621,21 @@ void outputOptimizationSettings(llvm::raw_ostream &hash_os) {
559621 hash_os << disableLoopVectorization;
560622 hash_os << disableSLPVectorization;
561623}
624+
625+ #ifdef IN_JITRT
626+ void setRtCompileVar (const Context &context, llvm::Module &module ,
627+ const char *name, const void *init) {
628+ assert (nullptr != name);
629+ assert (nullptr != init);
630+ auto var = module .getGlobalVariable (name);
631+ if (nullptr != var) {
632+ auto type = var->getValueType ();
633+ auto initializer =
634+ parseInitializer (module .getDataLayout (), *type, init,
635+ [&](const std::string &str) { fatal (context, str); });
636+ var->setConstant (true );
637+ var->setInitializer (initializer);
638+ var->setLinkage (llvm::GlobalValue::PrivateLinkage);
639+ }
640+ }
641+ #endif // IN_JITRT
0 commit comments