TripleOptions.cpp revision 533eae20118036f425f27bf0536ef0ccbb090b65
1//===- TripleOptions.cpp --------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include <mcld/TripleOptions.h> 10 11#include <mcld/LinkerConfig.h> 12#include <mcld/Support/Path.h> 13#include <mcld/Support/TargetRegistry.h> 14#include <mcld/Support/MsgHandling.h> 15#include <mcld/Support/SystemUtils.h> 16 17#include <llvm/ADT/StringSwitch.h> 18#include <llvm/MC/SubtargetFeature.h> 19 20namespace { 21 22llvm::cl::opt<std::string> ArgTargetTriple("mtriple", 23 llvm::cl::desc("Override target triple for module")); 24 25llvm::cl::opt<std::string> ArgMArch("march", 26 llvm::cl::desc("Architecture to generate code for (see --version)")); 27 28llvm::cl::opt<std::string> ArgMCPU("mcpu", 29 llvm::cl::desc("Target a specific cpu type (-mcpu=help for details)"), 30 llvm::cl::value_desc("cpu-name"), 31 llvm::cl::init("")); 32 33llvm::cl::list<std::string> ArgMAttrs("mattr", 34 llvm::cl::CommaSeparated, 35 llvm::cl::desc("Target specific attributes (-mattr=help for details)"), 36 llvm::cl::value_desc("a1,+a2,-a3,...")); 37 38llvm::cl::opt<std::string> ArgEmulation("m", 39 llvm::cl::ZeroOrMore, 40 llvm::cl::desc("Set GNU linker emulation"), 41 llvm::cl::value_desc("emulation"), 42 llvm::cl::Prefix); 43 44/// ParseProgName - Parse program name 45/// This function simplifies cross-compiling by reading triple from the program 46/// name. For example, if the program name is `arm-linux-eabi-ld.mcld', we can 47/// get the triple is arm-linux-eabi by the program name. 48inline std::string ParseProgName(const char *pProgName) 49{ 50 static const char *suffixes[] = { 51 "ld", 52 "ld.mcld" 53 }; 54 55 std::string ProgName(mcld::sys::fs::Path(pProgName).stem().native()); 56 57 for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { 58 if (ProgName == suffixes[i]) 59 return std::string(); 60 } 61 62 llvm::StringRef ProgNameRef(ProgName); 63 llvm::StringRef Prefix; 64 65 for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { 66 if (!ProgNameRef.endswith(suffixes[i])) 67 continue; 68 69 llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-', 70 ProgNameRef.size() - strlen(suffixes[i])); 71 if (LastComponent == llvm::StringRef::npos) 72 continue; 73 llvm::StringRef Prefix = ProgNameRef.slice(0, LastComponent); 74 std::string IgnoredError; 75 if (!mcld::TargetRegistry::lookupTarget(Prefix, IgnoredError)) 76 continue; 77 return Prefix.str(); 78 } 79 return std::string(); 80} 81 82inline void 83ParseEmulation(llvm::Triple& pTriple, const std::string& pEmulation) 84{ 85 llvm::Triple triple = llvm::StringSwitch<llvm::Triple>(pEmulation) 86 .Case("aarch64linux", llvm::Triple("aarch64", "", "linux", "gnu")) 87 .Case("armelf_linux_eabi", llvm::Triple("arm", "", "linux", "gnueabi")) 88 .Case("elf_i386", llvm::Triple("i386", "", "", "gnu")) 89 .Case("elf_x86_64", llvm::Triple("x86_64", "", "", "gnu")) 90 .Case("elf32_x86_64", llvm::Triple("x86_64", "", "", "gnux32")) 91 .Case("elf_i386_fbsd", llvm::Triple("i386", "", "freebsd", "gnu")) 92 .Case("elf_x86_64_fbsd", llvm::Triple("x86_64", "", "freebsd", "gnu")) 93 .Case("elf32ltsmip", llvm::Triple("mipsel", "", "", "gnu")) 94 .Default(llvm::Triple()); 95 96 if (triple.getArch() == llvm::Triple::UnknownArch && 97 triple.getOS() == llvm::Triple::UnknownOS && 98 triple.getEnvironment() == llvm::Triple::UnknownEnvironment) 99 mcld::error(mcld::diag::err_invalid_emulation) << pEmulation << "\n"; 100 101 if (triple.getArch() != llvm::Triple::UnknownArch) 102 pTriple.setArch(triple.getArch()); 103 104 if (triple.getOS() != llvm::Triple::UnknownOS) 105 pTriple.setOS(triple.getOS()); 106 107 if (triple.getEnvironment() != llvm::Triple::UnknownEnvironment) 108 pTriple.setEnvironment(triple.getEnvironment()); 109 110} 111 112} // anonymous namespace 113 114using namespace mcld; 115 116//===----------------------------------------------------------------------===// 117// TripleOptions 118//===----------------------------------------------------------------------===// 119TripleOptions::TripleOptions() 120 : m_TargetTriple(ArgTargetTriple), 121 m_MArch(ArgMArch), 122 m_MCPU(ArgMCPU), 123 m_MAttrs(ArgMAttrs), 124 m_Emulation(ArgEmulation) { 125} 126 127bool TripleOptions::parse(int pArgc, char* pArgv[], LinkerConfig& pConfig) 128{ 129 llvm::Triple triple; 130 if (!m_TargetTriple.empty()) { 131 // 1. Use the triple from command. 132 triple.setTriple(m_TargetTriple); 133 } 134 else { 135 std::string prog_triple = ParseProgName(pArgv[0]); 136 if (!prog_triple.empty()) { 137 // 2. Use the triple from the program name prefix. 138 triple.setTriple(prog_triple); 139 } 140 else { 141 // 3. Use the default target triple. 142 triple.setTriple(mcld::sys::getDefaultTargetTriple()); 143 } 144 } 145 146 // If a specific emulation was requested, apply it now. 147 if (!m_Emulation.empty()) 148 ParseEmulation(triple, m_Emulation); 149 else 150 pConfig.targets().setArch(m_MArch); 151 152 pConfig.targets().setTriple(triple); 153 pConfig.targets().setTargetCPU(m_MCPU); 154 155 // Package up features to be passed to target/subtarget 156 std::string feature_str; 157 if (m_MAttrs.size()) { 158 llvm::SubtargetFeatures features; 159 for (unsigned i = 0; i != m_MAttrs.size(); ++i) 160 features.AddFeature(m_MAttrs[i]); 161 feature_str = features.getString(); 162 } 163 pConfig.targets().setTargetFeatureString(feature_str); 164 return true; 165} 166 167