1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "BareMetal.h" |
10 | |
11 | #include "CommonArgs.h" |
12 | #include "InputInfo.h" |
13 | #include "Gnu.h" |
14 | |
15 | #include "clang/Driver/Compilation.h" |
16 | #include "clang/Driver/Driver.h" |
17 | #include "clang/Driver/DriverDiagnostic.h" |
18 | #include "clang/Driver/Options.h" |
19 | #include "llvm/Option/ArgList.h" |
20 | #include "llvm/Support/Path.h" |
21 | #include "llvm/Support/VirtualFileSystem.h" |
22 | #include "llvm/Support/raw_ostream.h" |
23 | |
24 | using namespace llvm::opt; |
25 | using namespace clang; |
26 | using namespace clang::driver; |
27 | using namespace clang::driver::tools; |
28 | using namespace clang::driver::toolchains; |
29 | |
30 | BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple, |
31 | const ArgList &Args) |
32 | : ToolChain(D, Triple, Args) { |
33 | getProgramPaths().push_back(getDriver().getInstalledDir()); |
34 | if (getDriver().getInstalledDir() != getDriver().Dir) |
35 | getProgramPaths().push_back(getDriver().Dir); |
36 | } |
37 | |
38 | BareMetal::~BareMetal() {} |
39 | |
40 | |
41 | static bool isARMBareMetal(const llvm::Triple &Triple) { |
42 | if (Triple.getArch() != llvm::Triple::arm && |
43 | Triple.getArch() != llvm::Triple::thumb) |
44 | return false; |
45 | |
46 | if (Triple.getVendor() != llvm::Triple::UnknownVendor) |
47 | return false; |
48 | |
49 | if (Triple.getOS() != llvm::Triple::UnknownOS) |
50 | return false; |
51 | |
52 | if (Triple.getEnvironment() != llvm::Triple::EABI && |
53 | Triple.getEnvironment() != llvm::Triple::EABIHF) |
54 | return false; |
55 | |
56 | return true; |
57 | } |
58 | |
59 | bool BareMetal::handlesTarget(const llvm::Triple &Triple) { |
60 | return isARMBareMetal(Triple); |
61 | } |
62 | |
63 | Tool *BareMetal::buildLinker() const { |
64 | return new tools::baremetal::Linker(*this); |
65 | } |
66 | |
67 | std::string BareMetal::getRuntimesDir() const { |
68 | SmallString<128> Dir(getDriver().ResourceDir); |
69 | llvm::sys::path::append(Dir, "lib", "baremetal"); |
70 | return Dir.str(); |
71 | } |
72 | |
73 | void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
74 | ArgStringList &CC1Args) const { |
75 | if (DriverArgs.hasArg(options::OPT_nostdinc)) |
76 | return; |
77 | |
78 | if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
79 | SmallString<128> Dir(getDriver().ResourceDir); |
80 | llvm::sys::path::append(Dir, "include"); |
81 | addSystemInclude(DriverArgs, CC1Args, Dir.str()); |
82 | } |
83 | |
84 | if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) { |
85 | SmallString<128> Dir(getDriver().SysRoot); |
86 | llvm::sys::path::append(Dir, "include"); |
87 | addSystemInclude(DriverArgs, CC1Args, Dir.str()); |
88 | } |
89 | } |
90 | |
91 | void BareMetal::addClangTargetOptions(const ArgList &DriverArgs, |
92 | ArgStringList &CC1Args, |
93 | Action::OffloadKind) const { |
94 | CC1Args.push_back("-nostdsysteminc"); |
95 | } |
96 | |
97 | void BareMetal::AddClangCXXStdlibIncludeArgs( |
98 | const ArgList &DriverArgs, ArgStringList &CC1Args) const { |
99 | if (DriverArgs.hasArg(options::OPT_nostdinc) || |
100 | DriverArgs.hasArg(options::OPT_nostdlibinc) || |
101 | DriverArgs.hasArg(options::OPT_nostdincxx)) |
102 | return; |
103 | |
104 | StringRef SysRoot = getDriver().SysRoot; |
105 | if (SysRoot.empty()) |
106 | return; |
107 | |
108 | switch (GetCXXStdlibType(DriverArgs)) { |
109 | case ToolChain::CST_Libcxx: { |
110 | SmallString<128> Dir(SysRoot); |
111 | llvm::sys::path::append(Dir, "include", "c++", "v1"); |
112 | addSystemInclude(DriverArgs, CC1Args, Dir.str()); |
113 | break; |
114 | } |
115 | case ToolChain::CST_Libstdcxx: { |
116 | SmallString<128> Dir(SysRoot); |
117 | llvm::sys::path::append(Dir, "include", "c++"); |
118 | std::error_code EC; |
119 | Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""}; |
120 | |
121 | for (llvm::vfs::directory_iterator |
122 | LI = getDriver().getVFS().dir_begin(Dir.str(), EC), |
123 | LE; |
124 | !EC && LI != LE; LI = LI.increment(EC)) { |
125 | StringRef VersionText = llvm::sys::path::filename(LI->path()); |
126 | auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText); |
127 | if (CandidateVersion.Major == -1) |
128 | continue; |
129 | if (CandidateVersion <= Version) |
130 | continue; |
131 | Version = CandidateVersion; |
132 | } |
133 | if (Version.Major == -1) |
134 | return; |
135 | llvm::sys::path::append(Dir, Version.Text); |
136 | addSystemInclude(DriverArgs, CC1Args, Dir.str()); |
137 | break; |
138 | } |
139 | } |
140 | } |
141 | |
142 | void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args, |
143 | ArgStringList &CmdArgs) const { |
144 | switch (GetCXXStdlibType(Args)) { |
145 | case ToolChain::CST_Libcxx: |
146 | CmdArgs.push_back("-lc++"); |
147 | CmdArgs.push_back("-lc++abi"); |
148 | break; |
149 | case ToolChain::CST_Libstdcxx: |
150 | CmdArgs.push_back("-lstdc++"); |
151 | CmdArgs.push_back("-lsupc++"); |
152 | break; |
153 | } |
154 | CmdArgs.push_back("-lunwind"); |
155 | } |
156 | |
157 | void BareMetal::AddLinkRuntimeLib(const ArgList &Args, |
158 | ArgStringList &CmdArgs) const { |
159 | CmdArgs.push_back(Args.MakeArgString("-lclang_rt.builtins-" + |
160 | getTriple().getArchName() + ".a")); |
161 | } |
162 | |
163 | void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
164 | const InputInfo &Output, |
165 | const InputInfoList &Inputs, |
166 | const ArgList &Args, |
167 | const char *LinkingOutput) const { |
168 | ArgStringList CmdArgs; |
169 | |
170 | auto &TC = static_cast<const toolchains::BareMetal&>(getToolChain()); |
171 | |
172 | AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); |
173 | |
174 | CmdArgs.push_back("-Bstatic"); |
175 | |
176 | CmdArgs.push_back(Args.MakeArgString("-L" + TC.getRuntimesDir())); |
177 | |
178 | Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, |
179 | options::OPT_e, options::OPT_s, options::OPT_t, |
180 | options::OPT_Z_Flag, options::OPT_r}); |
181 | |
182 | if (TC.ShouldLinkCXXStdlib(Args)) |
183 | TC.AddCXXStdlibLibArgs(Args, CmdArgs); |
184 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { |
185 | CmdArgs.push_back("-lc"); |
186 | CmdArgs.push_back("-lm"); |
187 | |
188 | TC.AddLinkRuntimeLib(Args, CmdArgs); |
189 | } |
190 | |
191 | CmdArgs.push_back("-o"); |
192 | CmdArgs.push_back(Output.getFilename()); |
193 | |
194 | C.addCommand(llvm::make_unique<Command>(JA, *this, |
195 | Args.MakeArgString(TC.GetLinkerPath()), |
196 | CmdArgs, Inputs)); |
197 | } |
198 | |