#include "SparcTargetMachine.h"
#include "LeonPasses.h"
#include "Sparc.h"
#include "SparcTargetObjectFile.h"
#include "TargetInfo/SparcTargetInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/MC/TargetRegistry.h"
using namespace llvm;
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTarget() {
RegisterTargetMachine<SparcV8TargetMachine> X(getTheSparcTarget());
RegisterTargetMachine<SparcV9TargetMachine> Y(getTheSparcV9Target());
RegisterTargetMachine<SparcelTargetMachine> Z(getTheSparcelTarget());
}
static std::string computeDataLayout(const Triple &T, bool is64Bit) {
std::string Ret = T.getArch() == Triple::sparcel ? "e" : "E";
Ret += "-m:e";
if (!is64Bit)
Ret += "-p:32:32";
Ret += "-i64:64";
if (is64Bit)
Ret += "-n32:64";
else
Ret += "-f128:64-n32";
if (is64Bit)
Ret += "-S128";
else
Ret += "-S64";
return Ret;
}
static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
return RM.value_or(Reloc::Static);
}
static CodeModel::Model
getEffectiveSparcCodeModel(Optional<CodeModel::Model> CM, Reloc::Model RM,
bool Is64Bit, bool JIT) {
if (CM) {
if (*CM == CodeModel::Tiny)
report_fatal_error("Target does not support the tiny CodeModel", false);
if (*CM == CodeModel::Kernel)
report_fatal_error("Target does not support the kernel CodeModel", false);
return *CM;
}
if (Is64Bit) {
if (JIT)
return CodeModel::Large;
return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium;
}
return CodeModel::Small;
}
SparcTargetMachine::SparcTargetMachine(
const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
const TargetOptions &Options, Optional<Reloc::Model> RM,
Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT, bool is64bit)
: LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options,
getEffectiveRelocModel(RM),
getEffectiveSparcCodeModel(
CM, getEffectiveRelocModel(RM), is64bit, JIT),
OL),
TLOF(std::make_unique<SparcELFTargetObjectFile>()),
Subtarget(TT, std::string(CPU), std::string(FS), *this, is64bit),
is64Bit(is64bit) {
initAsmInfo();
}
SparcTargetMachine::~SparcTargetMachine() = default;
const SparcSubtarget *
SparcTargetMachine::getSubtargetImpl(const Function &F) const {
Attribute CPUAttr = F.getFnAttribute("target-cpu");
Attribute FSAttr = F.getFnAttribute("target-features");
std::string CPU =
CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
std::string FS =
FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
if (softFloat)
FS += FS.empty() ? "+soft-float" : ",+soft-float";
auto &I = SubtargetMap[CPU + FS];
if (!I) {
resetTargetOptions(F);
I = std::make_unique<SparcSubtarget>(TargetTriple, CPU, FS, *this,
this->is64Bit);
}
return I.get();
}
namespace {
class SparcPassConfig : public TargetPassConfig {
public:
SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
SparcTargetMachine &getSparcTargetMachine() const {
return getTM<SparcTargetMachine>();
}
void addIRPasses() override;
bool addInstSelector() override;
void addPreEmitPass() override;
};
}
TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {
return new SparcPassConfig(*this, PM);
}
void SparcPassConfig::addIRPasses() {
addPass(createAtomicExpandPass());
TargetPassConfig::addIRPasses();
}
bool SparcPassConfig::addInstSelector() {
addPass(createSparcISelDag(getSparcTargetMachine()));
return false;
}
void SparcPassConfig::addPreEmitPass(){
addPass(createSparcDelaySlotFillerPass());
if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad())
{
addPass(new InsertNOPLoad());
}
if (this->getSparcTargetMachine().getSubtargetImpl()->detectRoundChange()) {
addPass(new DetectRoundChange());
}
if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT())
{
addPass(new FixAllFDIVSQRT());
}
}
void SparcV8TargetMachine::anchor() { }
SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
Optional<Reloc::Model> RM,
Optional<CodeModel::Model> CM,
CodeGenOpt::Level OL, bool JIT)
: SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}
void SparcV9TargetMachine::anchor() { }
SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
Optional<Reloc::Model> RM,
Optional<CodeModel::Model> CM,
CodeGenOpt::Level OL, bool JIT)
: SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {}
void SparcelTargetMachine::anchor() {}
SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
Optional<Reloc::Model> RM,
Optional<CodeModel::Model> CM,
CodeGenOpt::Level OL, bool JIT)
: SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}