]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/LTOReader.hpp
ld64-123.2.tar.gz
[apple/ld64.git] / src / ld / LTOReader.hpp
diff --git a/src/ld/LTOReader.hpp b/src/ld/LTOReader.hpp
deleted file mode 100644 (file)
index 2e560cc..0000000
+++ /dev/null
@@ -1,742 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
- *
- * Copyright (c) 2006-2009 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __LTO_READER_H__
-#define __LTO_READER_H__
-
-#include <stdlib.h>
-#include <mach-o/dyld.h>
-#include <vector>
-#include <ext/hash_set>
-#include <ext/hash_map>
-
-#include "MachOFileAbstraction.hpp"
-#include "Architectures.hpp"
-#include "ObjectFile.h"
-#include "Options.h"
-
-#include "llvm-c/lto.h"
-
-
-namespace lto {
-
-
-//
-// Reference handles Atom references. These references facilitate 
-// symbol resolution.
-//
-
-class Reference : public ObjectFile::Reference
-{
-public:
-                                                                               Reference(const char* name) : fTargetName(name), fTargetAtom(NULL) { }
-                                                                               Reference(ObjectFile::Atom& atom) : fTargetName(NULL), fTargetAtom(&atom) { }
-
-       bool                                                            isTargetUnbound() const                         { return fTargetAtom == NULL; }
-       bool                                                            isFromTargetUnbound() const             { return true; }
-       uint8_t                                                         getKind() const                                         { return 0; }
-       uint64_t                                                        getFixUpOffset() const                          { return 0; }
-       const char *                                            getTargetName() const                           { return fTargetName; }
-       ObjectFile::Atom&                                       getTarget() const                                       { return *fTargetAtom; }
-       uint64_t                                                        getTargetOffset() const                         { return 0; }
-       bool                                                            hasFromTarget() const                           { return false; }
-       ObjectFile::Atom&                                       getFromTarget() const                           { return *((ObjectFile::Atom*)NULL); }
-       const char *                                            getFromTargetName() const                       { return NULL; }
-       uint64_t                                                        getFromTargetOffset() const             { return 0; }
-       TargetBinding                                           getTargetBinding() const;
-       TargetBinding                                           getFromTargetBinding() const  { return kDontBind; }
-       void                                                            setTarget (ObjectFile::Atom& a, uint64_t offset) 
-                                                                               { fTargetAtom = &a; }
-       void                                                            setFromTarget(ObjectFile::Atom &a)      { }
-       const char *                                            getDescription() const;
-
-private:
-       const char *                                            fTargetName;
-       ObjectFile::Atom *                                      fTargetAtom;
-};
-
-
-ObjectFile::Reference::TargetBinding Reference::getTargetBinding() const 
-{ 
-       if ( fTargetAtom == NULL ) 
-               return kUnboundByName;
-       else if ( fTargetName == NULL ) 
-               return kBoundDirectly;
-       else
-               return kBoundByName;
-}
-
-const char* Reference::getDescription() const
-{ 
-       static char temp[256];
-       strcpy(temp, "reference to ");
-       if ( fTargetName != NULL )
-               strcat(temp, fTargetName);
-       else
-               strcat(temp, fTargetAtom->getDisplayName());
-       return temp; 
-}
-
-
-class Segment : public ObjectFile::Segment
-{
-public:
-                                                                               Segment(const char* name, bool readable, bool writable, bool executable, bool fixedAddress)
-                                                                                       : fName(name), fReadable(readable), fWritable(writable), fExecutable(executable), fFixedAddress(fixedAddress) {}
-       virtual const char*                                     getName() const                                         { return fName; }
-       virtual bool                                            isContentReadable() const                       { return fReadable; }
-       virtual bool                                            isContentWritable() const                       { return fWritable; }
-       virtual bool                                            isContentExecutable() const                     { return fExecutable; }
-       virtual bool                                            hasFixedAddress() const                         { return fFixedAddress; }
-
-       static Segment                                          fgBootstrapSegment;
-
-private:
-       const char*                                                     fName;
-       const bool                                                      fReadable;
-       const bool                                                      fWritable;
-       const bool                                                      fExecutable;
-       const bool                                                      fFixedAddress;
-};
-
-Segment        Segment:: fgBootstrapSegment("__TEMP", true, false, false, false);
-  
-       
-         
-
-//
-// Atom acts as a proxy Atom for the symbols that are exported by LLVM bitcode file. Initially,
-// Reader creates Atoms to allow linker proceed with usual symbol resolution phase. After
-// optimization is performed, real Atoms are created for these symobls. However these real Atoms
-// are not inserted into global symbol table. Atom holds real Atom and forwards appropriate
-// methods to real atom.
-//
-class Atom : public ObjectFile::Atom
-{
-public:
-                                                                                               Atom(class Reader& owner, const char* name, Scope, DefinitionKind, uint8_t alignment, ObjectFile::Atom& internalAtom);
-       
-       ObjectFile::Reader*                                                     getFile() const                         { return (ObjectFile::Reader*)&fOwner; }
-       bool                                                                            getTranslationUnitSource (const char **dir, const char **name) const 
-                                                                                                                                                       { return fRealAtom->getTranslationUnitSource(dir, name); }
-       const char *                                                            getName () const                        { return fName; }
-       const char *                                                            getDisplayName() const          { return this->getName(); }
-       Scope                                                                           getScope() const                        { return (fRealAtom ? fRealAtom->getScope() : fScope); }
-       DefinitionKind                                                          getDefinitionKind() const       { return (fRealAtom ? fRealAtom->getDefinitionKind() : fKind); }
-       SymbolTableInclusion                                            getSymbolTableInclusion() const 
-                                                                                                                                                       { return (fRealAtom ? fRealAtom->getSymbolTableInclusion() : ObjectFile::Atom::kSymbolTableIn); }
-       bool                                                                            dontDeadStrip() const           { return false; }
-       bool                                                                            isZeroFill() const                      { return (fRealAtom ? fRealAtom->isZeroFill() : false); }
-       bool                                                                            isThumb() const                         { return false; }
-       uint64_t                                                                        getSize() const                         { return (fRealAtom ? fRealAtom->getSize() : 0); }
-       std::vector<ObjectFile::Reference*>&            getReferences() const 
-                                                                                                                                                       { return (fRealAtom ? fRealAtom->getReferences() : (std::vector<ObjectFile::Reference*>&)fReferences); }
-       bool                                                                            mustRemainInSection() const { return fRealAtom->mustRemainInSection(); }
-       const char *                                                            getSectionName() const          { return (fRealAtom ? fRealAtom->getSectionName() : NULL); }
-       // Linker::optimize() sets section for this atom, not fRealAtom. Use this Atom's fSection.
-       class ObjectFile::Section *                                     getSection() const                      { return fSection; }
-       ObjectFile::Segment&                                            getSegment() const                      { return (fRealAtom ? fRealAtom->getSegment() : Segment::fgBootstrapSegment); }
-       uint32_t                                                                        getOrdinal() const                      { return (fRealAtom ? fRealAtom->getOrdinal() : 0); }
-       ObjectFile::Atom&                                                       getFollowOnAtom() const         { return fRealAtom->getFollowOnAtom(); }
-       std::vector<ObjectFile::LineInfo>*                      getLineInfo() const             { return (fRealAtom ? fRealAtom->getLineInfo() : NULL); }
-       ObjectFile::Alignment                                           getAlignment() const            { return (fRealAtom ? fRealAtom->getAlignment() : ObjectFile::Alignment(fAlignment)); }
-       void                                                                            copyRawContent(uint8_t buffer[]) const 
-                                                                                                                                                       { if (fRealAtom) fRealAtom->copyRawContent(buffer); }
-       void                                                                            setScope(Scope s)                       { if (fRealAtom) fRealAtom->setScope(s); else fScope = s; }
-
-       void                                                                            setRealAtom (ObjectFile::Atom *atom) 
-                                                                                                                                                       { fRealAtom = atom; }
-       ObjectFile::Atom *                                                      getRealAtom() { return fRealAtom; }
-       void                                                                            addReference(ObjectFile::Reference *ref) 
-                                                                                                                                                       { fReferences.push_back(ref); }
-
-       void                                                                            setSectionOffset(uint64_t offset) { fSectionOffset = offset; if (fRealAtom) fRealAtom->setSectionOffset(offset); }
-       void                                                                            setSection(class ObjectFile::Section* sect) { fSection = sect; if (fRealAtom) fRealAtom->setSection(sect); }
-                                                                                                                                                       
-private:
-       class Reader&                                                           fOwner;
-       const char*                                                                     fName;
-       ObjectFile::Atom::Scope                                         fScope;
-       ObjectFile::Atom::DefinitionKind                        fKind;
-       uint8_t                                                                         fAlignment;
-       ObjectFile::Atom*                                                       fRealAtom;
-       std::vector<ObjectFile::Reference*>             fReferences;
-};
-
-
-Atom::Atom(class Reader& owner, const char* name, Scope scope, DefinitionKind kind, uint8_t alignment, ObjectFile::Atom& internalAtom) 
-: fOwner(owner), fName(name), fScope(scope), fKind(kind), fAlignment(alignment), fRealAtom(NULL)
-{
-       // every Atom references the InternalAtom for its reader
-       fReferences.push_back(new Reference(internalAtom));
-}
-
-
-//
-// ld64 only tracks non-internal symbols from an llvm bitcode file.  
-// We model this by having an InternalAtom which represent all internal functions and data.
-// All non-interal symbols from a bitcode file are represented by a Atom
-// and each Atom has a reference to the InternalAtom.  The InternalAtom
-// also has references to each symbol external to the bitcode file. 
-//
-class InternalAtom : public ObjectFile::Atom
-{
-public:
-                                                                                               InternalAtom(class Reader& owner) : fOwner(owner) {}
-
-       ObjectFile::Reader *                                            getFile() const                         { return (ObjectFile::Reader*)&fOwner; }
-       bool                                                                            getTranslationUnitSource (const char **dir, const char **name) const 
-                                                                                                                                                       { return false; }
-       const char *                                                            getName () const                        { return "__llvm-internal-atom";        }
-       const char *                                                            getDisplayName() const          { return "llvm bitcode"; }
-       Scope                                                                           getScope() const                        { return scopeTranslationUnit; }
-       DefinitionKind                                                          getDefinitionKind() const   { return kRegularDefinition; }
-       SymbolTableInclusion                                            getSymbolTableInclusion() const { return kSymbolTableNotIn; }
-       bool                                                                            dontDeadStrip() const           { return false; }
-       bool                                                                            isZeroFill() const                      { return false; }
-       bool                                                                            isThumb() const                         { return false; }
-       uint64_t                                                                        getSize() const                         { return 0; }
-       std::vector<ObjectFile::Reference*>&            getReferences() const           { return  (std::vector<ObjectFile::Reference*>&)fReferences; }
-       bool                                                                            mustRemainInSection() const { return false; }
-       const char *                                                            getSectionName() const          { return NULL; }
-       class ObjectFile::Section *                                     getSection() const                      { return NULL; }
-       ObjectFile::Segment&                                            getSegment() const                      { return Segment::fgBootstrapSegment; }
-       uint32_t                                                                        getOrdinal() const          { return 0; }
-       ObjectFile::Atom&                                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
-       std::vector<ObjectFile::LineInfo>*                      getLineInfo() const             { return NULL; }
-       ObjectFile::Alignment                                           getAlignment() const            { return ObjectFile::Alignment(0); }
-       void                                                                            copyRawContent(uint8_t buffer[]) const { }
-       void                                                                            setScope(Scope s)                       { }
-
-       void                                                                            addReference(const char* targetName);
-       
-private:
-       class Reader&                                                           fOwner;
-       std::vector<ObjectFile::Reference*>             fReferences;
-};
-
-
-void InternalAtom::addReference(const char* name)
-{
-       fReferences.push_back(new Reference(name));
-}
-
-
-
-
-class RemovableAtoms
-{
-public:
-       RemovableAtoms(std::set<ObjectFile::Atom*>& iAtoms) : fAtoms(iAtoms) {}
-
-       bool operator()(ObjectFile::Atom*& atom) const {
-               return ( fAtoms.count(atom) != 0 );
-       }
-
-private:
-       std::set<ObjectFile::Atom*>& fAtoms;
-};
-
-
-
-//
-// LLVM bitcode file reader
-//
-class Reader : public ObjectFile::Reader
-{
-public:
-       static bool                                                                             validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture);
-       static const char*                                                              fileKind(const uint8_t* fileContent);
-       static bool                                                                             loaded() { return (::lto_get_version() != NULL); }
-                                                                                                       Reader(const uint8_t* fileContent, uint64_t fileLength, 
-                                                                                                                               const char* path, time_t modTime, 
-                                                                                                                               const ObjectFile::ReaderOptions&, cpu_type_t arch);
-       virtual                                                                                 ~Reader();
-       
-       virtual std::vector<class ObjectFile::Atom*>&   getAtoms()                              { return (std::vector<class ObjectFile::Atom*>&)(fAtoms); }
-       virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) { return NULL; }
-       virtual const char*                                                             getPath()                               { return fPath; }
-       virtual time_t                                                                  getModificationTime()   { return fModTime; }
-       virtual ObjectFile::Reader::DebugInfoKind               getDebugInfoKind()              { return kDebugInfoNone; }
-       virtual std::vector<Stab>*                                              getStabs()                              { return NULL; }
-       virtual bool                                                                    optimize(const std::vector<ObjectFile::Atom*>& allAtoms, std::vector<ObjectFile::Atom*>& newAtoms, 
-                                                                                                                               std::vector<const char*>& additionalUndefines, const std::set<ObjectFile::Atom*>&,
-                                                                                                                               std::vector<ObjectFile::Atom*>& newDeadAtoms,
-                                                                                                                               uint32_t nextInputOrdinal, 
-                                                                                                                               ObjectFile::Reader* writer, ObjectFile::Atom* entryPointAtom,
-                                                                                                                               const std::vector<const char*>& llvmOptions,
-                                                                                                                               bool allGlobalsAReDeadStripRoots,
-                                                                                                                               int outputKind, bool verbose, bool saveTemps, const char* outputFilePath,
-                                                                                                                               bool pie, bool allowTextRelocs);
-
-private:
-
-       class CStringEquals
-       {
-       public:
-               bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
-       };
-       typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals>  CStringSet;
-       typedef __gnu_cxx::hash_map<const char*, Atom*, __gnu_cxx::hash<const char*>, CStringEquals> CStringToAtom;
-       
-       ObjectFile::Reader*                                                             makeMachOReader(const uint8_t* p, size_t len, uint32_t nextInputOrdinal);
-       static const char*                                                              tripletPrefixForArch(cpu_type_t);
-
-       cpu_type_t                                                                              fArchitecture;
-       const char*                                                                             fPath;
-       time_t                                                                                  fModTime;
-       lto_module_t                                                                    fModule;
-       std::vector<ObjectFile::Atom*>                                  fAtoms;
-       InternalAtom                                                                    fInternalAtom;
-       const ObjectFile::ReaderOptions&                                fReaderOptions;
-       static std::set<Reader*>                                                fgReaders;
-       static bool                                                                             fgOptimized;
-};
-
-bool                                   Reader::fgOptimized = false;
-std::set<Reader*>              Reader::fgReaders;
-
-
-Reader::~Reader()
-{
-       if ( fModule != NULL )
-               ::lto_module_dispose(fModule);
-}
-
-Reader::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, 
-                               const ObjectFile::ReaderOptions& options, cpu_type_t arch)
-       : fArchitecture(arch), fPath(strdup(path)), fModTime(modTime), fInternalAtom(*this), fReaderOptions(options)
-{
-       fgReaders.insert(this);
-
-       fModule = ::lto_module_create_from_memory(fileContent, fileLength);
-    if ( fModule == NULL )
-               throwf("could not parse object file %s: %s", path, lto_get_error_message());
-       
-       fAtoms.push_back(&fInternalAtom);
-       
-       uint32_t count = ::lto_module_get_num_symbols(fModule);
-       for (uint32_t i=0; i < count; ++i) {
-               const char* name = ::lto_module_get_symbol_name(fModule, i);
-               lto_symbol_attributes attr = lto_module_get_symbol_attribute(fModule, i);
-
-               // <rdar://problem/6378110> LTO doesn't like dtrace symbols
-               // ignore dtrace static probes for now
-               // later when codegen is done and a mach-o file is produces the probes will be processed
-               if ( (strncmp(name, "___dtrace_probe$", 16) == 0) || (strncmp(name, "___dtrace_isenabled$", 20) == 0) )
-                       continue;
-                               
-               ObjectFile::Atom::DefinitionKind kind;
-               switch ( attr & LTO_SYMBOL_DEFINITION_MASK ) {
-                       case LTO_SYMBOL_DEFINITION_REGULAR:
-                               kind = ObjectFile::Atom::kRegularDefinition;
-                               break;
-                       case LTO_SYMBOL_DEFINITION_TENTATIVE:
-                               kind = ObjectFile::Atom::kTentativeDefinition;
-                               break;
-                       case LTO_SYMBOL_DEFINITION_WEAK:
-                               kind = ObjectFile::Atom::kWeakDefinition;
-                               break;
-                       case LTO_SYMBOL_DEFINITION_UNDEFINED:
-                       case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
-                               kind = ObjectFile::Atom::kExternalDefinition;
-                               break;
-                       default:
-                               throwf("unknown definition kind for symbol %s in bitcode file %s", name, path);
-               }
-
-               // make LLVM atoms for definitions and a reference for undefines
-               if ( kind != ObjectFile::Atom::kExternalDefinition ) {
-                       ObjectFile::Atom::Scope scope;
-                       switch ( attr & LTO_SYMBOL_SCOPE_MASK) {
-                               case LTO_SYMBOL_SCOPE_INTERNAL:
-                                       scope = ObjectFile::Atom::scopeTranslationUnit;
-                                       break;
-                               case LTO_SYMBOL_SCOPE_HIDDEN:
-                                       scope = ObjectFile::Atom::scopeLinkageUnit;
-                                       break;
-                               case LTO_SYMBOL_SCOPE_DEFAULT:
-                                       scope = ObjectFile::Atom::scopeGlobal;
-                                       break;
-                               default:
-                                       throwf("unknown scope for symbol %s in bitcode file %s", name, path);
-                       }
-                       // only make atoms for non-internal symbols 
-                       if ( scope == ObjectFile::Atom::scopeTranslationUnit )
-                               continue;
-                       uint8_t alignment = (attr & LTO_SYMBOL_ALIGNMENT_MASK);
-                       // make Atom
-                       fAtoms.push_back(new Atom(*this, name, scope, kind, alignment, fInternalAtom));
-               }
-               else {
-                       // add to list of external references
-                       fInternalAtom.addReference(name);
-               }
-       }
-}
-
-const char* Reader::tripletPrefixForArch(cpu_type_t arch)
-{
-       switch (arch) {
-               case CPU_TYPE_POWERPC:
-                       return "powerpc-";
-               case CPU_TYPE_POWERPC64:
-                       return "powerpc64-";
-               case CPU_TYPE_I386:
-                       return "i386-";
-               case CPU_TYPE_X86_64:
-                       return "x86_64-";
-               case CPU_TYPE_ARM:
-                       return "arm";
-       }
-       return "";
-}
-
-bool Reader::validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture)
-{
-       return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, tripletPrefixForArch(architecture));
-}
-
-const char* Reader::fileKind(const uint8_t* p)
-{
-       if ( (p[0] == 0xDE) && (p[1] == 0xC0) && (p[2] == 0x17) && (p[3] == 0x0B) ) {
-               uint32_t arch = LittleEndian::get32(*((uint32_t*)(&p[16])));
-               switch (arch) {
-                       case CPU_TYPE_POWERPC:
-                               return "ppc";
-                       case CPU_TYPE_I386:
-                               return "i386";
-                       case CPU_TYPE_X86_64:
-                               return "x86_64";
-                       case CPU_TYPE_ARM:
-                               return "arm";
-               }
-               return "unknown bitcode architecture";
-       }
-       return NULL;
-}
-
-bool Reader::optimize(const std::vector<ObjectFile::Atom *>& allAtoms, std::vector<ObjectFile::Atom*>& newAtoms, 
-                                                       std::vector<const char*>& additionalUndefines, const std::set<ObjectFile::Atom*>& deadAtoms,
-                                                       std::vector<ObjectFile::Atom*>& newlyDeadAtoms,
-                                                       uint32_t nextInputOrdinal,  ObjectFile::Reader* writer, ObjectFile::Atom* entryPointAtom,
-                                                       const std::vector<const char*>& llvmOptions,
-                                                       bool allGlobalsAReDeadStripRoots,
-                                                       int okind, bool verbose, bool saveTemps, const char* outputFilePath,
-                                                       bool pie, bool allowTextRelocs)
-{ 
-       // this method is call on all Readers.  We want the first call to trigger optimization
-       // across all Readers and the subsequent calls to do nothing.
-       if ( fgOptimized ) 
-               return false;
-       fgOptimized = true;
-       
-       Options::OutputKind outputKind = (Options::OutputKind)okind; // HACK to work around upward dependency
-
-       // print out LTO version string if -v was used
-       if ( verbose )
-               fprintf(stderr, "%s\n", lto_get_version());
-       
-       // create optimizer and add each Reader
-       lto_code_gen_t generator = ::lto_codegen_create();
-       for (std::set<Reader*>::iterator it=fgReaders.begin(); it != fgReaders.end(); ++it) {
-               if ( ::lto_codegen_add_module(generator, (*it)->fModule) )
-                       throwf("lto: could not merge in %s because %s", (*it)->fPath, ::lto_get_error_message());
-       }
-
-       // add any -mllvm command line options
-       for (std::vector<const char*>::const_iterator it=llvmOptions.begin(); it != llvmOptions.end(); ++it) {
-               ::lto_codegen_debug_options(generator, *it);
-       }
-
-       // The atom graph uses directed edges (references). Collect all references where 
-       // originating atom is not part of any LTO Reader. This allows optimizer to optimize an 
-       // external (i.e. not originated from same .o file) reference if all originating atoms are also 
-       // defined in llvm bitcode file.
-       CStringSet nonLLVMRefs;
-       CStringToAtom llvmAtoms;
-    bool hasNonllvmAtoms = false;
-       for (std::vector<ObjectFile::Atom*>::const_iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) {
-               ObjectFile::Atom* atom = *it;
-               // only look at references come from an atom that is not an llvm atom
-               if ( fgReaders.count((Reader*)(atom->getFile())) == 0 ) {
-                               // remember if we've seen any atoms not from an llvm reader and not from the writer
-                               if ( atom->getFile() != writer )
-                                       hasNonllvmAtoms = true;
-                               std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
-                               for (std::vector<ObjectFile::Reference*>::iterator ri=refs.begin(), re=refs.end(); ri != re; ++ri) {
-                                       ObjectFile::Reference* ref = *ri;
-                                       // add target name to set if target is an llvm atom
-                                       if ( (ref->getTargetName() != NULL) && (fgReaders.count((Reader*)(ref->getTarget().getFile())) != 0) ) {
-                                               nonLLVMRefs.insert(ref->getTargetName());
-                               }
-                       }
-               }
-               else {
-                       const char* name = atom->getName();
-                       if ( name != NULL )
-                               llvmAtoms[name] = (Atom*)atom;
-               }
-       }
-       // if entry  point is in a llvm bitcode file, it must be preserved by LTO
-       if ( entryPointAtom != NULL ) {
-               if ( fgReaders.count((Reader*)(entryPointAtom->getFile())) != 0 ) 
-                       nonLLVMRefs.insert(entryPointAtom->getName());
-       }
-       
-       // deadAtoms are the atoms that the linker coalesced.  For instance weak or tentative definitions
-       // overriden by another atom.  If any of these deadAtoms are llvm atoms and they were replaced
-       // with a mach-o atom, we need to tell the lto engine to preserve (not optimize away) its dead 
-       // atom so that the linker can replace it with the mach-o one later.
-       CStringToAtom deadllvmAtoms;
-       for (std::set<ObjectFile::Atom*>::iterator it = deadAtoms.begin(); it != deadAtoms.end(); ++it) {
-               ObjectFile::Atom* atom = *it;
-               if ( fgReaders.count((Reader*)(atom->getFile())) != 0 ) {
-                       const char* name = atom->getName();
-                       ::lto_codegen_add_must_preserve_symbol(generator, name);
-                       deadllvmAtoms[name] = (Atom*)atom;
-               }
-       }
-
-       
-       // tell code generator about symbols that must be preserved
-       for (CStringToAtom::iterator it = llvmAtoms.begin(); it != llvmAtoms.end(); ++it) {
-               const char* name = it->first;
-               Atom* atom = it->second;
-               // Include llvm Symbol in export list if it meets one of following two conditions
-               // 1 - atom scope is global (and not linkage unit).
-               // 2 - included in nonLLVMRefs set.
-               // If a symbol is not listed in exportList then LTO is free to optimize it away.
-               if ( (atom->getScope() == ObjectFile::Atom::scopeGlobal) ) 
-                       ::lto_codegen_add_must_preserve_symbol(generator, name);
-               else if ( nonLLVMRefs.find(name) != nonLLVMRefs.end() ) 
-                       ::lto_codegen_add_must_preserve_symbol(generator, name);
-       }
-       
-    // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o)
-    if ( (outputKind == Options::kObjectFile) && !hasNonllvmAtoms ) {
-               if ( ! ::lto_codegen_write_merged_modules(generator, outputFilePath) ) {
-                       // HACK, no good way to tell linker we are all done, so just quit
-                       exit(0);
-               }
-               warning("could not produce merged bitcode file");
-    }
-    
-       // set code-gen model
-       lto_codegen_model model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
-       switch ( outputKind ) {
-               case Options::kDynamicExecutable:
-               case Options::kPreload:
-                       if ( pie )
-                               model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
-                       else
-                               model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
-                       break;
-               case Options::kDynamicLibrary:
-               case Options::kDynamicBundle:
-               case Options::kObjectFile: // ?? Is this appropriate ?
-               case Options::kDyld:
-               case Options::kKextBundle:
-                       if ( allowTextRelocs )
-                               model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
-                       else
-                               model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
-                       break;
-               case Options::kStaticExecutable:
-                       // darwin x86_64 "static" code model is really dynamic code model
-                       if ( fArchitecture == CPU_TYPE_X86_64 )
-                               model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
-                       else
-                               model = LTO_CODEGEN_PIC_MODEL_STATIC;
-                       break;
-       }
-       if ( ::lto_codegen_set_pic_model(generator, model) )
-               throwf("could not create set codegen model: %s", lto_get_error_message());
-
-    // if requested, save off merged bitcode file
-    if ( saveTemps ) {
-        char tempBitcodePath[MAXPATHLEN];
-        strcpy(tempBitcodePath, outputFilePath);
-        strcat(tempBitcodePath, ".lto.bc");
-        ::lto_codegen_write_merged_modules(generator, tempBitcodePath);
-    }
-
-#if LTO_API_VERSION >= 3
-       // find assembler next to linker
-       char path[PATH_MAX];
-       uint32_t bufSize = PATH_MAX;
-       if ( _NSGetExecutablePath(path, &bufSize) != -1 ) {
-               char* lastSlash = strrchr(path, '/');
-               if ( lastSlash != NULL ) {
-                       strcpy(lastSlash+1, "as");
-                       struct stat statInfo;
-                       if ( stat(path, &statInfo) == 0 )
-                               ::lto_codegen_set_assembler_path(generator, path);
-               }
-       }
-#endif
-       // run code generator
-       size_t machOFileLen;
-       const uint8_t* machOFile = (uint8_t*)::lto_codegen_compile(generator, &machOFileLen);
-       if ( machOFile == NULL ) 
-               throwf("could not do LTO codegen: %s", ::lto_get_error_message());
-       
-    // if requested, save off temp mach-o file
-    if ( saveTemps ) {
-        char tempMachoPath[MAXPATHLEN];
-        strcpy(tempMachoPath, outputFilePath);
-        strcat(tempMachoPath, ".lto.o");
-        int fd = ::open(tempMachoPath, O_CREAT | O_WRONLY | O_TRUNC, 0666);
-               if ( fd != -1) {
-                       ::write(fd, machOFile, machOFileLen);
-                       ::close(fd);
-               }
-               //      save off merged bitcode file
-               char tempOptBitcodePath[MAXPATHLEN];
-        strcpy(tempOptBitcodePath, outputFilePath);
-        strcat(tempOptBitcodePath, ".lto.opt.bc");
-        ::lto_codegen_write_merged_modules(generator, tempOptBitcodePath);
-       }
-
-       // parse generated mach-o file into a MachOReader
-       ObjectFile::Reader* machoReader = this->makeMachOReader(machOFile, machOFileLen, nextInputOrdinal);
-       
-       // sync generated mach-o atoms with existing atoms ld knows about
-       std::vector<ObjectFile::Atom*> machoAtoms = machoReader->getAtoms();
-       for (std::vector<ObjectFile::Atom *>::iterator it = machoAtoms.begin(); it != machoAtoms.end(); ++it) {
-               ObjectFile::Atom* atom = *it;
-               const char* name = atom->getName();
-               if ( name != NULL ) {
-                       CStringToAtom::iterator pos = llvmAtoms.find(name);
-                       if ( pos != llvmAtoms.end() ) {
-                               // turn Atom into a proxy for this mach-o atom
-                               pos->second->setRealAtom(atom);
-                       }
-                       else {
-                               // an atom of this name was not in the allAtoms list the linker gave us
-                               if ( deadllvmAtoms.find(name) != deadllvmAtoms.end() ) {
-                                       // this corresponding to an atom that the linker coalesced away.  Ignore it
-                                       // Make sure there any dependent atoms are also marked dead
-                                       std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
-                                       for (std::vector<ObjectFile::Reference*>::iterator ri=refs.begin(), re=refs.end(); ri != re; ++ri) {
-                                               ObjectFile::Reference* ref = *ri;
-                                               if ( ref->getKind() == 2 /*kGroupSubordinate*/ ) {      // FIX FIX
-                                                       ObjectFile::Atom* targ = &ref->getTarget();
-                                                       deadllvmAtoms[targ->getName()] = (Atom*)atom;
-                                               }
-                                       }
-                               }
-                               else
-                               {
-                                       // this is something new that lto conjured up, tell ld its new
-                                       newAtoms.push_back(atom);
-                               }
-                       }
-               }
-               else {
-                       // ld only knew about named atoms, so this one must be new
-                       newAtoms.push_back(atom);
-               }
-               std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
-               for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); ++rit) {
-                       ObjectFile::Reference* ref = *rit;
-                       const char* targetName = ref->getTargetName();
-                       CStringToAtom::iterator pos;
-                       if (targetName != NULL) {
-                               switch ( ref->getTargetBinding() ) {
-                                       case ObjectFile::Reference::kUnboundByName:
-                                               // accumulate unbounded references so that ld can bound them.
-                                               additionalUndefines.push_back(targetName);
-                                               break;
-                                       case ObjectFile::Reference::kBoundDirectly:
-                                       case ObjectFile::Reference::kBoundByName:
-                                               // If mach-o atom is referencing another mach-o atom then 
-                                               // reference is not going through Atom proxy. Fix it here to ensure that all
-                                               // llvm symbol references always go through Atom proxy.
-                                               pos = llvmAtoms.find(targetName);
-                                               if ( pos != llvmAtoms.end() )
-                                                       ref->setTarget(*pos->second, ref->getTargetOffset());
-                                               break;
-                                       case ObjectFile::Reference::kDontBind:
-                                               break;
-                               }
-                       }
-               }
-       }
-               
-       // Remove InternalAtoms from ld
-       for (std::set<Reader*>::iterator it=fgReaders.begin(); it != fgReaders.end(); ++it) {
-               newlyDeadAtoms.push_back(&((*it)->fInternalAtom));
-       }
-       // Remove Atoms from ld if code generator optimized them away
-       for (CStringToAtom::iterator li = llvmAtoms.begin(), le = llvmAtoms.end(); li != le; ++li) {
-               // check if setRealAtom() called on this Atom
-               if ( li->second->getRealAtom() == NULL )
-                       newlyDeadAtoms.push_back(li->second);
-       }
-       
-       return true;
-}
-
-
-ObjectFile::Reader* Reader::makeMachOReader(const uint8_t* p, size_t len, uint32_t nextInputOrdinal) 
-{
-       switch ( fArchitecture ) {
-               case CPU_TYPE_POWERPC:
-                       if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
-                               return new mach_o::relocatable::Reader<ppc>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
-                       break;
-               case CPU_TYPE_POWERPC64:
-                       if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
-                               return new mach_o::relocatable::Reader<ppc64>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
-                       break;
-               case CPU_TYPE_I386:
-                       if ( mach_o::relocatable::Reader<x86>::validFile(p) )
-                               return new mach_o::relocatable::Reader<x86>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
-                       break;
-               case CPU_TYPE_X86_64:
-                       if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
-                               return new mach_o::relocatable::Reader<x86_64>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
-                       break;
-               case CPU_TYPE_ARM:
-                       if ( mach_o::relocatable::Reader<arm>::validFile(p) )
-                               return new mach_o::relocatable::Reader<arm>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
-                       break;
-       }
-       throw "LLVM LTO, file is not of required architecture";
-}
-
-}; // namespace lto
-
-extern void printLTOVersion(Options& opts);
-
-void printLTOVersion(Options& opts) {
-       const char* vers = lto_get_version();
-       if ( vers != NULL )
-               fprintf(stderr, "%s\n", vers);
-}
-
-
-#endif
-