]> git.saurik.com Git - apple/ld64.git/blob - src/ld/LTOReader.hpp
0bd200ef4904babd464cfbd2140da8c81f2d8939
[apple/ld64.git] / src / ld / LTOReader.hpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2006-2009 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 #ifndef __LTO_READER_H__
26 #define __LTO_READER_H__
27
28 #include <stdlib.h>
29 #include <mach-o/dyld.h>
30 #include <vector>
31 #include <ext/hash_set>
32 #include <ext/hash_map>
33
34 #include "MachOFileAbstraction.hpp"
35 #include "Architectures.hpp"
36 #include "ObjectFile.h"
37 #include "Options.h"
38
39 #include "llvm-c/lto.h"
40
41
42 namespace lto {
43
44
45 //
46 // Reference handles Atom references. These references facilitate
47 // symbol resolution.
48 //
49
50 class Reference : public ObjectFile::Reference
51 {
52 public:
53 Reference(const char* name) : fTargetName(name), fTargetAtom(NULL) { }
54 Reference(ObjectFile::Atom& atom) : fTargetName(NULL), fTargetAtom(&atom) { }
55
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)
70 { fTargetAtom = &a; }
71 void setFromTarget(ObjectFile::Atom &a) { }
72 const char * getDescription() const;
73
74 private:
75 const char * fTargetName;
76 ObjectFile::Atom * fTargetAtom;
77 };
78
79
80 ObjectFile::Reference::TargetBinding Reference::getTargetBinding() const
81 {
82 if ( fTargetAtom == NULL )
83 return kUnboundByName;
84 else if ( fTargetName == NULL )
85 return kBoundDirectly;
86 else
87 return kBoundByName;
88 }
89
90 const char* Reference::getDescription() const
91 {
92 static char temp[256];
93 strcpy(temp, "reference to ");
94 if ( fTargetName != NULL )
95 strcat(temp, fTargetName);
96 else
97 strcat(temp, fTargetAtom->getDisplayName());
98 return temp;
99 }
100
101
102 class Segment : public ObjectFile::Segment
103 {
104 public:
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; }
112
113 static Segment fgBootstrapSegment;
114
115 private:
116 const char* fName;
117 const bool fReadable;
118 const bool fWritable;
119 const bool fExecutable;
120 const bool fFixedAddress;
121 };
122
123 Segment Segment:: fgBootstrapSegment("__TEMP", true, false, false, false);
124
125
126
127
128 //
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.
134 //
135 class Atom : public ObjectFile::Atom
136 {
137 public:
138 Atom(class Reader& owner, const char* name, Scope, DefinitionKind, uint8_t alignment, ObjectFile::Atom& internalAtom);
139
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 (fRealAtom ? fRealAtom->getScope() : 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; }
167
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); }
173
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); }
176
177 private:
178 class Reader& fOwner;
179 const char* fName;
180 ObjectFile::Atom::Scope fScope;
181 ObjectFile::Atom::DefinitionKind fKind;
182 uint8_t fAlignment;
183 ObjectFile::Atom* fRealAtom;
184 std::vector<ObjectFile::Reference*> fReferences;
185 };
186
187
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)
190 {
191 // every Atom references the InternalAtom for its reader
192 fReferences.push_back(new Reference(internalAtom));
193 }
194
195
196 //
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.
202 //
203 class InternalAtom : public ObjectFile::Atom
204 {
205 public:
206 InternalAtom(class Reader& owner) : fOwner(owner) {}
207
208 ObjectFile::Reader * getFile() const { return (ObjectFile::Reader*)&fOwner; }
209 bool getTranslationUnitSource (const char **dir, const char **name) const
210 { return false; }
211 const char * getName () const { return "__llvm-internal-atom"; }
212 const char * getDisplayName() const { return "llvm bitcode"; }
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) { }
231
232 void addReference(const char* targetName);
233
234 private:
235 class Reader& fOwner;
236 std::vector<ObjectFile::Reference*> fReferences;
237 };
238
239
240 void InternalAtom::addReference(const char* name)
241 {
242 fReferences.push_back(new Reference(name));
243 }
244
245
246
247
248 class RemovableAtoms
249 {
250 public:
251 RemovableAtoms(std::set<ObjectFile::Atom*>& iAtoms) : fAtoms(iAtoms) {}
252
253 bool operator()(ObjectFile::Atom*& atom) const {
254 return ( fAtoms.count(atom) != 0 );
255 }
256
257 private:
258 std::set<ObjectFile::Atom*>& fAtoms;
259 };
260
261
262
263 //
264 // LLVM bitcode file reader
265 //
266 class Reader : public ObjectFile::Reader
267 {
268 public:
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);
274 virtual ~Reader();
275
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 bool optimize(const std::vector<ObjectFile::Atom*>& allAtoms, std::vector<ObjectFile::Atom*>& newAtoms,
283 std::vector<const char*>& additionalUndefines, const std::set<ObjectFile::Atom*>&,
284 std::vector<ObjectFile::Atom*>& newDeadAtoms,
285 uint32_t nextInputOrdinal,
286 ObjectFile::Reader* writer, ObjectFile::Atom* entryPointAtom,
287 const std::vector<const char*>& llvmOptions,
288 bool allGlobalsAReDeadStripRoots,
289 int outputKind, bool verbose, bool saveTemps, const char* outputFilePath,
290 bool pie, bool allowTextRelocs);
291
292 private:
293
294 class CStringEquals
295 {
296 public:
297 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
298 };
299 typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals> CStringSet;
300 typedef __gnu_cxx::hash_map<const char*, Atom*, __gnu_cxx::hash<const char*>, CStringEquals> CStringToAtom;
301
302 ObjectFile::Reader* makeMachOReader(const uint8_t* p, size_t len, uint32_t nextInputOrdinal);
303 static const char* tripletPrefixForArch(cpu_type_t);
304
305 cpu_type_t fArchitecture;
306 const char* fPath;
307 time_t fModTime;
308 lto_module_t fModule;
309 std::vector<ObjectFile::Atom*> fAtoms;
310 InternalAtom fInternalAtom;
311 const ObjectFile::ReaderOptions& fReaderOptions;
312 static std::set<Reader*> fgReaders;
313 static bool fgOptimized;
314 };
315
316 bool Reader::fgOptimized = false;
317 std::set<Reader*> Reader::fgReaders;
318
319
320 Reader::~Reader()
321 {
322 if ( fModule != NULL )
323 ::lto_module_dispose(fModule);
324 }
325
326 Reader::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime,
327 const ObjectFile::ReaderOptions& options, cpu_type_t arch)
328 : fArchitecture(arch), fPath(strdup(path)), fModTime(modTime), fInternalAtom(*this), fReaderOptions(options)
329 {
330 fgReaders.insert(this);
331
332 fModule = ::lto_module_create_from_memory(fileContent, fileLength);
333 if ( fModule == NULL )
334 throwf("could not parse object file %s: %s", path, lto_get_error_message());
335
336 fAtoms.push_back(&fInternalAtom);
337
338 uint32_t count = ::lto_module_get_num_symbols(fModule);
339 for (uint32_t i=0; i < count; ++i) {
340 const char* name = ::lto_module_get_symbol_name(fModule, i);
341 lto_symbol_attributes attr = lto_module_get_symbol_attribute(fModule, i);
342
343 // <rdar://problem/6378110> LTO doesn't like dtrace symbols
344 // ignore dtrace static probes for now
345 // later when codegen is done and a mach-o file is produces the probes will be processed
346 if ( (strncmp(name, "___dtrace_probe$", 16) == 0) || (strncmp(name, "___dtrace_isenabled$", 20) == 0) )
347 continue;
348
349 ObjectFile::Atom::DefinitionKind kind;
350 switch ( attr & LTO_SYMBOL_DEFINITION_MASK ) {
351 case LTO_SYMBOL_DEFINITION_REGULAR:
352 kind = ObjectFile::Atom::kRegularDefinition;
353 break;
354 case LTO_SYMBOL_DEFINITION_TENTATIVE:
355 kind = ObjectFile::Atom::kTentativeDefinition;
356 break;
357 case LTO_SYMBOL_DEFINITION_WEAK:
358 kind = ObjectFile::Atom::kWeakDefinition;
359 break;
360 case LTO_SYMBOL_DEFINITION_UNDEFINED:
361 kind = ObjectFile::Atom::kExternalDefinition;
362 break;
363 default:
364 throwf("unknown definition kind for symbol %s in bitcode file %s", name, path);
365 }
366
367 // make LLVM atoms for definitions and a reference for undefines
368 if ( kind != ObjectFile::Atom::kExternalDefinition ) {
369 ObjectFile::Atom::Scope scope;
370 switch ( attr & LTO_SYMBOL_SCOPE_MASK) {
371 case LTO_SYMBOL_SCOPE_INTERNAL:
372 scope = ObjectFile::Atom::scopeTranslationUnit;
373 break;
374 case LTO_SYMBOL_SCOPE_HIDDEN:
375 scope = ObjectFile::Atom::scopeLinkageUnit;
376 break;
377 case LTO_SYMBOL_SCOPE_DEFAULT:
378 scope = ObjectFile::Atom::scopeGlobal;
379 break;
380 default:
381 throwf("unknown scope for symbol %s in bitcode file %s", name, path);
382 }
383 // only make atoms for non-internal symbols
384 if ( scope == ObjectFile::Atom::scopeTranslationUnit )
385 continue;
386 uint8_t alignment = (attr & LTO_SYMBOL_ALIGNMENT_MASK);
387 // make Atom
388 fAtoms.push_back(new Atom(*this, name, scope, kind, alignment, fInternalAtom));
389 }
390 else {
391 // add to list of external references
392 fInternalAtom.addReference(name);
393 }
394 }
395 }
396
397 const char* Reader::tripletPrefixForArch(cpu_type_t arch)
398 {
399 switch (arch) {
400 case CPU_TYPE_POWERPC:
401 return "powerpc-";
402 case CPU_TYPE_POWERPC64:
403 return "powerpc64-";
404 case CPU_TYPE_I386:
405 return "i386-";
406 case CPU_TYPE_X86_64:
407 return "x86_64-";
408 case CPU_TYPE_ARM:
409 return "arm";
410 }
411 return "";
412 }
413
414 bool Reader::validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture)
415 {
416 return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, tripletPrefixForArch(architecture));
417 }
418
419 bool Reader::optimize(const std::vector<ObjectFile::Atom *>& allAtoms, std::vector<ObjectFile::Atom*>& newAtoms,
420 std::vector<const char*>& additionalUndefines, const std::set<ObjectFile::Atom*>& deadAtoms,
421 std::vector<ObjectFile::Atom*>& newlyDeadAtoms,
422 uint32_t nextInputOrdinal, ObjectFile::Reader* writer, ObjectFile::Atom* entryPointAtom,
423 const std::vector<const char*>& llvmOptions,
424 bool allGlobalsAReDeadStripRoots,
425 int okind, bool verbose, bool saveTemps, const char* outputFilePath,
426 bool pie, bool allowTextRelocs)
427 {
428 // this method is call on all Readers. We want the first call to trigger optimization
429 // across all Readers and the subsequent calls to do nothing.
430 if ( fgOptimized )
431 return false;
432 fgOptimized = true;
433
434 Options::OutputKind outputKind = (Options::OutputKind)okind; // HACK to work around upward dependency
435
436 // print out LTO version string if -v was used
437 if ( verbose )
438 fprintf(stderr, "%s\n", lto_get_version());
439
440 // create optimizer and add each Reader
441 lto_code_gen_t generator = ::lto_codegen_create();
442 for (std::set<Reader*>::iterator it=fgReaders.begin(); it != fgReaders.end(); ++it) {
443 if ( ::lto_codegen_add_module(generator, (*it)->fModule) )
444 throwf("lto: could not merge in %s because %s", (*it)->fPath, ::lto_get_error_message());
445 }
446
447 // add any -mllvm command line options
448 for (std::vector<const char*>::const_iterator it=llvmOptions.begin(); it != llvmOptions.end(); ++it) {
449 ::lto_codegen_debug_options(generator, *it);
450 }
451
452 // The atom graph uses directed edges (references). Collect all references where
453 // originating atom is not part of any LTO Reader. This allows optimizer to optimize an
454 // external (i.e. not originated from same .o file) reference if all originating atoms are also
455 // defined in llvm bitcode file.
456 CStringSet nonLLVMRefs;
457 CStringToAtom llvmAtoms;
458 bool hasNonllvmAtoms = false;
459 for (std::vector<ObjectFile::Atom*>::const_iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) {
460 ObjectFile::Atom* atom = *it;
461 // only look at references come from an atom that is not an llvm atom
462 if ( fgReaders.count((Reader*)(atom->getFile())) == 0 ) {
463 // remember if we've seen any atoms not from an llvm reader and not from the writer
464 if ( atom->getFile() != writer )
465 hasNonllvmAtoms = true;
466 std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
467 for (std::vector<ObjectFile::Reference*>::iterator ri=refs.begin(), re=refs.end(); ri != re; ++ri) {
468 ObjectFile::Reference* ref = *ri;
469 // add target name to set if target is an llvm atom
470 if ( (ref->getTargetName() != NULL) && (fgReaders.count((Reader*)(ref->getTarget().getFile())) != 0) ) {
471 nonLLVMRefs.insert(ref->getTargetName());
472 }
473 }
474 }
475 else {
476 const char* name = atom->getName();
477 if ( name != NULL )
478 llvmAtoms[name] = (Atom*)atom;
479 }
480 }
481 // if entry point is in a llvm bitcode file, it must be preserved by LTO
482 if ( entryPointAtom != NULL ) {
483 if ( fgReaders.count((Reader*)(entryPointAtom->getFile())) != 0 )
484 nonLLVMRefs.insert(entryPointAtom->getName());
485 }
486
487 // deadAtoms are the atoms that the linker coalesced. For instance weak or tentative definitions
488 // overriden by another atom. If any of these deadAtoms are llvm atoms and they were replaced
489 // with a mach-o atom, we need to tell the lto engine to preserve (not optimize away) its dead
490 // atom so that the linker can replace it with the mach-o one later.
491 CStringToAtom deadllvmAtoms;
492 for (std::set<ObjectFile::Atom*>::iterator it = deadAtoms.begin(); it != deadAtoms.end(); ++it) {
493 ObjectFile::Atom* atom = *it;
494 if ( fgReaders.count((Reader*)(atom->getFile())) != 0 ) {
495 const char* name = atom->getName();
496 ::lto_codegen_add_must_preserve_symbol(generator, name);
497 deadllvmAtoms[name] = (Atom*)atom;
498 }
499 }
500
501
502 // tell code generator about symbols that must be preserved
503 for (CStringToAtom::iterator it = llvmAtoms.begin(); it != llvmAtoms.end(); ++it) {
504 const char* name = it->first;
505 Atom* atom = it->second;
506 // Include llvm Symbol in export list if it meets one of following two conditions
507 // 1 - atom scope is global (and not linkage unit).
508 // 2 - included in nonLLVMRefs set.
509 // If a symbol is not listed in exportList then LTO is free to optimize it away.
510 if ( (atom->getScope() == ObjectFile::Atom::scopeGlobal) )
511 ::lto_codegen_add_must_preserve_symbol(generator, name);
512 else if ( nonLLVMRefs.find(name) != nonLLVMRefs.end() )
513 ::lto_codegen_add_must_preserve_symbol(generator, name);
514 }
515
516 // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o)
517 if ( (outputKind == Options::kObjectFile) && !hasNonllvmAtoms ) {
518 if ( ! ::lto_codegen_write_merged_modules(generator, outputFilePath) ) {
519 // HACK, no good way to tell linker we are all done, so just quit
520 exit(0);
521 }
522 warning("could not produce merged bitcode file");
523 }
524
525 // set code-gen model
526 lto_codegen_model model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
527 switch ( outputKind ) {
528 case Options::kDynamicExecutable:
529 case Options::kPreload:
530 if ( pie )
531 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
532 else
533 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
534 break;
535 case Options::kDynamicLibrary:
536 case Options::kDynamicBundle:
537 case Options::kObjectFile: // ?? Is this appropriate ?
538 case Options::kDyld:
539 case Options::kKextBundle:
540 if ( allowTextRelocs )
541 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
542 else
543 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
544 break;
545 case Options::kStaticExecutable:
546 // darwin x86_64 "static" code model is really dynamic code model
547 if ( fArchitecture == CPU_TYPE_X86_64 )
548 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
549 else
550 model = LTO_CODEGEN_PIC_MODEL_STATIC;
551 break;
552 }
553 if ( ::lto_codegen_set_pic_model(generator, model) )
554 throwf("could not create set codegen model: %s", lto_get_error_message());
555
556 // if requested, save off merged bitcode file
557 if ( saveTemps ) {
558 char tempBitcodePath[MAXPATHLEN];
559 strcpy(tempBitcodePath, outputFilePath);
560 strcat(tempBitcodePath, ".lto.bc");
561 ::lto_codegen_write_merged_modules(generator, tempBitcodePath);
562 }
563
564 #if LTO_API_VERSION >= 3
565 // find assembler next to linker
566 char path[PATH_MAX];
567 uint32_t bufSize = PATH_MAX;
568 if ( _NSGetExecutablePath(path, &bufSize) != -1 ) {
569 char* lastSlash = strrchr(path, '/');
570 if ( lastSlash != NULL ) {
571 strcpy(lastSlash+1, "as");
572 struct stat statInfo;
573 if ( stat(path, &statInfo) == 0 )
574 ::lto_codegen_set_assembler_path(generator, path);
575 }
576 }
577 #endif
578 // run code generator
579 size_t machOFileLen;
580 const uint8_t* machOFile = (uint8_t*)::lto_codegen_compile(generator, &machOFileLen);
581 if ( machOFile == NULL )
582 throwf("could not do LTO codegen: %s", ::lto_get_error_message());
583
584 // if requested, save off temp mach-o file
585 if ( saveTemps ) {
586 char tempMachoPath[MAXPATHLEN];
587 strcpy(tempMachoPath, outputFilePath);
588 strcat(tempMachoPath, ".lto.o");
589 int fd = ::open(tempMachoPath, O_CREAT | O_WRONLY | O_TRUNC, 0666);
590 if ( fd != -1) {
591 ::write(fd, machOFile, machOFileLen);
592 ::close(fd);
593 }
594 // save off merged bitcode file
595 char tempOptBitcodePath[MAXPATHLEN];
596 strcpy(tempOptBitcodePath, outputFilePath);
597 strcat(tempOptBitcodePath, ".lto.opt.bc");
598 ::lto_codegen_write_merged_modules(generator, tempOptBitcodePath);
599 }
600
601 // parse generated mach-o file into a MachOReader
602 ObjectFile::Reader* machoReader = this->makeMachOReader(machOFile, machOFileLen, nextInputOrdinal);
603
604 // sync generated mach-o atoms with existing atoms ld knows about
605 std::vector<ObjectFile::Atom*> machoAtoms = machoReader->getAtoms();
606 for (std::vector<ObjectFile::Atom *>::iterator it = machoAtoms.begin(); it != machoAtoms.end(); ++it) {
607 ObjectFile::Atom* atom = *it;
608 const char* name = atom->getName();
609 if ( name != NULL ) {
610 CStringToAtom::iterator pos = llvmAtoms.find(name);
611 if ( pos != llvmAtoms.end() ) {
612 // turn Atom into a proxy for this mach-o atom
613 pos->second->setRealAtom(atom);
614 }
615 else {
616 // an atom of this name was not in the allAtoms list the linker gave us
617 if ( deadllvmAtoms.find(name) != deadllvmAtoms.end() ) {
618 // this corresponding to an atom that the linker coalesced away. Ignore it
619 // Make sure there any dependent atoms are also marked dead
620 std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
621 for (std::vector<ObjectFile::Reference*>::iterator ri=refs.begin(), re=refs.end(); ri != re; ++ri) {
622 ObjectFile::Reference* ref = *ri;
623 if ( ref->getKind() == 2 /*kGroupSubordinate*/ ) { // FIX FIX
624 ObjectFile::Atom* targ = &ref->getTarget();
625 deadllvmAtoms[targ->getName()] = (Atom*)atom;
626 }
627 }
628 }
629 else
630 {
631 // this is something new that lto conjured up, tell ld its new
632 newAtoms.push_back(atom);
633 }
634 }
635 }
636 else {
637 // ld only knew about named atoms, so this one must be new
638 newAtoms.push_back(atom);
639 }
640 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
641 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); ++rit) {
642 ObjectFile::Reference* ref = *rit;
643 const char* targetName = ref->getTargetName();
644 CStringToAtom::iterator pos;
645 if (targetName != NULL) {
646 switch ( ref->getTargetBinding() ) {
647 case ObjectFile::Reference::kUnboundByName:
648 // accumulate unbounded references so that ld can bound them.
649 additionalUndefines.push_back(targetName);
650 break;
651 case ObjectFile::Reference::kBoundDirectly:
652 case ObjectFile::Reference::kBoundByName:
653 // If mach-o atom is referencing another mach-o atom then
654 // reference is not going through Atom proxy. Fix it here to ensure that all
655 // llvm symbol references always go through Atom proxy.
656 pos = llvmAtoms.find(targetName);
657 if ( pos != llvmAtoms.end() )
658 ref->setTarget(*pos->second, ref->getTargetOffset());
659 break;
660 case ObjectFile::Reference::kDontBind:
661 break;
662 }
663 }
664 }
665 }
666
667 // Remove InternalAtoms from ld
668 for (std::set<Reader*>::iterator it=fgReaders.begin(); it != fgReaders.end(); ++it) {
669 newlyDeadAtoms.push_back(&((*it)->fInternalAtom));
670 }
671 // Remove Atoms from ld if code generator optimized them away
672 for (CStringToAtom::iterator li = llvmAtoms.begin(), le = llvmAtoms.end(); li != le; ++li) {
673 // check if setRealAtom() called on this Atom
674 if ( li->second->getRealAtom() == NULL )
675 newlyDeadAtoms.push_back(li->second);
676 }
677
678 return true;
679 }
680
681
682 ObjectFile::Reader* Reader::makeMachOReader(const uint8_t* p, size_t len, uint32_t nextInputOrdinal)
683 {
684 switch ( fArchitecture ) {
685 case CPU_TYPE_POWERPC:
686 if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
687 return new mach_o::relocatable::Reader<ppc>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
688 break;
689 case CPU_TYPE_POWERPC64:
690 if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
691 return new mach_o::relocatable::Reader<ppc64>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
692 break;
693 case CPU_TYPE_I386:
694 if ( mach_o::relocatable::Reader<x86>::validFile(p) )
695 return new mach_o::relocatable::Reader<x86>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
696 break;
697 case CPU_TYPE_X86_64:
698 if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
699 return new mach_o::relocatable::Reader<x86_64>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
700 break;
701 case CPU_TYPE_ARM:
702 if ( mach_o::relocatable::Reader<arm>::validFile(p) )
703 return new mach_o::relocatable::Reader<arm>(p, "/tmp/lto.o", 0, fReaderOptions, nextInputOrdinal);
704 break;
705 }
706 throw "LLVM LTO, file is not of required architecture";
707 }
708
709 }; // namespace lto
710
711 extern void printLTOVersion(Options& opts);
712
713 void printLTOVersion(Options& opts) {
714 const char* vers = lto_get_version();
715 if ( vers != NULL )
716 fprintf(stderr, "%s\n", vers);
717 }
718
719
720 #endif
721