Skip to content

Commit 4da4982

Browse files
committed
move all codegen pass handling to aotcompile.cpp
1 parent 4a9affb commit 4da4982

File tree

6 files changed

+208
-214
lines changed

6 files changed

+208
-214
lines changed

src/aotcompile.cpp

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141
#include <llvm/Bitcode/BitcodeWriterPass.h>
4242
#include "llvm/Object/ArchiveWriter.h"
4343
#include <llvm/IR/IRPrintingPasses.h>
44+
#include <llvm/CodeGen/MachineModuleInfo.h>
45+
#include <llvm/CodeGen/TargetPassConfig.h>
46+
#if JL_LLVM_VERSION < 50000
47+
#include <llvm/CodeGen/Passes.h>
48+
#include <llvm/CodeGen/AsmPrinter.h>
49+
#endif
4450

4551
#include <llvm/IR/LegacyPassManagers.h>
4652
#include <llvm/Transforms/Utils/Cloning.h>
@@ -721,3 +727,199 @@ extern "C" JL_DLLEXPORT
721727
void jl_add_optimization_passes(LLVMPassManagerRef PM, int opt_level) {
722728
addOptimizationPasses(unwrap(PM), opt_level);
723729
}
730+
731+
// --- native code info, and dump function to IR and ASM ---
732+
// Get pointer to llvm::Function instance, compiling if necessary
733+
// for use in reflection from Julia.
734+
// this is paired with jl_dump_function_ir, jl_dump_method_asm, jl_dump_llvm_asm in particular ways:
735+
// misuse will leak memory or cause read-after-free
736+
extern "C" JL_DLLEXPORT
737+
void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, char getwrapper, char optimize, const jl_cgparams_t params)
738+
{
739+
if (jl_is_method(linfo->def.method) && linfo->def.method->source == NULL &&
740+
linfo->def.method->generator == NULL) {
741+
// not a generic function
742+
return NULL;
743+
}
744+
745+
static legacy::PassManager *PM;
746+
if (!PM) {
747+
PM = new legacy::PassManager();
748+
addTargetPasses(PM, jl_TargetMachine);
749+
addOptimizationPasses(PM, jl_options.opt_level);
750+
}
751+
752+
// get the source code for this function
753+
jl_code_info_t *src = (jl_code_info_t*)linfo->inferred;
754+
JL_GC_PUSH1(&src);
755+
if (!src || (jl_value_t*)src == jl_nothing) {
756+
src = jl_type_infer(&linfo, world, 0);
757+
if (!src && jl_is_method(linfo->def.method))
758+
src = linfo->def.method->generator ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def.method->source;
759+
}
760+
if ((jl_value_t*)src == jl_nothing)
761+
src = NULL;
762+
if (src && !jl_is_code_info(src) && jl_is_method(linfo->def.method))
763+
src = jl_uncompress_ast(linfo->def.method, (jl_array_t*)src);
764+
765+
// emit this function into a new module
766+
if (src && jl_is_code_info(src)) {
767+
jl_codegen_params_t output;
768+
output.world = world;
769+
output.params = &params;
770+
std::unique_ptr<Module> m;
771+
jl_llvm_functions_t decls;
772+
jl_value_t *rettype;
773+
uint8_t api;
774+
JL_LOCK(&codegen_lock);
775+
std::tie(m, decls, rettype, api) = jl_compile_linfo1(linfo, src, output);
776+
777+
Function *F = NULL;
778+
if (m) {
779+
// if compilation succeeded, prepare to return the result
780+
const std::string *fname;
781+
if (!getwrapper && !decls.specFunctionObject.empty())
782+
fname = &decls.specFunctionObject;
783+
else
784+
fname = &decls.functionObject;
785+
if (optimize)
786+
PM->run(*m.get());
787+
F = cast<Function>(m->getNamedValue(*fname));
788+
m.release(); // the return object `llvmf` will be the owning pointer
789+
}
790+
JL_GC_POP();
791+
JL_UNLOCK(&codegen_lock); // Might GC
792+
if (F)
793+
return F;
794+
}
795+
796+
const char *mname = name_from_method_instance(linfo);
797+
jl_errorf("unable to compile source for function %s", mname);
798+
}
799+
800+
/// addPassesToX helper drives creation and initialization of TargetPassConfig.
801+
#if JL_LLVM_VERSION >= 50000
802+
static MCContext *
803+
addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM) {
804+
TargetPassConfig *PassConfig = TM->createPassConfig(PM);
805+
#if JL_LLVM_VERSION < 60000
806+
PassConfig->setStartStopPasses(nullptr, nullptr, nullptr, nullptr);
807+
#endif
808+
PassConfig->setDisableVerify(false);
809+
PM.add(PassConfig);
810+
MachineModuleInfo *MMI = new MachineModuleInfo(TM);
811+
PM.add(MMI);
812+
if (PassConfig->addISelPasses())
813+
return NULL;
814+
PassConfig->addMachinePasses();
815+
PassConfig->setInitialized();
816+
return &MMI->getContext();
817+
}
818+
#else
819+
static MCContext *
820+
addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM) {
821+
// When in emulated TLS mode, add the LowerEmuTLS pass.
822+
if (TM->Options.EmulatedTLS)
823+
PM.add(createLowerEmuTLSPass(TM));
824+
825+
PM.add(createPreISelIntrinsicLoweringPass());
826+
827+
// Add internal analysis passes from the target machine.
828+
PM.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
829+
830+
// Targets may override createPassConfig to provide a target-specific
831+
// subclass.
832+
TargetPassConfig *PassConfig = TM->createPassConfig(PM);
833+
PassConfig->setStartStopPasses(nullptr, nullptr, nullptr);
834+
835+
// Set PassConfig options provided by TargetMachine.
836+
PassConfig->setDisableVerify(false);
837+
838+
PM.add(PassConfig);
839+
840+
PassConfig->addIRPasses();
841+
842+
PassConfig->addCodeGenPrepare();
843+
844+
PassConfig->addPassesToHandleExceptions();
845+
846+
PassConfig->addISelPrepare();
847+
848+
MachineModuleInfo &MMI = TM->addMachineModuleInfo(PM);
849+
TM->addMachineFunctionAnalysis(PM, nullptr);
850+
851+
// Disable FastISel with -O0
852+
TM->setO0WantsFastISel(false);
853+
854+
if (PassConfig->addInstSelector())
855+
return nullptr;
856+
857+
PassConfig->addMachinePasses();
858+
859+
PassConfig->setInitialized();
860+
861+
return &MMI.getContext();
862+
}
863+
#endif
864+
865+
void jl_strip_llvm_debug(Module *m);
866+
867+
868+
// get a native assembly for llvm::Function
869+
extern "C" JL_DLLEXPORT
870+
jl_value_t *jl_dump_llvm_asm(void *F, const char* asm_variant)
871+
{
872+
// precise printing via IR assembler
873+
SmallVector<char, 4096> ObjBufferSV;
874+
{ // scope block
875+
Function *f = (Function*)F;
876+
llvm::raw_svector_ostream asmfile(ObjBufferSV);
877+
assert(!f->isDeclaration());
878+
std::unique_ptr<Module> m(f->getParent());
879+
for (auto &f2 : m->functions()) {
880+
if (f != &f2 && !f->isDeclaration())
881+
f2.deleteBody();
882+
}
883+
jl_strip_llvm_debug(m.get());
884+
legacy::PassManager PM;
885+
LLVMTargetMachine *TM = static_cast<LLVMTargetMachine*>(jl_TargetMachine);
886+
MCContext *Context = addPassesToGenerateCode(TM, PM);
887+
if (Context) {
888+
#if JL_LLVM_VERSION >= 60000
889+
const MCSubtargetInfo &STI = *TM->getMCSubtargetInfo();
890+
#endif
891+
const MCAsmInfo &MAI = *TM->getMCAsmInfo();
892+
const MCRegisterInfo &MRI = *TM->getMCRegisterInfo();
893+
const MCInstrInfo &MII = *TM->getMCInstrInfo();
894+
unsigned OutputAsmDialect = MAI.getAssemblerDialect();
895+
if (!strcmp(asm_variant, "att"))
896+
OutputAsmDialect = 0;
897+
if (!strcmp(asm_variant, "intel"))
898+
OutputAsmDialect = 1;
899+
MCInstPrinter *InstPrinter = TM->getTarget().createMCInstPrinter(
900+
TM->getTargetTriple(), OutputAsmDialect, MAI, MII, MRI);
901+
MCAsmBackend *MAB = TM->getTarget().createMCAsmBackend(
902+
#if JL_LLVM_VERSION >= 60000
903+
STI, MRI, TM->Options.MCOptions
904+
#elif JL_LLVM_VERSION >= 40000
905+
MRI, TM->getTargetTriple().str(), TM->getTargetCPU(), TM->Options.MCOptions
906+
#else
907+
MRI, TM->getTargetTriple().str(), TM->getTargetCPU()
908+
#endif
909+
);
910+
auto FOut = llvm::make_unique<formatted_raw_ostream>(asmfile);
911+
MCCodeEmitter *MCE = nullptr;
912+
std::unique_ptr<MCStreamer> S(TM->getTarget().createAsmStreamer(
913+
*Context, std::move(FOut), true,
914+
true, InstPrinter, MCE, MAB, false));
915+
AsmPrinter *Printer =
916+
TM->getTarget().createAsmPrinter(*TM, std::move(S));
917+
if (Printer) {
918+
PM.add(Printer);
919+
PM.run(*m);
920+
}
921+
}
922+
delete f;
923+
}
924+
return jl_pchar_to_string(ObjBufferSV.data(), ObjBufferSV.size());
925+
}

src/codegen.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,6 @@ namespace llvm {
105105
#include "processor.h"
106106
#include "julia_assert.h"
107107

108-
// LLVM version compatibility macros
109-
legacy::PassManager *jl_globalPM;
110-
111108
#if JL_LLVM_VERSION >= 40000
112109
#define DIFlagZero (DINode::FlagZero)
113110
#else
@@ -6638,10 +6635,6 @@ extern "C" void jl_init_codegen(void)
66386635
box64_func = boxfunc_llvm(ft2arg(T_pjlvalue, T_pjlvalue, T_int64),
66396636
"jl_box64", &jl_box64, m);
66406637
jl_init_intrinsic_functions_codegen(m);
6641-
6642-
jl_globalPM = new legacy::PassManager();
6643-
addTargetPasses(jl_globalPM, jl_TargetMachine);
6644-
addOptimizationPasses(jl_globalPM, jl_options.opt_level);
66456638
}
66466639

66476640
// the rest of this file are convenience functions

src/disasm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ void jl_strip_llvm_debug(Module *m)
318318
// print an llvm IR acquired from jl_get_llvmf
319319
// warning: this takes ownership of, and destroys, f->getParent()
320320
extern "C" JL_DLLEXPORT
321-
jl_value_t *jl_dump_function_ir(void *f, bool strip_ir_metadata, bool dump_module)
321+
jl_value_t *jl_dump_function_ir(void *f, char strip_ir_metadata, char dump_module)
322322
{
323323
std::string code;
324324
llvm::raw_string_ostream stream(code);

0 commit comments

Comments
 (0)