1 1.1 joerg //===-- CrossWindows.cpp - Cross Windows Tool Chain -----------------------===// 2 1.1 joerg // 3 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 joerg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 joerg // 7 1.1 joerg //===----------------------------------------------------------------------===// 8 1.1 joerg 9 1.1 joerg #include "CrossWindows.h" 10 1.1 joerg #include "CommonArgs.h" 11 1.1 joerg #include "clang/Driver/Compilation.h" 12 1.1 joerg #include "clang/Driver/Driver.h" 13 1.1 joerg #include "clang/Driver/Options.h" 14 1.1 joerg #include "clang/Driver/SanitizerArgs.h" 15 1.1 joerg #include "llvm/Option/ArgList.h" 16 1.1 joerg #include "llvm/Support/Path.h" 17 1.1 joerg 18 1.1 joerg using namespace clang::driver; 19 1.1 joerg using namespace clang::driver::toolchains; 20 1.1 joerg 21 1.1 joerg using llvm::opt::ArgList; 22 1.1 joerg using llvm::opt::ArgStringList; 23 1.1 joerg 24 1.1 joerg void tools::CrossWindows::Assembler::ConstructJob( 25 1.1 joerg Compilation &C, const JobAction &JA, const InputInfo &Output, 26 1.1 joerg const InputInfoList &Inputs, const ArgList &Args, 27 1.1 joerg const char *LinkingOutput) const { 28 1.1 joerg claimNoWarnArgs(Args); 29 1.1 joerg const auto &TC = 30 1.1 joerg static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain()); 31 1.1 joerg ArgStringList CmdArgs; 32 1.1 joerg const char *Exec; 33 1.1 joerg 34 1.1 joerg switch (TC.getArch()) { 35 1.1 joerg default: 36 1.1 joerg llvm_unreachable("unsupported architecture"); 37 1.1 joerg case llvm::Triple::arm: 38 1.1 joerg case llvm::Triple::thumb: 39 1.1 joerg case llvm::Triple::aarch64: 40 1.1 joerg break; 41 1.1 joerg case llvm::Triple::x86: 42 1.1 joerg CmdArgs.push_back("--32"); 43 1.1 joerg break; 44 1.1 joerg case llvm::Triple::x86_64: 45 1.1 joerg CmdArgs.push_back("--64"); 46 1.1 joerg break; 47 1.1 joerg } 48 1.1 joerg 49 1.1 joerg Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 50 1.1 joerg 51 1.1 joerg CmdArgs.push_back("-o"); 52 1.1 joerg CmdArgs.push_back(Output.getFilename()); 53 1.1 joerg 54 1.1 joerg for (const auto &Input : Inputs) 55 1.1 joerg CmdArgs.push_back(Input.getFilename()); 56 1.1 joerg 57 1.1 joerg const std::string Assembler = TC.GetProgramPath("as"); 58 1.1 joerg Exec = Args.MakeArgString(Assembler); 59 1.1 joerg 60 1.1.1.2 joerg C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 61 1.1.1.2 joerg Exec, CmdArgs, Inputs, Output)); 62 1.1 joerg } 63 1.1 joerg 64 1.1 joerg void tools::CrossWindows::Linker::ConstructJob( 65 1.1 joerg Compilation &C, const JobAction &JA, const InputInfo &Output, 66 1.1 joerg const InputInfoList &Inputs, const ArgList &Args, 67 1.1 joerg const char *LinkingOutput) const { 68 1.1 joerg const auto &TC = 69 1.1 joerg static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain()); 70 1.1 joerg const llvm::Triple &T = TC.getTriple(); 71 1.1 joerg const Driver &D = TC.getDriver(); 72 1.1 joerg SmallString<128> EntryPoint; 73 1.1 joerg ArgStringList CmdArgs; 74 1.1 joerg const char *Exec; 75 1.1 joerg 76 1.1 joerg // Silence warning for "clang -g foo.o -o foo" 77 1.1 joerg Args.ClaimAllArgs(options::OPT_g_Group); 78 1.1 joerg // and "clang -emit-llvm foo.o -o foo" 79 1.1 joerg Args.ClaimAllArgs(options::OPT_emit_llvm); 80 1.1 joerg // and for "clang -w foo.o -o foo" 81 1.1 joerg Args.ClaimAllArgs(options::OPT_w); 82 1.1 joerg // Other warning options are already handled somewhere else. 83 1.1 joerg 84 1.1 joerg if (!D.SysRoot.empty()) 85 1.1 joerg CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 86 1.1 joerg 87 1.1 joerg if (Args.hasArg(options::OPT_pie)) 88 1.1 joerg CmdArgs.push_back("-pie"); 89 1.1 joerg if (Args.hasArg(options::OPT_rdynamic)) 90 1.1 joerg CmdArgs.push_back("-export-dynamic"); 91 1.1 joerg if (Args.hasArg(options::OPT_s)) 92 1.1 joerg CmdArgs.push_back("--strip-all"); 93 1.1 joerg 94 1.1 joerg CmdArgs.push_back("-m"); 95 1.1 joerg switch (TC.getArch()) { 96 1.1 joerg default: 97 1.1 joerg llvm_unreachable("unsupported architecture"); 98 1.1 joerg case llvm::Triple::arm: 99 1.1 joerg case llvm::Triple::thumb: 100 1.1 joerg // FIXME: this is incorrect for WinCE 101 1.1 joerg CmdArgs.push_back("thumb2pe"); 102 1.1 joerg break; 103 1.1 joerg case llvm::Triple::aarch64: 104 1.1 joerg CmdArgs.push_back("arm64pe"); 105 1.1 joerg break; 106 1.1 joerg case llvm::Triple::x86: 107 1.1 joerg CmdArgs.push_back("i386pe"); 108 1.1 joerg EntryPoint.append("_"); 109 1.1 joerg break; 110 1.1 joerg case llvm::Triple::x86_64: 111 1.1 joerg CmdArgs.push_back("i386pep"); 112 1.1 joerg break; 113 1.1 joerg } 114 1.1 joerg 115 1.1 joerg if (Args.hasArg(options::OPT_shared)) { 116 1.1 joerg switch (T.getArch()) { 117 1.1 joerg default: 118 1.1 joerg llvm_unreachable("unsupported architecture"); 119 1.1 joerg case llvm::Triple::aarch64: 120 1.1 joerg case llvm::Triple::arm: 121 1.1 joerg case llvm::Triple::thumb: 122 1.1 joerg case llvm::Triple::x86_64: 123 1.1 joerg EntryPoint.append("_DllMainCRTStartup"); 124 1.1 joerg break; 125 1.1 joerg case llvm::Triple::x86: 126 1.1 joerg EntryPoint.append("_DllMainCRTStartup@12"); 127 1.1 joerg break; 128 1.1 joerg } 129 1.1 joerg 130 1.1 joerg CmdArgs.push_back("-shared"); 131 1.1 joerg CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic" 132 1.1 joerg : "-Bdynamic"); 133 1.1 joerg 134 1.1 joerg CmdArgs.push_back("--enable-auto-image-base"); 135 1.1 joerg 136 1.1 joerg CmdArgs.push_back("--entry"); 137 1.1 joerg CmdArgs.push_back(Args.MakeArgString(EntryPoint)); 138 1.1 joerg } else { 139 1.1 joerg EntryPoint.append("mainCRTStartup"); 140 1.1 joerg 141 1.1 joerg CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic" 142 1.1 joerg : "-Bdynamic"); 143 1.1 joerg 144 1.1 joerg if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 145 1.1 joerg CmdArgs.push_back("--entry"); 146 1.1 joerg CmdArgs.push_back(Args.MakeArgString(EntryPoint)); 147 1.1 joerg } 148 1.1 joerg 149 1.1 joerg // FIXME: handle subsystem 150 1.1 joerg } 151 1.1 joerg 152 1.1 joerg // NOTE: deal with multiple definitions on Windows (e.g. COMDAT) 153 1.1 joerg CmdArgs.push_back("--allow-multiple-definition"); 154 1.1 joerg 155 1.1 joerg CmdArgs.push_back("-o"); 156 1.1 joerg CmdArgs.push_back(Output.getFilename()); 157 1.1 joerg 158 1.1 joerg if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) { 159 1.1 joerg SmallString<261> ImpLib(Output.getFilename()); 160 1.1 joerg llvm::sys::path::replace_extension(ImpLib, ".lib"); 161 1.1 joerg 162 1.1 joerg CmdArgs.push_back("--out-implib"); 163 1.1 joerg CmdArgs.push_back(Args.MakeArgString(ImpLib)); 164 1.1 joerg } 165 1.1 joerg 166 1.1 joerg Args.AddAllArgs(CmdArgs, options::OPT_L); 167 1.1 joerg TC.AddFilePathLibArgs(Args, CmdArgs); 168 1.1 joerg AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 169 1.1 joerg 170 1.1 joerg if (TC.ShouldLinkCXXStdlib(Args)) { 171 1.1 joerg bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) && 172 1.1 joerg !Args.hasArg(options::OPT_static); 173 1.1 joerg if (StaticCXX) 174 1.1 joerg CmdArgs.push_back("-Bstatic"); 175 1.1 joerg TC.AddCXXStdlibLibArgs(Args, CmdArgs); 176 1.1 joerg if (StaticCXX) 177 1.1 joerg CmdArgs.push_back("-Bdynamic"); 178 1.1 joerg } 179 1.1 joerg 180 1.1 joerg if (!Args.hasArg(options::OPT_nostdlib)) { 181 1.1 joerg if (!Args.hasArg(options::OPT_nodefaultlibs)) { 182 1.1 joerg // TODO handle /MT[d] /MD[d] 183 1.1 joerg CmdArgs.push_back("-lmsvcrt"); 184 1.1 joerg AddRunTimeLibs(TC, D, CmdArgs, Args); 185 1.1 joerg } 186 1.1 joerg } 187 1.1 joerg 188 1.1 joerg if (TC.getSanitizerArgs().needsAsanRt()) { 189 1.1 joerg // TODO handle /MT[d] /MD[d] 190 1.1 joerg if (Args.hasArg(options::OPT_shared)) { 191 1.1 joerg CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk")); 192 1.1 joerg } else { 193 1.1 joerg for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"}) 194 1.1 joerg CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 195 1.1 joerg // Make sure the dynamic runtime thunk is not optimized out at link time 196 1.1 joerg // to ensure proper SEH handling. 197 1.1 joerg CmdArgs.push_back(Args.MakeArgString("--undefined")); 198 1.1 joerg CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86 199 1.1 joerg ? "___asan_seh_interceptor" 200 1.1 joerg : "__asan_seh_interceptor")); 201 1.1 joerg } 202 1.1 joerg } 203 1.1 joerg 204 1.1 joerg Exec = Args.MakeArgString(TC.GetLinkerPath()); 205 1.1 joerg 206 1.1.1.2 joerg C.addCommand(std::make_unique<Command>(JA, *this, 207 1.1.1.2 joerg ResponseFileSupport::AtFileUTF8(), 208 1.1.1.2 joerg Exec, CmdArgs, Inputs, Output)); 209 1.1 joerg } 210 1.1 joerg 211 1.1 joerg CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D, 212 1.1 joerg const llvm::Triple &T, 213 1.1 joerg const llvm::opt::ArgList &Args) 214 1.1 joerg : Generic_GCC(D, T, Args) {} 215 1.1 joerg 216 1.1 joerg bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList &Args) const { 217 1.1 joerg // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does 218 1.1 joerg // not know how to emit them. 219 1.1 joerg return getArch() == llvm::Triple::x86_64; 220 1.1 joerg } 221 1.1 joerg 222 1.1 joerg bool CrossWindowsToolChain::isPICDefault() const { 223 1.1 joerg return getArch() == llvm::Triple::x86_64; 224 1.1 joerg } 225 1.1 joerg 226 1.1 joerg bool CrossWindowsToolChain::isPIEDefault() const { 227 1.1 joerg return getArch() == llvm::Triple::x86_64; 228 1.1 joerg } 229 1.1 joerg 230 1.1 joerg bool CrossWindowsToolChain::isPICDefaultForced() const { 231 1.1 joerg return getArch() == llvm::Triple::x86_64; 232 1.1 joerg } 233 1.1 joerg 234 1.1 joerg void CrossWindowsToolChain:: 235 1.1 joerg AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, 236 1.1 joerg llvm::opt::ArgStringList &CC1Args) const { 237 1.1 joerg const Driver &D = getDriver(); 238 1.1 joerg const std::string &SysRoot = D.SysRoot; 239 1.1 joerg 240 1.1 joerg auto AddSystemAfterIncludes = [&]() { 241 1.1 joerg for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after)) 242 1.1 joerg addSystemInclude(DriverArgs, CC1Args, P); 243 1.1 joerg }; 244 1.1 joerg 245 1.1 joerg if (DriverArgs.hasArg(options::OPT_nostdinc)) { 246 1.1 joerg AddSystemAfterIncludes(); 247 1.1 joerg return; 248 1.1 joerg } 249 1.1 joerg 250 1.1 joerg addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include"); 251 1.1 joerg if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 252 1.1 joerg SmallString<128> ResourceDir(D.ResourceDir); 253 1.1 joerg llvm::sys::path::append(ResourceDir, "include"); 254 1.1 joerg addSystemInclude(DriverArgs, CC1Args, ResourceDir); 255 1.1 joerg } 256 1.1 joerg AddSystemAfterIncludes(); 257 1.1 joerg addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); 258 1.1 joerg } 259 1.1 joerg 260 1.1 joerg void CrossWindowsToolChain:: 261 1.1 joerg AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, 262 1.1 joerg llvm::opt::ArgStringList &CC1Args) const { 263 1.1 joerg const std::string &SysRoot = getDriver().SysRoot; 264 1.1 joerg 265 1.1 joerg if (DriverArgs.hasArg(options::OPT_nostdinc) || 266 1.1 joerg DriverArgs.hasArg(options::OPT_nostdincxx)) 267 1.1 joerg return; 268 1.1 joerg 269 1.1 joerg if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) 270 1.1 joerg addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1"); 271 1.1 joerg } 272 1.1 joerg 273 1.1 joerg void CrossWindowsToolChain:: 274 1.1.1.2 joerg AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 275 1.1.1.2 joerg llvm::opt::ArgStringList &CmdArgs) const { 276 1.1.1.2 joerg if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) 277 1.1.1.2 joerg CmdArgs.push_back("-lc++"); 278 1.1 joerg } 279 1.1 joerg 280 1.1 joerg clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const { 281 1.1 joerg SanitizerMask Res = ToolChain::getSupportedSanitizers(); 282 1.1 joerg Res |= SanitizerKind::Address; 283 1.1 joerg Res |= SanitizerKind::PointerCompare; 284 1.1 joerg Res |= SanitizerKind::PointerSubtract; 285 1.1 joerg return Res; 286 1.1 joerg } 287 1.1 joerg 288 1.1 joerg Tool *CrossWindowsToolChain::buildLinker() const { 289 1.1 joerg return new tools::CrossWindows::Linker(*this); 290 1.1 joerg } 291 1.1 joerg 292 1.1 joerg Tool *CrossWindowsToolChain::buildAssembler() const { 293 1.1 joerg return new tools::CrossWindows::Assembler(*this); 294 1.1 joerg } 295