blob: 9d7758648d527a7625b13de0e4337fbc0d0065e1 [file] [log] [blame]
Ted Kremenekcc927092007-12-13 17:54:02 +00001//===--- TranslationUnit.cpp - Abstraction for Translation Units ----------===//
Ted Kremenek2f743592007-12-05 21:36:08 +00002//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Ted Kremenek2f743592007-12-05 21:36:08 +00007//
8// FIXME: This should eventually be moved out of the driver, or replaced
9// with its eventual successor.
10//
11//===----------------------------------------------------------------------===//
12
Ted Kremenek525fdbc2007-12-18 21:36:21 +000013#include "clang/AST/TranslationUnit.h"
Ted Kremenek2f743592007-12-05 21:36:08 +000014
15#include "clang/Basic/TargetInfo.h"
16#include "clang/Basic/SourceManager.h"
17#include "clang/AST/AST.h"
18
19#include "llvm/Bitcode/Serialize.h"
20#include "llvm/Bitcode/Deserialize.h"
21#include "llvm/Support/MemoryBuffer.h"
22#include "llvm/System/Path.h"
Ted Kremenek2f743592007-12-05 21:36:08 +000023
Ted Kremenek27f8a282008-05-20 00:43:19 +000024#include "llvm/ADT/OwningPtr.h"
25#include "llvm/ADT/DenseSet.h"
Ted Kremenek2f743592007-12-05 21:36:08 +000026
Ted Kremenek2f743592007-12-05 21:36:08 +000027using namespace clang;
28
Ted Kremenek63ea8632007-12-19 19:27:38 +000029enum { BasicMetadataBlock = 1,
30 ASTContextBlock = 2,
31 DeclsBlock = 3 };
32
Sam Bishop0f9c72f2008-04-03 14:20:28 +000033TranslationUnit::~TranslationUnit() {
Ted Kremenek27f8a282008-05-20 00:43:19 +000034
35 llvm::DenseSet<Decl*> Killed;
36
37 for (iterator I=begin(), E=end(); I!=E; ++I) {
38 if (Killed.count(*I)) continue;
39
40 Killed.insert(*I);
Sam Bishopbb45c512008-04-11 15:01:25 +000041 (*I)->Destroy(*Context);
Ted Kremenek27f8a282008-05-20 00:43:19 +000042 }
Ted Kremenekc1e9dea2008-04-23 16:25:39 +000043
44 if (OwnsMetaData && Context) {
45 // The ASTContext object has the sole references to the IdentifierTable
46 // Selectors, and the Target information. Go and delete them, since
47 // the TranslationUnit effectively owns them.
48
49 delete &(Context->Idents);
50 delete &(Context->Selectors);
51 delete &(Context->Target);
52 delete Context;
53 }
Sam Bishop71de20e2008-04-03 05:35:20 +000054}
Ted Kremenek63ea8632007-12-19 19:27:38 +000055
Ted Kremenekc1e9dea2008-04-23 16:25:39 +000056bool clang::EmitASTBitcodeFile(const TranslationUnit* TU,
57 const llvm::sys::Path& Filename) {
58
59 return TU ? EmitASTBitcodeFile(*TU, Filename) : false;
60}
61
Ted Kremenekdca29272007-12-18 21:44:50 +000062bool clang::EmitASTBitcodeFile(const TranslationUnit& TU,
63 const llvm::sys::Path& Filename) {
Ted Kremenekc1e9dea2008-04-23 16:25:39 +000064
Ted Kremenek2f743592007-12-05 21:36:08 +000065 // Reserve 256K for bitstream buffer.
66 std::vector<unsigned char> Buffer;
67 Buffer.reserve(256*1024);
68
69 // Create bitstream.
70 llvm::BitstreamWriter Stream(Buffer);
71
72 // Emit the preamble.
73 Stream.Emit((unsigned)'B', 8);
74 Stream.Emit((unsigned)'C', 8);
75 Stream.Emit(0xC, 4);
76 Stream.Emit(0xF, 4);
77 Stream.Emit(0xE, 4);
78 Stream.Emit(0x0, 4);
79
80 {
81 // Create serializer. Placing it in its own scope assures any necessary
82 // finalization of bits to the buffer in the serializer's dstor.
83 llvm::Serializer Sezr(Stream);
84
85 // Emit the translation unit.
Ted Kremenekdca29272007-12-18 21:44:50 +000086 TU.Emit(Sezr);
Ted Kremenek2f743592007-12-05 21:36:08 +000087 }
88
89 // Write the bits to disk.
90 if (FILE* fp = fopen(Filename.c_str(),"wb")) {
91 fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
92 fclose(fp);
93 return true;
94 }
95
96 return false;
97}
98
99void TranslationUnit::Emit(llvm::Serializer& Sezr) const {
100
101 // ===---------------------------------------------------===/
102 // Serialize the top-level decls.
103 // ===---------------------------------------------------===/
104
105 Sezr.EnterBlock(DeclsBlock);
106
107 // Only serialize the head of a decl chain. The ASTConsumer interfaces
108 // provides us with each top-level decl, including those nested in
109 // a decl chain, so we may be passed decls that are already serialized.
110 for (const_iterator I=begin(), E=end(); I!=E; ++I)
111 if (!Sezr.isRegistered(*I))
112 Sezr.EmitOwnedPtr(*I);
113
114 Sezr.ExitBlock();
115
116 // ===---------------------------------------------------===/
117 // Serialize the "Translation Unit" metadata.
118 // ===---------------------------------------------------===/
119
120 // Emit ASTContext.
121 Sezr.EnterBlock(ASTContextBlock);
122 Sezr.EmitOwnedPtr(Context);
123 Sezr.ExitBlock();
124
125 Sezr.EnterBlock(BasicMetadataBlock);
126
127 // Block for SourceManager, LangOptions, and Target. Allows easy skipping
128 // around to the block for the Selectors during deserialization.
129 Sezr.EnterBlock();
Ted Kremenekfdfc1982007-12-19 22:24:34 +0000130
Ted Kremenek2f743592007-12-05 21:36:08 +0000131 // Emit the SourceManager.
Ted Kremenek7a9d49f2007-12-11 21:27:55 +0000132 Sezr.Emit(Context->getSourceManager());
Ted Kremenek2f743592007-12-05 21:36:08 +0000133
134 // Emit the LangOptions.
135 Sezr.Emit(LangOpts);
136
137 // Emit the Target.
138 Sezr.EmitPtr(&Context->Target);
139 Sezr.EmitCStr(Context->Target.getTargetTriple());
140
141 Sezr.ExitBlock(); // exit "BasicMetadataBlock"
142
143 // Emit the Selectors.
144 Sezr.Emit(Context->Selectors);
145
146 // Emit the Identifier Table.
147 Sezr.Emit(Context->Idents);
148
149 Sezr.ExitBlock(); // exit "ASTContextBlock"
150}
151
Ted Kremeneka1fa3a12007-12-13 00:37:31 +0000152TranslationUnit*
Ted Kremenekdca29272007-12-18 21:44:50 +0000153clang::ReadASTBitcodeFile(const llvm::sys::Path& Filename, FileManager& FMgr) {
Ted Kremenek2f743592007-12-05 21:36:08 +0000154
155 // Create the memory buffer that contains the contents of the file.
Ted Kremenekee533642007-12-20 19:47:16 +0000156 llvm::OwningPtr<llvm::MemoryBuffer>
Chris Lattner35de5122008-04-01 18:04:30 +0000157 MBuffer(llvm::MemoryBuffer::getFile(Filename.c_str()));
Ted Kremenek2f743592007-12-05 21:36:08 +0000158
159 if (!MBuffer) {
160 // FIXME: Provide diagnostic.
161 return NULL;
162 }
163
164 // Check if the file is of the proper length.
165 if (MBuffer->getBufferSize() & 0x3) {
166 // FIXME: Provide diagnostic: "Length should be a multiple of 4 bytes."
167 return NULL;
168 }
169
170 // Create the bitstream reader.
171 unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
172 llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
173
174 if (Stream.Read(8) != 'B' ||
175 Stream.Read(8) != 'C' ||
176 Stream.Read(4) != 0xC ||
177 Stream.Read(4) != 0xF ||
178 Stream.Read(4) != 0xE ||
179 Stream.Read(4) != 0x0) {
180 // FIXME: Provide diagnostic.
181 return NULL;
182 }
183
184 // Create the deserializer.
185 llvm::Deserializer Dezr(Stream);
186
Ted Kremenekdca29272007-12-18 21:44:50 +0000187 return TranslationUnit::Create(Dezr,FMgr);
Ted Kremenek2f743592007-12-05 21:36:08 +0000188}
189
190TranslationUnit* TranslationUnit::Create(llvm::Deserializer& Dezr,
191 FileManager& FMgr) {
192
193 // Create the translation unit object.
194 TranslationUnit* TU = new TranslationUnit();
195
196 // ===---------------------------------------------------===/
197 // Deserialize the "Translation Unit" metadata.
198 // ===---------------------------------------------------===/
199
200 // Skip to the BasicMetaDataBlock. First jump to ASTContextBlock
201 // (which will appear earlier) and record its location.
202
203 bool FoundBlock = Dezr.SkipToBlock(ASTContextBlock);
204 assert (FoundBlock);
205
206 llvm::Deserializer::Location ASTContextBlockLoc =
207 Dezr.getCurrentBlockLocation();
208
209 FoundBlock = Dezr.SkipToBlock(BasicMetadataBlock);
210 assert (FoundBlock);
Ted Kremenek63ea8632007-12-19 19:27:38 +0000211
Ted Kremenek2f743592007-12-05 21:36:08 +0000212 // Read the SourceManager.
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000213 SourceManager::CreateAndRegister(Dezr,FMgr);
Ted Kremenek2f743592007-12-05 21:36:08 +0000214
215 // Read the LangOptions.
216 TU->LangOpts.Read(Dezr);
217
Ted Kremenekbbced582007-12-12 18:05:32 +0000218 { // Read the TargetInfo.
Ted Kremenek2f743592007-12-05 21:36:08 +0000219 llvm::SerializedPtrID PtrID = Dezr.ReadPtrID();
220 char* triple = Dezr.ReadCStr(NULL,0,true);
Ted Kremenekc1e9dea2008-04-23 16:25:39 +0000221 Dezr.RegisterPtr(PtrID, TargetInfo::CreateTargetInfo(std::string(triple)));
Ted Kremenek2f743592007-12-05 21:36:08 +0000222 delete [] triple;
Ted Kremenek2f743592007-12-05 21:36:08 +0000223 }
224
225 // For Selectors, we must read the identifier table first because the
226 // SelectorTable depends on the identifiers being already deserialized.
227 llvm::Deserializer::Location SelectorBlkLoc = Dezr.getCurrentBlockLocation();
228 Dezr.SkipBlock();
229
230 // Read the identifier table.
231 IdentifierTable::CreateAndRegister(Dezr);
232
233 // Now jump back and read the selectors.
234 Dezr.JumpTo(SelectorBlkLoc);
235 SelectorTable::CreateAndRegister(Dezr);
236
237 // Now jump back to ASTContextBlock and read the ASTContext.
238 Dezr.JumpTo(ASTContextBlockLoc);
239 TU->Context = Dezr.ReadOwnedPtr<ASTContext>();
240
241 // "Rewind" the stream. Find the block with the serialized top-level decls.
242 Dezr.Rewind();
243 FoundBlock = Dezr.SkipToBlock(DeclsBlock);
244 assert (FoundBlock);
245 llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation();
246
247 while (!Dezr.FinishedBlock(DeclBlockLoc))
Sam Bishope2563ca2008-04-07 21:55:54 +0000248 TU->AddTopLevelDecl(Dezr.ReadOwnedPtr<Decl>(*TU->Context));
Ted Kremenek2f743592007-12-05 21:36:08 +0000249
250 return TU;
251}
252