blob: 3c07c370770db48e6316adffc42e9e7f7a4d198a [file] [log] [blame]
Chris Lattnereb8c9632007-10-07 06:04:32 +00001//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
Chris Lattner4b009652007-07-25 00:24:17 +00002//
3// The LLVM Compiler Infrastructure
4//
Chris Lattnereb8c9632007-10-07 06:04:32 +00005// This file was developed by Chris Lattner and is distributed under the
Chris Lattner4b009652007-07-25 00:24:17 +00006// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattnereb8c9632007-10-07 06:04:32 +000010// AST Consumer Implementations.
Chris Lattner4b009652007-07-25 00:24:17 +000011//
12//===----------------------------------------------------------------------===//
13
Chris Lattnereb8c9632007-10-07 06:04:32 +000014#include "ASTConsumers.h"
Chris Lattner4b009652007-07-25 00:24:17 +000015#include "clang/AST/AST.h"
Chris Lattnerb73abd52007-09-15 23:02:28 +000016#include "clang/AST/ASTConsumer.h"
Ted Kremenek97f75312007-08-21 21:42:03 +000017#include "clang/AST/CFG.h"
Ted Kremenekaa04c512007-09-06 00:17:54 +000018#include "clang/Analysis/LiveVariables.h"
Ted Kremeneke805c4a2007-09-06 23:00:42 +000019#include "clang/Analysis/LocalCheckers.h"
Chris Lattner95578782007-08-08 22:51:59 +000020using namespace clang;
Chris Lattner4b009652007-07-25 00:24:17 +000021
Chris Lattner95578782007-08-08 22:51:59 +000022
23static void PrintFunctionDeclStart(FunctionDecl *FD) {
Chris Lattner4b009652007-07-25 00:24:17 +000024 bool HasBody = FD->getBody();
25
Chris Lattner987058a2007-08-26 04:02:13 +000026 fprintf(stderr, "\n");
27
28 switch (FD->getStorageClass()) {
29 default: assert(0 && "Unknown storage class");
30 case FunctionDecl::None: break;
31 case FunctionDecl::Extern: fprintf(stderr, "extern "); break;
32 case FunctionDecl::Static: fprintf(stderr, "static "); break;
33 }
34
35 if (FD->isInline())
36 fprintf(stderr, "inline ");
37
Chris Lattner4b009652007-07-25 00:24:17 +000038 std::string Proto = FD->getName();
39 FunctionType *AFT = cast<FunctionType>(FD->getType());
40
41 if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
42 Proto += "(";
43 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
44 if (i) Proto += ", ";
45 std::string ParamStr;
46 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
47
48 FT->getArgType(i).getAsStringInternal(ParamStr);
49 Proto += ParamStr;
50 }
51
52 if (FT->isVariadic()) {
53 if (FD->getNumParams()) Proto += ", ";
54 Proto += "...";
55 }
56 Proto += ")";
57 } else {
58 assert(isa<FunctionTypeNoProto>(AFT));
59 Proto += "()";
60 }
61
62 AFT->getResultType().getAsStringInternal(Proto);
Chris Lattner987058a2007-08-26 04:02:13 +000063 fprintf(stderr, "%s", Proto.c_str());
Chris Lattner4b009652007-07-25 00:24:17 +000064
Chris Lattner95578782007-08-08 22:51:59 +000065 if (!FD->getBody())
Chris Lattner4b009652007-07-25 00:24:17 +000066 fprintf(stderr, ";\n");
Chris Lattner95578782007-08-08 22:51:59 +000067 // Doesn't print the body.
Chris Lattner4b009652007-07-25 00:24:17 +000068}
69
Chris Lattner95578782007-08-08 22:51:59 +000070static void PrintTypeDefDecl(TypedefDecl *TD) {
Chris Lattner4b009652007-07-25 00:24:17 +000071 std::string S = TD->getName();
72 TD->getUnderlyingType().getAsStringInternal(S);
73 fprintf(stderr, "typedef %s;\n", S.c_str());
74}
75
Steve Narofffaed3bf2007-09-10 20:51:04 +000076static void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
Fariborz Jahanianc04aff12007-10-08 23:06:41 +000077 std::string I = OID->getName();
78 ObjcInterfaceDecl *SID = OID->getSuperClass();
79 if (SID) {
80 std::string S = SID->getName();
81 fprintf(stderr, "@interface %s : %s", I.c_str(), S.c_str());
82 }
83 else
84 fprintf(stderr, "@interface %s", I.c_str());
85 // Protocols?
86 int count = OID->getNumIntfRefProtocols();
87 if (count > 0) {
88 ObjcProtocolDecl **refProtocols = OID->getReferencedProtocols();
89 for (int i = 0; i < count; i++)
90 fprintf(stderr, "%c%s", (i == 0 ? '<' : ','),
91 refProtocols[i]->getName());
92 }
93 if (count > 0)
Fariborz Jahanianf468b312007-10-26 16:29:12 +000094 fprintf(stderr, ">\n");
Fariborz Jahanianc04aff12007-10-08 23:06:41 +000095 else
Fariborz Jahanianf468b312007-10-26 16:29:12 +000096 fprintf(stderr, "\n");
97
98 int NumIvars = OID->getIntfDeclNumIvars();
99 if (NumIvars > 0) {
100 ObjcIvarDecl **Ivars = OID->getIntfDeclIvars();
101 fprintf(stderr,"{");
102 for (int i = 0; i < NumIvars; i++) {
103 fprintf(stderr, "\t%s %s;\n", Ivars[i]->getType().getAsString().c_str(),
104 Ivars[i]->getName());
105 }
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000106 fprintf(stderr, "}\n");
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000107 }
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000108
109 int NumProperties = OID->getNumPropertyDecl();
110 if (NumProperties > 0) {
111 for (int i = 0; i < NumProperties; i++) {
112 ObjcPropertyDecl *PDecl = OID->getPropertyDecl()[i];
113 fprintf(stderr, "@property");
114 if (PDecl->getPropertyAttributes() != ObjcPropertyDecl::OBJC_PR_noattr) {
115 bool first = true;
116 fprintf(stderr, " (");
117 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readonly)
118 {
119 fprintf(stderr, "%creadonly", first ? ' ' : ',');
120 first = false;
121 }
122
123 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_getter)
124 {
125 fprintf(stderr, "%cgetter = %s", first ? ' ' : ','
126 , PDecl->getGetterName()->getName());
127 first = false;
128 }
129 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_setter)
130 {
131 fprintf(stderr, "%csetter = %s:", first ? ' ' : ','
132 , PDecl->getSetterName()->getName());
133 first = false;
134 }
135
136 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_assign)
137 {
138 fprintf(stderr, "%cassign", first ? ' ' : ',');
139 first = false;
140 }
141
142 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readwrite)
143 {
144 fprintf(stderr, "%creadwrite", first ? ' ' : ',');
145 first = false;
146 }
147
148 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_retain)
149 {
150 fprintf(stderr, "%cretain", first ? ' ' : ',');
151 first = false;
152 }
153
154 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_copy)
155 {
156 fprintf(stderr, "%ccopy", first ? ' ' : ',');
157 first = false;
158 }
159
160 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_nonatomic)
161 {
162 fprintf(stderr, "%cnonatomic", first ? ' ' : ',');
163 first = false;
164 }
165 fprintf(stderr, " )");
166 }
167 ObjcIvarDecl **IDecl = PDecl->getPropertyDecls();
168 fprintf(stderr, " %s %s", IDecl[0]->getType().getAsString().c_str(),
169 IDecl[0]->getName());
170
171 for (int j = 1; j < PDecl->getNumPropertyDecls(); j++) {
172 fprintf(stderr, ", %s", IDecl[j]->getName());
173 }
174 fprintf(stderr, ";\n");
175 }
176 }
177 fprintf(stderr,"@end\n");
Steve Narofffaed3bf2007-09-10 20:51:04 +0000178 // FIXME: implement the rest...
179}
180
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000181static void PrintObjcProtocolDecl(ObjcProtocolDecl *PID) {
182 std::string S = PID->getName();
183 fprintf(stderr, "@protocol %s;\n", S.c_str());
184 // FIXME: implement the rest...
185}
186
187static void PrintObjcCategoryImplDecl(ObjcCategoryImplDecl *PID) {
188 std::string S = PID->getName();
189 std::string I = PID->getClassInterface()->getName();
190 fprintf(stderr, "@implementation %s(%s);\n", I.c_str(), S.c_str());
191 // FIXME: implement the rest...
192}
193
194static void PrintObjcCategoryDecl(ObjcCategoryDecl *PID) {
195 std::string S = PID->getName();
196 std::string I = PID->getClassInterface()->getName();
197 fprintf(stderr, "@interface %s(%s);\n", I.c_str(), S.c_str());
198 // FIXME: implement the rest...
199}
200
Fariborz Jahanian05d212a2007-10-11 23:42:27 +0000201static void PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID) {
202 std::string A = AID->getName();
203 std::string I = AID->getClassInterface()->getName();
204 fprintf(stderr, "@compatibility_alias %s %s;\n", A.c_str(), I.c_str());
205}
206
Chris Lattnerb73abd52007-09-15 23:02:28 +0000207namespace {
208 class ASTPrinter : public ASTConsumer {
209 virtual void HandleTopLevelDecl(Decl *D) {
210 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
211 PrintFunctionDeclStart(FD);
212
213 if (FD->getBody()) {
214 fprintf(stderr, " ");
215 FD->getBody()->dumpPretty();
216 fprintf(stderr, "\n");
217 }
218 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
219 PrintTypeDefDecl(TD);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000220 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
221 PrintObjcInterfaceDecl(OID);
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000222 } else if (ObjcProtocolDecl *PID = dyn_cast<ObjcProtocolDecl>(D)) {
223 PrintObjcProtocolDecl(PID);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000224 } else if (ObjcForwardProtocolDecl *OFPD =
225 dyn_cast<ObjcForwardProtocolDecl>(D)) {
226 fprintf(stderr, "@protocol ");
227 for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
228 const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
229 if (i) fprintf(stderr, ", ");
230 fprintf(stderr, "%s", D->getName());
231 }
Chris Lattnera845bbe2007-10-06 19:08:22 +0000232 fprintf(stderr, ";\n");
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000233 } else if (ObjcImplementationDecl *OID =
234 dyn_cast<ObjcImplementationDecl>(D)) {
235 fprintf(stderr, "@implementation %s [printing todo]\n",
236 OID->getName());
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000237 } else if (ObjcCategoryImplDecl *OID =
238 dyn_cast<ObjcCategoryImplDecl>(D)) {
239 PrintObjcCategoryImplDecl(OID);
240 } else if (ObjcCategoryDecl *OID =
241 dyn_cast<ObjcCategoryDecl>(D)) {
242 PrintObjcCategoryDecl(OID);
Fariborz Jahanian05d212a2007-10-11 23:42:27 +0000243 } else if (ObjcCompatibleAliasDecl *OID =
244 dyn_cast<ObjcCompatibleAliasDecl>(D)) {
245 PrintObjcCompatibleAliasDecl(OID);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000246 } else if (isa<ObjcClassDecl>(D)) {
247 fprintf(stderr, "@class [printing todo]\n");
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000248 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
249 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000250 } else {
251 assert(0 && "Unknown decl type!");
Chris Lattner95578782007-08-08 22:51:59 +0000252 }
Chris Lattner4b009652007-07-25 00:24:17 +0000253 }
Chris Lattnerb73abd52007-09-15 23:02:28 +0000254 };
Chris Lattner4b009652007-07-25 00:24:17 +0000255}
Chris Lattner95578782007-08-08 22:51:59 +0000256
Chris Lattnerb73abd52007-09-15 23:02:28 +0000257ASTConsumer *clang::CreateASTPrinter() { return new ASTPrinter(); }
258
259namespace {
260 class ASTDumper : public ASTConsumer {
261 SourceManager *SM;
262 public:
263 void Initialize(ASTContext &Context, unsigned MainFileID) {
264 SM = &Context.SourceMgr;
Chris Lattner95578782007-08-08 22:51:59 +0000265 }
Chris Lattnerb73abd52007-09-15 23:02:28 +0000266
267 virtual void HandleTopLevelDecl(Decl *D) {
268 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
269 PrintFunctionDeclStart(FD);
270
271 if (FD->getBody()) {
272 fprintf(stderr, "\n");
273 FD->getBody()->dumpAll(*SM);
274 fprintf(stderr, "\n");
275 }
276 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
277 PrintTypeDefDecl(TD);
278 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
279 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000280 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
281 fprintf(stderr, "Read objc interface '%s'\n", OID->getName());
Steve Naroffd5d18732007-10-14 17:03:01 +0000282 } else if (ObjcProtocolDecl *OPD = dyn_cast<ObjcProtocolDecl>(D)) {
283 fprintf(stderr, "Read objc protocol '%s'\n", OPD->getName());
284 } else if (ObjcCategoryDecl *OCD = dyn_cast<ObjcCategoryDecl>(D)) {
285 fprintf(stderr, "Read objc category '%s'\n", OCD->getName());
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000286 } else if (isa<ObjcForwardProtocolDecl>(D)) {
287 fprintf(stderr, "Read objc fwd protocol decl\n");
Steve Naroffd5d18732007-10-14 17:03:01 +0000288 } else if (isa<ObjcClassDecl>(D)) {
289 fprintf(stderr, "Read objc fwd class decl\n");
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000290 } else {
291 assert(0 && "Unknown decl type!");
Chris Lattnerb73abd52007-09-15 23:02:28 +0000292 }
293 }
294 };
Chris Lattner95578782007-08-08 22:51:59 +0000295}
296
Chris Lattnerb73abd52007-09-15 23:02:28 +0000297ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
298
Ted Kremenekb6976a22007-09-19 21:29:43 +0000299namespace {
300 class ASTViewer : public ASTConsumer {
301 SourceManager *SM;
302 public:
303 void Initialize(ASTContext &Context, unsigned MainFileID) {
304 SM = &Context.SourceMgr;
305 }
306
307 virtual void HandleTopLevelDecl(Decl *D) {
308 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
309 PrintFunctionDeclStart(FD);
310
311 if (FD->getBody()) {
312 fprintf(stderr, "\n");
313 FD->getBody()->viewAST();
314 fprintf(stderr, "\n");
315 }
316 }
317 }
318 };
319}
320
321ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
322
323
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000324//===----------------------------------------------------------------------===//
325// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
326// the CFGs for all function definitions.
327
328namespace {
329
Chris Lattner52332d02007-09-15 23:21:08 +0000330class CFGVisitor : public ASTConsumer {
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000331public:
Chris Lattner52332d02007-09-15 23:21:08 +0000332 // CFG Visitor interface to be implemented by subclass.
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000333 virtual void VisitCFG(CFG& C) = 0;
334 virtual bool printFuncDeclStart() { return true; }
Chris Lattner52332d02007-09-15 23:21:08 +0000335
336 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000337};
338
339} // end anonymous namespace
340
Chris Lattner52332d02007-09-15 23:21:08 +0000341void CFGVisitor::HandleTopLevelDecl(Decl *D) {
342 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
343 if (!FD || !FD->getBody())
344 return;
345
346 if (printFuncDeclStart()) {
347 PrintFunctionDeclStart(FD);
348 fprintf(stderr,"\n");
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000349 }
Chris Lattner52332d02007-09-15 23:21:08 +0000350
Ted Kremenek3e88d752007-09-17 17:10:02 +0000351 CFG *C = CFG::buildCFG(FD->getBody());
352 VisitCFG(*C);
353 delete C;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000354}
355
356//===----------------------------------------------------------------------===//
357// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
358
359namespace {
360 class CFGDumper : public CFGVisitor {
361 const bool UseGraphviz;
362 public:
363 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
364
Chris Lattner52332d02007-09-15 23:21:08 +0000365 virtual void VisitCFG(CFG &C) {
366 if (UseGraphviz)
367 C.viewCFG();
368 else
369 C.dump();
370 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000371 };
372} // end anonymous namespace
373
Chris Lattner52332d02007-09-15 23:21:08 +0000374ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
375 return new CFGDumper(ViewGraphs);
Ted Kremenek97f75312007-08-21 21:42:03 +0000376}
377
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000378//===----------------------------------------------------------------------===//
379// AnalyzeLiveVariables - perform live variable analysis and dump results
380
381namespace {
382 class LivenessVisitor : public CFGVisitor {
Chris Lattner52332d02007-09-15 23:21:08 +0000383 SourceManager *SM;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000384 public:
Chris Lattner52332d02007-09-15 23:21:08 +0000385 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
386 SM = &Context.SourceMgr;
387 }
388
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000389 virtual void VisitCFG(CFG& C) {
Ted Kremenek8ce772b2007-10-01 20:33:52 +0000390 LiveVariables L(C);
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000391 L.runOnCFG(C);
Ted Kremenekd7a2f812007-09-25 04:31:27 +0000392 L.dumpBlockLiveness(*SM);
Ted Kremenekaa04c512007-09-06 00:17:54 +0000393 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000394 };
395} // end anonymous namespace
396
Chris Lattner52332d02007-09-15 23:21:08 +0000397ASTConsumer *clang::CreateLiveVarAnalyzer() {
398 return new LivenessVisitor();
Ted Kremenekaa04c512007-09-06 00:17:54 +0000399}
400
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000401//===----------------------------------------------------------------------===//
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000402// DeadStores - run checker to locate dead stores in a function
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000403
404namespace {
405 class DeadStoreVisitor : public CFGVisitor {
Chris Lattner52332d02007-09-15 23:21:08 +0000406 Diagnostic &Diags;
407 ASTContext *Ctx;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000408 public:
Chris Lattner52332d02007-09-15 23:21:08 +0000409 DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
410 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
411 Ctx = &Context;
412 }
413
414 virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
Ted Kremenek39b8c4b2007-09-07 23:54:15 +0000415 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000416 };
417} // end anonymous namespace
418
Chris Lattner52332d02007-09-15 23:21:08 +0000419ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
420 return new DeadStoreVisitor(Diags);
Ted Kremeneke805c4a2007-09-06 23:00:42 +0000421}
Chris Lattner129758d2007-09-16 19:46:59 +0000422
423//===----------------------------------------------------------------------===//
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000424// Unitialized Values - run checker to flag potential uses of uninitalized
425// variables.
426
427namespace {
428 class UninitValsVisitor : public CFGVisitor {
429 Diagnostic &Diags;
430 ASTContext *Ctx;
431 public:
432 UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
433 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
434 Ctx = &Context;
435 }
436
437 virtual void VisitCFG(CFG& C) { CheckUninitializedValues(C, *Ctx, Diags); }
438 virtual bool printFuncDeclStart() { return false; }
439 };
440} // end anonymous namespace
441
442ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
443 return new UninitValsVisitor(Diags);
444}
445
446//===----------------------------------------------------------------------===//
Chris Lattner129758d2007-09-16 19:46:59 +0000447// LLVM Emitter
448
449#include "clang/Basic/Diagnostic.h"
Devang Patela8fccb82007-10-31 20:01:01 +0000450#include "clang/Basic/TargetInfo.h"
Chris Lattner129758d2007-09-16 19:46:59 +0000451#include "clang/CodeGen/ModuleBuilder.h"
452#include "llvm/Module.h"
Devang Patela8fccb82007-10-31 20:01:01 +0000453#include "llvm/Target/TargetData.h"
454#include "llvm/Target/TargetMachine.h"
Chris Lattner129758d2007-09-16 19:46:59 +0000455#include <iostream>
456
457namespace {
458 class LLVMEmitter : public ASTConsumer {
459 Diagnostic &Diags;
460 llvm::Module *M;
Devang Patela8fccb82007-10-31 20:01:01 +0000461 const llvm::TargetData *TD;
Chris Lattner129758d2007-09-16 19:46:59 +0000462 ASTContext *Ctx;
463 CodeGen::BuilderTy *Builder;
464 public:
465 LLVMEmitter(Diagnostic &diags) : Diags(diags) {}
466 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
467 Ctx = &Context;
468 M = new llvm::Module("foo");
Devang Patela8fccb82007-10-31 20:01:01 +0000469 M->setTargetTriple(Ctx->Target.getTargetTriple());
470 TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
471 Builder = CodeGen::Init(Context, *M, *TD);
Chris Lattner129758d2007-09-16 19:46:59 +0000472 }
473
474 virtual void HandleTopLevelDecl(Decl *D) {
475 // If an error occurred, stop code generation, but continue parsing and
476 // semantic analysis (to ensure all warnings and errors are emitted).
477 if (Diags.hasErrorOccurred())
478 return;
479
480 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
481 CodeGen::CodeGenFunction(Builder, FD);
482 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
483 CodeGen::CodeGenGlobalVar(Builder, FVD);
484 } else {
485 assert(isa<TypedefDecl>(D) && "Only expected typedefs here");
486 // don't codegen for now, eventually pass down for debug info.
487 //std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n";
488 }
489 }
490
491 ~LLVMEmitter() {
492 CodeGen::Terminate(Builder);
493
494 // Print the generated code.
495 M->print(std::cout);
496 delete M;
497 }
498 };
499} // end anonymous namespace
500
501ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags) {
502 return new LLVMEmitter(Diags);
503}
504