Home | History | Annotate | Download | only in Sparc
      1 //===-- SparcTargetMachine.cpp - Define TargetMachine for Sparc -----------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "SparcTargetMachine.h"
     14 #include "SparcTargetObjectFile.h"
     15 #include "Sparc.h"
     16 #include "LeonPasses.h"
     17 #include "llvm/CodeGen/Passes.h"
     18 #include "llvm/CodeGen/TargetPassConfig.h"
     19 #include "llvm/IR/LegacyPassManager.h"
     20 #include "llvm/Support/TargetRegistry.h"
     21 using namespace llvm;
     22 
     23 extern "C" void LLVMInitializeSparcTarget() {
     24   // Register the target.
     25   RegisterTargetMachine<SparcV8TargetMachine> X(TheSparcTarget);
     26   RegisterTargetMachine<SparcV9TargetMachine> Y(TheSparcV9Target);
     27   RegisterTargetMachine<SparcelTargetMachine> Z(TheSparcelTarget);
     28 }
     29 
     30 static std::string computeDataLayout(const Triple &T, bool is64Bit) {
     31   // Sparc is typically big endian, but some are little.
     32   std::string Ret = T.getArch() == Triple::sparcel ? "e" : "E";
     33   Ret += "-m:e";
     34 
     35   // Some ABIs have 32bit pointers.
     36   if (!is64Bit)
     37     Ret += "-p:32:32";
     38 
     39   // Alignments for 64 bit integers.
     40   Ret += "-i64:64";
     41 
     42   // On SparcV9 128 floats are aligned to 128 bits, on others only to 64.
     43   // On SparcV9 registers can hold 64 or 32 bits, on others only 32.
     44   if (is64Bit)
     45     Ret += "-n32:64";
     46   else
     47     Ret += "-f128:64-n32";
     48 
     49   if (is64Bit)
     50     Ret += "-S128";
     51   else
     52     Ret += "-S64";
     53 
     54   return Ret;
     55 }
     56 
     57 static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
     58   if (!RM.hasValue())
     59     return Reloc::Static;
     60   return *RM;
     61 }
     62 
     63 /// Create an ILP32 architecture model
     64 SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT,
     65                                        StringRef CPU, StringRef FS,
     66                                        const TargetOptions &Options,
     67                                        Optional<Reloc::Model> RM,
     68                                        CodeModel::Model CM,
     69                                        CodeGenOpt::Level OL, bool is64bit)
     70     : LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options,
     71                         getEffectiveRelocModel(RM), CM, OL),
     72       TLOF(make_unique<SparcELFTargetObjectFile>()),
     73       Subtarget(TT, CPU, FS, *this, is64bit), is64Bit(is64bit) {
     74   initAsmInfo();
     75 }
     76 
     77 SparcTargetMachine::~SparcTargetMachine() {}
     78 
     79 const SparcSubtarget *
     80 SparcTargetMachine::getSubtargetImpl(const Function &F) const {
     81   Attribute CPUAttr = F.getFnAttribute("target-cpu");
     82   Attribute FSAttr = F.getFnAttribute("target-features");
     83 
     84   std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
     85                         ? CPUAttr.getValueAsString().str()
     86                         : TargetCPU;
     87   std::string FS = !FSAttr.hasAttribute(Attribute::None)
     88                        ? FSAttr.getValueAsString().str()
     89                        : TargetFS;
     90 
     91   // FIXME: This is related to the code below to reset the target options,
     92   // we need to know whether or not the soft float flag is set on the
     93   // function, so we can enable it as a subtarget feature.
     94   bool softFloat =
     95       F.hasFnAttribute("use-soft-float") &&
     96       F.getFnAttribute("use-soft-float").getValueAsString() == "true";
     97 
     98   if (softFloat)
     99     FS += FS.empty() ? "+soft-float" : ",+soft-float";
    100 
    101   auto &I = SubtargetMap[CPU + FS];
    102   if (!I) {
    103     // This needs to be done before we create a new subtarget since any
    104     // creation will depend on the TM and the code generation flags on the
    105     // function that reside in TargetOptions.
    106     resetTargetOptions(F);
    107     I = llvm::make_unique<SparcSubtarget>(TargetTriple, CPU, FS, *this,
    108                                           this->is64Bit);
    109   }
    110   return I.get();
    111 }
    112 
    113 namespace {
    114 /// Sparc Code Generator Pass Configuration Options.
    115 class SparcPassConfig : public TargetPassConfig {
    116 public:
    117   SparcPassConfig(SparcTargetMachine *TM, PassManagerBase &PM)
    118       : TargetPassConfig(TM, PM) {}
    119 
    120   SparcTargetMachine &getSparcTargetMachine() const {
    121     return getTM<SparcTargetMachine>();
    122   }
    123 
    124   void addIRPasses() override;
    125   bool addInstSelector() override;
    126   void addPreEmitPass() override;
    127 };
    128 } // namespace
    129 
    130 TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {
    131   return new SparcPassConfig(this, PM);
    132 }
    133 
    134 void SparcPassConfig::addIRPasses() {
    135   addPass(createAtomicExpandPass(&getSparcTargetMachine()));
    136 
    137   TargetPassConfig::addIRPasses();
    138 }
    139 
    140 bool SparcPassConfig::addInstSelector() {
    141   addPass(createSparcISelDag(getSparcTargetMachine()));
    142   return false;
    143 }
    144 
    145 void SparcPassConfig::addPreEmitPass() {
    146   addPass(createSparcDelaySlotFillerPass(getSparcTargetMachine()));
    147   if (this->getSparcTargetMachine().getSubtargetImpl()->ignoreZeroFlag()) {
    148     addPass(new IgnoreZeroFlag(getSparcTargetMachine()));
    149   }
    150   if (this->getSparcTargetMachine().getSubtargetImpl()->performSDIVReplace()) {
    151     addPass(new ReplaceSDIV(getSparcTargetMachine()));
    152   }
    153   if (this->getSparcTargetMachine().getSubtargetImpl()->fixCallImmediates()) {
    154     addPass(new FixCALL(getSparcTargetMachine()));
    155   }
    156   if (this->getSparcTargetMachine().getSubtargetImpl()->fixFSMULD()) {
    157     addPass(new FixFSMULD(getSparcTargetMachine()));
    158   }
    159   if (this->getSparcTargetMachine().getSubtargetImpl()->replaceFMULS()) {
    160     addPass(new ReplaceFMULS(getSparcTargetMachine()));
    161   }
    162   if (this->getSparcTargetMachine().getSubtargetImpl()->preventRoundChange()) {
    163     addPass(new PreventRoundChange(getSparcTargetMachine()));
    164   }
    165   if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT()) {
    166     addPass(new FixAllFDIVSQRT(getSparcTargetMachine()));
    167   }
    168   if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPsLoadStore()) {
    169     addPass(new InsertNOPsLoadStore(getSparcTargetMachine()));
    170   }
    171   if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) {
    172     addPass(new InsertNOPLoad(getSparcTargetMachine()));
    173   }
    174   if (this->getSparcTargetMachine().getSubtargetImpl()->flushCacheLineSWAP()) {
    175     addPass(new FlushCacheLineSWAP(getSparcTargetMachine()));
    176   }
    177   if (this->getSparcTargetMachine()
    178           .getSubtargetImpl()
    179           ->insertNOPDoublePrecision()) {
    180     addPass(new InsertNOPDoublePrecision(getSparcTargetMachine()));
    181   }
    182 }
    183 
    184 void SparcV8TargetMachine::anchor() {}
    185 
    186 SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,
    187                                            StringRef CPU, StringRef FS,
    188                                            const TargetOptions &Options,
    189                                            Optional<Reloc::Model> RM,
    190                                            CodeModel::Model CM,
    191                                            CodeGenOpt::Level OL)
    192     : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
    193 
    194 void SparcV9TargetMachine::anchor() {}
    195 
    196 SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT,
    197                                            StringRef CPU, StringRef FS,
    198                                            const TargetOptions &Options,
    199                                            Optional<Reloc::Model> RM,
    200                                            CodeModel::Model CM,
    201                                            CodeGenOpt::Level OL)
    202     : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
    203 
    204 void SparcelTargetMachine::anchor() {}
    205 
    206 SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT,
    207                                            StringRef CPU, StringRef FS,
    208                                            const TargetOptions &Options,
    209                                            Optional<Reloc::Model> RM,
    210                                            CodeModel::Model CM,
    211                                            CodeGenOpt::Level OL)
    212     : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
    213