1 //===--- VE.cpp - VE ToolChain Implementations ------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "VEToolchain.h"
10 #include "CommonArgs.h"
11 #include "clang/Driver/Compilation.h"
12 #include "clang/Driver/Driver.h"
13 #include "clang/Driver/Options.h"
14 #include "llvm/Option/ArgList.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/Path.h"
17 #include <cstdlib> // ::getenv
18 
19 using namespace clang::driver;
20 using namespace clang::driver::toolchains;
21 using namespace clang;
22 using namespace llvm::opt;
23 
24 /// VE tool chain
VEToolChain(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)25 VEToolChain::VEToolChain(const Driver &D, const llvm::Triple &Triple,
26                          const ArgList &Args)
27     : Linux(D, Triple, Args) {
28   getProgramPaths().push_back("/opt/nec/ve/bin");
29   // ProgramPaths are found via 'PATH' environment variable.
30 
31   // Default library paths are following:
32   //   ${RESOURCEDIR}/lib/ve-unknown-linux-gnu,
33   // These are OK.
34 
35   // Default file paths are following:
36   //   ${RESOURCEDIR}/lib/ve-unknown-linux-gnu, (== getArchSpecificLibPaths)
37   //   ${RESOURCEDIR}/lib/linux/ve, (== getArchSpecificLibPaths)
38   //   /lib/../lib64,
39   //   /usr/lib/../lib64,
40   //   ${BINPATH}/../lib,
41   //   /lib,
42   //   /usr/lib,
43   // These are OK for host, but no go for VE.
44 
45   // Define file paths from scratch here.
46   getFilePaths().clear();
47 
48   // Add library directories:
49   //   ${BINPATH}/../lib/ve-unknown-linux-gnu, (== getStdlibPath)
50   //   ${RESOURCEDIR}/lib/ve-unknown-linux-gnu, (== getArchSpecificLibPaths)
51   //   ${RESOURCEDIR}/lib/linux/ve, (== getArchSpecificLibPaths)
52   //   ${SYSROOT}/opt/nec/ve/lib,
53   if (std::optional<std::string> Path = getStdlibPath())
54     getFilePaths().push_back(std::move(*Path));
55   for (const auto &Path : getArchSpecificLibPaths())
56     getFilePaths().push_back(Path);
57   getFilePaths().push_back(computeSysRoot() + "/opt/nec/ve/lib");
58 }
59 
buildAssembler() const60 Tool *VEToolChain::buildAssembler() const {
61   return new tools::gnutools::Assembler(*this);
62 }
63 
buildLinker() const64 Tool *VEToolChain::buildLinker() const {
65   return new tools::gnutools::Linker(*this);
66 }
67 
isPICDefault() const68 bool VEToolChain::isPICDefault() const { return false; }
69 
isPIEDefault(const llvm::opt::ArgList & Args) const70 bool VEToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
71   return false;
72 }
73 
isPICDefaultForced() const74 bool VEToolChain::isPICDefaultForced() const { return false; }
75 
SupportsProfiling() const76 bool VEToolChain::SupportsProfiling() const { return false; }
77 
hasBlocksRuntime() const78 bool VEToolChain::hasBlocksRuntime() const { return false; }
79 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const80 void VEToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
81                                             ArgStringList &CC1Args) const {
82   if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
83     return;
84 
85   if (DriverArgs.hasArg(options::OPT_nobuiltininc) &&
86       DriverArgs.hasArg(options::OPT_nostdlibinc))
87     return;
88 
89   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
90     SmallString<128> P(getDriver().ResourceDir);
91     llvm::sys::path::append(P, "include");
92     addSystemInclude(DriverArgs, CC1Args, P);
93   }
94 
95   if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
96     if (const char *cl_include_dir = getenv("NCC_C_INCLUDE_PATH")) {
97       SmallVector<StringRef, 4> Dirs;
98       const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
99       StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
100       ArrayRef<StringRef> DirVec(Dirs);
101       addSystemIncludes(DriverArgs, CC1Args, DirVec);
102     } else {
103       addSystemInclude(DriverArgs, CC1Args,
104                        getDriver().SysRoot + "/opt/nec/ve/include");
105     }
106   }
107 }
108 
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind) const109 void VEToolChain::addClangTargetOptions(const ArgList &DriverArgs,
110                                         ArgStringList &CC1Args,
111                                         Action::OffloadKind) const {
112   CC1Args.push_back("-nostdsysteminc");
113   bool UseInitArrayDefault = true;
114   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
115                           options::OPT_fno_use_init_array, UseInitArrayDefault))
116     CC1Args.push_back("-fno-use-init-array");
117 }
118 
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const119 void VEToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
120                                                ArgStringList &CC1Args) const {
121   if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) ||
122       DriverArgs.hasArg(options::OPT_nostdlibinc) ||
123       DriverArgs.hasArg(options::OPT_nostdincxx))
124     return;
125   if (const char *cl_include_dir = getenv("NCC_CPLUS_INCLUDE_PATH")) {
126     SmallVector<StringRef, 4> Dirs;
127     const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
128     StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
129     ArrayRef<StringRef> DirVec(Dirs);
130     addSystemIncludes(DriverArgs, CC1Args, DirVec);
131   } else {
132     // Add following paths for multiple target installation.
133     //   ${INSTALLDIR}/include/ve-unknown-linux-gnu/c++/v1,
134     //   ${INSTALLDIR}/include/c++/v1,
135     addLibCxxIncludePaths(DriverArgs, CC1Args);
136   }
137 }
138 
AddCXXStdlibLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const139 void VEToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
140                                       ArgStringList &CmdArgs) const {
141   assert((GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) &&
142          "Only -lc++ (aka libxx) is supported in this toolchain.");
143 
144   tools::addArchSpecificRPath(*this, Args, CmdArgs);
145 
146   // Add paths for libc++.so and other shared libraries.
147   if (std::optional<std::string> Path = getStdlibPath()) {
148     CmdArgs.push_back("-rpath");
149     CmdArgs.push_back(Args.MakeArgString(*Path));
150   }
151 
152   CmdArgs.push_back("-lc++");
153   if (Args.hasArg(options::OPT_fexperimental_library))
154     CmdArgs.push_back("-lc++experimental");
155   CmdArgs.push_back("-lc++abi");
156   CmdArgs.push_back("-lunwind");
157   // libc++ requires -lpthread under glibc environment
158   CmdArgs.push_back("-lpthread");
159   // libunwind requires -ldl under glibc environment
160   CmdArgs.push_back("-ldl");
161 }
162 
163 llvm::ExceptionHandling
GetExceptionModel(const ArgList & Args) const164 VEToolChain::GetExceptionModel(const ArgList &Args) const {
165   // VE uses SjLj exceptions.
166   return llvm::ExceptionHandling::SjLj;
167 }
168