blob: f788b90f74643aca03e3561ccdd2ffdb41e26d69 [file]
//
// Created by Sergey.Bogolepov on 24.03.2022.
//
#include <CAPIExtensions.h>
#include <llvm/IR/Module.h>
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Passes/StandardInstrumentations.h>
#include <llvm/Transforms/Utils/Cloning.h>
#include "PassesProfileHandler.h"
using namespace llvm;
namespace {
TargetMachine *unwrap(LLVMTargetMachineRef P) {
return reinterpret_cast<TargetMachine *>(P);
}
}
void LLVMKotlinInitializeTargets() {
#define INIT_LLVM_TARGET(TargetName) \
LLVMInitialize##TargetName##TargetInfo();\
LLVMInitialize##TargetName##Target();\
LLVMInitialize##TargetName##TargetMC();
INIT_LLVM_TARGET(AArch64)
INIT_LLVM_TARGET(ARM)
INIT_LLVM_TARGET(X86)
#undef INIT_LLVM_TARGET
}
void LLVMSetNoTailCall(LLVMValueRef Call) {
unwrap<CallInst>(Call)->setTailCallKind(CallInst::TCK_NoTail);
}
int LLVMInlineCall(LLVMValueRef call) {
InlineFunctionInfo IFI;
return InlineFunction(*unwrap<CallBase>(call), IFI).isSuccess();
}
extern "C" LLVMErrorRef LLVMKotlinRunPasses(
LLVMModuleRef M,
const char *Passes,
LLVMTargetMachineRef TM,
int InlinerThreshold,
LLVMKotlinPassesProfileRef* Profile
) {
// Implementation is taken from https://github.com/Kotlin/llvm-project/blob/0fa53d5183ec3c0654631d719dd6dfa7a270ca98/llvm/lib/Passes/PassBuilderBindings.cpp#L47
TargetMachine *Machine = unwrap(TM);
Module *Mod = unwrap(M);
PipelineTuningOptions PTO;
PTO.InlinerThreshold = InlinerThreshold;
PTO.MaxDevirtIterations = 0;
PassInstrumentationCallbacks PIC;
PassBuilder PB(Machine, PTO, std::nullopt, &PIC);
LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
CGSCCAnalysisManager CGAM;
ModuleAnalysisManager MAM;
PB.registerLoopAnalyses(LAM);
PB.registerFunctionAnalyses(FAM);
PB.registerCGSCCAnalyses(CGAM);
PB.registerModuleAnalyses(MAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
StandardInstrumentations SI(Mod->getContext(), false, false);
SI.registerCallbacks(PIC, &MAM);
PassesProfileHandler PPH(Profile != nullptr);
// Putting last to make this the last callback for before* events;
// the handler will additionally make sure its after* events are handled before anything else.
// This makes it so the profile tracks phases only, ignoring other callbacks.
PPH.registerCallbacks(PIC);
ModulePassManager MPM;
if (auto Err = PB.parsePassPipeline(MPM, Passes))
return wrap(std::move(Err));
MPM.run(*Mod, MAM);
if (Profile != nullptr) {
*Profile = wrap(new PassesProfile(PPH.serialize()));
}
return LLVMErrorSuccess;
}