blob: 747d1615673976c1a1292795d793c1b372e0fd97 [file] [log] [blame]
Nick Kledzik6b079f52013-01-05 02:22:35 +00001//===- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp -------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10
Michael J. Spencer64afcb42013-01-23 01:18:43 +000011#include "lld/ReaderWriter/Reader.h"
12#include "lld/ReaderWriter/Writer.h"
13
Nick Kledzik6b079f52013-01-05 02:22:35 +000014#include "lld/Core/ArchiveLibraryFile.h"
15#include "lld/Core/DefinedAtom.h"
16#include "lld/Core/Error.h"
17#include "lld/Core/File.h"
18#include "lld/Core/LLVM.h"
19#include "lld/Core/Reference.h"
Nick Kledzik6b079f52013-01-05 02:22:35 +000020
21#include "llvm/ADT/ArrayRef.h"
22#include "llvm/ADT/OwningPtr.h"
23#include "llvm/ADT/StringMap.h"
24#include "llvm/ADT/Twine.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/ErrorHandling.h"
27#include "llvm/Support/Format.h"
28#include "llvm/Support/MemoryBuffer.h"
29#include "llvm/Support/raw_ostream.h"
30#include "llvm/Support/system_error.h"
31#include "llvm/Support/YAMLTraits.h"
32
33#include <string>
34
35using llvm::yaml::MappingTraits;
36using llvm::yaml::ScalarEnumerationTraits;
37using llvm::yaml::ScalarTraits;
38using llvm::yaml::IO;
39using llvm::yaml::SequenceTraits;
40using llvm::yaml::DocumentListTraits;
41
Michael J. Spencer64afcb42013-01-23 01:18:43 +000042using namespace lld;
Nick Kledzik6b079f52013-01-05 02:22:35 +000043
44/// The conversion of Atoms to and from YAML uses LLVM's YAML I/O. This
45/// file just defines template specializations on the lld types which control
46/// how the mapping is done to and from YAML.
47
48
49namespace {
50/// Most of the traits are context-free and always do the same transformation.
51/// But, there are some traits that need some contextual information to properly
Shankar Easwaran8962feb2013-03-14 16:09:49 +000052/// do their transform. This struct is available via io.getContext() and
Nick Kledzik6b079f52013-01-05 02:22:35 +000053/// supplies contextual information.
54class ContextInfo {
55public:
Michael J. Spencer64afcb42013-01-23 01:18:43 +000056 ContextInfo(const TargetInfo &ti) : _currentFile(nullptr), _targetInfo(ti) {}
Nick Kledzik6b079f52013-01-05 02:22:35 +000057
Michael J. Spencer64afcb42013-01-23 01:18:43 +000058 lld::File *_currentFile;
59 const TargetInfo &_targetInfo;
Nick Kledzik6b079f52013-01-05 02:22:35 +000060};
61
Nick Kledzik6b079f52013-01-05 02:22:35 +000062/// Used when writing yaml files.
63/// In most cases, atoms names are unambiguous, so references can just
64/// use the atom name as the target (e.g. target: foo). But in a few
65/// cases that does not work, so ref-names are added. These are labels
66/// used only in yaml. The labels do not exist in the Atom model.
67///
68/// One need for ref-names are when atoms have no user supplied name
69/// (e.g. c-string literal). Another case is when two object files with
70/// identically named static functions are merged (ld -r) into one object file.
71/// In that case referencing the function by name is ambiguous, so a unique
72/// ref-name is added.
73class RefNameBuilder {
74public:
Shankar Easwaran8962feb2013-03-14 16:09:49 +000075 RefNameBuilder(const lld::File &file)
Nick Kledzik6b079f52013-01-05 02:22:35 +000076 : _collisionCount(0), _unnamedCounter(0) {
77 if (&file == nullptr)
78 return;
79 // visit all atoms
80 for (const lld::DefinedAtom *atom : file.defined()) {
81 // Build map of atoms names to detect duplicates
82 if (!atom->name().empty())
83 buildDuplicateNameMap(*atom);
84
85 // Find references to unnamed atoms and create ref-names for them.
86 for (const lld::Reference *ref : *atom) {
87 // create refname for any unnamed reference target
88 const lld::Atom *target = ref->target();
89 if ((target != nullptr) && target->name().empty()) {
90 std::string storage;
91 llvm::raw_string_ostream buffer(storage);
92 buffer << llvm::format("L%03d", _unnamedCounter++);
93 llvm::StringRef newName = copyString(buffer.str());
94 _refNames[target] = newName;
Shankar Easwaran8962feb2013-03-14 16:09:49 +000095 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
96 << "unnamed atom: creating ref-name: '" << newName
97 << "' (" << (void*)newName.data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +000098 << newName.size() << ")\n");
99 }
100 }
101 }
102 for (const lld::UndefinedAtom *undefAtom : file.undefined()) {
103 buildDuplicateNameMap(*undefAtom);
104 }
105 for (const lld::SharedLibraryAtom *shlibAtom : file.sharedLibrary()) {
106 buildDuplicateNameMap(*shlibAtom);
107 }
108 for (const lld::AbsoluteAtom *absAtom : file.absolute()) {
109 buildDuplicateNameMap(*absAtom);
110 }
111 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000112
Nick Kledzik6b079f52013-01-05 02:22:35 +0000113 void buildDuplicateNameMap(const lld::Atom &atom) {
114 assert(!atom.name().empty());
115 NameToAtom::iterator pos = _nameMap.find(atom.name());
116 if ( pos != _nameMap.end() ) {
117 // Found name collision, give each a unique ref-name.
118 std::string Storage;
119 llvm::raw_string_ostream buffer(Storage);
120 buffer << atom.name() << llvm::format(".%03d", ++_collisionCount);
121 llvm::StringRef newName = copyString(buffer.str());
122 _refNames[&atom] = newName;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000123 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
Nick Kledzik6b079f52013-01-05 02:22:35 +0000124 << "name collsion: creating ref-name: '" << newName
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000125 << "' (" << (void*)newName.data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +0000126 << newName.size() << ")\n");
127 const lld::Atom *prevAtom = pos->second;
128 AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
129 if ( pos2 == _refNames.end() ) {
130 // Only create ref-name for previous if none already created.
131 std::string Storage2;
132 llvm::raw_string_ostream buffer2(Storage2);
133 buffer2 << prevAtom->name() << llvm::format(".%03d", ++_collisionCount);
134 llvm::StringRef newName2 = copyString(buffer2.str());
135 _refNames[prevAtom] = newName2;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000136 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
Nick Kledzik6b079f52013-01-05 02:22:35 +0000137 << "name collsion: creating ref-name: '" << newName2
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000138 << "' (" << (void*)newName2.data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +0000139 << newName2.size() << ")\n");
140 }
141 }
142 else {
143 // First time we've seen this name, just add it to map.
144 _nameMap[atom.name()] = &atom;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000145 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
146 << "atom name seen for first time: '" << atom.name()
147 << "' (" << (void*)atom.name().data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +0000148 << atom.name().size() << ")\n");
149 }
150 }
151
152 bool hasRefName(const lld::Atom *atom) {
153 return _refNames.count(atom);
154 }
155
156 llvm::StringRef refName(const lld::Atom *atom) {
157 return _refNames.find(atom)->second;
158 }
159
160private:
161 typedef llvm::StringMap<const lld::Atom*> NameToAtom;
162 typedef llvm::DenseMap<const lld::Atom*, std::string> AtomToRefName;
163
164 // Allocate a new copy of this string and keep track of allocations
165 // in _stringCopies, so they can be freed when RefNameBuilder is destroyed.
166 llvm::StringRef copyString(llvm::StringRef str) {
167 // We want _stringCopies to own the string memory so it is deallocated
168 // when the File object is destroyed. But we need a StringRef that
169 // points into that memory.
Michael J. Spencer20231f12013-01-26 12:26:56 +0000170 std::unique_ptr<char[]> s(new char[str.size()]);
Nick Kledzik6b079f52013-01-05 02:22:35 +0000171 memcpy(s.get(), str.data(), str.size());
172 llvm::StringRef r = llvm::StringRef(s.get(), str.size());
173 _stringCopies.push_back(std::move(s));
174 return r;
175 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000176
Nick Kledzik6b079f52013-01-05 02:22:35 +0000177 unsigned int _collisionCount;
178 unsigned int _unnamedCounter;
179 NameToAtom _nameMap;
180 AtomToRefName _refNames;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000181 std::vector<std::unique_ptr<char[]>> _stringCopies;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000182};
183
184
185/// Used when reading yaml files to find the target of a reference
186/// that could be a name or ref-name.
187class RefNameResolver {
188public:
189 RefNameResolver(const lld::File *file, IO &io);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000190
Nick Kledzik6b079f52013-01-05 02:22:35 +0000191 const lld::Atom *lookup(llvm::StringRef name) const {
192 NameToAtom::const_iterator pos = _nameMap.find(name);
193 if (pos != _nameMap.end()) {
194 return pos->second;
195 }
196 else {
197 _io.setError(llvm::Twine("no such atom name: ") + name);
198 return nullptr;
199 }
200 }
201
202private:
203 typedef llvm::StringMap<const lld::Atom*> NameToAtom;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000204
Nick Kledzik6b079f52013-01-05 02:22:35 +0000205 void add(llvm::StringRef name, const lld::Atom *atom) {
206 if (_nameMap.count(name)) {
207 _io.setError(llvm::Twine("duplicate atom name: ") + name);
208 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000209 else {
Nick Kledzik6b079f52013-01-05 02:22:35 +0000210 _nameMap[name] = atom;
211 }
212 }
213
214 IO &_io;
215 NameToAtom _nameMap;
216};
217
218
219// Used in NormalizedFile to hold the atoms lists.
220template <typename T>
221class AtomList : public lld::File::atom_collection<T> {
222public:
Michael J. Spencerc3c8bc12013-02-11 23:03:35 +0000223 virtual lld::File::atom_iterator<T> begin() const {
224 return lld::File::atom_iterator<
225 T>(*this,
226 _atoms.empty() ? 0 : reinterpret_cast<const void *>(_atoms.data()));
Nick Kledzik6b079f52013-01-05 02:22:35 +0000227 }
Michael J. Spencerc3c8bc12013-02-11 23:03:35 +0000228 virtual lld::File::atom_iterator<T> end() const{
229 return lld::File::atom_iterator<
230 T>(*this, _atoms.empty() ? 0 :
231 reinterpret_cast<const void *>(_atoms.data() + _atoms.size()));
Nick Kledzik6b079f52013-01-05 02:22:35 +0000232 }
233 virtual const T *deref(const void *it) const {
234 return *reinterpret_cast<const T *const*>(it);
235 }
236 virtual void next(const void *&it) const {
237 const T *const *p = reinterpret_cast<const T *const *>(it);
238 ++p;
239 it = reinterpret_cast<const void*>(p);
240 }
241 virtual void push_back(const T *element) {
242 _atoms.push_back(element);
243 }
Shankar Easwarancc068912013-04-29 04:10:42 +0000244 virtual uint64_t size() const { return _atoms.size(); }
245 std::vector<const T *> _atoms;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000246};
247
248/// Mapping of kind: field in yaml files.
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000249enum FileKinds {
Nick Kledzik6b079f52013-01-05 02:22:35 +0000250 fileKindObjectAtoms, // atom based object file encoded in yaml
251 fileKindArchive, // static archive library encoded in yaml
252 fileKindObjectELF, // ELF object files encoded in yaml
253 fileKindObjectMachO // mach-o object files encoded in yaml
254};
255
256struct ArchMember {
257 FileKinds _kind;
258 llvm::StringRef _name;
259 const lld::File *_content;
260};
261
Nick Kledzikbd491982013-01-08 23:51:03 +0000262
Nick Kledzik6b079f52013-01-05 02:22:35 +0000263// The content bytes in a DefinedAtom are just uint8_t but we want
264// special formatting, so define a strong type.
Nick Kledzikbd491982013-01-08 23:51:03 +0000265LLVM_YAML_STRONG_TYPEDEF(uint8_t, ImplicitHex8)
Nick Kledzik6b079f52013-01-05 02:22:35 +0000266
267// SharedLibraryAtoms have a bool canBeNull() method which we'd like to be
268// more readable than just true/false.
Nick Kledzikbd491982013-01-08 23:51:03 +0000269LLVM_YAML_STRONG_TYPEDEF(bool, ShlibCanBeNull)
Nick Kledzik6b079f52013-01-05 02:22:35 +0000270
271// lld::Reference::Kind is a typedef of int32. We need a stronger
272// type to make template matching work, so invent RefKind.
Nick Kledzikbd491982013-01-08 23:51:03 +0000273LLVM_YAML_STRONG_TYPEDEF(lld::Reference::Kind, RefKind)
Nick Kledzik6b079f52013-01-05 02:22:35 +0000274
Nick Kledzik6b079f52013-01-05 02:22:35 +0000275} // namespace anon
276
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000277LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember)
278 LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference *)
279 // Always write DefinedAtoms content bytes as a flow sequence.
280 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(ImplicitHex8)
281 // for compatibility with gcc-4.7 in C++11 mode, add extra namespace
282 namespace llvm {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000283 namespace yaml {
Nick Kledzikbd491982013-01-08 23:51:03 +0000284
Nick Kledzik6b079f52013-01-05 02:22:35 +0000285// This is a custom formatter for RefKind
286template<>
287struct ScalarTraits<RefKind> {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000288 static void output(const RefKind &value, void *ctxt,
Nick Kledzik6b079f52013-01-05 02:22:35 +0000289 llvm::raw_ostream &out) {
290 assert(ctxt != nullptr);
291 ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt);
Nick Kledzikc314b462013-04-04 18:59:24 +0000292 switch (value) {
293 case lld::Reference::kindLayoutAfter:
294 out << "layout-after";
295 break;
296 case lld::Reference::kindLayoutBefore:
297 out << "layout-before";
298 break;
299 case lld::Reference::kindInGroup:
300 out << "in-group";
301 break;
302 default:
303 if (auto relocStr = info->_targetInfo.stringFromRelocKind(value))
304 out << *relocStr;
Shankar Easwarancc068912013-04-29 04:10:42 +0000305 else
Nick Kledzikc314b462013-04-04 18:59:24 +0000306 out << "<unknown>";
307 break;
308 }
Shankar Easwarancc068912013-04-29 04:10:42 +0000309 }
Nick Kledzik6b079f52013-01-05 02:22:35 +0000310
311 static StringRef input(StringRef scalar, void *ctxt, RefKind &value) {
312 assert(ctxt != nullptr);
313 ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt);
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000314 auto relocKind = info->_targetInfo.relocKindFromString(scalar);
Nick Kledzikc314b462013-04-04 18:59:24 +0000315 if (!relocKind) {
316 if (scalar.equals("layout-after")) {
317 value = lld::Reference::kindLayoutAfter;
318 return StringRef();
319 }
320 if (scalar.equals("layout-before")) {
321 value = lld::Reference::kindLayoutBefore;
322 return StringRef();
323 }
324 if (scalar.equals("in-group")) {
325 value = lld::Reference::kindInGroup;
326 return StringRef();
327 }
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000328 return "Invalid relocation kind";
Nick Kledzikc314b462013-04-04 18:59:24 +0000329 }
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000330 value = *relocKind;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000331 return StringRef();
332 }
333};
334
335
336template <>
337struct ScalarEnumerationTraits<lld::File::Kind> {
338 static void enumeration(IO &io, lld::File::Kind &value) {
339 io.enumCase(value, "object", lld::File::kindObject);
340 io.enumCase(value, "shared-library", lld::File::kindSharedLibrary);
341 io.enumCase(value, "static-library", lld::File::kindArchiveLibrary);
342 }
343};
344
345template <>
346struct ScalarEnumerationTraits<lld::Atom::Scope> {
347 static void enumeration(IO &io, lld::Atom::Scope &value) {
348 io.enumCase(value, "global", lld::Atom::scopeGlobal);
349 io.enumCase(value, "hidden", lld::Atom::scopeLinkageUnit);
350 io.enumCase(value, "static", lld::Atom::scopeTranslationUnit);
351 }
352};
353
354template <>
355struct ScalarEnumerationTraits<lld::DefinedAtom::SectionChoice> {
356 static void enumeration(IO &io, lld::DefinedAtom::SectionChoice &value) {
357 io.enumCase(value, "content", lld::DefinedAtom::sectionBasedOnContent);
358 io.enumCase(value, "custom", lld::DefinedAtom::sectionCustomPreferred);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000359 io.enumCase(value, "custom-required",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000360 lld::DefinedAtom::sectionCustomRequired);
361 }
362};
363
364template <>
Nick Kledzik36293f62013-01-23 22:32:56 +0000365struct ScalarEnumerationTraits<lld::DefinedAtom::SectionPosition> {
366 static void enumeration(IO &io, lld::DefinedAtom::SectionPosition &value) {
367 io.enumCase(value, "start", lld::DefinedAtom::sectionPositionStart);
368 io.enumCase(value, "early", lld::DefinedAtom::sectionPositionEarly);
369 io.enumCase(value, "any", lld::DefinedAtom::sectionPositionAny);
370 io.enumCase(value, "end", lld::DefinedAtom::sectionPositionEnd);
371 }
372};
373
374template <>
Nick Kledzik6b079f52013-01-05 02:22:35 +0000375struct ScalarEnumerationTraits<lld::DefinedAtom::Interposable> {
376 static void enumeration(IO &io, lld::DefinedAtom::Interposable &value) {
377 io.enumCase(value, "no", lld::DefinedAtom::interposeNo);
378 io.enumCase(value, "yes", lld::DefinedAtom::interposeYes);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000379 io.enumCase(value, "yes-and-weak",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000380 lld::DefinedAtom::interposeYesAndRuntimeWeak);
381 }
382};
383
384template <>
385struct ScalarEnumerationTraits<lld::DefinedAtom::Merge> {
386 static void enumeration(IO &io, lld::DefinedAtom::Merge &value) {
387 io.enumCase(value, "no", lld::DefinedAtom::mergeNo);
388 io.enumCase(value, "as-tentative", lld::DefinedAtom::mergeAsTentative);
389 io.enumCase(value, "as-weak", lld::DefinedAtom::mergeAsWeak);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000390 io.enumCase(value, "as-addressed-weak",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000391 lld::DefinedAtom::mergeAsWeakAndAddressUsed);
Nick Kledzik233f5372013-01-15 00:17:57 +0000392 io.enumCase(value, "by-content", lld::DefinedAtom::mergeByContent);
Nick Kledzik6b079f52013-01-05 02:22:35 +0000393 }
394};
395
396template <>
397struct ScalarEnumerationTraits<lld::DefinedAtom::DeadStripKind> {
398 static void enumeration(IO &io, lld::DefinedAtom::DeadStripKind &value) {
399 io.enumCase(value, "normal", lld::DefinedAtom::deadStripNormal);
400 io.enumCase(value, "never", lld::DefinedAtom::deadStripNever);
401 io.enumCase(value, "always", lld::DefinedAtom::deadStripAlways);
402 }
403};
404
405template <>
406struct ScalarEnumerationTraits<lld::DefinedAtom::ContentPermissions> {
407 static void enumeration(IO &io, lld::DefinedAtom::ContentPermissions &value) {
Nick Kledzikcc3d2dc2013-01-09 01:17:12 +0000408 io.enumCase(value, "---", lld::DefinedAtom::perm___);
409 io.enumCase(value, "r--", lld::DefinedAtom::permR__);
410 io.enumCase(value, "r-x", lld::DefinedAtom::permR_X);
411 io.enumCase(value, "rw-", lld::DefinedAtom::permRW_);
412 io.enumCase(value, "rwx", lld::DefinedAtom::permRWX);
413 io.enumCase(value, "rw-l", lld::DefinedAtom::permRW_L);
414 io.enumCase(value, "unknown", lld::DefinedAtom::permUnknown);
Nick Kledzik6b079f52013-01-05 02:22:35 +0000415 }
416};
417
418template <>
419struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000420 static void enumeration(IO &io, lld::DefinedAtom::ContentType &value) {
421 io.enumCase(value, "unknown",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000422 lld::DefinedAtom::typeUnknown);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000423 io.enumCase(value, "code",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000424 lld::DefinedAtom::typeCode);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000425 io.enumCase(value, "stub",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000426 lld::DefinedAtom::typeStub);
Shankar Easwaran873c9ff2013-02-22 17:18:53 +0000427 io.enumCase(value, "constant", lld::DefinedAtom::typeConstant);
428 io.enumCase(value, "data", lld::DefinedAtom::typeData);
429 io.enumCase(value, "quick-data", lld::DefinedAtom::typeDataFast);
430 io.enumCase(value, "zero-fill", lld::DefinedAtom::typeZeroFill);
Shankar Easwarandb74ffb2013-02-24 03:09:10 +0000431 io.enumCase(value, "zero-fill-quick", lld::DefinedAtom::typeZeroFillFast);
Shankar Easwaran873c9ff2013-02-22 17:18:53 +0000432 io.enumCase(value, "const-data", lld::DefinedAtom::typeConstData);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000433 io.enumCase(value, "got",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000434 lld::DefinedAtom::typeGOT);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000435 io.enumCase(value, "resolver",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000436 lld::DefinedAtom::typeResolver);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000437 io.enumCase(value, "branch-island",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000438 lld::DefinedAtom::typeBranchIsland);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000439 io.enumCase(value, "branch-shim",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000440 lld::DefinedAtom::typeBranchShim);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000441 io.enumCase(value, "stub-helper",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000442 lld::DefinedAtom::typeStubHelper);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000443 io.enumCase(value, "c-string",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000444 lld::DefinedAtom::typeCString);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000445 io.enumCase(value, "utf16-string",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000446 lld::DefinedAtom::typeUTF16String);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000447 io.enumCase(value, "unwind-cfi",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000448 lld::DefinedAtom::typeCFI);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000449 io.enumCase(value, "unwind-lsda",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000450 lld::DefinedAtom::typeLSDA);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000451 io.enumCase(value, "const-4-byte",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000452 lld::DefinedAtom::typeLiteral4);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000453 io.enumCase(value, "const-8-byte",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000454 lld::DefinedAtom::typeLiteral8);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000455 io.enumCase(value, "const-16-byte",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000456 lld::DefinedAtom::typeLiteral16);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000457 io.enumCase(value, "lazy-pointer",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000458 lld::DefinedAtom::typeLazyPointer);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000459 io.enumCase(value, "lazy-dylib-pointer",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000460 lld::DefinedAtom::typeLazyDylibPointer);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000461 io.enumCase(value, "cfstring",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000462 lld::DefinedAtom::typeCFString);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000463 io.enumCase(value, "initializer-pointer",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000464 lld::DefinedAtom::typeInitializerPtr);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000465 io.enumCase(value, "terminator-pointer",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000466 lld::DefinedAtom::typeTerminatorPtr);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000467 io.enumCase(value, "c-string-pointer",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000468 lld::DefinedAtom::typeCStringPtr);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000469 io.enumCase(value, "objc-class-pointer",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000470 lld::DefinedAtom::typeObjCClassPtr);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000471 io.enumCase(value, "objc-category-list",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000472 lld::DefinedAtom::typeObjC2CategoryList);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000473 io.enumCase(value, "objc-class1",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000474 lld::DefinedAtom::typeObjC1Class);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000475 io.enumCase(value, "dtraceDOF",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000476 lld::DefinedAtom::typeDTraceDOF);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000477 io.enumCase(value, "lto-temp",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000478 lld::DefinedAtom::typeTempLTO);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000479 io.enumCase(value, "compact-unwind",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000480 lld::DefinedAtom::typeCompactUnwindInfo);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000481 io.enumCase(value, "tlv-thunk",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000482 lld::DefinedAtom::typeThunkTLV);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000483 io.enumCase(value, "tlv-data",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000484 lld::DefinedAtom::typeTLVInitialData);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000485 io.enumCase(value, "tlv-zero-fill",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000486 lld::DefinedAtom::typeTLVInitialZeroFill);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000487 io.enumCase(value, "tlv-initializer-ptr",
Nick Kledzik6b079f52013-01-05 02:22:35 +0000488 lld::DefinedAtom::typeTLVInitializerPtr);
Nick Kledzik6b079f52013-01-05 02:22:35 +0000489 }
490};
491
492template <>
493struct ScalarEnumerationTraits<lld::UndefinedAtom::CanBeNull> {
494 static void enumeration(IO &io, lld::UndefinedAtom::CanBeNull &value) {
495 io.enumCase(value, "never", lld::UndefinedAtom::canBeNullNever);
496 io.enumCase(value, "at-runtime", lld::UndefinedAtom::canBeNullAtRuntime);
497 io.enumCase(value, "at-buildtime", lld::UndefinedAtom::canBeNullAtBuildtime);
498 }
499};
500
501
502template <>
503struct ScalarEnumerationTraits<ShlibCanBeNull> {
504 static void enumeration(IO &io, ShlibCanBeNull &value) {
505 io.enumCase(value, "never", false);
506 io.enumCase(value, "at-runtime", true);
507 }
508};
509
510
511
512/// This is a custom formatter for lld::DefinedAtom::Alignment. Values look
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000513/// like:
Nick Kledzik6b079f52013-01-05 02:22:35 +0000514/// 2^3 # 8-byte aligned
515/// 7 mod 2^4 # 16-byte aligned plus 7 bytes
516template<>
517struct ScalarTraits<lld::DefinedAtom::Alignment> {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000518 static void output(const lld::DefinedAtom::Alignment &value, void *ctxt,
Nick Kledzik6b079f52013-01-05 02:22:35 +0000519 llvm::raw_ostream &out) {
520 if (value.modulus == 0) {
521 out << llvm::format("2^%d", value.powerOf2);
522 }
523 else {
524 out << llvm::format("%d mod 2^%d", value.modulus, value.powerOf2);
525 }
526 }
527
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000528 static StringRef input(StringRef scalar, void *ctxt,
Nick Kledzik6b079f52013-01-05 02:22:35 +0000529 lld::DefinedAtom::Alignment &value) {
530 value.modulus = 0;
531 size_t modStart = scalar.find("mod");
532 if (modStart != StringRef::npos) {
533 StringRef modStr = scalar.slice(0, modStart);
534 modStr = modStr.rtrim();
535 unsigned int modulus;
536 if (modStr.getAsInteger(0, modulus)) {
537 return "malformed alignment modulus";
538 }
539 value.modulus = modulus;
540 scalar = scalar.drop_front(modStart+3);
541 scalar = scalar.ltrim();
542 }
543 if (!scalar.startswith("2^")) {
544 return "malformed alignment";
545 }
546 StringRef powerStr = scalar.drop_front(2);
547 unsigned int power;
548 if (powerStr.getAsInteger(0, power)) {
549 return "malformed alignment power";
550 }
551 value.powerOf2 = power;
552 if (value.modulus > (1<<value.powerOf2)) {
553 return "malformed alignment, modulus too large for power";
554 }
555 return StringRef(); // returning empty string means success
556 }
557};
558
559
560
561
562template <>
563struct ScalarEnumerationTraits<FileKinds> {
564 static void enumeration(IO &io, FileKinds &value) {
565 io.enumCase(value, "object", fileKindObjectAtoms);
566 io.enumCase(value, "archive", fileKindArchive);
567 io.enumCase(value, "object-elf", fileKindObjectELF);
568 io.enumCase(value, "object-mach-o", fileKindObjectMachO);
569 }
570};
571
572template <>
573struct MappingTraits<ArchMember> {
574 static void mapping(IO &io, ArchMember &member) {
575 io.mapOptional("kind", member._kind, fileKindObjectAtoms);
576 io.mapOptional("name", member._name);
577 io.mapRequired("content", member._content);
578 }
579};
580
Nick Kledzik6b079f52013-01-05 02:22:35 +0000581
582
583// Declare that an AtomList is a yaml sequence.
584template<typename T>
585struct SequenceTraits<AtomList<T>> {
586 static size_t size(IO &io, AtomList<T> &seq) {
587 return seq._atoms.size();
588 }
589 static const T *&element(IO &io, AtomList<T> &seq, size_t index) {
590 if (index >= seq._atoms.size())
591 seq._atoms.resize(index+1);
592 return seq._atoms[index];
593 }
594};
595
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000596// Used to allow DefinedAtom content bytes to be a flow sequence of
Nick Kledzik6b079f52013-01-05 02:22:35 +0000597// two-digit hex numbers without the leading 0x (e.g. FF, 04, 0A)
598template<>
599struct ScalarTraits<ImplicitHex8> {
600 static void output(const ImplicitHex8 &val, void*, llvm::raw_ostream &out) {
601 uint8_t num = val;
602 out << llvm::format("%02X", num);
603 }
604
605 static llvm::StringRef input(llvm::StringRef str, void*, ImplicitHex8 &val) {
606 unsigned long long n;
607 if (getAsUnsignedInteger(str, 16, n))
608 return "invalid two-digit-hex number";
609 if (n > 0xFF)
610 return "out of range two-digit-hex number";
611 val = n;
612 return StringRef(); // returning empty string means success
613 }
614};
615
Nick Kledzik6b079f52013-01-05 02:22:35 +0000616
617// YAML conversion for std::vector<const lld::File*>
618template<>
619struct DocumentListTraits< std::vector<const lld::File*> > {
620 static size_t size(IO &io, std::vector<const lld::File*> &seq) {
621 return seq.size();
622 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000623 static const lld::File *&element(IO &io, std::vector<const lld::File*> &seq,
Nick Kledzik6b079f52013-01-05 02:22:35 +0000624 size_t index) {
625 if (index >= seq.size())
626 seq.resize(index+1);
627 return seq[index];
628 }
629};
630
631
632// YAML conversion for const lld::File*
633template <>
634struct MappingTraits<const lld::File*> {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000635
636 class NormArchiveFile : public lld::ArchiveLibraryFile {
637 public:
638 NormArchiveFile(IO &io)
639 : ArchiveLibraryFile(((ContextInfo *)io.getContext())->_targetInfo,
640 ""),
641 _path() {
642 }
643 NormArchiveFile(IO &io, const lld::File *file)
644 : ArchiveLibraryFile(((ContextInfo *)io.getContext())->_targetInfo,
645 file->path()),
646 _path(file->path()) {
Nick Kledzik6b079f52013-01-05 02:22:35 +0000647 // If we want to support writing archives, this constructor would
648 // need to populate _members.
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000649 }
Nick Kledzik6b079f52013-01-05 02:22:35 +0000650
651 const lld::File *denormalize(IO &io) {
652 return this;
653 }
Michael J. Spencer57752dc2013-01-12 02:45:54 +0000654
Nick Kledzik36293f62013-01-23 22:32:56 +0000655 virtual void setOrdinalAndIncrement(uint64_t &ordinal) const {
656 _ordinal = ordinal++;
657 // Assign sequential ordinals to member files
658 for (const ArchMember &member : _members) {
659 member._content->setOrdinalAndIncrement(ordinal);
660 }
661 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000662
Nick Kledzik6b079f52013-01-05 02:22:35 +0000663 virtual const atom_collection<lld::DefinedAtom> &defined() const {
664 return _noDefinedAtoms;
665 }
666 virtual const atom_collection<lld::UndefinedAtom> &undefined() const {
667 return _noUndefinedAtoms;
668 }
669 virtual const atom_collection<lld::SharedLibraryAtom> &sharedLibrary()const{
670 return _noSharedLibaryAtoms;
671 }
672 virtual const atom_collection<lld::AbsoluteAtom> &absolute() const {
673 return _noAbsoluteAtoms;
674 }
675 virtual const File *find(StringRef name, bool dataSymbolOnly) const {
676 for (const ArchMember &member : _members) {
677 for (const lld::DefinedAtom *atom : member._content->defined() ) {
678 if (name == atom->name()) {
679 if (!dataSymbolOnly)
680 return member._content;
681 switch (atom->contentType()) {
682 case lld::DefinedAtom::typeData:
683 case lld::DefinedAtom::typeZeroFill:
684 return member._content;
685 default:
686 break;
687 }
688 }
689 }
690 }
691 return nullptr;
692 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000693
Nick Kledzik6b079f52013-01-05 02:22:35 +0000694 StringRef _path;
695 std::vector<ArchMember> _members;
696 };
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000697
698 class NormalizedFile : public lld::File {
699 public:
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000700 NormalizedFile(IO &io) : File("", kindObject), _IO(io), _rnb(nullptr) {}
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000701 NormalizedFile(IO &io, const lld::File *file)
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000702 : File(file->path(), kindObject), _IO(io), _rnb(new RefNameBuilder(*file)),
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000703 _path(file->path()) {
704 for (const lld::DefinedAtom *a : file->defined())
705 _definedAtoms.push_back(a);
706 for (const lld::UndefinedAtom *a : file->undefined())
Nick Kledzik6b079f52013-01-05 02:22:35 +0000707 _undefinedAtoms.push_back(a);
708 for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
709 _sharedLibraryAtoms.push_back(a);
710 for (const lld::AbsoluteAtom *a : file->absolute())
711 _absoluteAtoms.push_back(a);
712 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000713 const lld::File *denormalize(IO &io);
Michael J. Spencer57752dc2013-01-12 02:45:54 +0000714
Nick Kledzik6b079f52013-01-05 02:22:35 +0000715 virtual const atom_collection<lld::DefinedAtom> &defined() const {
716 return _definedAtoms;
717 }
718 virtual const atom_collection<lld::UndefinedAtom> &undefined() const {
719 return _undefinedAtoms;
720 }
721 virtual const atom_collection<lld::SharedLibraryAtom> &sharedLibrary()const{
722 return _sharedLibraryAtoms;
723 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000724 virtual const atom_collection<lld::AbsoluteAtom> &absolute() const {
725 return _absoluteAtoms;
726 }
727
728 virtual const TargetInfo &getTargetInfo() const {
729 return ((ContextInfo *)_IO.getContext())->_targetInfo;
730 }
731
732 // Allocate a new copy of this string and keep track of allocations
733 // in _stringCopies, so they can be freed when File is destroyed.
Nick Kledzik6b079f52013-01-05 02:22:35 +0000734 StringRef copyString(StringRef str) {
735 // We want _stringCopies to own the string memory so it is deallocated
736 // when the File object is destroyed. But we need a StringRef that
737 // points into that memory.
Michael J. Spencer20231f12013-01-26 12:26:56 +0000738 std::unique_ptr<char[]> s(new char[str.size()]);
Nick Kledzik6b079f52013-01-05 02:22:35 +0000739 memcpy(s.get(), str.data(), str.size());
740 llvm::StringRef r = llvm::StringRef(s.get(), str.size());
741 _stringCopies.push_back(std::move(s));
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000742 return r;
743 }
744
745 IO &_IO;
746 RefNameBuilder *_rnb;
747 StringRef _path;
748 AtomList<lld::DefinedAtom> _definedAtoms;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000749 AtomList<lld::UndefinedAtom> _undefinedAtoms;
750 AtomList<lld::SharedLibraryAtom> _sharedLibraryAtoms;
751 AtomList<lld::AbsoluteAtom> _absoluteAtoms;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000752 std::vector<std::unique_ptr<char[]>> _stringCopies;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000753 };
754
755
756 static void mapping(IO &io, const lld::File *&file) {
757 // We only support writing atom based YAML
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000758 FileKinds kind = fileKindObjectAtoms;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000759 // If reading, peek ahead to see what kind of file this is.
760 io.mapOptional("kind", kind, fileKindObjectAtoms);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000761 //
Nick Kledzik6b079f52013-01-05 02:22:35 +0000762 switch (kind) {
763 case fileKindObjectAtoms:
764 mappingAtoms(io, file);
765 break;
766 case fileKindArchive:
767 mappingArchive(io, file);
768 break;
769 case fileKindObjectELF:
770 case fileKindObjectMachO:
771 // Eventually we will have an external function to call, similar
772 // to mappingAtoms() and mappingArchive() but implememented
773 // with coresponding file format code.
Nick Kledzik6b079f52013-01-05 02:22:35 +0000774 llvm_unreachable("section based YAML not supported yet");
775 }
776 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000777
Nick Kledzik6b079f52013-01-05 02:22:35 +0000778 static void mappingAtoms(IO &io, const lld::File *&file) {
779 MappingNormalizationHeap<NormalizedFile, const lld::File*> keys(io, file);
780 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
781 assert(info != nullptr);
782 info->_currentFile = keys.operator->();
783
784 io.mapOptional("path", keys->_path);
785 io.mapOptional("defined-atoms", keys->_definedAtoms);
786 io.mapOptional("undefined-atoms", keys->_undefinedAtoms);
787 io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
788 io.mapOptional("absolute-atoms", keys->_absoluteAtoms);
789 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000790
Nick Kledzik6b079f52013-01-05 02:22:35 +0000791 static void mappingArchive(IO &io, const lld::File *&file) {
792 MappingNormalizationHeap<NormArchiveFile, const lld::File*> keys(io, file);
793
794 io.mapOptional("path", keys->_path);
795 io.mapOptional("members", keys->_members);
796 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000797
Nick Kledzik6b079f52013-01-05 02:22:35 +0000798};
799
800
801
802// YAML conversion for const lld::Reference*
803template <>
804struct MappingTraits<const lld::Reference*> {
805
806 class NormalizedReference : public lld::Reference {
807 public:
808 NormalizedReference(IO &io)
Michael J. Spencerfa405272013-03-20 18:57:52 +0000809 : _target(nullptr), _targetName(), _offset(0), _addend(0) {}
810
Nick Kledzik6b079f52013-01-05 02:22:35 +0000811 NormalizedReference(IO &io, const lld::Reference *ref)
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000812 : _target(nullptr),
813 _targetName(targetName(io, ref)),
814 _offset(ref->offsetInAtom()),
Nick Kledzik6b079f52013-01-05 02:22:35 +0000815 _addend(ref->addend()),
Michael J. Spencerfa405272013-03-20 18:57:52 +0000816 _mappedKind(ref->kind()) {
Nick Kledzik6b079f52013-01-05 02:22:35 +0000817 }
Michael J. Spencerfa405272013-03-20 18:57:52 +0000818
Nick Kledzik6b079f52013-01-05 02:22:35 +0000819 const lld::Reference *denormalize(IO &io) {
820 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
821 assert(info != nullptr);
822 typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile;
823 NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile);
824 if (!_targetName.empty())
825 _targetName = f->copyString(_targetName);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000826 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
827 << "created Reference to name: '" << _targetName
828 << "' (" << (void*)_targetName.data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +0000829 << _targetName.size() << ")\n");
Michael J. Spencerfa405272013-03-20 18:57:52 +0000830 setKind(_mappedKind);
Nick Kledzik6b079f52013-01-05 02:22:35 +0000831 return this;
832 }
833 void bind(const RefNameResolver&);
834 static StringRef targetName(IO &io, const lld::Reference *ref);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000835
Nick Kledzik6b079f52013-01-05 02:22:35 +0000836 virtual uint64_t offsetInAtom() const { return _offset; }
Nick Kledzik6b079f52013-01-05 02:22:35 +0000837 virtual const lld::Atom *target() const { return _target; }
838 virtual Addend addend() const { return _addend; }
Nick Kledzik6b079f52013-01-05 02:22:35 +0000839 virtual void setAddend(Addend a) { _addend = a; }
840 virtual void setTarget(const lld::Atom *a) { _target = a; }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000841
Nick Kledzik6b079f52013-01-05 02:22:35 +0000842 const lld::Atom *_target;
843 StringRef _targetName;
844 uint32_t _offset;
845 Addend _addend;
Michael J. Spencerfa405272013-03-20 18:57:52 +0000846 RefKind _mappedKind;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000847 };
848
849
850 static void mapping(IO &io, const lld::Reference *&ref) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000851 MappingNormalizationHeap<NormalizedReference,
Nick Kledzik6b079f52013-01-05 02:22:35 +0000852 const lld::Reference*> keys(io, ref);
853
Michael J. Spencerfa405272013-03-20 18:57:52 +0000854 io.mapRequired("kind", keys->_mappedKind);
Nick Kledzik6b079f52013-01-05 02:22:35 +0000855 io.mapOptional("offset", keys->_offset);
856 io.mapOptional("target", keys->_targetName);
857 io.mapOptional("addend", keys->_addend, (lld::Reference::Addend)0);
858 }
859};
860
Nick Kledzik6b079f52013-01-05 02:22:35 +0000861
862
863// YAML conversion for const lld::DefinedAtom*
864template <>
865struct MappingTraits<const lld::DefinedAtom*> {
866
867 class NormalizedAtom : public lld::DefinedAtom {
868 public:
869 NormalizedAtom(IO &io)
Michael J. Spencer096ea032013-04-05 21:07:44 +0000870 : _file(fileFromContext(io)), _name(), _refName(), _contentType(),
Nick Kledzik6b079f52013-01-05 02:22:35 +0000871 _alignment(0), _content(), _references() {
Nick Kledzik36293f62013-01-23 22:32:56 +0000872 static uint32_t ordinalCounter = 1;
873 _ordinal = ordinalCounter++;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000874 }
875 NormalizedAtom(IO &io, const lld::DefinedAtom *atom)
876 : _file(fileFromContext(io)),
877 _name(atom->name()),
878 _refName(),
879 _scope(atom->scope()),
880 _interpose(atom->interposable()),
881 _merge(atom->merge()),
882 _contentType(atom->contentType()),
883 _alignment(atom->alignment()),
884 _sectionChoice(atom->sectionChoice()),
Nick Kledzik36293f62013-01-23 22:32:56 +0000885 _sectionPosition(atom->sectionPosition()),
Nick Kledzik6b079f52013-01-05 02:22:35 +0000886 _deadStrip(atom->deadStrip()),
887 _permissions(atom->permissions()),
888 _size(atom->size()),
889 _sectionName(atom->customSectionName()) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000890 for ( const lld::Reference *r : *atom )
Nick Kledzik6b079f52013-01-05 02:22:35 +0000891 _references.push_back(r);
892 ArrayRef<uint8_t> cont = atom->rawContent();
893 _content.reserve(cont.size());
894 for (uint8_t x : cont)
895 _content.push_back(x);
896 }
897 const lld::DefinedAtom *denormalize(IO &io) {
898 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
899 assert(info != nullptr);
900 typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile;
901 NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile);
902 if ( !_name.empty() )
903 _name = f->copyString(_name);
904 if ( !_refName.empty() )
905 _refName = f->copyString(_refName);
906 if ( !_sectionName.empty() )
907 _sectionName = f->copyString(_sectionName);
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000908 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
909 << "created DefinedAtom named: '" << _name
910 << "' (" << (void*)_name.data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +0000911 << _name.size() << ")\n");
912 return this;
913 }
914 void bind(const RefNameResolver&);
915 // Extract current File object from YAML I/O parsing context
916 const lld::File &fileFromContext(IO &io) {
917 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
918 assert(info != nullptr);
919 assert(info->_currentFile != nullptr);
920 return *info->_currentFile;
921 }
922
923 virtual const lld::File &file() const { return _file; }
924 virtual StringRef name() const { return _name; }
925 virtual uint64_t size() const { return _size; }
926 virtual Scope scope() const { return _scope; }
927 virtual Interposable interposable() const { return _interpose; }
928 virtual Merge merge() const { return _merge; }
929 virtual ContentType contentType() const { return _contentType; }
930 virtual Alignment alignment() const { return _alignment; }
931 virtual SectionChoice sectionChoice() const { return _sectionChoice; }
932 virtual StringRef customSectionName() const { return _sectionName;}
Nick Kledzik36293f62013-01-23 22:32:56 +0000933 virtual SectionPosition sectionPosition() const{return _sectionPosition;}
Nick Kledzik6b079f52013-01-05 02:22:35 +0000934 virtual DeadStripKind deadStrip() const { return _deadStrip; }
935 virtual ContentPermissions permissions() const { return _permissions; }
936 virtual bool isThumb() const { return false; }
937 virtual bool isAlias() const { return false; }
Michael J. Spencer74ba7222013-01-13 01:09:39 +0000938 ArrayRef<uint8_t> rawContent() const {
939 return ArrayRef<uint8_t>(
940 reinterpret_cast<const uint8_t *>(_content.data()), _content.size());
941 }
942
Nick Kledzik36293f62013-01-23 22:32:56 +0000943 virtual uint64_t ordinal() const { return _ordinal; }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000944
945 reference_iterator begin() const {
Nick Kledzik6b079f52013-01-05 02:22:35 +0000946 uintptr_t index = 0;
947 const void *it = reinterpret_cast<const void*>(index);
948 return reference_iterator(*this, it);
949 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000950 reference_iterator end() const {
Nick Kledzik6b079f52013-01-05 02:22:35 +0000951 uintptr_t index = _references.size();
952 const void *it = reinterpret_cast<const void*>(index);
953 return reference_iterator(*this, it);
954 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000955 const lld::Reference *derefIterator(const void *it) const {
Nick Kledzik6b079f52013-01-05 02:22:35 +0000956 uintptr_t index = reinterpret_cast<uintptr_t>(it);
957 assert(index < _references.size());
958 return _references[index];
959 }
960 void incrementIterator(const void *&it) const {
961 uintptr_t index = reinterpret_cast<uintptr_t>(it);
962 ++index;
963 it = reinterpret_cast<const void*>(index);
964 }
965
966 const lld::File &_file;
967 StringRef _name;
968 StringRef _refName;
969 Scope _scope;
970 Interposable _interpose;
971 Merge _merge;
972 ContentType _contentType;
973 Alignment _alignment;
974 SectionChoice _sectionChoice;
Nick Kledzik36293f62013-01-23 22:32:56 +0000975 SectionPosition _sectionPosition;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000976 DeadStripKind _deadStrip;
977 ContentPermissions _permissions;
Nick Kledzik36293f62013-01-23 22:32:56 +0000978 uint32_t _ordinal;
Nick Kledzik6b079f52013-01-05 02:22:35 +0000979 std::vector<ImplicitHex8> _content;
980 uint64_t _size;
981 StringRef _sectionName;
982 std::vector<const lld::Reference*> _references;
983 };
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000984
Nick Kledzik6b079f52013-01-05 02:22:35 +0000985 static void mapping(IO &io, const lld::DefinedAtom *&atom) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000986 MappingNormalizationHeap<NormalizedAtom,
Nick Kledzik6b079f52013-01-05 02:22:35 +0000987 const lld::DefinedAtom*> keys(io, atom);
988 if ( io.outputting() ) {
989 // If writing YAML, check if atom needs a ref-name.
990 typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile;
991 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
992 assert(info != nullptr);
993 NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile);
994 assert(f);
995 assert(f->_rnb);
996 if ( f->_rnb->hasRefName(atom) ) {
997 keys->_refName = f->_rnb->refName(atom);
998 }
999 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001000
1001 io.mapOptional("name", keys->_name,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001002 StringRef());
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001003 io.mapOptional("ref-name", keys->_refName,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001004 StringRef());
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001005 io.mapOptional("scope", keys->_scope,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001006 lld::DefinedAtom::scopeTranslationUnit);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001007 io.mapOptional("type", keys->_contentType,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001008 lld::DefinedAtom::typeCode);
1009 io.mapOptional("content", keys->_content);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001010 io.mapOptional("size", keys->_size,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001011 (uint64_t)keys->_content.size());
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001012 io.mapOptional("interposable", keys->_interpose,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001013 lld::DefinedAtom::interposeNo);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001014 io.mapOptional("merge", keys->_merge,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001015 lld::DefinedAtom::mergeNo);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001016 io.mapOptional("alignment", keys->_alignment,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001017 lld::DefinedAtom::Alignment(0));
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001018 io.mapOptional("section-choice", keys->_sectionChoice,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001019 lld::DefinedAtom::sectionBasedOnContent);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001020 io.mapOptional("section-name", keys->_sectionName,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001021 StringRef());
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001022 io.mapOptional("section-position",keys->_sectionPosition,
Nick Kledzik36293f62013-01-23 22:32:56 +00001023 lld::DefinedAtom::sectionPositionAny);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001024 io.mapOptional("dead-strip", keys->_deadStrip,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001025 lld::DefinedAtom::deadStripNormal);
Nick Kledzikcc3d2dc2013-01-09 01:17:12 +00001026 // default permissions based on content type
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001027 io.mapOptional("permissions", keys->_permissions,
Nick Kledzikcc3d2dc2013-01-09 01:17:12 +00001028 lld::DefinedAtom::permissions(
1029 keys->_contentType));
Nick Kledzik8a3052e2013-01-08 21:12:13 +00001030 io.mapOptional("references", keys->_references);
Nick Kledzik6b079f52013-01-05 02:22:35 +00001031 }
1032};
1033
1034
1035
1036
Nick Kledzik6b079f52013-01-05 02:22:35 +00001037// YAML conversion for const lld::UndefinedAtom*
1038template <>
1039struct MappingTraits<const lld::UndefinedAtom*> {
1040
1041 class NormalizedAtom : public lld::UndefinedAtom {
1042 public:
1043 NormalizedAtom(IO &io)
1044 : _file(fileFromContext(io)), _name(), _canBeNull(canBeNullNever) {
1045 }
1046 NormalizedAtom(IO &io, const lld::UndefinedAtom *atom)
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001047 : _file(fileFromContext(io)),
1048 _name(atom->name()),
Nick Kledzik6b079f52013-01-05 02:22:35 +00001049 _canBeNull(atom->canBeNull()) {
1050 }
1051 const lld::UndefinedAtom *denormalize(IO &io) {
1052 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
1053 assert(info != nullptr);
1054 typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile;
1055 NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile);
1056 if ( !_name.empty() )
1057 _name = f->copyString(_name);
1058
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001059 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
1060 << "created UndefinedAtom named: '" << _name
1061 << "' (" << (void*)_name.data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +00001062 << _name.size() << ")\n");
1063 return this;
1064 }
1065 // Extract current File object from YAML I/O parsing context
1066 const lld::File &fileFromContext(IO &io) {
1067 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
1068 assert(info != nullptr);
1069 assert(info->_currentFile != nullptr);
1070 return *info->_currentFile;
1071 }
1072
1073 virtual const lld::File &file() const { return _file; }
1074 virtual StringRef name() const { return _name; }
1075 virtual CanBeNull canBeNull() const { return _canBeNull; }
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001076
Nick Kledzik6b079f52013-01-05 02:22:35 +00001077 const lld::File &_file;
1078 StringRef _name;
1079 CanBeNull _canBeNull;
1080 };
1081
1082
1083 static void mapping(IO &io, const lld::UndefinedAtom* &atom) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001084 MappingNormalizationHeap<NormalizedAtom,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001085 const lld::UndefinedAtom*> keys(io, atom);
1086
1087 io.mapRequired("name", keys->_name);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001088 io.mapOptional("can-be-null", keys->_canBeNull,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001089 lld::UndefinedAtom::canBeNullNever);
1090 }
1091};
1092
1093
Nick Kledzik36293f62013-01-23 22:32:56 +00001094
Nick Kledzik6b079f52013-01-05 02:22:35 +00001095// YAML conversion for const lld::SharedLibraryAtom*
1096template <>
1097struct MappingTraits<const lld::SharedLibraryAtom*> {
1098
1099 class NormalizedAtom : public lld::SharedLibraryAtom {
1100 public:
1101 NormalizedAtom(IO &io)
1102 : _file(fileFromContext(io)), _name(), _loadName(), _canBeNull(false) {
1103 }
1104 NormalizedAtom(IO &io, const lld::SharedLibraryAtom *atom)
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001105 : _file(fileFromContext(io)),
1106 _name(atom->name()),
1107 _loadName(atom->loadName()),
Nick Kledzik6b079f52013-01-05 02:22:35 +00001108 _canBeNull(atom->canBeNullAtRuntime()) {
1109 }
1110 const lld::SharedLibraryAtom *denormalize(IO &io) {
1111 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
1112 assert(info != nullptr);
1113 typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile;
1114 NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile);
1115 if ( !_name.empty() )
1116 _name = f->copyString(_name);
1117 if ( !_loadName.empty() )
1118 _loadName = f->copyString(_loadName);
1119
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001120 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
1121 << "created SharedLibraryAtom named: '" << _name
1122 << "' (" << (void*)_name.data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +00001123 << _name.size() << ")\n");
1124 return this;
1125 }
1126 // Extract current File object from YAML I/O parsing context
1127 const lld::File &fileFromContext(IO &io) {
1128 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
1129 assert(info != nullptr);
1130 assert(info->_currentFile != nullptr);
1131 return *info->_currentFile;
1132 }
1133
1134 virtual const lld::File &file() const { return _file; }
1135 virtual StringRef name() const { return _name; }
1136 virtual StringRef loadName() const { return _loadName;}
1137 virtual bool canBeNullAtRuntime() const { return _canBeNull; }
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001138
Nick Kledzik6b079f52013-01-05 02:22:35 +00001139 const lld::File &_file;
1140 StringRef _name;
1141 StringRef _loadName;
1142 ShlibCanBeNull _canBeNull;
1143 };
1144
1145
1146 static void mapping(IO &io, const lld::SharedLibraryAtom *&atom) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001147
1148 MappingNormalizationHeap<NormalizedAtom,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001149 const lld::SharedLibraryAtom*> keys(io, atom);
1150
1151 io.mapRequired("name", keys->_name);
1152 io.mapOptional("load-name", keys->_loadName);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001153 io.mapOptional("can-be-null", keys->_canBeNull,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001154 (ShlibCanBeNull)false);
1155 }
1156};
1157
1158
1159// YAML conversion for const lld::AbsoluteAtom*
1160template <>
1161struct MappingTraits<const lld::AbsoluteAtom*> {
1162
1163 class NormalizedAtom : public lld::AbsoluteAtom {
1164 public:
1165 NormalizedAtom(IO &io)
1166 : _file(fileFromContext(io)), _name(), _scope(), _value(0) {
1167 }
1168 NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001169 : _file(fileFromContext(io)),
1170 _name(atom->name()),
Nick Kledzik6b079f52013-01-05 02:22:35 +00001171 _scope(atom->scope()),
1172 _value(atom->value()) {
1173 }
1174 const lld::AbsoluteAtom *denormalize(IO &io) {
1175 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
1176 assert(info != nullptr);
1177 typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile;
1178 NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile);
1179 if ( !_name.empty() )
1180 _name = f->copyString(_name);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001181
1182 DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
1183 << "created AbsoluteAtom named: '" << _name
1184 << "' (" << (void*)_name.data() << ", "
Nick Kledzik6b079f52013-01-05 02:22:35 +00001185 << _name.size() << ")\n");
1186 return this;
1187 }
1188 // Extract current File object from YAML I/O parsing context
1189 const lld::File &fileFromContext(IO &io) {
1190 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
1191 assert(info != nullptr);
1192 assert(info->_currentFile != nullptr);
1193 return *info->_currentFile;
1194 }
1195
1196 virtual const lld::File &file() const { return _file; }
1197 virtual StringRef name() const { return _name; }
1198 virtual uint64_t value() const { return _value; }
1199 virtual Scope scope() const { return _scope; }
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001200
Nick Kledzik6b079f52013-01-05 02:22:35 +00001201 const lld::File &_file;
1202 StringRef _name;
1203 StringRef _refName;
1204 Scope _scope;
1205 Hex64 _value;
1206 };
1207
1208
1209 static void mapping(IO &io, const lld::AbsoluteAtom *&atom) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001210 MappingNormalizationHeap<NormalizedAtom,
Nick Kledzik6b079f52013-01-05 02:22:35 +00001211 const lld::AbsoluteAtom*> keys(io, atom);
1212
1213 if ( io.outputting() ) {
1214 typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile;
1215 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
1216 assert(info != nullptr);
1217 NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile);
1218 assert(f);
1219 assert(f->_rnb);
1220 if ( f->_rnb->hasRefName(atom) ) {
1221 keys->_refName = f->_rnb->refName(atom);
1222 }
1223 }
1224
1225 io.mapRequired("name", keys->_name);
1226 io.mapOptional("ref-name", keys->_refName, StringRef());
1227 io.mapOptional("scope", keys->_scope);
1228 io.mapRequired("value", keys->_value);
1229 }
1230};
1231
Nick Kledzikbd491982013-01-08 23:51:03 +00001232} // namespace llvm
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001233} // namespace yaml
Nick Kledzikbd491982013-01-08 23:51:03 +00001234
Nick Kledzik6b079f52013-01-05 02:22:35 +00001235
1236RefNameResolver::RefNameResolver(const lld::File *file, IO &io) : _io(io) {
1237 typedef MappingTraits<const lld::DefinedAtom*>::NormalizedAtom NormalizedAtom;
1238 for (const lld::DefinedAtom *a : file->defined() ) {
1239 NormalizedAtom *na = (NormalizedAtom*)a;
1240 if ( na->_refName.empty() )
1241 add(na->_name, a);
1242 else
1243 add(na->_refName, a);
1244 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001245
Nick Kledzik6b079f52013-01-05 02:22:35 +00001246 for (const lld::UndefinedAtom *a : file->undefined() )
1247 add(a->name(), a);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001248
Nick Kledzik6b079f52013-01-05 02:22:35 +00001249 for (const lld::SharedLibraryAtom *a : file->sharedLibrary() )
1250 add(a->name(), a);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001251
Nick Kledzik6b079f52013-01-05 02:22:35 +00001252 typedef MappingTraits<const lld::AbsoluteAtom*>::NormalizedAtom NormAbsAtom;
1253 for (const lld::AbsoluteAtom *a : file->absolute() ) {
1254 NormAbsAtom *na = (NormAbsAtom*)a;
1255 if ( na->_refName.empty() )
1256 add(na->_name, a);
1257 else
1258 add(na->_refName, a);
1259 }
1260}
1261
1262
Nick Kledzikbd491982013-01-08 23:51:03 +00001263
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001264inline
Nick Kledzikbd491982013-01-08 23:51:03 +00001265const lld::File*
1266MappingTraits<const lld::File*>::NormalizedFile::denormalize(IO &io) {
1267 typedef MappingTraits<const lld::DefinedAtom*>::NormalizedAtom NormalizedAtom;
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001268
Nick Kledzikbd491982013-01-08 23:51:03 +00001269 RefNameResolver nameResolver(this, io);
1270 // Now that all atoms are parsed, references can be bound.
1271 for (const lld::DefinedAtom *a : this->defined() ) {
1272 NormalizedAtom *normAtom = (NormalizedAtom*)a;
1273 normAtom->bind(nameResolver);
1274 }
1275 return this;
1276}
1277
1278inline
1279void MappingTraits<const lld::DefinedAtom*>::
1280 NormalizedAtom::bind(const RefNameResolver &resolver) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001281 typedef MappingTraits<const lld::Reference*>::NormalizedReference
Nick Kledzikbd491982013-01-08 23:51:03 +00001282 NormalizedReference;
1283 for (const lld::Reference *ref : _references) {
1284 NormalizedReference *normRef = (NormalizedReference*)ref;
1285 normRef->bind(resolver);
1286 }
1287}
1288
1289inline
1290void MappingTraits<const lld::Reference*>::
1291 NormalizedReference::bind(const RefNameResolver &resolver) {
1292 _target = resolver.lookup(_targetName);
1293}
1294
1295
Nick Kledzik6b079f52013-01-05 02:22:35 +00001296inline
1297llvm::StringRef MappingTraits<const lld::Reference*>::NormalizedReference::
1298 targetName(IO &io, const lld::Reference *ref) {
1299 if ( ref->target() == nullptr )
1300 return llvm::StringRef();
1301 ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext());
1302 assert(info != nullptr);
1303 typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile;
1304 NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile);
1305 RefNameBuilder *rnb = f->_rnb;
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001306 if ( rnb->hasRefName(ref->target()) )
Nick Kledzik6b079f52013-01-05 02:22:35 +00001307 return rnb->refName(ref->target());
1308 return ref->target()->name();
1309}
1310
1311
1312
1313namespace lld {
1314namespace yaml {
1315
1316class Writer : public lld::Writer {
1317public:
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001318 Writer(const TargetInfo &ti) : _targetInfo(ti) {}
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001319
Nick Kledzik6b079f52013-01-05 02:22:35 +00001320 virtual error_code writeFile(const lld::File &file, StringRef outPath) {
1321 // Create stream to path.
1322 std::string errorInfo;
1323 llvm::raw_fd_ostream out(outPath.data(), errorInfo);
1324 if (!errorInfo.empty())
1325 return llvm::make_error_code(llvm::errc::no_such_file_or_directory);
1326
1327 // Create yaml Output writer, using yaml options for context.
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001328 ContextInfo context(_targetInfo);
Nick Kledzik6b079f52013-01-05 02:22:35 +00001329 llvm::yaml::Output yout(out, &context);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001330
Nick Kledzik6b079f52013-01-05 02:22:35 +00001331 // Write yaml output.
1332 const lld::File *fileRef = &file;
1333 yout << fileRef;
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001334
Nick Kledzik6b079f52013-01-05 02:22:35 +00001335 return error_code::success();
1336 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001337
Nick Kledzik6b079f52013-01-05 02:22:35 +00001338private:
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001339 const TargetInfo &_targetInfo;
Nick Kledzik6b079f52013-01-05 02:22:35 +00001340};
1341
Nick Kledzik6b079f52013-01-05 02:22:35 +00001342class ReaderYAML : public Reader {
1343public:
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001344 ReaderYAML(const TargetInfo &ti) : Reader(ti) {}
Nick Kledzik6b079f52013-01-05 02:22:35 +00001345
Michael J. Spencere6d56092013-04-05 22:04:44 +00001346 error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
Nick Kledzikc314b462013-04-04 18:59:24 +00001347 std::vector<std::unique_ptr<File>> &result) const {
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001348 // Note: we do not take ownership of the MemoryBuffer. That is
Nick Kledzik6b079f52013-01-05 02:22:35 +00001349 // because yaml may produce multiple File objects, so there is no
1350 // *one* File to take ownership. Therefore, the yaml File objects
1351 // produced must make copies of all strings that come from YAML I/O.
1352 // Otherwise the strings will become invalid when this MemoryBuffer
1353 // is deallocated.
1354
1355 // Create YAML Input parser.
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001356 ContextInfo context(_targetInfo);
Nick Kledzik6b079f52013-01-05 02:22:35 +00001357 llvm::yaml::Input yin(mb->getBuffer(), &context);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001358
Nick Kledzik6b079f52013-01-05 02:22:35 +00001359 // Fill vector with File objects created by parsing yaml.
1360 std::vector<const lld::File*> createdFiles;
1361 yin >> createdFiles;
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001362
Nick Kledzik6b079f52013-01-05 02:22:35 +00001363 // Quit now if there were parsing errors.
1364 if ( yin.error() )
1365 return make_error_code(lld::yaml_reader_error::illegal_value);
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001366
Nick Kledzik6b079f52013-01-05 02:22:35 +00001367 for (const File *file : createdFiles) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +00001368 // Note: parseFile() should return vector of *const* File
Nick Kledzik6b079f52013-01-05 02:22:35 +00001369 File *f = const_cast<File*>(file);
1370 result.emplace_back(f);
1371 }
1372 return make_error_code(lld::yaml_reader_error::success);
1373 }
Nick Kledzik6b079f52013-01-05 02:22:35 +00001374};
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001375} // end namespace yaml
Nick Kledzik6b079f52013-01-05 02:22:35 +00001376
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001377std::unique_ptr<Writer> createWriterYAML(const TargetInfo &ti) {
1378 return std::unique_ptr<Writer>(new lld::yaml::Writer(ti));
Nick Kledzik6b079f52013-01-05 02:22:35 +00001379}
1380
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001381std::unique_ptr<Reader> createReaderYAML(const TargetInfo &ti) {
1382 return std::unique_ptr<Reader>(new lld::yaml::ReaderYAML(ti));
Nick Kledzik6b079f52013-01-05 02:22:35 +00001383}
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001384} // end namespace lld