1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2006-2008 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
25 #ifndef __LTO_READER_H__
26 #define __LTO_READER_H__
29 #include <mach-o/dyld.h>
31 #include <ext/hash_set>
32 #include <ext/hash_map>
34 #include "MachOFileAbstraction.hpp"
35 #include "Architectures.hpp"
36 #include "ObjectFile.h"
39 #include "llvm-c/lto.h"
46 // Reference handles Atom references. These references facilitate
50 class Reference : public ObjectFile::Reference
53 Reference(const char* name) : fTargetName(name), fTargetAtom(NULL) { }
54 Reference(ObjectFile::Atom& atom) : fTargetName(NULL), fTargetAtom(&atom) { }
56 bool isTargetUnbound() const { return fTargetAtom == NULL; }
57 bool isFromTargetUnbound() const { return true; }
58 uint8_t getKind() const { return 0; }
59 uint64_t getFixUpOffset() const { return 0; }
60 const char * getTargetName() const { return fTargetName; }
61 ObjectFile::Atom& getTarget() const { return *fTargetAtom; }
62 uint64_t getTargetOffset() const { return 0; }
63 bool hasFromTarget() const { return false; }
64 ObjectFile::Atom& getFromTarget() const { return *((ObjectFile::Atom*)NULL); }
65 const char * getFromTargetName() const { return NULL; }
66 uint64_t getFromTargetOffset() const { return 0; }
67 TargetBinding getTargetBinding() const;
68 TargetBinding getFromTargetBinding() const { return kDontBind; }
69 void setTarget (ObjectFile::Atom& a, uint64_t offset)
71 void setFromTarget(ObjectFile::Atom &a) { }
72 const char * getDescription() const;
75 const char * fTargetName;
76 ObjectFile::Atom * fTargetAtom;
80 ObjectFile::Reference::TargetBinding Reference::getTargetBinding() const
82 if ( fTargetAtom == NULL )
83 return kUnboundByName;
84 else if ( fTargetName == NULL )
85 return kBoundDirectly;
90 const char* Reference::getDescription() const
92 static char temp[256];
93 strcpy(temp, "reference to ");
94 if ( fTargetName != NULL )
95 strcat(temp, fTargetName);
97 strcat(temp, fTargetAtom->getDisplayName());
102 class Segment : public ObjectFile::Segment
105 Segment(const char* name, bool readable, bool writable, bool executable, bool fixedAddress)
106 : fName(name), fReadable(readable), fWritable(writable), fExecutable(executable), fFixedAddress(fixedAddress) {}
107 virtual const char* getName() const { return fName; }
108 virtual bool isContentReadable() const { return fReadable; }
109 virtual bool isContentWritable() const { return fWritable; }
110 virtual bool isContentExecutable() const { return fExecutable; }
111 virtual bool hasFixedAddress() const { return fFixedAddress; }
113 static Segment fgBootstrapSegment;
117 const bool fReadable;
118 const bool fWritable;
119 const bool fExecutable;
120 const bool fFixedAddress;
123 Segment Segment:: fgBootstrapSegment("__TEMP", true, false, false, false);
129 // Atom acts as a proxy Atom for the symbols that are exported by LLVM bitcode file. Initially,
130 // Reader creates Atoms to allow linker proceed with usual symbol resolution phase. After
131 // optimization is performed, real Atoms are created for these symobls. However these real Atoms
132 // are not inserted into global symbol table. Atom holds real Atom and forwards appropriate
133 // methods to real atom.
135 class Atom : public ObjectFile::Atom
138 Atom(class Reader& owner, const char* name, Scope, DefinitionKind, uint8_t alignment, ObjectFile::Atom& internalAtom);
140 ObjectFile::Reader* getFile() const { return (ObjectFile::Reader*)&fOwner; }
141 bool getTranslationUnitSource (const char **dir, const char **name) const
142 { return fRealAtom->getTranslationUnitSource(dir, name); }
143 const char * getName () const { return fName; }
144 const char * getDisplayName() const { return this->getName(); }
145 Scope getScope() const { return fScope; }
146 DefinitionKind getDefinitionKind() const { return (fRealAtom ? fRealAtom->getDefinitionKind() : fKind); }
147 SymbolTableInclusion getSymbolTableInclusion() const
148 { return fRealAtom->getSymbolTableInclusion(); }
149 bool dontDeadStrip() const { return false; }
150 bool isZeroFill() const { return (fRealAtom ? fRealAtom->isZeroFill() : false); }
151 bool isThumb() const { return false; }
152 uint64_t getSize() const { return (fRealAtom ? fRealAtom->getSize() : 0); }
153 std::vector<ObjectFile::Reference*>& getReferences() const
154 { return (fRealAtom ? fRealAtom->getReferences() : (std::vector<ObjectFile::Reference*>&)fReferences); }
155 bool mustRemainInSection() const { return fRealAtom->mustRemainInSection(); }
156 const char * getSectionName() const { return (fRealAtom ? fRealAtom->getSectionName() : NULL); }
157 // Linker::optimize() sets section for this atom, not fRealAtom. Use this Atom's fSection.
158 class ObjectFile::Section * getSection() const { return fSection; }
159 ObjectFile::Segment& getSegment() const { return (fRealAtom ? fRealAtom->getSegment() : Segment::fgBootstrapSegment); }
160 uint32_t getOrdinal() const { return (fRealAtom ? fRealAtom->getOrdinal() : 0); }
161 ObjectFile::Atom& getFollowOnAtom() const { return fRealAtom->getFollowOnAtom(); }
162 std::vector<ObjectFile::LineInfo>* getLineInfo() const { return (fRealAtom ? fRealAtom->getLineInfo() : NULL); }
163 ObjectFile::Alignment getAlignment() const { return (fRealAtom ? fRealAtom->getAlignment() : ObjectFile::Alignment(fAlignment)); }
164 void copyRawContent(uint8_t buffer[]) const
165 { if (fRealAtom) fRealAtom->copyRawContent(buffer); }
166 void setScope(Scope s) { if (fRealAtom) fRealAtom->setScope(s); else fScope = s; }
168 void setRealAtom (ObjectFile::Atom *atom)
169 { fRealAtom = atom; }
170 ObjectFile::Atom * getRealAtom() { return fRealAtom; }
171 void addReference(ObjectFile::Reference *ref)
172 { fReferences.push_back(ref); }
174 void setSectionOffset(uint64_t offset) { fSectionOffset = offset; if (fRealAtom) fRealAtom->setSectionOffset(offset); }
175 void setSection(class ObjectFile::Section* sect) { fSection = sect; if (fRealAtom) fRealAtom->setSection(sect); }
178 class Reader& fOwner;
180 ObjectFile::Atom::Scope fScope;
181 ObjectFile::Atom::DefinitionKind fKind;
183 ObjectFile::Atom* fRealAtom;
184 std::vector<ObjectFile::Reference*> fReferences;
188 Atom::Atom(class Reader& owner, const char* name, Scope scope, DefinitionKind kind, uint8_t alignment, ObjectFile::Atom& internalAtom)
189 : fOwner(owner), fName(name), fScope(scope), fKind(kind), fAlignment(alignment), fRealAtom(NULL)
191 // every Atom references the InternalAtom for its reader
192 fReferences.push_back(new Reference(internalAtom));
197 // ld64 only tracks non-internal symbols from an llvm bitcode file.
198 // We model this by having an InternalAtom which represent all internal functions and data.
199 // All non-interal symbols from a bitcode file are represented by a Atom
200 // and each Atom has a reference to the InternalAtom. The InternalAtom
201 // also has references to each symbol external to the bitcode file.
203 class InternalAtom : public ObjectFile::Atom
206 InternalAtom(class Reader& owner) : fOwner(owner) {}
208 ObjectFile::Reader * getFile() const { return (ObjectFile::Reader*)&fOwner; }
209 bool getTranslationUnitSource (const char **dir, const char **name) const
211 const char * getName () const { return "__llvm-internal-atom"; }
212 const char * getDisplayName() const { return this->getName(); }
213 Scope getScope() const { return scopeTranslationUnit; }
214 DefinitionKind getDefinitionKind() const { return kRegularDefinition; }
215 SymbolTableInclusion getSymbolTableInclusion() const { return kSymbolTableNotIn; }
216 bool dontDeadStrip() const { return false; }
217 bool isZeroFill() const { return false; }
218 bool isThumb() const { return false; }
219 uint64_t getSize() const { return 0; }
220 std::vector<ObjectFile::Reference*>& getReferences() const { return (std::vector<ObjectFile::Reference*>&)fReferences; }
221 bool mustRemainInSection() const { return false; }
222 const char * getSectionName() const { return NULL; }
223 class ObjectFile::Section * getSection() const { return NULL; }
224 ObjectFile::Segment& getSegment() const { return Segment::fgBootstrapSegment; }
225 uint32_t getOrdinal() const { return 0; }
226 ObjectFile::Atom& getFollowOnAtom() const { return *((ObjectFile::Atom*)NULL); }
227 std::vector<ObjectFile::LineInfo>* getLineInfo() const { return NULL; }
228 ObjectFile::Alignment getAlignment() const { return ObjectFile::Alignment(0); }
229 void copyRawContent(uint8_t buffer[]) const { }
230 void setScope(Scope s) { }
232 void addReference(const char* targetName);
235 class Reader& fOwner;
236 std::vector<ObjectFile::Reference*> fReferences;
240 void InternalAtom::addReference(const char* name)
242 fReferences.push_back(new Reference(name));
251 RemovableAtoms(std::set<ObjectFile::Atom*>& iAtoms) : fAtoms(iAtoms) {}
253 bool operator()(ObjectFile::Atom*& atom) const {
254 return ( fAtoms.count(atom) != 0 );
258 std::set<ObjectFile::Atom*>& fAtoms;
264 // LLVM bitcode file reader
266 class Reader : public ObjectFile::Reader
269 static bool validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture);
270 static bool loaded() { return (::lto_get_version() != NULL); }
271 Reader(const uint8_t* fileContent, uint64_t fileLength,
272 const char* path, time_t modTime,
273 const ObjectFile::ReaderOptions&, cpu_type_t arch);
276 virtual std::vector<class ObjectFile::Atom*>& getAtoms() { return (std::vector<class ObjectFile::Atom*>&)(fAtoms); }
277 virtual std::vector<class ObjectFile::Atom*>* getJustInTimeAtomsFor(const char* name) { return NULL; }
278 virtual const char* getPath() { return fPath; }
279 virtual time_t getModificationTime() { return fModTime; }
280 virtual ObjectFile::Reader::DebugInfoKind getDebugInfoKind() { return kDebugInfoNone; }
281 virtual std::vector<Stab>* getStabs() { return NULL; }
282 virtual void optimize(std::vector<ObjectFile::Atom*> &allAtoms, std::vector<ObjectFile::Atom*> &newAtoms,
283 std::vector<const char*> &additionalUndefines, uint32_t nextInputOrdinal,
284 ObjectFile::Reader* writer, bool allGlobalsAReDeadStripRoots,
285 int outputKind, bool verbose, bool saveTemps, const char* outputFilePath,
286 bool pie, bool allowTextRelocs);
293 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
295 typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals> CStringSet;
296 typedef __gnu_cxx::hash_map<const char*, Atom*, __gnu_cxx::hash<const char*>, CStringEquals> CStringToAtom;
298 ObjectFile::Reader* makeMachOReader(const uint8_t* p, size_t len, uint32_t nextInputOrdinal);
299 static const char* tripletPrefixForArch(cpu_type_t);
301 cpu_type_t fArchitecture;
304 lto_module_t fModule;
305 std::vector<ObjectFile::Atom*> fAtoms;
306 InternalAtom fInternalAtom;
307 const ObjectFile::ReaderOptions& fReaderOptions;
308 static std::set<Reader*> fgReaders;
309 static bool fgOptimized;
312 bool Reader::fgOptimized = false;
313 std::set<Reader*> Reader::fgReaders;
318 if ( fModule != NULL )
319 ::lto_module_dispose(fModule);
322 Reader::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime,
323 const ObjectFile::ReaderOptions& options, cpu_type_t arch)
324 : fArchitecture(arch), fPath(path), fModTime(modTime), fInternalAtom(*this), fReaderOptions(options)
326 fgReaders.insert(this);
328 fModule = ::lto_module_create_from_memory(fileContent, fileLength);
329 if ( fModule == NULL )
330 throwf("could not parse object file %s: %s", path, lto_get_error_message());
333 uint32_t count = ::lto_module_get_num_symbols(fModule);
334 for (uint32_t i=0; i < count; ++i) {
335 const char* name = ::lto_module_get_symbol_name(fModule, i);
336 lto_symbol_attributes attr = lto_module_get_symbol_attribute(fModule, i);
338 ObjectFile::Atom::DefinitionKind kind;
339 switch ( attr & LTO_SYMBOL_DEFINITION_MASK ) {
340 case LTO_SYMBOL_DEFINITION_REGULAR:
341 kind = ObjectFile::Atom::kRegularDefinition;
343 case LTO_SYMBOL_DEFINITION_TENTATIVE:
344 kind = ObjectFile::Atom::kTentativeDefinition;
346 case LTO_SYMBOL_DEFINITION_WEAK:
347 kind = ObjectFile::Atom::kWeakDefinition;
349 case LTO_SYMBOL_DEFINITION_UNDEFINED:
350 kind = ObjectFile::Atom::kExternalDefinition;
353 throwf("unknown definition kind for symbol %s in bitcode file %s", name, path);
356 // make LLVM atoms for definitions and a reference for undefines
357 if ( kind != ObjectFile::Atom::kExternalDefinition ) {
358 ObjectFile::Atom::Scope scope;
359 switch ( attr & LTO_SYMBOL_SCOPE_MASK) {
360 case LTO_SYMBOL_SCOPE_INTERNAL:
361 scope = ObjectFile::Atom::scopeTranslationUnit;
363 case LTO_SYMBOL_SCOPE_HIDDEN:
364 scope = ObjectFile::Atom::scopeLinkageUnit;
366 case LTO_SYMBOL_SCOPE_DEFAULT:
367 scope = ObjectFile::Atom::scopeGlobal;
370 throwf("unknown scope for symbol %s in bitcode file %s", name, path);
372 // only make atoms for non-internal symbols
373 if ( scope == ObjectFile::Atom::scopeTranslationUnit )
375 uint8_t alignment = (attr & LTO_SYMBOL_ALIGNMENT_MASK);
377 fAtoms.push_back(new Atom(*this, name, scope, kind, alignment, fInternalAtom));
380 // add to list of external references
381 fInternalAtom.addReference(name);
386 const char* Reader::tripletPrefixForArch(cpu_type_t arch)
389 case CPU_TYPE_POWERPC:
391 case CPU_TYPE_POWERPC64:
395 case CPU_TYPE_X86_64:
403 bool Reader::validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture)
405 return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, tripletPrefixForArch(architecture));
408 void Reader::optimize(std::vector<ObjectFile::Atom *>& allAtoms, std::vector<ObjectFile::Atom*>& newAtoms,
409 std::vector<const char*>& additionalUndefines, uint32_t nextInputOrdinal,
410 ObjectFile::Reader* writer, bool allGlobalsAReDeadStripRoots,
411 int okind, bool verbose, bool saveTemps, const char* outputFilePath,
412 bool pie, bool allowTextRelocs)
414 // this method is call on all Readers. We want the first call to trigger optimization
415 // across all Readers and the subsequent calls to do nothing.
420 Options::OutputKind outputKind = (Options::OutputKind)okind; // HACK to work around upward dependency
422 // print out LTO version string if -v was used
424 fprintf(stderr, "%s\n", lto_get_version());
426 // create optimizer and add each Reader
427 lto_code_gen_t generator = ::lto_codegen_create();
428 for (std::set<Reader*>::iterator it=fgReaders.begin(); it != fgReaders.end(); ++it) {
429 if ( ::lto_codegen_add_module(generator, (*it)->fModule) )
430 throwf("lto: could not merge in %s", (*it)->fPath);
433 // the linker must preserve all globals in dylibs and flat images
434 const bool globalsNeedPreserving = allGlobalsAReDeadStripRoots || fReaderOptions.fFlatNamespace;
436 // The atom graph uses directed edges (references). Collect all references where
437 // originating atom is not part of any LTO Reader. This allows optimizer to optimize an
438 // external (i.e. not originated from same .o file) reference if all originating atoms are also
439 // defined in llvm bitcode file.
440 CStringSet nonLLVMRefs;
441 CStringToAtom llvmAtoms;
442 bool hasNonllvmAtoms = false;
443 for (std::vector<ObjectFile::Atom*>::iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) {
444 ObjectFile::Atom* atom = *it;
445 // only look at references come from an atom that is not an llvm atom
446 if ( fgReaders.count((Reader*)(atom->getFile())) == 0 ) {
447 // remember if we've seen an atoms not from an llvm reader and not from the writer
448 if ( atom->getFile() != writer )
449 hasNonllvmAtoms = true;
450 std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
451 for (std::vector<ObjectFile::Reference*>::iterator ri=refs.begin(), re=refs.end(); ri != re; ++ri) {
452 ObjectFile::Reference* ref = *ri;
453 // add target name to set if target is an llvm atom
454 if ( (ref->getTargetName() != NULL) && (fgReaders.count((Reader*)(ref->getTarget().getFile())) != 0) ) {
455 nonLLVMRefs.insert(ref->getTargetName());
460 const char* name = atom->getName();
462 llvmAtoms[name] = (Atom*)atom;
465 // tell code generator about symbols that must be preserved
466 for (CStringToAtom::iterator it = llvmAtoms.begin(); it != llvmAtoms.end(); ++it) {
467 const char* name = it->first;
468 Atom* atom = it->second;
469 // Include llvm Symbol in export list if it meets one of following two conditions
470 // 1 - globals need preserving and atom scope is global (and not linkage unit).
471 // 2 - included in nonLLVMRefs set.
472 // If a symbol is not listed in exportList then LTO is free to optimize it away.
473 if ( globalsNeedPreserving && (atom->getScope() == ObjectFile::Atom::scopeGlobal) )
474 ::lto_codegen_add_must_preserve_symbol(generator, name);
475 else if ( nonLLVMRefs.find(name) != nonLLVMRefs.end() )
476 ::lto_codegen_add_must_preserve_symbol(generator, name);
479 // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o)
480 if ( (outputKind == Options::kObjectFile) && !hasNonllvmAtoms ) {
481 if ( ! ::lto_codegen_write_merged_modules(generator, outputFilePath) ) {
482 // HACK, no good way to tell linker we are all done, so just quit
485 warning("could not produce merged bitcode file");
488 // if requested, save off merged bitcode file
490 char tempBitcodePath[MAXPATHLEN];
491 strcpy(tempBitcodePath, outputFilePath);
492 strcat(tempBitcodePath, ".lto.bc");
493 ::lto_codegen_write_merged_modules(generator, tempBitcodePath);
496 // set code-gen model
497 lto_codegen_model model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
498 switch ( outputKind ) {
499 case Options::kDynamicExecutable:
501 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
503 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
505 case Options::kDynamicLibrary:
506 case Options::kDynamicBundle:
507 case Options::kObjectFile: // ?? Is this appropriate ?
509 if ( allowTextRelocs )
510 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
512 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
514 case Options::kStaticExecutable:
515 model = LTO_CODEGEN_PIC_MODEL_STATIC;
518 if ( ::lto_codegen_set_pic_model(generator, model) )
519 throwf("could not create set codegen model: %s", lto_get_error_message());
521 // run code generator
523 const uint8_t* machOFile = (uint8_t*)::lto_codegen_compile(generator, &machOFileLen);
524 if ( machOFile == NULL )
525 throwf("could not do LTO codegen: %s", ::lto_get_error_message());
527 // if requested, save off temp mach-o file
529 char tempMachoPath[MAXPATHLEN];
530 strcpy(tempMachoPath, outputFilePath);
531 strcat(tempMachoPath, ".lto.o");
532 int fd = ::open(tempMachoPath, O_CREAT | O_WRONLY | O_TRUNC, 0666);
534 ::write(fd, machOFile, machOFileLen);
539 // parse generated mach-o file into a MachOReader
540 ObjectFile::Reader* machoReader = this->makeMachOReader(machOFile, machOFileLen, nextInputOrdinal);
542 // sync generated mach-o atoms with existing atoms ld know about
543 std::vector<ObjectFile::Atom*> machoAtoms = machoReader->getAtoms();
544 for (std::vector<ObjectFile::Atom *>::iterator it = machoAtoms.begin(); it != machoAtoms.end(); ++it) {
545 ObjectFile::Atom* atom = *it;
546 const char* name = atom->getName();
547 if ( name != NULL ) {
548 CStringToAtom::iterator pos = llvmAtoms.find(name);
549 if ( pos != llvmAtoms.end() ) {
550 // turn Atom into a proxy for this mach-o atom
551 pos->second->setRealAtom(atom);
554 // this atom is did not exist orginally, tell ld about it
555 newAtoms.push_back(atom);
559 // ld only knew about named atoms, so this one must be new
560 newAtoms.push_back(atom);
562 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
563 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); ++rit) {
564 ObjectFile::Reference* ref = *rit;
565 const char* targetName = ref->getTargetName();
566 CStringToAtom::iterator pos;
567 if (targetName != NULL) {
568 switch ( ref->getTargetBinding() ) {
569 case ObjectFile::Reference::kUnboundByName:
570 // accumulate unbounded references so that ld can bound them.
571 additionalUndefines.push_back(targetName);
573 case ObjectFile::Reference::kBoundDirectly:
574 case ObjectFile::Reference::kBoundByName:
575 // If mach-o atom is referencing another mach-o atom then
576 // reference is not going through Atom proxy. Fix it here to ensure that all
577 // llvm symbol references always go through Atom proxy.
578 pos = llvmAtoms.find(targetName);
579 if ( pos != llvmAtoms.end() )
580 ref->setTarget(*pos->second, ref->getTargetOffset());
582 case ObjectFile::Reference::kDontBind:
589 // Remove InternalAtoms from ld
590 std::set<class ObjectFile::Atom*> deletedAtoms;
591 for (std::set<Reader*>::iterator it=fgReaders.begin(); it != fgReaders.end(); ++it) {
592 deletedAtoms.insert(&((*it)->fInternalAtom));
594 // Remove Atoms from ld if code generator optimized them away
595 for (CStringToAtom::iterator li = llvmAtoms.begin(), le = llvmAtoms.end(); li != le; ++li) {
596 // check if setRealAtom() called on this Atom
597 if ( li->second->getRealAtom() == NULL )
598 deletedAtoms.insert(li->second);
600 allAtoms.erase(std::remove_if(allAtoms.begin(), allAtoms.end(), RemovableAtoms(deletedAtoms)), allAtoms.end());
604 ObjectFile::Reader* Reader::makeMachOReader(const uint8_t* p, size_t len, uint32_t nextInputOrdinal)
606 switch ( fArchitecture ) {
607 case CPU_TYPE_POWERPC:
608 if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
609 return new mach_o::relocatable::Reader<ppc>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
611 case CPU_TYPE_POWERPC64:
612 if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
613 return new mach_o::relocatable::Reader<ppc64>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
616 if ( mach_o::relocatable::Reader<x86>::validFile(p) )
617 return new mach_o::relocatable::Reader<x86>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
619 case CPU_TYPE_X86_64:
620 if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
621 return new mach_o::relocatable::Reader<x86_64>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
624 if ( mach_o::relocatable::Reader<arm>::validFile(p) )
625 return new mach_o::relocatable::Reader<arm>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
628 throw "LLVM LTO, file is not of required architecture";
634 void printLTOVersion(Options &opts) {
635 const char* vers = lto_get_version();
637 fprintf(stderr, "%s\n", vers);