]> granicus.if.org Git - clang/blob - Driver/ASTConsumers.cpp
pull .ll and .bc writing out of the ASTConsumer destructors into some top
[clang] / Driver / ASTConsumers.cpp
1 //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // AST Consumer Implementations.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ASTConsumers.h"
15 #include "clang/AST/TranslationUnit.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Basic/FileManager.h"
18 #include "clang/AST/AST.h"
19 #include "clang/AST/ASTConsumer.h"
20 #include "clang/AST/CFG.h"
21 #include "clang/Analysis/Analyses/LiveVariables.h"
22 #include "clang/Analysis/Analyses/GRConstants.h"
23 #include "clang/Analysis/LocalCheckers.h"
24 #include "llvm/Support/Streams.h"
25 using namespace clang;
26
27 //===----------------------------------------------------------------------===//
28 /// DeclPrinter - Utility class for printing top-level decls.
29
30 namespace {
31   class DeclPrinter {
32   public:
33     std::ostream& Out;
34
35     DeclPrinter(std::ostream* out) : Out(out ? *out : *llvm::cerr.stream()) {}
36     DeclPrinter() : Out(*llvm::cerr.stream()) {}
37     
38     void PrintDecl(Decl *D);
39     void PrintFunctionDeclStart(FunctionDecl *FD);    
40     void PrintTypeDefDecl(TypedefDecl *TD);    
41     void PrintLinkageSpec(LinkageSpecDecl *LS);
42     void PrintObjCMethodDecl(ObjCMethodDecl *OMD);    
43     void PrintObjCImplementationDecl(ObjCImplementationDecl *OID);
44     void PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID);
45     void PrintObjCProtocolDecl(ObjCProtocolDecl *PID);  
46     void PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID);    
47     void PrintObjCCategoryDecl(ObjCCategoryDecl *PID);    
48     void PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID);
49   };
50 } // end anonymous namespace
51
52 void DeclPrinter:: PrintDecl(Decl *D) {
53   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
54     PrintFunctionDeclStart(FD);
55
56     if (FD->getBody()) {
57       Out << ' ';
58       FD->getBody()->printPretty(Out);
59       Out << '\n';
60     }
61   } else if (isa<ObjCMethodDecl>(D)) {
62     // Do nothing, methods definitions are printed in
63     // PrintObjCImplementationDecl.
64   } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
65     PrintTypeDefDecl(TD);
66   } else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
67     PrintObjCInterfaceDecl(OID);
68   } else if (ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(D)) {
69     PrintObjCProtocolDecl(PID);
70   } else if (ObjCForwardProtocolDecl *OFPD = 
71              dyn_cast<ObjCForwardProtocolDecl>(D)) {
72     Out << "@protocol ";
73     for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
74       const ObjCProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
75       if (i) Out << ", ";
76       Out << D->getName();
77     }
78     Out << ";\n";
79   } else if (ObjCImplementationDecl *OID = 
80              dyn_cast<ObjCImplementationDecl>(D)) {
81     PrintObjCImplementationDecl(OID);
82   } else if (ObjCCategoryImplDecl *OID = 
83              dyn_cast<ObjCCategoryImplDecl>(D)) {
84     PrintObjCCategoryImplDecl(OID);
85   } else if (ObjCCategoryDecl *OID = 
86              dyn_cast<ObjCCategoryDecl>(D)) {
87     PrintObjCCategoryDecl(OID);
88   } else if (ObjCCompatibleAliasDecl *OID = 
89              dyn_cast<ObjCCompatibleAliasDecl>(D)) {
90     PrintObjCCompatibleAliasDecl(OID);
91   } else if (isa<ObjCClassDecl>(D)) {
92     Out << "@class [printing todo]\n";
93   } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
94     Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
95   } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
96     Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
97   } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
98     PrintLinkageSpec(LSD);
99   } else {
100     assert(0 && "Unknown decl type!");
101   }
102 }
103
104 void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
105   bool HasBody = FD->getBody();
106   
107   Out << '\n';
108
109   switch (FD->getStorageClass()) {
110   default: assert(0 && "Unknown storage class");
111   case FunctionDecl::None: break;
112   case FunctionDecl::Extern: Out << "extern "; break;
113   case FunctionDecl::Static: Out << "static "; break;
114   }
115   
116   if (FD->isInline())
117     Out << "inline ";
118   
119   std::string Proto = FD->getName();
120   const FunctionType *AFT = FD->getType()->getAsFunctionType();
121
122   if (const FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
123     Proto += "(";
124     for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
125       if (i) Proto += ", ";
126       std::string ParamStr;
127       if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
128       
129       FT->getArgType(i).getAsStringInternal(ParamStr);
130       Proto += ParamStr;
131     }
132     
133     if (FT->isVariadic()) {
134       if (FD->getNumParams()) Proto += ", ";
135       Proto += "...";
136     }
137     Proto += ")";
138   } else {
139     assert(isa<FunctionTypeNoProto>(AFT));
140     Proto += "()";
141   }
142
143   AFT->getResultType().getAsStringInternal(Proto);
144   Out << Proto;
145   
146   if (!FD->getBody())
147     Out << ";\n";
148   // Doesn't print the body.
149 }
150
151 void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
152   std::string S = TD->getName();
153   TD->getUnderlyingType().getAsStringInternal(S);
154   Out << "typedef " << S << ";\n";
155 }
156
157 void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
158   const char *l;
159   if (LS->getLanguage() == LinkageSpecDecl::lang_c)
160     l = "C";
161   else if (LS->getLanguage() == LinkageSpecDecl::lang_cxx)
162     l = "C++";
163   else assert(0 && "unknown language in linkage specification");
164   Out << "extern \"" << l << "\" { ";
165   PrintDecl(LS->getDecl());
166   Out << "}\n";
167 }
168
169 void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) {
170   if (OMD->isInstance())
171     Out << "\n- ";
172   else 
173     Out << "\n+ ";
174   if (!OMD->getResultType().isNull())
175     Out << '(' << OMD->getResultType().getAsString() << ") ";
176   // FIXME: just print original selector name!
177   Out << OMD->getSelector().getName();
178   
179   for (int i = 0; i < OMD->getNumParams(); i++) {
180     ParmVarDecl *PDecl = OMD->getParamDecl(i);
181     // FIXME: selector is missing here!    
182     Out << " :(" << PDecl->getType().getAsString() << ") " << PDecl->getName(); 
183   }
184 }
185
186 void DeclPrinter::PrintObjCImplementationDecl(ObjCImplementationDecl *OID) {
187   std::string I = OID->getName();
188   ObjCInterfaceDecl *SID = OID->getSuperClass();
189
190   if (SID)
191     Out << "@implementation " << I << " : " << SID->getName();
192   else
193     Out << "@implementation " << I;
194   
195   for (ObjCImplementationDecl::instmeth_iterator I = OID->instmeth_begin(),
196        E = OID->instmeth_end(); I != E; ++I) {
197     ObjCMethodDecl *OMD = *I;
198     PrintObjCMethodDecl(OMD);
199     if (OMD->getBody()) {
200       Out << ' ';
201       OMD->getBody()->printPretty(Out);
202       Out << '\n';
203     }
204   }
205   
206   for (ObjCImplementationDecl::classmeth_iterator I = OID->classmeth_begin(),
207        E = OID->classmeth_end(); I != E; ++I) {
208     ObjCMethodDecl *OMD = *I;
209     PrintObjCMethodDecl(OMD);
210     if (OMD->getBody()) {
211       Out << ' ';
212       OMD->getBody()->printPretty(Out);
213       Out << '\n';
214     }
215   }
216   
217   Out << "@end\n";
218 }
219
220
221 void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
222   std::string I = OID->getName();
223   ObjCInterfaceDecl *SID = OID->getSuperClass();
224
225   if (SID)
226     Out << "@interface " << I << " : " << SID->getName();
227   else
228     Out << "@interface " << I;
229   
230   // Protocols?
231   int count = OID->getNumIntfRefProtocols();
232
233   if (count > 0) {
234     ObjCProtocolDecl **refProtocols = OID->getReferencedProtocols();
235     for (int i = 0; i < count; i++)
236       Out << (i == 0 ? '<' : ',') << refProtocols[i]->getName();
237   }
238   
239   if (count > 0)
240     Out << ">\n";
241   else
242     Out << '\n';
243   
244   if (OID->getNumInstanceVariables() > 0) {
245     Out << '{';
246     for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
247          E = OID->ivar_end(); I != E; ++I) {
248       Out << '\t' << (*I)->getType().getAsString()
249           << ' '  << (*I)->getName() << ";\n";      
250     }
251     Out << "}\n";
252   }
253   
254   int NumProperties = OID->getNumPropertyDecl();
255   if (NumProperties > 0) {
256     for (int i = 0; i < NumProperties; i++) {
257       ObjCPropertyDecl *PDecl = OID->getPropertyDecl()[i];
258       Out << "@property";
259       if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
260         bool first = true;
261         Out << " (";
262         if (PDecl->getPropertyAttributes() & 
263             ObjCPropertyDecl::OBJC_PR_readonly) {
264           Out << (first ? ' ' : ',') << "readonly";
265           first = false;
266         }
267         
268         if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
269           Out << (first ? ' ' : ',') << "getter = "
270               << PDecl->getGetterName()->getName();
271           first = false;
272         }
273         if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
274           Out << (first ? ' ' : ',') << "setter = "
275               << PDecl->getSetterName()->getName();
276           first = false;
277         }
278         
279         if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
280           Out << (first ? ' ' : ',') << "assign";
281           first = false;
282         }
283         
284         if (PDecl->getPropertyAttributes() &
285             ObjCPropertyDecl::OBJC_PR_readwrite) {
286           Out << (first ? ' ' : ',') << "readwrite";
287           first = false;
288         }
289         
290         if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
291           Out << (first ? ' ' : ',') << "retain";
292           first = false;
293         }
294         
295         if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
296           Out << (first ? ' ' : ',') << "copy";
297           first = false;
298         }
299         
300         if (PDecl->getPropertyAttributes() & 
301             ObjCPropertyDecl::OBJC_PR_nonatomic) {
302           Out << (first ? ' ' : ',') << "nonatomic";
303           first = false;
304         }
305         Out << " )";
306       }
307       
308       ObjCIvarDecl **IDecl = PDecl->getPropertyDecls();
309       
310       Out << ' ' << IDecl[0]->getType().getAsString()
311           << ' ' << IDecl[0]->getName();
312       
313       for (int j = 1; j < PDecl->getNumPropertyDecls(); j++)
314         Out << ", " << IDecl[j]->getName();
315
316       Out << ";\n";
317     }
318   }
319   
320   Out << "@end\n";
321   // FIXME: implement the rest...
322 }
323
324 void DeclPrinter::PrintObjCProtocolDecl(ObjCProtocolDecl *PID) {
325   Out << "@protocol " << PID->getName() << '\n';
326   // FIXME: implement the rest...
327 }
328
329 void DeclPrinter::PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
330   Out << "@implementation "
331       << PID->getClassInterface()->getName()
332       << '(' << PID->getName() << ");\n";  
333   
334   // FIXME: implement the rest...
335 }
336
337 void DeclPrinter::PrintObjCCategoryDecl(ObjCCategoryDecl *PID) {
338   Out << "@interface " 
339       << PID->getClassInterface()->getName()
340       << '(' << PID->getName() << ");\n";
341   // FIXME: implement the rest...
342 }
343
344 void DeclPrinter::PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
345   Out << "@compatibility_alias " << AID->getName() 
346       << ' ' << AID->getClassInterface()->getName() << ";\n";  
347 }
348
349 //===----------------------------------------------------------------------===//
350 /// ASTPrinter - Pretty-printer of ASTs
351
352 namespace {
353   class ASTPrinter : public ASTConsumer, public DeclPrinter {
354   public:
355     ASTPrinter(std::ostream* o = NULL) : DeclPrinter(o) {}
356     
357     virtual void HandleTopLevelDecl(Decl *D) {
358       PrintDecl(D);
359     }
360   };
361 }
362
363 ASTConsumer *clang::CreateASTPrinter(std::ostream* out) {
364   return new ASTPrinter(out);
365 }
366
367 //===----------------------------------------------------------------------===//
368 /// ASTDumper - Low-level dumper of ASTs
369
370 namespace {
371   class ASTDumper : public ASTConsumer, public DeclPrinter {
372     SourceManager *SM;
373   public:
374     ASTDumper() : DeclPrinter() {}
375     
376     void Initialize(ASTContext &Context) {
377       SM = &Context.getSourceManager();
378     }
379     
380     virtual void HandleTopLevelDecl(Decl *D) {
381       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
382         PrintFunctionDeclStart(FD);
383         
384         if (FD->getBody()) {
385           Out << '\n';
386           // FIXME: convert dumper to use std::ostream?
387           FD->getBody()->dumpAll(*SM);
388           Out << '\n';
389         }
390       } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
391         PrintTypeDefDecl(TD);
392       } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
393         Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
394       } else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
395         Out << "Read objc interface '" << OID->getName() << "'\n";
396       } else if (ObjCProtocolDecl *OPD = dyn_cast<ObjCProtocolDecl>(D)) {
397         Out << "Read objc protocol '" << OPD->getName() << "'\n";
398       } else if (ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(D)) {
399         Out << "Read objc category '" << OCD->getName() << "'\n";
400       } else if (isa<ObjCForwardProtocolDecl>(D)) {
401         Out << "Read objc fwd protocol decl\n";
402       } else if (isa<ObjCClassDecl>(D)) {
403         Out << "Read objc fwd class decl\n";
404       } else {
405         assert(0 && "Unknown decl type!");
406       }
407     }
408   };
409 }
410
411 ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
412
413 //===----------------------------------------------------------------------===//
414 /// ASTViewer - AST Visualization
415
416 namespace {
417   class ASTViewer : public ASTConsumer {
418     SourceManager *SM;
419   public:
420     void Initialize(ASTContext &Context) {
421       SM = &Context.getSourceManager();
422     }
423     
424     virtual void HandleTopLevelDecl(Decl *D) {
425       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
426         DeclPrinter().PrintFunctionDeclStart(FD);
427         
428         if (FD->getBody()) {
429           llvm::cerr << '\n';
430           FD->getBody()->viewAST();
431           llvm::cerr << '\n';
432         }
433       }
434     }
435   };
436 }
437
438 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
439
440
441 //===----------------------------------------------------------------------===//
442 // CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
443 //   the CFGs for all function definitions.
444
445 namespace {
446
447 class CFGVisitor : public ASTConsumer {
448 public:
449   // CFG Visitor interface to be implemented by subclass.
450   virtual void VisitCFG(CFG& C, FunctionDecl& FD) = 0;
451   virtual bool printFuncDeclStart() { return true; }
452   
453   virtual void HandleTopLevelDecl(Decl *D);
454 };
455
456 } // end anonymous namespace
457
458 void CFGVisitor::HandleTopLevelDecl(Decl *D) {
459   FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
460   if (!FD || !FD->getBody())
461     return;
462       
463   if (printFuncDeclStart()) {
464     DeclPrinter().PrintFunctionDeclStart(FD);
465     llvm::cerr << '\n';
466   }
467     
468   CFG *C = CFG::buildCFG(FD->getBody());
469   VisitCFG(*C, *FD);
470   delete C;
471 }
472
473 //===----------------------------------------------------------------------===//
474 // DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
475
476 namespace {
477   class CFGDumper : public CFGVisitor {
478     const bool UseGraphviz;
479   public:
480     CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
481     
482     virtual void VisitCFG(CFG& C, FunctionDecl&) {
483       if (UseGraphviz)
484         C.viewCFG();
485       else
486         C.dump();
487     }
488   }; 
489 } // end anonymous namespace 
490   
491 ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
492   return new CFGDumper(ViewGraphs);
493 }
494
495 //===----------------------------------------------------------------------===//
496 // AnalyzeLiveVariables - perform live variable analysis and dump results
497
498 namespace {
499   class LivenessVisitor : public CFGVisitor {
500     SourceManager *SM;
501   public:
502     virtual void Initialize(ASTContext &Context) {
503       SM = &Context.getSourceManager();
504     }
505
506     virtual void VisitCFG(CFG& C, FunctionDecl& FD) {
507       LiveVariables L(C, FD);
508       L.runOnCFG(C);
509       L.dumpBlockLiveness(*SM);
510     }
511   };
512 } // end anonymous namespace
513   
514 ASTConsumer *clang::CreateLiveVarAnalyzer() {
515   return new LivenessVisitor();
516 }
517
518 //===----------------------------------------------------------------------===//
519 // DeadStores - run checker to locate dead stores in a function
520
521 namespace {
522   class DeadStoreVisitor : public CFGVisitor {
523     Diagnostic &Diags;
524     ASTContext *Ctx;
525   public:
526     DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
527     virtual void Initialize(ASTContext &Context) {
528       Ctx = &Context;
529     }
530     
531     virtual void VisitCFG(CFG& C, FunctionDecl& FD) {
532       CheckDeadStores(C, FD, *Ctx, Diags);
533     }
534     
535     virtual bool printFuncDeclStart() { return false; }
536   }; 
537 } // end anonymous namespace
538
539 ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
540   return new DeadStoreVisitor(Diags);
541 }
542
543 //===----------------------------------------------------------------------===//
544 // Unitialized Values - run checker to flag potential uses of uninitalized
545 //  variables.
546
547 namespace {
548   class UninitValsVisitor : public CFGVisitor {
549     Diagnostic &Diags;
550     ASTContext *Ctx;
551   public:
552     UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
553     virtual void Initialize(ASTContext &Context) {
554       Ctx = &Context;
555     }
556     
557     virtual void VisitCFG(CFG& C, FunctionDecl&) { 
558       CheckUninitializedValues(C, *Ctx, Diags);
559     }
560     
561     virtual bool printFuncDeclStart() { return false; }
562   }; 
563 } // end anonymous namespace
564
565 ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
566   return new UninitValsVisitor(Diags);
567 }
568
569 //===----------------------------------------------------------------------===//
570 // GRConstants - Perform intra-procedural, path-sensitive constant propagation.
571
572 namespace {
573   class GRConstantsVisitor : public CFGVisitor {
574     ASTContext* Ctx;
575   public:
576     
577     virtual void Initialize(ASTContext &Context) { Ctx = &Context; }    
578     virtual void VisitCFG(CFG& C, FunctionDecl&);
579   };
580 } // end anonymous namespace
581
582 ASTConsumer* clang::CreateGRConstants() {
583   return new GRConstantsVisitor();
584 }
585
586 void GRConstantsVisitor::VisitCFG(CFG& C, FunctionDecl& FD) {
587   RunGRConstants(C, FD, *Ctx);
588 }
589
590 //===----------------------------------------------------------------------===//
591 // LLVM Emitter
592
593 #include "clang/Basic/Diagnostic.h"
594 #include "clang/Basic/TargetInfo.h"
595 #include "clang/CodeGen/ModuleBuilder.h"
596 #include "llvm/Module.h"
597 #include "llvm/Target/TargetData.h"
598 #include "llvm/Target/TargetMachine.h"
599 #include "llvm/Bitcode/ReaderWriter.h"
600
601 namespace {
602   class CodeGenerator : public ASTConsumer {
603     Diagnostic &Diags;
604     const llvm::TargetData *TD;
605     ASTContext *Ctx;
606     const LangOptions &Features;
607   protected:
608     llvm::Module *&M;
609     CodeGen::CodeGenModule *Builder;
610   public:
611     CodeGenerator(Diagnostic &diags, const LangOptions &LO,
612                   llvm::Module *&DestModule)
613       : Diags(diags), Features(LO), M(DestModule) {}
614     
615     ~CodeGenerator() {
616       CodeGen::Terminate(Builder);
617     }
618     
619     virtual void Initialize(ASTContext &Context) {
620       Ctx = &Context;
621       
622       M->setTargetTriple(Ctx->Target.getTargetTriple());
623       M->setDataLayout(Ctx->Target.getTargetDescription());
624       TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
625       Builder = CodeGen::Init(Context, Features, *M, *TD, Diags);
626     }
627     
628     virtual void HandleTopLevelDecl(Decl *D) {
629       // If an error occurred, stop code generation, but continue parsing and
630       // semantic analysis (to ensure all warnings and errors are emitted).
631       if (Diags.hasErrorOccurred())
632         return;
633       
634       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
635         CodeGen::CodeGenFunction(Builder, FD);
636       } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
637         CodeGen::CodeGenGlobalVar(Builder, FVD);
638       } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
639         CodeGen::CodeGenLinkageSpec(Builder, LSD);
640       } else {
641         CodeGen::CodeGenTypeDecl(Builder, cast<TypeDecl>(D));
642       }
643     }
644   };
645 }
646
647 ASTConsumer *clang::CreateLLVMCodeGen(Diagnostic &Diags, 
648                                       const LangOptions &Features,
649                                       llvm::Module *&DestModule) {
650   return new CodeGenerator(Diags, Features, DestModule);
651 }
652
653 //===----------------------------------------------------------------------===//
654 // AST Serializer
655
656 namespace {
657
658 class ASTSerializer : public ASTConsumer {
659 protected:
660   Diagnostic &Diags;
661   TranslationUnit TU;
662 public:
663   ASTSerializer(Diagnostic& diags, const LangOptions& LO)
664     : Diags(diags), TU(LO) {}
665   
666   virtual void Initialize(ASTContext &Context) {
667     TU.setContext(&Context);
668   }
669   
670   virtual void HandleTopLevelDecl(Decl *D) {
671     if (Diags.hasErrorOccurred())
672       return;
673     
674     TU.AddTopLevelDecl(D);
675   }
676 };
677     
678 class SingleFileSerializer : public ASTSerializer {
679   const llvm::sys::Path FName;
680 public:
681   SingleFileSerializer(const llvm::sys::Path& F, Diagnostic &diags,
682                           const LangOptions &LO)
683   : ASTSerializer(diags,LO), FName(F) {}    
684   
685   ~SingleFileSerializer() {
686     EmitASTBitcodeFile(TU,FName);
687   }
688 };
689
690 class BuildSerializer : public ASTSerializer {
691   llvm::sys::Path EmitDir;  
692 public:
693   BuildSerializer(const llvm::sys::Path& dir, Diagnostic &diags,
694                   const LangOptions &LO)
695   : ASTSerializer(diags,LO), EmitDir(dir) {}
696   
697   ~BuildSerializer() {
698     SourceManager& SourceMgr = TU.getASTContext()->getSourceManager();
699     unsigned ID = SourceMgr.getMainFileID();
700     assert (ID && "MainFileID not set!");
701     const FileEntry* FE = SourceMgr.getFileEntryForID(ID);
702     assert (FE && "No FileEntry for main file.");
703     
704     // FIXME: This is not portable to Windows.
705     // FIXME: This logic should probably be moved elsewhere later.
706         
707     llvm::sys::Path FName(EmitDir);
708     
709     std::vector<char> buf;
710     buf.reserve(strlen(FE->getName())+100);    
711     
712     sprintf(&buf[0], "dev_%llx", (uint64_t) FE->getDevice());
713     FName.appendComponent(&buf[0]);
714     FName.createDirectoryOnDisk(true);
715     if (!FName.canWrite() || !FName.isDirectory()) {
716       assert (false && "Could not create 'device' serialization directory.");
717       return;
718     }
719             
720     sprintf(&buf[0], "%s-%llX.ast", FE->getName(), (uint64_t) FE->getInode());
721     FName.appendComponent(&buf[0]);    
722     EmitASTBitcodeFile(TU,FName);
723     
724     // Now emit the sources.
725     
726   }
727 };
728   
729   
730 } // end anonymous namespace
731
732
733 ASTConsumer* clang::CreateASTSerializer(const std::string& InFile,
734                                         const std::string& OutputFile,
735                                         Diagnostic &Diags,
736                                         const LangOptions &Features) {
737   
738   if (OutputFile.size()) {
739     if (InFile == "-") {
740       llvm::cerr <<
741         "error: Cannot use --serialize with -o for source read from STDIN.\n";
742       return NULL;
743     }
744     
745     // The user specified an AST-emission directory.  Determine if the path
746     // is absolute.    
747     llvm::sys::Path EmitDir(OutputFile);
748     
749     if (!EmitDir.isAbsolute()) {
750       llvm::cerr << 
751         "error: Output directory for --serialize must be an absolute path.\n";
752       
753       return NULL;
754     }
755     
756     // Create the directory if it does not exist.
757     EmitDir.createDirectoryOnDisk(true);
758     if (!EmitDir.canWrite() || !EmitDir.isDirectory()) {
759       llvm::cerr <<
760         "error: Could not create output directory for --serialize.\n";
761       
762       return NULL;
763     }
764     
765     // FIXME: We should probably only allow using BuildSerializer when
766     // the ASTs come from parsed source files, and not from .ast files.
767     return new BuildSerializer(EmitDir, Diags, Features);
768   }
769
770   // The user did not specify an output directory for serialized ASTs.
771   // Serialize the translation to a single file whose name is the same
772   // as the input file with the ".ast" extension appended.
773   
774   llvm::sys::Path FName(InFile.c_str());
775   FName.appendSuffix("ast");
776   return new SingleFileSerializer(FName, Diags, Features);  
777 }