1 //===--- OpenBSD.cpp - OpenBSD ToolChain Implementations --------*- C++ -*-===// 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 #include "OpenBSD.h" 11 #include "Arch/Mips.h" 12 #include "Arch/Sparc.h" 13 #include "CommonArgs.h" 14 #include "clang/Driver/Compilation.h" 15 #include "clang/Driver/Options.h" 16 #include "llvm/Option/ArgList.h" 17 18 using namespace clang::driver; 19 using namespace clang::driver::tools; 20 using namespace clang::driver::toolchains; 21 using namespace clang; 22 using namespace llvm::opt; 23 24 void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 25 const InputInfo &Output, 26 const InputInfoList &Inputs, 27 const ArgList &Args, 28 const char *LinkingOutput) const { 29 claimNoWarnArgs(Args); 30 ArgStringList CmdArgs; 31 32 switch (getToolChain().getArch()) { 33 case llvm::Triple::x86: 34 // When building 32-bit code on OpenBSD/amd64, we have to explicitly 35 // instruct as in the base system to assemble 32-bit code. 36 CmdArgs.push_back("--32"); 37 break; 38 39 case llvm::Triple::ppc: 40 CmdArgs.push_back("-mppc"); 41 CmdArgs.push_back("-many"); 42 break; 43 44 case llvm::Triple::sparc: 45 case llvm::Triple::sparcel: { 46 CmdArgs.push_back("-32"); 47 std::string CPU = getCPUName(Args, getToolChain().getTriple()); 48 CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); 49 AddAssemblerKPIC(getToolChain(), Args, CmdArgs); 50 break; 51 } 52 53 case llvm::Triple::sparcv9: { 54 CmdArgs.push_back("-64"); 55 std::string CPU = getCPUName(Args, getToolChain().getTriple()); 56 CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); 57 AddAssemblerKPIC(getToolChain(), Args, CmdArgs); 58 break; 59 } 60 61 case llvm::Triple::mips64: 62 case llvm::Triple::mips64el: { 63 StringRef CPUName; 64 StringRef ABIName; 65 mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); 66 67 CmdArgs.push_back("-mabi"); 68 CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); 69 70 if (getToolChain().getArch() == llvm::Triple::mips64) 71 CmdArgs.push_back("-EB"); 72 else 73 CmdArgs.push_back("-EL"); 74 75 AddAssemblerKPIC(getToolChain(), Args, CmdArgs); 76 break; 77 } 78 79 default: 80 break; 81 } 82 83 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 84 85 CmdArgs.push_back("-o"); 86 CmdArgs.push_back(Output.getFilename()); 87 88 for (const auto &II : Inputs) 89 CmdArgs.push_back(II.getFilename()); 90 91 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 92 C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 93 } 94 95 void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, 96 const InputInfo &Output, 97 const InputInfoList &Inputs, 98 const ArgList &Args, 99 const char *LinkingOutput) const { 100 const Driver &D = getToolChain().getDriver(); 101 ArgStringList CmdArgs; 102 103 // Silence warning for "clang -g foo.o -o foo" 104 Args.ClaimAllArgs(options::OPT_g_Group); 105 // and "clang -emit-llvm foo.o -o foo" 106 Args.ClaimAllArgs(options::OPT_emit_llvm); 107 // and for "clang -w foo.o -o foo". Other warning options are already 108 // handled somewhere else. 109 Args.ClaimAllArgs(options::OPT_w); 110 111 if (getToolChain().getArch() == llvm::Triple::mips64) 112 CmdArgs.push_back("-EB"); 113 else if (getToolChain().getArch() == llvm::Triple::mips64el) 114 CmdArgs.push_back("-EL"); 115 116 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) { 117 CmdArgs.push_back("-e"); 118 CmdArgs.push_back("__start"); 119 } 120 121 CmdArgs.push_back("--eh-frame-hdr"); 122 if (Args.hasArg(options::OPT_static)) { 123 CmdArgs.push_back("-Bstatic"); 124 } else { 125 if (Args.hasArg(options::OPT_rdynamic)) 126 CmdArgs.push_back("-export-dynamic"); 127 CmdArgs.push_back("-Bdynamic"); 128 if (Args.hasArg(options::OPT_shared)) { 129 CmdArgs.push_back("-shared"); 130 } else { 131 CmdArgs.push_back("-dynamic-linker"); 132 CmdArgs.push_back("/usr/libexec/ld.so"); 133 } 134 } 135 136 if (Args.hasArg(options::OPT_nopie)) 137 CmdArgs.push_back("-nopie"); 138 139 if (Output.isFilename()) { 140 CmdArgs.push_back("-o"); 141 CmdArgs.push_back(Output.getFilename()); 142 } else { 143 assert(Output.isNothing() && "Invalid output."); 144 } 145 146 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 147 if (!Args.hasArg(options::OPT_shared)) { 148 if (Args.hasArg(options::OPT_pg)) 149 CmdArgs.push_back( 150 Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o"))); 151 else if (Args.hasArg(options::OPT_static) && 152 !Args.hasArg(options::OPT_nopie)) 153 CmdArgs.push_back( 154 Args.MakeArgString(getToolChain().GetFilePath("rcrt0.o"))); 155 else 156 CmdArgs.push_back( 157 Args.MakeArgString(getToolChain().GetFilePath("crt0.o"))); 158 CmdArgs.push_back( 159 Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); 160 } else { 161 CmdArgs.push_back( 162 Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o"))); 163 } 164 } 165 166 std::string Triple = getToolChain().getTripleString(); 167 if (Triple.substr(0, 6) == "x86_64") 168 Triple.replace(0, 6, "amd64"); 169 CmdArgs.push_back( 170 Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1")); 171 172 Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, 173 options::OPT_e, options::OPT_s, options::OPT_t, 174 options::OPT_Z_Flag, options::OPT_r}); 175 176 AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); 177 178 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 179 if (D.CCCIsCXX()) { 180 getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); 181 if (Args.hasArg(options::OPT_pg)) 182 CmdArgs.push_back("-lm_p"); 183 else 184 CmdArgs.push_back("-lm"); 185 } 186 187 // FIXME: For some reason GCC passes -lgcc before adding 188 // the default system libraries. Just mimic this for now. 189 CmdArgs.push_back("-lgcc"); 190 191 if (Args.hasArg(options::OPT_pthread)) { 192 if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg)) 193 CmdArgs.push_back("-lpthread_p"); 194 else 195 CmdArgs.push_back("-lpthread"); 196 } 197 198 if (!Args.hasArg(options::OPT_shared)) { 199 if (Args.hasArg(options::OPT_pg)) 200 CmdArgs.push_back("-lc_p"); 201 else 202 CmdArgs.push_back("-lc"); 203 } 204 205 CmdArgs.push_back("-lgcc"); 206 } 207 208 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 209 if (!Args.hasArg(options::OPT_shared)) 210 CmdArgs.push_back( 211 Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); 212 else 213 CmdArgs.push_back( 214 Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); 215 } 216 217 const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); 218 C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 219 } 220 221 /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. 222 223 OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple, 224 const ArgList &Args) 225 : Generic_ELF(D, Triple, Args) { 226 getFilePaths().push_back(getDriver().Dir + "/../lib"); 227 getFilePaths().push_back("/usr/lib"); 228 } 229 230 Tool *OpenBSD::buildAssembler() const { 231 return new tools::openbsd::Assembler(*this); 232 } 233 234 Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); } 235