]> git.saurik.com Git - apple/ld64.git/blob - src/LLVMReader.hpp
ld64-77.1.tar.gz
[apple/ld64.git] / src / LLVMReader.hpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2006-2007 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 __LLVM_READER_H__
26 #define __LLVM_READER_H__
27
28 #include <stdlib.h>
29 #include <vector>
30 #include "MachOFileAbstraction.hpp"
31 #include "Architectures.hpp"
32 #include "ObjectFile.h"
33 #include "llvm/LinkTimeOptimizer.h"
34
35 #define LLVMLinkTimeOptimizer "LLVMlto.dylib"
36
37 class LLVMReader;
38
39 //
40 // LLVMReference handles LLVMAtom references. These references facilitate
41 // symbol resolution.
42 //
43
44 class LLVMReference : public ObjectFile::Reference
45 {
46 public:
47 LLVMReference (const char *n) : fName(n), fAtom(0), fFromAtom(0) { }
48
49 bool isTargetUnbound() const { return fAtom == 0; }
50 bool isFromTargetUnbound() const { return true; }
51 uint8_t getKind() const { return 0; }
52 uint64_t getFixUpOffset() const { return 0; }
53 const char * getTargetName() const { return fName; }
54 ObjectFile::Atom& getTarget() const { return *fAtom; }
55 uint64_t getTargetOffset() const { return 0; }
56 bool hasFromTarget() const { return false; }
57 ObjectFile::Atom& getFromTarget() const { return *fFromAtom; }
58 const char * getFromTargetName() const { return NULL; }
59 uint64_t getFromTargetOffset() const { return 0; }
60 TargetBinding getTargetBinding() const;
61 TargetBinding getFromTargetBinding() const { return kDontBind; }
62 void setTarget (ObjectFile::Atom &a, uint64_t offset)
63 { fAtom = &a; }
64 void setFromTarget(ObjectFile::Atom &a) { }
65 const char * getDescription() const { return NULL; }
66
67 private:
68 const char * fName;
69 ObjectFile::Atom * fAtom;
70 ObjectFile::Atom * fFromAtom;
71 };
72
73 ObjectFile::Reference::TargetBinding LLVMReference::getTargetBinding() const
74 {
75 if (strncmp (fName, "__ld64.llvm", 11) == 0)
76 return kDontBind;
77 else return kUnboundByName;
78 }
79
80 //
81 // LLVMAtom acts as a proxy Atom for the symbols that are exported by LLVM bytecode file. Initially,
82 // LLVMReader creates LLVMAtoms to allow linker proceed with usual symbol resolution phase. After
83 // optimization is performed, real Atoms are created for these symobls. However these real Atoms
84 // are not inserted into global symbol table. LLVMAtom holds real Atom and forwards appropriate
85 // methods to real atom.
86 //
87
88 class LLVMAtom : public ObjectFile::Atom
89 {
90 public:
91 ObjectFile::Reader * getFile() const { return fOwner; }
92 bool getTranslationUnitSource (const char **dir, const char **name) const
93 { return fRealAtom->getTranslationUnitSource (dir, name); }
94 const char * getName () const { return fAtomName; }
95 const char * getDisplayName() const { return this->getName(); }
96 Scope getScope() const { return fScope; }
97 DefinitionKind getDefinitionKind() const;
98 SymbolTableInclusion getSymbolTableInclusion() const
99 { return fRealAtom->getSymbolTableInclusion(); }
100 bool dontDeadStrip() const { return false; }
101 bool isZeroFill() const { return fRealAtom->isZeroFill(); }
102 uint64_t getSize() const { return fRealAtom->getSize(); }
103 std::vector<ObjectFile::Reference*>& getReferences() const
104 { return (fRealAtom ? fRealAtom->getReferences() : (std::vector<ObjectFile::Reference*>&)fReferences); }
105 bool mustRemainInSection() const { return fRealAtom->mustRemainInSection(); }
106 const char * getSectionName() const { return (fRealAtom ? fRealAtom->getSectionName() : NULL); }
107 // Linker::optimize() sets section for this atom, not fRealAtom. Use this Atom's fSection.
108 class ObjectFile::Section * getSection() const { return fSection; }
109 ObjectFile::Segment& getSegment() const { return fRealAtom->getSegment(); }
110 uint32_t getOrdinal() const { return (fRealAtom ? fRealAtom->getOrdinal() : 0); }
111 ObjectFile::Atom& getFollowOnAtom() const { return fRealAtom->getFollowOnAtom(); }
112 std::vector<ObjectFile::LineInfo>* getLineInfo() const { return fRealAtom->getLineInfo(); }
113 ObjectFile::Alignment getAlignment() const;
114 void copyRawContent(uint8_t buffer[]) const
115 { fRealAtom->copyRawContent(buffer); }
116 void setScope(Scope s) { if (fRealAtom) fRealAtom->setScope(s); }
117
118 LLVMAtom(ObjectFile::Reader *owner, const char *n, llvm::LLVMSymbol *ls);
119
120 void setRealAtom (ObjectFile::Atom *atom)
121 { fRealAtom = atom; }
122 void addReference(ObjectFile::Reference *ref)
123 { fReferences.push_back(ref); }
124
125 void setSectionOffset(uint64_t offset) { fSectionOffset = offset; if (fRealAtom) fRealAtom->setSectionOffset(offset); }
126 void setSection(class ObjectFile::Section* sect) { fSection = sect; if (fRealAtom) fRealAtom->setSection(sect); }
127
128 private:
129 ObjectFile::Reader * fOwner;
130 const char * fAtomName;
131 llvm::LLVMSymbol * fLLVMSymbol;
132 ObjectFile::Atom * fRealAtom;
133 std::vector<ObjectFile::Reference*> fReferences;
134 ObjectFile::Atom::Scope fScope;
135 ObjectFile::Atom::DefinitionKind fDefKind;
136 };
137
138 ObjectFile::Atom::DefinitionKind LLVMAtom::getDefinitionKind() const
139 {
140 if (fRealAtom)
141 return fRealAtom->getDefinitionKind();
142 else
143 return fDefKind;
144 }
145
146 LLVMAtom::LLVMAtom(ObjectFile::Reader *owner, const char *n, llvm::LLVMSymbol *ls) : fOwner(owner), fAtomName(n), fLLVMSymbol(ls), fRealAtom(0)
147 {
148
149 if (!ls) return;
150
151 switch (ls->getLinkage()) {
152 case llvm::LTOExternalLinkage:
153 fScope = scopeGlobal;
154 fDefKind = kRegularDefinition;
155 break;
156 case llvm::LTOLinkOnceLinkage:
157 case llvm::LTOWeakLinkage:
158 // ??? How to differentiate between this two linkage types ?
159 fScope = scopeGlobal;
160 fDefKind = kWeakDefinition;
161 break;
162 default:
163 throw "Unexpected LLVM Symbol Linkage info\n";
164 break;
165 }
166 }
167
168 ObjectFile::Alignment LLVMAtom::getAlignment() const
169 {
170 if (fRealAtom)
171 return fRealAtom->getAlignment();
172 else {
173 ObjectFile::Alignment alignment(fLLVMSymbol->getAlignment());
174 return alignment;
175 }
176 }
177
178 //
179 // LLVMReader does not expose internal symbols defined and used inside bytecode file. However,
180 // these symbols may refere other external symbols. IntercessorAtom facilitate by acting as a
181 // orignator of such references during pre-optimization symbol resoultion phase. These atoms
182 // are immediately removed after optimization.
183 //
184
185 class IntercessorAtom : public ObjectFile::Atom
186 {
187 public:
188 ObjectFile::Reader * getFile() const { return fOwner; }
189 bool getTranslationUnitSource (const char **dir, const char **name) const
190 { return false; }
191 const char * getName () const { return fAtomName; }
192 const char * getDisplayName() const { return this->getName(); }
193 Scope getScope() const { return scopeGlobal; }
194 DefinitionKind getDefinitionKind() const { return kRegularDefinition; }
195 SymbolTableInclusion getSymbolTableInclusion() const
196 { return kSymbolTableNotIn; }
197 bool dontDeadStrip() const { return false; }
198 bool isZeroFill() const { return false; }
199 uint64_t getSize() const { return 0; }
200 std::vector<ObjectFile::Reference*>& getReferences() const { return (std::vector<ObjectFile::Reference*>&)fReferences; }
201 bool mustRemainInSection() const { return false; }
202 const char * getSectionName() const { return NULL; }
203 class ObjectFile::Section * getSection() const { return NULL; }
204 ObjectFile::Segment& getSegment() const { return this->getSegment(); }
205 uint32_t getOrdinal() const { return 0; }
206 ObjectFile::Atom& getFollowOnAtom() const { return this->getFollowOnAtom(); }
207 std::vector<ObjectFile::LineInfo>* getLineInfo() const { return NULL; }
208 ObjectFile::Alignment getAlignment() const { ObjectFile::Alignment a(0); return a; }
209 void copyRawContent(uint8_t buffer[]) const
210 { }
211 void setScope(Scope s) { }
212
213
214 IntercessorAtom(ObjectFile::Reader *owner, std::set<std::string> &references);
215
216 void addReference(ObjectFile::Reference *ref)
217 { fReferences.push_back(ref); }
218 void addReferences(std::set<std::string> &references);
219 private:
220 ObjectFile::Reader * fOwner;
221 char * fAtomName;
222 std::vector<ObjectFile::Reference*> fReferences;
223 ObjectFile::Atom::Scope fScope;
224 ObjectFile::Atom::DefinitionKind fDefKind;
225 };
226
227 IntercessorAtom::IntercessorAtom(ObjectFile::Reader *owner, std::set<std::string> &references)
228 {
229 static int sCount = 0;
230 fOwner = owner;
231 fAtomName = (char *) malloc (sizeof(char)*20);
232 sprintf (fAtomName,"__ld64.llvm%d__",sCount++);
233
234 for (std::set<std::string>::iterator it = references.begin(); it != references.end(); it++) {
235 std::string r = *it;
236 this->addReference(new LLVMReference(r.c_str()));
237 }
238 }
239
240 void IntercessorAtom::addReferences(std::set<std::string> &references)
241 {
242 for (std::set<std::string>::iterator it = references.begin(); it != references.end(); it++) {
243 std::string r = *it;
244 this->addReference(new LLVMReference(r.c_str()));
245 }
246 }
247
248 class InIntercessorSet
249 {
250 public:
251 InIntercessorSet(std::set<ObjectFile::Atom*>& iAtoms) : fIntercessorAtoms(iAtoms) {}
252
253 bool operator()(ObjectFile::Atom*& atom) const {
254 return ( fIntercessorAtoms.count(atom) != 0 );
255 }
256
257 private:
258 std::set<ObjectFile::Atom*>& fIntercessorAtoms;
259 };
260
261 //
262 // LLVMOptimizer class is responsible for communicating with LLVM LTO library.
263 // One LLVMOptimizer object is created per Linker invocation. All LLVMReaders share this
264 // one single optimizer object.
265 //
266
267 class LLVMOptimizer
268 {
269 public:
270 LLVMOptimizer(Options &opt);
271 ~LLVMOptimizer() { if (fLLVMHandle) dlclose(fLLVMHandle); }
272
273
274 void optimize(std::vector<ObjectFile::Atom *>&, std::vector<ObjectFile::Atom*>&, uint32_t);
275 void read(ObjectFile::Reader *, const char *, std::set<std::string>&, std::vector<ObjectFile::Atom*>&, const char *);
276 void reconcileOptimizedAtoms(std::vector<class ObjectFile::Atom*>&, std::vector<class ObjectFile::Atom*>&);
277 void addIntercessor(IntercessorAtom * atom) { fIntercessorAtoms.insert(atom); }
278 void addReader(ObjectFile::Reader *reader) { fLLVMReaders[reader->getPath()] = reader; }
279 cpu_type_t getCpuType(std::string &targetTriple);
280 bool validArchitecture(const char *path, cpu_type_t architecture);
281 class LCStringEquals
282 {
283 public:
284 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
285 };
286 typedef hash_map<const char*, LLVMAtom*, hash<const char*>, LCStringEquals> LLVMAtomToNameMapper;
287 typedef hash_map<const char*, ObjectFile::Reader*, hash<const char*>, LCStringEquals> ReaderToPathMapper;
288
289 typedef llvm::LinkTimeOptimizer * (*createLLVMOptimizer_func_t) ();
290 private:
291 bool fOptimized;
292 llvm::LinkTimeOptimizer *fOptimizer;
293 void *fLLVMHandle;
294 LLVMAtomToNameMapper fLLVMSymbols;
295 Options& fOptions;
296 std::set<ObjectFile::Atom*> fIntercessorAtoms;
297 ReaderToPathMapper fLLVMReaders;
298 };
299
300 LLVMOptimizer::LLVMOptimizer(Options &opts) : fOptions(opts)
301 {
302 fLLVMHandle = (llvm::LinkTimeOptimizer *) dlopen (LLVMLinkTimeOptimizer, RTLD_LAZY);
303 if (!fLLVMHandle)
304 throwf("Unable to load LLVM library: \n", dlerror());
305
306 createLLVMOptimizer_func_t createLLVMOptimizer_fp = (createLLVMOptimizer_func_t)dlsym(fLLVMHandle, "createLLVMOptimizer");
307 if (createLLVMOptimizer_fp == NULL)
308 throwf("couldn't find \"createLLVMOptimizer\" ", dlerror());
309 fOptimizer = createLLVMOptimizer_fp();
310 fOptimized = false;
311 }
312
313 cpu_type_t LLVMOptimizer::getCpuType(std::string &targetTriple)
314 {
315 if ( strncmp (targetTriple.c_str(), "powerpc-", 8) == 0)
316 return CPU_TYPE_POWERPC;
317 else if ( strncmp (targetTriple.c_str(), "powerpc64-", 10))
318 return CPU_TYPE_POWERPC64;
319 // match "i[3-9]86-*".
320 else if ( targetTriple.size() >= 5 && targetTriple[0] == 'i' && targetTriple[2] == '8' && targetTriple[3] == '6' && targetTriple[4] == '-' && targetTriple[1] - '3' < 6 )
321 return CPU_TYPE_I386;
322 else
323 return CPU_TYPE_ANY;
324 }
325
326 bool LLVMOptimizer::validArchitecture(const char *path, cpu_type_t architecture)
327 {
328 std::string targetTriple;
329 fOptimizer->getTargetTriple(path, targetTriple);
330 if (architecture != getCpuType(targetTriple)) {
331 fOptimizer->removeModule(path);
332 return false;
333 }
334
335 return true;
336 }
337
338 void LLVMOptimizer::optimize(std::vector<ObjectFile::Atom*> &allAtoms, std::vector<ObjectFile::Atom*> &newAtoms, uint32_t nextInputOrdinal)
339 {
340 if (fOptimized)
341 return;
342
343 char * tmp = "/tmp/ld64XXXXXXXX";
344 char * bigOfile = (char *) malloc (strlen (tmp) + 3);
345 if (!bigOfile)
346 throw "Unable to create temp file name";
347 strcpy (bigOfile, tmp);
348 mktemp (bigOfile);
349 strcat (bigOfile, ".o");
350
351 std::vector <const char *> exportList;
352 for (std::vector<ObjectFile::Atom*>::iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) {
353 ObjectFile::Atom *atom = *it;
354 if (atom->getName()) {
355 ReaderToPathMapper::iterator pos = fLLVMReaders.find(atom->getFile()->getPath());
356 if (pos != fLLVMReaders.end())
357 exportList.push_back(atom->getName());
358 }
359
360 }
361
362 std::string targetTriple;
363 llvm::LTOStatus status = fOptimizer->optimizeModules(bigOfile, exportList, targetTriple, fOptions.saveTempFiles(), fOptions.getOutputFilePath());
364 if (status != llvm::LTO_OPT_SUCCESS) {
365 if (status == llvm::LTO_WRITE_FAILURE)
366 throw "Unable to write optimized output file";
367 if (status == llvm::LTO_ASM_FAILURE)
368 throw "Unable to assemble optimized output file";
369 if (status == llvm::LTO_MODULE_MERGE_FAILURE)
370 throw "Unable to merge bytecode files";
371 if (status == llvm::LTO_NO_TARGET)
372 throw "Unable to load target optimizer";
373 }
374 fOptimized = true;
375
376 Options::FileInfo info = fOptions.findFile (bigOfile);
377 ObjectFile::Reader* nr = NULL;
378 int fd = ::open(info.path, O_RDONLY, 0);
379 if ( fd == -1 )
380 throwf("can't open file, errno=%d", errno);
381 if ( info.fileLen < 20 )
382 throw "file too small";
383
384 uint8_t* p = (uint8_t*)::mmap(NULL, info.fileLen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
385 if ( p == (uint8_t*)(-1) )
386 throwf("can't map file, errno=%d", errno);
387
388 cpu_type_t cpt = getCpuType(targetTriple);
389 switch (cpt) {
390 case CPU_TYPE_POWERPC:
391 if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
392 nr = new mach_o::relocatable::Reader<ppc>(p, info.path, info.modTime, fOptions.readerOptions(), nextInputOrdinal);
393 break;
394 case CPU_TYPE_POWERPC64:
395 if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
396 nr = new mach_o::relocatable::Reader<ppc64>(p, info.path, info.modTime, fOptions.readerOptions(), nextInputOrdinal);
397 break;
398 case CPU_TYPE_I386:
399 if ( mach_o::relocatable::Reader<x86>::validFile(p) )
400 nr = new mach_o::relocatable::Reader<x86>(p, info.path, info.modTime, fOptions.readerOptions(), nextInputOrdinal);
401 break;
402 default:
403 throw "file is not of required architecture";
404 break;
405 }
406
407 std::vector<class ObjectFile::Atom*> optimizedAtoms;
408 optimizedAtoms = nr->getAtoms();
409 reconcileOptimizedAtoms(optimizedAtoms, newAtoms);
410
411 allAtoms.erase(std::remove_if(allAtoms.begin(), allAtoms.end(), InIntercessorSet(fIntercessorAtoms)), allAtoms.end());
412 unlink(bigOfile);
413 free(bigOfile);
414 }
415
416 void LLVMOptimizer::read(ObjectFile::Reader *reader, const char *path, std::set<std::string> &references, std::vector<ObjectFile::Atom*> &atoms, const char *intercessorName)
417 {
418 llvm::LinkTimeOptimizer::NameToSymbolMap symbols;
419 llvm::LTOStatus status = fOptimizer->readLLVMObjectFile (path, symbols, references);
420 if (status != llvm::LTO_READ_SUCCESS)
421 throw "Unable to read LLVM bytecode file";
422
423 for (llvm::LinkTimeOptimizer::NameToSymbolMap::iterator itr = symbols.begin();
424 itr != symbols.end(); itr++) {
425 const char *name = itr->first;
426 llvm::LLVMSymbol *ls = itr->second;
427 LLVMAtom *a = new LLVMAtom(reader, name, ls);
428
429 LLVMAtomToNameMapper::iterator pos = fLLVMSymbols.find(name);
430 bool insertNewAtom = true;
431 if (pos != fLLVMSymbols.end()) {
432 LLVMAtom *existingAtom = pos->second;
433 ObjectFile::Atom::DefinitionKind newDefKind = a->getDefinitionKind();
434 ObjectFile::Atom::DefinitionKind existingDefKind = existingAtom->getDefinitionKind();
435 if (newDefKind == ObjectFile::Atom::kRegularDefinition
436 && existingDefKind == ObjectFile::Atom::kRegularDefinition)
437 throwf ("duplicate symbol %s in %s and %s\n", name, a->getFile()->getPath(), existingAtom->getFile()->getPath());
438 else if (newDefKind == ObjectFile::Atom::kWeakDefinition
439 && existingDefKind == ObjectFile::Atom::kRegularDefinition)
440 insertNewAtom = false;
441 else if (newDefKind == ObjectFile::Atom::kWeakDefinition
442 && existingDefKind == ObjectFile::Atom::kWeakDefinition)
443 // pick one
444 insertNewAtom = false;
445 else if (newDefKind == ObjectFile::Atom::kRegularDefinition
446 && existingDefKind == ObjectFile::Atom::kWeakDefinition)
447 insertNewAtom = true;
448 }
449 if (insertNewAtom) {
450 atoms.push_back(a);
451 fLLVMSymbols[name] = a;
452 a->addReference(new LLVMReference (intercessorName));
453 }
454 }
455 }
456
457 void LLVMOptimizer::reconcileOptimizedAtoms(std::vector<class ObjectFile::Atom*>& optimizedAtoms,
458 std::vector<class ObjectFile::Atom*>& newAtoms)
459 {
460 for (std::vector<ObjectFile::Atom *>::iterator itr = optimizedAtoms.begin();
461 itr != optimizedAtoms.end(); ++itr) {
462
463 ObjectFile::Atom* atom = *itr;
464 if (!atom->getName()) {
465 newAtoms.push_back(atom);
466 continue;
467 }
468
469 LLVMAtomToNameMapper::iterator pos = fLLVMSymbols.find(atom->getName());
470 if ( pos != fLLVMSymbols.end() ) {
471
472 LLVMAtom *la = fLLVMSymbols[atom->getName()];
473 la->setRealAtom(atom);
474
475 }
476 else
477 newAtoms.push_back(atom);
478 }
479 }
480
481 //
482 // LLVM bytecode file reader
483 //
484
485 class LLVMReader : public ObjectFile::Reader
486 {
487 public:
488 static bool validFile(const uint8_t* fileContent, const char *path, cpu_type_t architecture, Options &opts);
489 static LLVMReader* make(const uint8_t* fileContent, const char* path, time_t modTime, Options& options)
490 { return new LLVMReader(fileContent, path, modTime, options); }
491 virtual ~LLVMReader();
492 virtual std::vector<class ObjectFile::Atom*>& getAtoms() { return (std::vector<class ObjectFile::Atom*>&)(fAtoms); }
493 virtual std::vector<class ObjectFile::Atom*>* getJustInTimeAtomsFor(const char* name) { return NULL; }
494 virtual const char* getPath() { return fPath; }
495 virtual time_t getModificationTime() { return fModTime; }
496 virtual ObjectFile::Reader::DebugInfoKind getDebugInfoKind() { return kDebugInfoNone; }
497 virtual std::vector<Stab>* getStabs() { return NULL; }
498
499 ObjectFile::Atom * retriveIntercessorAtom() { fAtoms.pop_back();return fIntercessorAtom; }
500 ObjectFile::Atom * getIntercessorAtom() { return fIntercessorAtom; }
501
502 private:
503
504 LLVMReader(const uint8_t* fileContent, const char* path, time_t modTime, Options& options);
505 void optimize(std::vector<ObjectFile::Atom*>& allAtoms, std::vector<ObjectFile::Atom*> &newAtoms, uint32_t);
506
507 const char* fPath;
508 time_t fModTime;
509 std::vector<ObjectFile::Atom*> fAtoms;
510 IntercessorAtom * fIntercessorAtom;
511 static LLVMOptimizer *fOptimizer;
512 std::set<std::string> fLLVMReferences;
513 };
514
515 LLVMOptimizer *LLVMReader::fOptimizer = NULL;
516
517 LLVMReader::~LLVMReader()
518 {
519 if (fOptimizer)
520 delete fOptimizer;
521 }
522
523 LLVMReader::LLVMReader (const uint8_t* fileContent, const char *path, time_t modTime, Options& options)
524 {
525
526 fPath = path;
527 fModTime = modTime;
528 fIntercessorAtom = new IntercessorAtom(this, fLLVMReferences);
529 fOptimizer->read(this, path, fLLVMReferences, fAtoms, fIntercessorAtom->getName());
530 fIntercessorAtom->addReferences(fLLVMReferences);
531 fAtoms.push_back(fIntercessorAtom);
532 fOptimizer->addIntercessor(fIntercessorAtom);
533 fOptimizer->addReader(this);
534 }
535
536 bool LLVMReader::validFile(const uint8_t* fileContent, const char *path, cpu_type_t architecture, Options &opts)
537 {
538 if (fileContent[0] == 'l'
539 && fileContent[1] == 'l'
540 && fileContent[2] == 'v'
541 && (fileContent[3] == 'c' || fileContent[3] == 'm')) {
542
543 // create optimizer
544 if (!fOptimizer)
545 fOptimizer = new LLVMOptimizer(opts);
546
547 if (fOptimizer->validArchitecture(path, architecture))
548 return true;
549 }
550
551 return false;
552 }
553
554 void LLVMReader::optimize(std::vector<ObjectFile::Atom *> &allAtoms, std::vector<ObjectFile::Atom*> &newAtoms, uint32_t nextInputOrdinal)
555 {
556 if (fOptimizer)
557 fOptimizer->optimize(allAtoms, newAtoms, nextInputOrdinal);
558 }
559
560 #endif
561