1fe6060f1SDimitry Andric //===- IFSHandler.cpp -----------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===-----------------------------------------------------------------------===/
8fe6060f1SDimitry Andric
9fe6060f1SDimitry Andric #include "llvm/InterfaceStub/IFSHandler.h"
1081ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h"
11fe6060f1SDimitry Andric #include "llvm/ADT/StringRef.h"
12fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
13fe6060f1SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
14fe6060f1SDimitry Andric #include "llvm/InterfaceStub/IFSStub.h"
15fe6060f1SDimitry Andric #include "llvm/Support/Error.h"
1681ad6265SDimitry Andric #include "llvm/Support/GlobPattern.h"
17fe6060f1SDimitry Andric #include "llvm/Support/LineIterator.h"
18fe6060f1SDimitry Andric #include "llvm/Support/YAMLTraits.h"
1906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
2081ad6265SDimitry Andric #include <functional>
21bdd1243dSDimitry Andric #include <optional>
22fe6060f1SDimitry Andric
23fe6060f1SDimitry Andric using namespace llvm;
24fe6060f1SDimitry Andric using namespace llvm::ifs;
25fe6060f1SDimitry Andric
26fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(IFSSymbol)
27fe6060f1SDimitry Andric
28fe6060f1SDimitry Andric namespace llvm {
29fe6060f1SDimitry Andric namespace yaml {
30fe6060f1SDimitry Andric
31fe6060f1SDimitry Andric /// YAML traits for ELFSymbolType.
32fe6060f1SDimitry Andric template <> struct ScalarEnumerationTraits<IFSSymbolType> {
enumerationllvm::yaml::ScalarEnumerationTraits33fe6060f1SDimitry Andric static void enumeration(IO &IO, IFSSymbolType &SymbolType) {
34fe6060f1SDimitry Andric IO.enumCase(SymbolType, "NoType", IFSSymbolType::NoType);
35fe6060f1SDimitry Andric IO.enumCase(SymbolType, "Func", IFSSymbolType::Func);
36fe6060f1SDimitry Andric IO.enumCase(SymbolType, "Object", IFSSymbolType::Object);
37fe6060f1SDimitry Andric IO.enumCase(SymbolType, "TLS", IFSSymbolType::TLS);
38fe6060f1SDimitry Andric IO.enumCase(SymbolType, "Unknown", IFSSymbolType::Unknown);
39fe6060f1SDimitry Andric // Treat other symbol types as noise, and map to Unknown.
40fe6060f1SDimitry Andric if (!IO.outputting() && IO.matchEnumFallback())
41fe6060f1SDimitry Andric SymbolType = IFSSymbolType::Unknown;
42fe6060f1SDimitry Andric }
43fe6060f1SDimitry Andric };
44fe6060f1SDimitry Andric
45fe6060f1SDimitry Andric template <> struct ScalarTraits<IFSEndiannessType> {
outputllvm::yaml::ScalarTraits46fe6060f1SDimitry Andric static void output(const IFSEndiannessType &Value, void *,
47fe6060f1SDimitry Andric llvm::raw_ostream &Out) {
48fe6060f1SDimitry Andric switch (Value) {
49fe6060f1SDimitry Andric case IFSEndiannessType::Big:
50fe6060f1SDimitry Andric Out << "big";
51fe6060f1SDimitry Andric break;
52fe6060f1SDimitry Andric case IFSEndiannessType::Little:
53fe6060f1SDimitry Andric Out << "little";
54fe6060f1SDimitry Andric break;
55fe6060f1SDimitry Andric default:
56fe6060f1SDimitry Andric llvm_unreachable("Unsupported endianness");
57fe6060f1SDimitry Andric }
58fe6060f1SDimitry Andric }
59fe6060f1SDimitry Andric
inputllvm::yaml::ScalarTraits60fe6060f1SDimitry Andric static StringRef input(StringRef Scalar, void *, IFSEndiannessType &Value) {
61fe6060f1SDimitry Andric Value = StringSwitch<IFSEndiannessType>(Scalar)
62fe6060f1SDimitry Andric .Case("big", IFSEndiannessType::Big)
63fe6060f1SDimitry Andric .Case("little", IFSEndiannessType::Little)
64fe6060f1SDimitry Andric .Default(IFSEndiannessType::Unknown);
65fe6060f1SDimitry Andric if (Value == IFSEndiannessType::Unknown) {
66fe6060f1SDimitry Andric return "Unsupported endianness";
67fe6060f1SDimitry Andric }
68fe6060f1SDimitry Andric return StringRef();
69fe6060f1SDimitry Andric }
70fe6060f1SDimitry Andric
mustQuotellvm::yaml::ScalarTraits71fe6060f1SDimitry Andric static QuotingType mustQuote(StringRef) { return QuotingType::None; }
72fe6060f1SDimitry Andric };
73fe6060f1SDimitry Andric
74fe6060f1SDimitry Andric template <> struct ScalarTraits<IFSBitWidthType> {
outputllvm::yaml::ScalarTraits75fe6060f1SDimitry Andric static void output(const IFSBitWidthType &Value, void *,
76fe6060f1SDimitry Andric llvm::raw_ostream &Out) {
77fe6060f1SDimitry Andric switch (Value) {
78fe6060f1SDimitry Andric case IFSBitWidthType::IFS32:
79fe6060f1SDimitry Andric Out << "32";
80fe6060f1SDimitry Andric break;
81fe6060f1SDimitry Andric case IFSBitWidthType::IFS64:
82fe6060f1SDimitry Andric Out << "64";
83fe6060f1SDimitry Andric break;
84fe6060f1SDimitry Andric default:
85fe6060f1SDimitry Andric llvm_unreachable("Unsupported bit width");
86fe6060f1SDimitry Andric }
87fe6060f1SDimitry Andric }
88fe6060f1SDimitry Andric
inputllvm::yaml::ScalarTraits89fe6060f1SDimitry Andric static StringRef input(StringRef Scalar, void *, IFSBitWidthType &Value) {
90fe6060f1SDimitry Andric Value = StringSwitch<IFSBitWidthType>(Scalar)
91fe6060f1SDimitry Andric .Case("32", IFSBitWidthType::IFS32)
92fe6060f1SDimitry Andric .Case("64", IFSBitWidthType::IFS64)
93fe6060f1SDimitry Andric .Default(IFSBitWidthType::Unknown);
94fe6060f1SDimitry Andric if (Value == IFSBitWidthType::Unknown) {
95fe6060f1SDimitry Andric return "Unsupported bit width";
96fe6060f1SDimitry Andric }
97fe6060f1SDimitry Andric return StringRef();
98fe6060f1SDimitry Andric }
99fe6060f1SDimitry Andric
mustQuotellvm::yaml::ScalarTraits100fe6060f1SDimitry Andric static QuotingType mustQuote(StringRef) { return QuotingType::None; }
101fe6060f1SDimitry Andric };
102fe6060f1SDimitry Andric
103fe6060f1SDimitry Andric template <> struct MappingTraits<IFSTarget> {
mappingllvm::yaml::MappingTraits104fe6060f1SDimitry Andric static void mapping(IO &IO, IFSTarget &Target) {
105fe6060f1SDimitry Andric IO.mapOptional("ObjectFormat", Target.ObjectFormat);
106fe6060f1SDimitry Andric IO.mapOptional("Arch", Target.ArchString);
107fe6060f1SDimitry Andric IO.mapOptional("Endianness", Target.Endianness);
108fe6060f1SDimitry Andric IO.mapOptional("BitWidth", Target.BitWidth);
109fe6060f1SDimitry Andric }
110fe6060f1SDimitry Andric
111fe6060f1SDimitry Andric // Compacts symbol information into a single line.
112fe6060f1SDimitry Andric static const bool flow = true; // NOLINT(readability-identifier-naming)
113fe6060f1SDimitry Andric };
114fe6060f1SDimitry Andric
115fe6060f1SDimitry Andric /// YAML traits for ELFSymbol.
116fe6060f1SDimitry Andric template <> struct MappingTraits<IFSSymbol> {
mappingllvm::yaml::MappingTraits117fe6060f1SDimitry Andric static void mapping(IO &IO, IFSSymbol &Symbol) {
118fe6060f1SDimitry Andric IO.mapRequired("Name", Symbol.Name);
119fe6060f1SDimitry Andric IO.mapRequired("Type", Symbol.Type);
120fe6060f1SDimitry Andric // The need for symbol size depends on the symbol type.
121fe6060f1SDimitry Andric if (Symbol.Type == IFSSymbolType::NoType) {
12281ad6265SDimitry Andric // Size is None, so we are reading it in, or it is non 0 so we
12381ad6265SDimitry Andric // should emit it.
12481ad6265SDimitry Andric if (!Symbol.Size || *Symbol.Size)
12581ad6265SDimitry Andric IO.mapOptional("Size", Symbol.Size);
12681ad6265SDimitry Andric } else if (Symbol.Type != IFSSymbolType::Func) {
12781ad6265SDimitry Andric IO.mapOptional("Size", Symbol.Size);
128fe6060f1SDimitry Andric }
129fe6060f1SDimitry Andric IO.mapOptional("Undefined", Symbol.Undefined, false);
130fe6060f1SDimitry Andric IO.mapOptional("Weak", Symbol.Weak, false);
131fe6060f1SDimitry Andric IO.mapOptional("Warning", Symbol.Warning);
132fe6060f1SDimitry Andric }
133fe6060f1SDimitry Andric
134fe6060f1SDimitry Andric // Compacts symbol information into a single line.
135fe6060f1SDimitry Andric static const bool flow = true; // NOLINT(readability-identifier-naming)
136fe6060f1SDimitry Andric };
137fe6060f1SDimitry Andric
138fe6060f1SDimitry Andric /// YAML traits for ELFStub objects.
139fe6060f1SDimitry Andric template <> struct MappingTraits<IFSStub> {
mappingllvm::yaml::MappingTraits140fe6060f1SDimitry Andric static void mapping(IO &IO, IFSStub &Stub) {
141fe6060f1SDimitry Andric if (!IO.mapTag("!ifs-v1", true))
142fe6060f1SDimitry Andric IO.setError("Not a .tbe YAML file.");
143fe6060f1SDimitry Andric IO.mapRequired("IfsVersion", Stub.IfsVersion);
144fe6060f1SDimitry Andric IO.mapOptional("SoName", Stub.SoName);
145fe6060f1SDimitry Andric IO.mapOptional("Target", Stub.Target);
146fe6060f1SDimitry Andric IO.mapOptional("NeededLibs", Stub.NeededLibs);
147fe6060f1SDimitry Andric IO.mapRequired("Symbols", Stub.Symbols);
148fe6060f1SDimitry Andric }
149fe6060f1SDimitry Andric };
150fe6060f1SDimitry Andric
151fe6060f1SDimitry Andric /// YAML traits for ELFStubTriple objects.
152fe6060f1SDimitry Andric template <> struct MappingTraits<IFSStubTriple> {
mappingllvm::yaml::MappingTraits153fe6060f1SDimitry Andric static void mapping(IO &IO, IFSStubTriple &Stub) {
154fe6060f1SDimitry Andric if (!IO.mapTag("!ifs-v1", true))
155fe6060f1SDimitry Andric IO.setError("Not a .tbe YAML file.");
156fe6060f1SDimitry Andric IO.mapRequired("IfsVersion", Stub.IfsVersion);
157fe6060f1SDimitry Andric IO.mapOptional("SoName", Stub.SoName);
158fe6060f1SDimitry Andric IO.mapOptional("Target", Stub.Target.Triple);
159fe6060f1SDimitry Andric IO.mapOptional("NeededLibs", Stub.NeededLibs);
160fe6060f1SDimitry Andric IO.mapRequired("Symbols", Stub.Symbols);
161fe6060f1SDimitry Andric }
162fe6060f1SDimitry Andric };
163fe6060f1SDimitry Andric } // end namespace yaml
164fe6060f1SDimitry Andric } // end namespace llvm
165fe6060f1SDimitry Andric
166fe6060f1SDimitry Andric /// Attempt to determine if a Text stub uses target triple.
usesTriple(StringRef Buf)167fe6060f1SDimitry Andric bool usesTriple(StringRef Buf) {
168fe6060f1SDimitry Andric for (line_iterator I(MemoryBufferRef(Buf, "ELFStub")); !I.is_at_eof(); ++I) {
169fe6060f1SDimitry Andric StringRef Line = (*I).trim();
1705f757f3fSDimitry Andric if (Line.starts_with("Target:")) {
171349cc55cSDimitry Andric if (Line == "Target:" || Line.contains("{")) {
172fe6060f1SDimitry Andric return false;
173fe6060f1SDimitry Andric }
174fe6060f1SDimitry Andric }
175fe6060f1SDimitry Andric }
176fe6060f1SDimitry Andric return true;
177fe6060f1SDimitry Andric }
178fe6060f1SDimitry Andric
readIFSFromBuffer(StringRef Buf)179fe6060f1SDimitry Andric Expected<std::unique_ptr<IFSStub>> ifs::readIFSFromBuffer(StringRef Buf) {
180fe6060f1SDimitry Andric yaml::Input YamlIn(Buf);
181fe6060f1SDimitry Andric std::unique_ptr<IFSStubTriple> Stub(new IFSStubTriple());
182fe6060f1SDimitry Andric if (usesTriple(Buf)) {
183fe6060f1SDimitry Andric YamlIn >> *Stub;
184fe6060f1SDimitry Andric } else {
185fe6060f1SDimitry Andric YamlIn >> *static_cast<IFSStub *>(Stub.get());
186fe6060f1SDimitry Andric }
187fe6060f1SDimitry Andric if (std::error_code Err = YamlIn.error()) {
188fe6060f1SDimitry Andric return createStringError(Err, "YAML failed reading as IFS");
189fe6060f1SDimitry Andric }
190fe6060f1SDimitry Andric
191fe6060f1SDimitry Andric if (Stub->IfsVersion > IFSVersionCurrent)
192fe6060f1SDimitry Andric return make_error<StringError>(
193fe6060f1SDimitry Andric "IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.",
194fe6060f1SDimitry Andric std::make_error_code(std::errc::invalid_argument));
195fe6060f1SDimitry Andric if (Stub->Target.ArchString) {
19606c3fb27SDimitry Andric uint16_t eMachine =
19781ad6265SDimitry Andric ELF::convertArchNameToEMachine(*Stub->Target.ArchString);
19806c3fb27SDimitry Andric if (eMachine == ELF::EM_NONE)
19906c3fb27SDimitry Andric return createStringError(
20006c3fb27SDimitry Andric std::make_error_code(std::errc::invalid_argument),
20106c3fb27SDimitry Andric "IFS arch '" + *Stub->Target.ArchString + "' is unsupported");
20206c3fb27SDimitry Andric Stub->Target.Arch = eMachine;
203fe6060f1SDimitry Andric }
204*7a6dacacSDimitry Andric for (const auto &Item : Stub->Symbols) {
205*7a6dacacSDimitry Andric if (Item.Type == IFSSymbolType::Unknown)
206*7a6dacacSDimitry Andric return createStringError(
207*7a6dacacSDimitry Andric std::make_error_code(std::errc::invalid_argument),
208*7a6dacacSDimitry Andric "IFS symbol type for symbol '" + Item.Name + "' is unsupported");
209*7a6dacacSDimitry Andric }
210fe6060f1SDimitry Andric return std::move(Stub);
211fe6060f1SDimitry Andric }
212fe6060f1SDimitry Andric
writeIFSToOutputStream(raw_ostream & OS,const IFSStub & Stub)213fe6060f1SDimitry Andric Error ifs::writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub) {
21404eeddc0SDimitry Andric yaml::Output YamlOut(OS, nullptr, /*WrapColumn =*/0);
215fe6060f1SDimitry Andric std::unique_ptr<IFSStubTriple> CopyStub(new IFSStubTriple(Stub));
216fe6060f1SDimitry Andric if (Stub.Target.Arch) {
217753f127fSDimitry Andric CopyStub->Target.ArchString =
218bdd1243dSDimitry Andric std::string(ELF::convertEMachineToArchName(*Stub.Target.Arch));
219fe6060f1SDimitry Andric }
220fe6060f1SDimitry Andric IFSTarget Target = Stub.Target;
221fe6060f1SDimitry Andric
222fe6060f1SDimitry Andric if (CopyStub->Target.Triple ||
223fe6060f1SDimitry Andric (!CopyStub->Target.ArchString && !CopyStub->Target.Endianness &&
224fe6060f1SDimitry Andric !CopyStub->Target.BitWidth))
225fe6060f1SDimitry Andric YamlOut << *CopyStub;
226fe6060f1SDimitry Andric else
227fe6060f1SDimitry Andric YamlOut << *static_cast<IFSStub *>(CopyStub.get());
228fe6060f1SDimitry Andric return Error::success();
229fe6060f1SDimitry Andric }
230fe6060f1SDimitry Andric
overrideIFSTarget(IFSStub & Stub,std::optional<IFSArch> OverrideArch,std::optional<IFSEndiannessType> OverrideEndianness,std::optional<IFSBitWidthType> OverrideBitWidth,std::optional<std::string> OverrideTriple)231bdd1243dSDimitry Andric Error ifs::overrideIFSTarget(
232bdd1243dSDimitry Andric IFSStub &Stub, std::optional<IFSArch> OverrideArch,
233bdd1243dSDimitry Andric std::optional<IFSEndiannessType> OverrideEndianness,
234bdd1243dSDimitry Andric std::optional<IFSBitWidthType> OverrideBitWidth,
235bdd1243dSDimitry Andric std::optional<std::string> OverrideTriple) {
236fe6060f1SDimitry Andric std::error_code OverrideEC(1, std::generic_category());
237fe6060f1SDimitry Andric if (OverrideArch) {
238bdd1243dSDimitry Andric if (Stub.Target.Arch && *Stub.Target.Arch != *OverrideArch) {
239fe6060f1SDimitry Andric return make_error<StringError>(
240fe6060f1SDimitry Andric "Supplied Arch conflicts with the text stub", OverrideEC);
241fe6060f1SDimitry Andric }
242bdd1243dSDimitry Andric Stub.Target.Arch = *OverrideArch;
243fe6060f1SDimitry Andric }
244fe6060f1SDimitry Andric if (OverrideEndianness) {
245fe6060f1SDimitry Andric if (Stub.Target.Endianness &&
246bdd1243dSDimitry Andric *Stub.Target.Endianness != *OverrideEndianness) {
247fe6060f1SDimitry Andric return make_error<StringError>(
248fe6060f1SDimitry Andric "Supplied Endianness conflicts with the text stub", OverrideEC);
249fe6060f1SDimitry Andric }
250bdd1243dSDimitry Andric Stub.Target.Endianness = *OverrideEndianness;
251fe6060f1SDimitry Andric }
252fe6060f1SDimitry Andric if (OverrideBitWidth) {
253bdd1243dSDimitry Andric if (Stub.Target.BitWidth && *Stub.Target.BitWidth != *OverrideBitWidth) {
254fe6060f1SDimitry Andric return make_error<StringError>(
255fe6060f1SDimitry Andric "Supplied BitWidth conflicts with the text stub", OverrideEC);
256fe6060f1SDimitry Andric }
257bdd1243dSDimitry Andric Stub.Target.BitWidth = *OverrideBitWidth;
258fe6060f1SDimitry Andric }
259fe6060f1SDimitry Andric if (OverrideTriple) {
260bdd1243dSDimitry Andric if (Stub.Target.Triple && *Stub.Target.Triple != *OverrideTriple) {
261fe6060f1SDimitry Andric return make_error<StringError>(
262fe6060f1SDimitry Andric "Supplied Triple conflicts with the text stub", OverrideEC);
263fe6060f1SDimitry Andric }
264bdd1243dSDimitry Andric Stub.Target.Triple = *OverrideTriple;
265fe6060f1SDimitry Andric }
266fe6060f1SDimitry Andric return Error::success();
267fe6060f1SDimitry Andric }
268fe6060f1SDimitry Andric
validateIFSTarget(IFSStub & Stub,bool ParseTriple)269fe6060f1SDimitry Andric Error ifs::validateIFSTarget(IFSStub &Stub, bool ParseTriple) {
270fe6060f1SDimitry Andric std::error_code ValidationEC(1, std::generic_category());
271fe6060f1SDimitry Andric if (Stub.Target.Triple) {
272fe6060f1SDimitry Andric if (Stub.Target.Arch || Stub.Target.BitWidth || Stub.Target.Endianness ||
273fe6060f1SDimitry Andric Stub.Target.ObjectFormat) {
274fe6060f1SDimitry Andric return make_error<StringError>(
275fe6060f1SDimitry Andric "Target triple cannot be used simultaneously with ELF target format",
276fe6060f1SDimitry Andric ValidationEC);
277fe6060f1SDimitry Andric }
278fe6060f1SDimitry Andric if (ParseTriple) {
27981ad6265SDimitry Andric IFSTarget TargetFromTriple = parseTriple(*Stub.Target.Triple);
280fe6060f1SDimitry Andric Stub.Target.Arch = TargetFromTriple.Arch;
281fe6060f1SDimitry Andric Stub.Target.BitWidth = TargetFromTriple.BitWidth;
282fe6060f1SDimitry Andric Stub.Target.Endianness = TargetFromTriple.Endianness;
283fe6060f1SDimitry Andric }
284fe6060f1SDimitry Andric return Error::success();
285fe6060f1SDimitry Andric }
286fe6060f1SDimitry Andric if (!Stub.Target.Arch || !Stub.Target.BitWidth || !Stub.Target.Endianness) {
287fe6060f1SDimitry Andric // TODO: unify the error message.
288fe6060f1SDimitry Andric if (!Stub.Target.Arch) {
289fe6060f1SDimitry Andric return make_error<StringError>("Arch is not defined in the text stub",
290fe6060f1SDimitry Andric ValidationEC);
291fe6060f1SDimitry Andric }
292fe6060f1SDimitry Andric if (!Stub.Target.BitWidth) {
293fe6060f1SDimitry Andric return make_error<StringError>("BitWidth is not defined in the text stub",
294fe6060f1SDimitry Andric ValidationEC);
295fe6060f1SDimitry Andric }
296fe6060f1SDimitry Andric if (!Stub.Target.Endianness) {
297fe6060f1SDimitry Andric return make_error<StringError>(
298fe6060f1SDimitry Andric "Endianness is not defined in the text stub", ValidationEC);
299fe6060f1SDimitry Andric }
300fe6060f1SDimitry Andric }
301fe6060f1SDimitry Andric return Error::success();
302fe6060f1SDimitry Andric }
303fe6060f1SDimitry Andric
parseTriple(StringRef TripleStr)304fe6060f1SDimitry Andric IFSTarget ifs::parseTriple(StringRef TripleStr) {
305fe6060f1SDimitry Andric Triple IFSTriple(TripleStr);
306fe6060f1SDimitry Andric IFSTarget RetTarget;
307fe6060f1SDimitry Andric // TODO: Implement a Triple Arch enum to e_machine map.
308fe6060f1SDimitry Andric switch (IFSTriple.getArch()) {
309fe6060f1SDimitry Andric case Triple::ArchType::aarch64:
310fe6060f1SDimitry Andric RetTarget.Arch = (IFSArch)ELF::EM_AARCH64;
311fe6060f1SDimitry Andric break;
312fe6060f1SDimitry Andric case Triple::ArchType::x86_64:
313fe6060f1SDimitry Andric RetTarget.Arch = (IFSArch)ELF::EM_X86_64;
314fe6060f1SDimitry Andric break;
31506c3fb27SDimitry Andric case Triple::ArchType::riscv64:
31606c3fb27SDimitry Andric RetTarget.Arch = (IFSArch)ELF::EM_RISCV;
31706c3fb27SDimitry Andric break;
318fe6060f1SDimitry Andric default:
319fe6060f1SDimitry Andric RetTarget.Arch = (IFSArch)ELF::EM_NONE;
320fe6060f1SDimitry Andric }
321fe6060f1SDimitry Andric RetTarget.Endianness = IFSTriple.isLittleEndian() ? IFSEndiannessType::Little
322fe6060f1SDimitry Andric : IFSEndiannessType::Big;
323fe6060f1SDimitry Andric RetTarget.BitWidth =
324fe6060f1SDimitry Andric IFSTriple.isArch64Bit() ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32;
325fe6060f1SDimitry Andric return RetTarget;
326fe6060f1SDimitry Andric }
327fe6060f1SDimitry Andric
stripIFSTarget(IFSStub & Stub,bool StripTriple,bool StripArch,bool StripEndianness,bool StripBitWidth)328fe6060f1SDimitry Andric void ifs::stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch,
329fe6060f1SDimitry Andric bool StripEndianness, bool StripBitWidth) {
330fe6060f1SDimitry Andric if (StripTriple || StripArch) {
331fe6060f1SDimitry Andric Stub.Target.Arch.reset();
332fe6060f1SDimitry Andric Stub.Target.ArchString.reset();
333fe6060f1SDimitry Andric }
334fe6060f1SDimitry Andric if (StripTriple || StripEndianness) {
335fe6060f1SDimitry Andric Stub.Target.Endianness.reset();
336fe6060f1SDimitry Andric }
337fe6060f1SDimitry Andric if (StripTriple || StripBitWidth) {
338fe6060f1SDimitry Andric Stub.Target.BitWidth.reset();
339fe6060f1SDimitry Andric }
340fe6060f1SDimitry Andric if (StripTriple) {
341fe6060f1SDimitry Andric Stub.Target.Triple.reset();
342fe6060f1SDimitry Andric }
343fe6060f1SDimitry Andric if (!Stub.Target.Arch && !Stub.Target.BitWidth && !Stub.Target.Endianness) {
344fe6060f1SDimitry Andric Stub.Target.ObjectFormat.reset();
345fe6060f1SDimitry Andric }
346fe6060f1SDimitry Andric }
347349cc55cSDimitry Andric
filterIFSSyms(IFSStub & Stub,bool StripUndefined,const std::vector<std::string> & Exclude)34881ad6265SDimitry Andric Error ifs::filterIFSSyms(IFSStub &Stub, bool StripUndefined,
34981ad6265SDimitry Andric const std::vector<std::string> &Exclude) {
35081ad6265SDimitry Andric std::function<bool(const IFSSymbol &)> Filter = [](const IFSSymbol &) {
35181ad6265SDimitry Andric return false;
35281ad6265SDimitry Andric };
35381ad6265SDimitry Andric
35481ad6265SDimitry Andric if (StripUndefined) {
35581ad6265SDimitry Andric Filter = [Filter](const IFSSymbol &Sym) {
35681ad6265SDimitry Andric return Sym.Undefined || Filter(Sym);
35781ad6265SDimitry Andric };
358349cc55cSDimitry Andric }
35981ad6265SDimitry Andric
36081ad6265SDimitry Andric for (StringRef Glob : Exclude) {
36181ad6265SDimitry Andric Expected<llvm::GlobPattern> PatternOrErr = llvm::GlobPattern::create(Glob);
36281ad6265SDimitry Andric if (!PatternOrErr)
36381ad6265SDimitry Andric return PatternOrErr.takeError();
36481ad6265SDimitry Andric Filter = [Pattern = *PatternOrErr, Filter](const IFSSymbol &Sym) {
36581ad6265SDimitry Andric return Pattern.match(Sym.Name) || Filter(Sym);
36681ad6265SDimitry Andric };
367349cc55cSDimitry Andric }
36881ad6265SDimitry Andric
36981ad6265SDimitry Andric llvm::erase_if(Stub.Symbols, Filter);
37081ad6265SDimitry Andric
37181ad6265SDimitry Andric return Error::success();
372349cc55cSDimitry Andric }
373