LLVM API Documentation
00001 //===-- MipsSubtarget.cpp - Mips Subtarget Information --------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the Mips specific subclass of TargetSubtargetInfo. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "MipsMachineFunction.h" 00015 #include "Mips.h" 00016 #include "MipsRegisterInfo.h" 00017 #include "MipsSubtarget.h" 00018 #include "MipsTargetMachine.h" 00019 #include "llvm/IR/Attributes.h" 00020 #include "llvm/IR/Function.h" 00021 #include "llvm/Support/CommandLine.h" 00022 #include "llvm/Support/Debug.h" 00023 #include "llvm/Support/TargetRegistry.h" 00024 #include "llvm/Support/raw_ostream.h" 00025 00026 using namespace llvm; 00027 00028 #define DEBUG_TYPE "mips-subtarget" 00029 00030 #define GET_SUBTARGETINFO_TARGET_DESC 00031 #define GET_SUBTARGETINFO_CTOR 00032 #include "MipsGenSubtargetInfo.inc" 00033 00034 // FIXME: Maybe this should be on by default when Mips16 is specified 00035 // 00036 static cl::opt<bool> Mixed16_32( 00037 "mips-mixed-16-32", 00038 cl::init(false), 00039 cl::desc("Allow for a mixture of Mips16 " 00040 "and Mips32 code in a single source file"), 00041 cl::Hidden); 00042 00043 static cl::opt<bool> Mips_Os16( 00044 "mips-os16", 00045 cl::init(false), 00046 cl::desc("Compile all functions that don' use " 00047 "floating point as Mips 16"), 00048 cl::Hidden); 00049 00050 static cl::opt<bool> 00051 Mips16HardFloat("mips16-hard-float", cl::NotHidden, 00052 cl::desc("MIPS: mips16 hard float enable."), 00053 cl::init(false)); 00054 00055 static cl::opt<bool> 00056 Mips16ConstantIslands( 00057 "mips16-constant-islands", cl::NotHidden, 00058 cl::desc("MIPS: mips16 constant islands enable."), 00059 cl::init(true)); 00060 00061 /// Select the Mips CPU for the given triple and cpu name. 00062 /// FIXME: Merge with the copy in MipsMCTargetDesc.cpp 00063 static StringRef selectMipsCPU(Triple TT, StringRef CPU) { 00064 if (CPU.empty() || CPU == "generic") { 00065 if (TT.getArch() == Triple::mips || TT.getArch() == Triple::mipsel) 00066 CPU = "mips32"; 00067 else 00068 CPU = "mips64"; 00069 } 00070 return CPU; 00071 } 00072 00073 void MipsSubtarget::anchor() { } 00074 00075 static std::string computeDataLayout(const MipsSubtarget &ST) { 00076 std::string Ret = ""; 00077 00078 // There are both little and big endian mips. 00079 if (ST.isLittle()) 00080 Ret += "e"; 00081 else 00082 Ret += "E"; 00083 00084 Ret += "-m:m"; 00085 00086 // Pointers are 32 bit on some ABIs. 00087 if (!ST.isABI_N64()) 00088 Ret += "-p:32:32"; 00089 00090 // 8 and 16 bit integers only need no have natural alignment, but try to 00091 // align them to 32 bits. 64 bit integers have natural alignment. 00092 Ret += "-i8:8:32-i16:16:32-i64:64"; 00093 00094 // 32 bit registers are always available and the stack is at least 64 bit 00095 // aligned. On N64 64 bit registers are also available and the stack is 00096 // 128 bit aligned. 00097 if (ST.isABI_N64() || ST.isABI_N32()) 00098 Ret += "-n32:64-S128"; 00099 else 00100 Ret += "-n32-S64"; 00101 00102 return Ret; 00103 } 00104 00105 MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, 00106 const std::string &FS, bool little, 00107 MipsTargetMachine *_TM) 00108 : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(Mips32), 00109 MipsABI(UnknownABI), IsLittle(little), IsSingleFloat(false), 00110 IsFPXX(false), NoABICalls(false), IsFP64bit(false), UseOddSPReg(true), 00111 IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false), HasCnMips(false), 00112 IsLinux(true), HasMips3_32(false), HasMips3_32r2(false), 00113 HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false), 00114 InMips16Mode(false), InMips16HardFloat(Mips16HardFloat), 00115 InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), 00116 AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), 00117 HasMSA(false), TM(_TM), TargetTriple(TT), 00118 DL(computeDataLayout(initializeSubtargetDependencies(CPU, FS, TM))), 00119 TSInfo(DL), InstrInfo(MipsInstrInfo::create(*this)), 00120 FrameLowering(MipsFrameLowering::create(*this)), 00121 TLInfo(MipsTargetLowering::create(*TM, *this)) { 00122 00123 PreviousInMips16Mode = InMips16Mode; 00124 00125 // Don't even attempt to generate code for MIPS-I, MIPS-II, MIPS-III, and 00126 // MIPS-V. They have not been tested and currently exist for the integrated 00127 // assembler only. 00128 if (MipsArchVersion == Mips1) 00129 report_fatal_error("Code generation for MIPS-I is not implemented", false); 00130 if (MipsArchVersion == Mips2) 00131 report_fatal_error("Code generation for MIPS-II is not implemented", false); 00132 if (MipsArchVersion == Mips3) 00133 report_fatal_error("Code generation for MIPS-III is not implemented", 00134 false); 00135 if (MipsArchVersion == Mips5) 00136 report_fatal_error("Code generation for MIPS-V is not implemented", false); 00137 00138 // Assert exactly one ABI was chosen. 00139 assert(MipsABI != UnknownABI); 00140 assert((((getFeatureBits() & Mips::FeatureO32) != 0) + 00141 ((getFeatureBits() & Mips::FeatureEABI) != 0) + 00142 ((getFeatureBits() & Mips::FeatureN32) != 0) + 00143 ((getFeatureBits() & Mips::FeatureN64) != 0)) == 1); 00144 00145 // Check if Architecture and ABI are compatible. 00146 assert(((!isGP64bit() && (isABI_O32() || isABI_EABI())) || 00147 (isGP64bit() && (isABI_N32() || isABI_N64()))) && 00148 "Invalid Arch & ABI pair."); 00149 00150 if (hasMSA() && !isFP64bit()) 00151 report_fatal_error("MSA requires a 64-bit FPU register file (FR=1 mode). " 00152 "See -mattr=+fp64.", 00153 false); 00154 00155 if (!isABI_O32() && !useOddSPReg()) 00156 report_fatal_error("-mattr=+nooddspreg requires the O32 ABI.", false); 00157 00158 if (IsFPXX && (isABI_N32() || isABI_N64())) 00159 report_fatal_error("FPXX is not permitted for the N32/N64 ABI's.", false); 00160 00161 if (hasMips32r6()) { 00162 StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6"; 00163 00164 assert(isFP64bit()); 00165 assert(isNaN2008()); 00166 if (hasDSP()) 00167 report_fatal_error(ISA + " is not compatible with the DSP ASE", false); 00168 } 00169 00170 // Is the target system Linux ? 00171 if (TT.find("linux") == std::string::npos) 00172 IsLinux = false; 00173 00174 // Set UseSmallSection. 00175 // TODO: Investigate the IsLinux check. I suspect it's really checking for 00176 // bare-metal. 00177 UseSmallSection = !IsLinux && (TM->getRelocationModel() == Reloc::Static); 00178 } 00179 00180 /// This overrides the PostRAScheduler bit in the SchedModel for any CPU. 00181 bool MipsSubtarget::enablePostMachineScheduler() const { return true; } 00182 00183 void MipsSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { 00184 CriticalPathRCs.clear(); 00185 CriticalPathRCs.push_back(isGP64bit() ? 00186 &Mips::GPR64RegClass : &Mips::GPR32RegClass); 00187 } 00188 00189 CodeGenOpt::Level MipsSubtarget::getOptLevelToEnablePostRAScheduler() const { 00190 return CodeGenOpt::Aggressive; 00191 } 00192 00193 MipsSubtarget & 00194 MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, 00195 const TargetMachine *TM) { 00196 std::string CPUName = selectMipsCPU(TargetTriple, CPU); 00197 00198 // Parse features string. 00199 ParseSubtargetFeatures(CPUName, FS); 00200 // Initialize scheduling itinerary for the specified CPU. 00201 InstrItins = getInstrItineraryForCPU(CPUName); 00202 00203 if (InMips16Mode && !TM->Options.UseSoftFloat) 00204 InMips16HardFloat = true; 00205 00206 return *this; 00207 } 00208 00209 bool MipsSubtarget::abiUsesSoftFloat() const { 00210 return TM->Options.UseSoftFloat && !InMips16HardFloat; 00211 } 00212 00213 bool MipsSubtarget::useConstantIslands() { 00214 DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands << "\n"); 00215 return Mips16ConstantIslands; 00216 } 00217 00218 Reloc::Model MipsSubtarget::getRelocationModel() const { 00219 return TM->getRelocationModel(); 00220 }