LLVM 24.0.0git
IFSHandler.cpp
Go to the documentation of this file.
1//===- IFSHandler.cpp -----------------------------------------------------===//
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
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Error.h"
20#include <functional>
21#include <optional>
22
23using namespace llvm;
24using namespace llvm::ifs;
25
27
28namespace llvm {
29namespace yaml {
30
31/// YAML traits for ELFSymbolType.
39 // Treat other symbol types as noise, and map to Unknown.
42 }
43};
44
45template <> struct ScalarTraits<IFSEndiannessType> {
46 static void output(const IFSEndiannessType &Value, void *,
47 llvm::raw_ostream &Out) {
48 switch (Value) {
50 Out << "big";
51 break;
53 Out << "little";
54 break;
55 default:
56 llvm_unreachable("Unsupported endianness");
57 }
58 }
59
66 return "Unsupported endianness";
67 }
68 return StringRef();
69 }
70
72};
73
74template <> struct ScalarTraits<IFSBitWidthType> {
75 static void output(const IFSBitWidthType &Value, void *,
76 llvm::raw_ostream &Out) {
77 switch (Value) {
79 Out << "32";
80 break;
82 Out << "64";
83 break;
84 default:
85 llvm_unreachable("Unsupported bit width");
86 }
87 }
88
95 return "Unsupported bit width";
96 }
97 return StringRef();
98 }
99
101};
102
103template <> struct MappingTraits<IFSTarget> {
104 static void mapping(IO &IO, IFSTarget &Target) {
105 IO.mapOptional("ObjectFormat", Target.ObjectFormat);
106 IO.mapOptional("Arch", Target.ArchString);
107 IO.mapOptional("Endianness", Target.Endianness);
108 IO.mapOptional("BitWidth", Target.BitWidth);
109 }
110
111 // Compacts symbol information into a single line.
112 static const bool flow = true; // NOLINT(readability-identifier-naming)
113};
114
115/// YAML traits for ELFSymbol.
116template <> struct MappingTraits<IFSSymbol> {
117 static void mapping(IO &IO, IFSSymbol &Symbol) {
118 IO.mapRequired("Name", Symbol.Name);
119 IO.mapRequired("Type", Symbol.Type);
120 // The need for symbol size depends on the symbol type.
121 if (Symbol.Type == IFSSymbolType::NoType) {
122 // Size is None, so we are reading it in, or it is non 0 so we
123 // should emit it.
124 if (!Symbol.Size || *Symbol.Size)
125 IO.mapOptional("Size", Symbol.Size);
126 } else if (Symbol.Type != IFSSymbolType::Func) {
127 IO.mapOptional("Size", Symbol.Size);
128 }
129 IO.mapOptional("Undefined", Symbol.Undefined, false);
130 IO.mapOptional("Weak", Symbol.Weak, false);
131 IO.mapOptional("Warning", Symbol.Warning);
132 }
133
134 // Compacts symbol information into a single line.
135 static const bool flow = true; // NOLINT(readability-identifier-naming)
136};
137
138/// YAML traits for ELFStub objects.
139template <> struct MappingTraits<IFSStub> {
140 static void mapping(IO &IO, IFSStub &Stub) {
141 if (!IO.mapTag("!ifs-v1", true))
142 IO.setError("Not a .tbe YAML file.");
143 IO.mapRequired("IfsVersion", Stub.IfsVersion);
144 IO.mapOptional("SoName", Stub.SoName);
145 IO.mapOptional("Target", Stub.Target);
146 IO.mapOptional("NeededLibs", Stub.NeededLibs);
147 IO.mapRequired("Symbols", Stub.Symbols);
148 }
149};
150
151/// YAML traits for ELFStubTriple objects.
152template <> struct MappingTraits<IFSStubTriple> {
153 static void mapping(IO &IO, IFSStubTriple &Stub) {
154 if (!IO.mapTag("!ifs-v1", true))
155 IO.setError("Not a .tbe YAML file.");
156 IO.mapRequired("IfsVersion", Stub.IfsVersion);
157 IO.mapOptional("SoName", Stub.SoName);
158 IO.mapOptional("Target", Stub.Target.Triple);
159 IO.mapOptional("NeededLibs", Stub.NeededLibs);
160 IO.mapRequired("Symbols", Stub.Symbols);
161 }
162};
163} // end namespace yaml
164} // end namespace llvm
165
166/// Attempt to determine if a Text stub uses target triple.
168 for (line_iterator I(MemoryBufferRef(Buf, "ELFStub")); !I.is_at_eof(); ++I) {
169 StringRef Line = (*I).trim();
170 if (Line.starts_with("Target:")) {
171 if (Line == "Target:" || Line.contains("{")) {
172 return false;
173 }
174 }
175 }
176 return true;
177}
178
180 yaml::Input YamlIn(Buf);
181 std::unique_ptr<IFSStubTriple> Stub(new IFSStubTriple());
182 if (usesTriple(Buf)) {
183 YamlIn >> *Stub;
184 } else {
185 YamlIn >> *static_cast<IFSStub *>(Stub.get());
186 }
187 if (std::error_code Err = YamlIn.error()) {
188 return createStringError(Err, "YAML failed reading as IFS");
189 }
190
191 if (Stub->IfsVersion > IFSVersionCurrent)
193 "IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.",
194 std::make_error_code(std::errc::invalid_argument));
195 if (Stub->Target.ArchString) {
196 uint16_t eMachine =
197 ELF::convertArchNameToEMachine(*Stub->Target.ArchString);
198 if (eMachine == ELF::EM_NONE)
199 return createStringError(
200 std::make_error_code(std::errc::invalid_argument),
201 "IFS arch '" + *Stub->Target.ArchString + "' is unsupported");
202 Stub->Target.Arch = eMachine;
203 }
204 for (const auto &Item : Stub->Symbols) {
205 if (Item.Type == IFSSymbolType::Unknown)
206 return createStringError(
207 std::make_error_code(std::errc::invalid_argument),
208 "IFS symbol type for symbol '" + Item.Name + "' is unsupported");
209 }
210 return std::move(Stub);
211}
212
214 yaml::Output YamlOut(OS, nullptr, /*WrapColumn =*/0);
215 std::unique_ptr<IFSStubTriple> CopyStub(new IFSStubTriple(Stub));
216 if (Stub.Target.Arch) {
217 CopyStub->Target.ArchString =
218 std::string(ELF::convertEMachineToArchName(*Stub.Target.Arch));
219 }
220
221 if (CopyStub->Target.Triple ||
222 (!CopyStub->Target.ArchString && !CopyStub->Target.Endianness &&
223 !CopyStub->Target.BitWidth))
224 YamlOut << *CopyStub;
225 else
226 YamlOut << *static_cast<IFSStub *>(CopyStub.get());
227 return Error::success();
228}
229
231 IFSStub &Stub, std::optional<IFSArch> OverrideArch,
232 std::optional<IFSEndiannessType> OverrideEndianness,
233 std::optional<IFSBitWidthType> OverrideBitWidth,
234 std::optional<std::string> OverrideTriple) {
235 std::error_code OverrideEC(1, std::generic_category());
236 if (OverrideArch) {
237 if (Stub.Target.Arch && *Stub.Target.Arch != *OverrideArch) {
239 "Supplied Arch conflicts with the text stub", OverrideEC);
240 }
241 Stub.Target.Arch = *OverrideArch;
242 }
243 if (OverrideEndianness) {
244 if (Stub.Target.Endianness &&
245 *Stub.Target.Endianness != *OverrideEndianness) {
247 "Supplied Endianness conflicts with the text stub", OverrideEC);
248 }
249 Stub.Target.Endianness = *OverrideEndianness;
250 }
251 if (OverrideBitWidth) {
252 if (Stub.Target.BitWidth && *Stub.Target.BitWidth != *OverrideBitWidth) {
254 "Supplied BitWidth conflicts with the text stub", OverrideEC);
255 }
256 Stub.Target.BitWidth = *OverrideBitWidth;
257 }
258 if (OverrideTriple) {
259 if (Stub.Target.Triple && *Stub.Target.Triple != *OverrideTriple) {
261 "Supplied Triple conflicts with the text stub", OverrideEC);
262 }
263 Stub.Target.Triple = *OverrideTriple;
264 }
265 return Error::success();
266}
267
268Error ifs::validateIFSTarget(IFSStub &Stub, bool ParseTriple) {
269 std::error_code ValidationEC(1, std::generic_category());
270 if (Stub.Target.Triple) {
271 if (Stub.Target.Arch || Stub.Target.BitWidth || Stub.Target.Endianness ||
272 Stub.Target.ObjectFormat) {
274 "Target triple cannot be used simultaneously with ELF target format",
275 ValidationEC);
276 }
277 if (ParseTriple) {
278 IFSTarget TargetFromTriple = parseTriple(*Stub.Target.Triple);
279 Stub.Target.Arch = TargetFromTriple.Arch;
280 Stub.Target.BitWidth = TargetFromTriple.BitWidth;
281 Stub.Target.Endianness = TargetFromTriple.Endianness;
282 }
283 return Error::success();
284 }
285 if (!Stub.Target.Arch || !Stub.Target.BitWidth || !Stub.Target.Endianness) {
286 // TODO: unify the error message.
287 if (!Stub.Target.Arch) {
288 return make_error<StringError>("Arch is not defined in the text stub",
289 ValidationEC);
290 }
291 if (!Stub.Target.BitWidth) {
292 return make_error<StringError>("BitWidth is not defined in the text stub",
293 ValidationEC);
294 }
295 if (!Stub.Target.Endianness) {
297 "Endianness is not defined in the text stub", ValidationEC);
298 }
299 }
300 return Error::success();
301}
302
304 Triple IFSTriple(TripleStr);
305 IFSTarget RetTarget;
306 IFSArch TripleArch =
308 if (TripleArch != ELF::EM_NONE) {
309 RetTarget.Arch = TripleArch;
310 }
311 RetTarget.Endianness = IFSTriple.isLittleEndian() ? IFSEndiannessType::Little
313 RetTarget.BitWidth =
315 return RetTarget;
316}
317
318void ifs::stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch,
319 bool StripEndianness, bool StripBitWidth) {
320 if (StripTriple || StripArch) {
321 Stub.Target.Arch.reset();
322 Stub.Target.ArchString.reset();
323 }
324 if (StripTriple || StripEndianness) {
325 Stub.Target.Endianness.reset();
326 }
327 if (StripTriple || StripBitWidth) {
328 Stub.Target.BitWidth.reset();
329 }
330 if (StripTriple) {
331 Stub.Target.Triple.reset();
332 }
333 if (!Stub.Target.Arch && !Stub.Target.BitWidth && !Stub.Target.Endianness) {
334 Stub.Target.ObjectFormat.reset();
335 }
336}
337
338Error ifs::filterIFSSyms(IFSStub &Stub, bool StripUndefined,
339 const std::vector<std::string> &Exclude) {
340 std::function<bool(const IFSSymbol &)> Filter = [](const IFSSymbol &) {
341 return false;
342 };
343
344 if (StripUndefined) {
345 Filter = [Filter](const IFSSymbol &Sym) {
346 return Sym.Undefined || Filter(Sym);
347 };
348 }
349
350 for (StringRef Glob : Exclude) {
352 if (!PatternOrErr)
353 return PatternOrErr.takeError();
354 Filter = [Pattern = *PatternOrErr, Filter](const IFSSymbol &Sym) {
355 return Pattern.match(Sym.Name) || Filter(Sym);
356 };
357 }
358
360
361 return Error::success();
362}
bool usesTriple(StringRef Buf)
Attempt to determine if a Text stub uses target triple.
This file declares an interface for reading and writing .ifs (text-based InterFace Stub) files.
This file defines an internal representation of an InterFace Stub.
#define I(x, y, z)
Definition MD5.cpp:57
This file contains some templates that are useful if you are working with the STL at all.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define LLVM_YAML_IS_SEQUENCE_VECTOR(type)
Utility for declaring that a std::vector of a particular type should be considered a YAML sequence.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
static LLVM_ABI Expected< GlobPattern > create(StringRef Pat, std::optional< size_t > MaxSubPatterns={}, bool SlashAgnostic=false)
LLVM_ABI_FOR_TEST MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition StringRef.h:850
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
LLVM_ABI bool isLittleEndian() const
Tests whether the target triple is little endian.
Definition Triple.cpp:2213
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition Triple.h:515
LLVM_ABI bool isArch64Bit() const
Test whether the architecture is 64-bit.
Definition Triple.cpp:1829
LLVM Value Representation.
Definition Value.h:75
A forward iterator which reads text lines from a buffer.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
virtual bool outputting() const =0
virtual bool mapTag(StringRef Tag, bool Default=false)=0
void enumCase(T &Val, StringRef Str, const T ConstVal)
Definition YAMLTraits.h:735
void mapOptional(StringRef Key, T &Val)
Definition YAMLTraits.h:800
virtual void setError(const Twine &)=0
void mapRequired(StringRef Key, T &Val)
Definition YAMLTraits.h:790
virtual bool matchEnumFallback()=0
The Input class is used to parse a yaml document into in-memory structs and vectors.
std::error_code error() override
The Output class is used to generate a yaml document from in-memory structs and vectors.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI uint16_t convertTripleArchTypeToEMachine(Triple::ArchType ArchType)
Definition ELF.cpp:30
LLVM_ABI uint16_t convertArchNameToEMachine(StringRef Arch)
Convert an architecture name into ELF's e_machine value.
Definition ELF.cpp:23
LLVM_ABI StringRef convertEMachineToArchName(uint16_t EMachine)
Convert an ELF's e_machine value into an architecture name.
Definition ELF.cpp:96
LLVM_ABI void stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch, bool StripEndianness, bool StripBitWidth)
Strips target platform information from the text stub.
uint16_t IFSArch
Definition IFSStub.h:25
LLVM_ABI Expected< std::unique_ptr< IFSStub > > readIFSFromBuffer(StringRef Buf)
Attempts to read an IFS interface file from a StringRef buffer.
LLVM_ABI Error validateIFSTarget(IFSStub &Stub, bool ParseTriple)
Validate the target platform inforation in the text stub.
LLVM_ABI IFSTarget parseTriple(StringRef TripleStr)
Parse llvm triple string into a IFSTarget struct.
LLVM_ABI Error writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub)
Attempts to write an IFS interface file to a raw_ostream.
const VersionTuple IFSVersionCurrent(3, 0)
IFSEndiannessType
Definition IFSStub.h:37
IFSBitWidthType
Definition IFSStub.h:45
LLVM_ABI Error filterIFSSyms(IFSStub &Stub, bool StripUndefined, const std::vector< std::string > &Exclude={})
IFSSymbolType
Definition IFSStub.h:27
LLVM_ABI Error overrideIFSTarget(IFSStub &Stub, std::optional< IFSArch > OverrideArch, std::optional< IFSEndiannessType > OverrideEndianness, std::optional< IFSBitWidthType > OverrideBitWidth, std::optional< std::string > OverrideTriple)
Override the target platform inforation in the text stub.
QuotingType
Describe which type of quotes should be used when quoting is necessary.
Definition YAMLTraits.h:132
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2208
std::vector< IFSSymbol > Symbols
Definition IFSStub.h:96
VersionTuple IfsVersion
Definition IFSStub.h:92
IFSTarget Target
Definition IFSStub.h:94
std::optional< std::string > SoName
Definition IFSStub.h:93
std::vector< std::string > NeededLibs
Definition IFSStub.h:95
std::optional< std::string > ArchString
Definition IFSStub.h:69
std::optional< std::string > Triple
Definition IFSStub.h:66
std::optional< IFSEndiannessType > Endianness
Definition IFSStub.h:70
std::optional< IFSBitWidthType > BitWidth
Definition IFSStub.h:71
std::optional< std::string > ObjectFormat
Definition IFSStub.h:67
std::optional< IFSArch > Arch
Definition IFSStub.h:68
static void mapping(IO &IO, IFSStubTriple &Stub)
static void mapping(IO &IO, IFSStub &Stub)
static void mapping(IO &IO, IFSSymbol &Symbol)
static void mapping(IO &IO, IFSTarget &Target)
This class should be specialized by any type that needs to be converted to/from a YAML mapping.
Definition YAMLTraits.h:63
static void enumeration(IO &IO, IFSSymbolType &SymbolType)
This class should be specialized by any integral type that converts to/from a YAML scalar where there...
Definition YAMLTraits.h:108
static StringRef input(StringRef Scalar, void *, IFSBitWidthType &Value)
static void output(const IFSBitWidthType &Value, void *, llvm::raw_ostream &Out)
static QuotingType mustQuote(StringRef)
static StringRef input(StringRef Scalar, void *, IFSEndiannessType &Value)
static QuotingType mustQuote(StringRef)
static void output(const IFSEndiannessType &Value, void *, llvm::raw_ostream &Out)
This class should be specialized by type that requires custom conversion to/from a yaml scalar.
Definition YAMLTraits.h:150