blob: 8c68e35dcdffc39235093a0543702f198a18709a [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//
5// This file was developed by Ted Kremenek and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
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"
23#include "llvm/ADT/scoped_ptr.h"
24
25#include <stdio.h>
26
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
33
Ted Kremenekdca29272007-12-18 21:44:50 +000034bool clang::EmitASTBitcodeFile(const TranslationUnit& TU,
35 const llvm::sys::Path& Filename) {
Ted Kremenek2f743592007-12-05 21:36:08 +000036
37 // Reserve 256K for bitstream buffer.
38 std::vector<unsigned char> Buffer;
39 Buffer.reserve(256*1024);
40
41 // Create bitstream.
42 llvm::BitstreamWriter Stream(Buffer);
43
44 // Emit the preamble.
45 Stream.Emit((unsigned)'B', 8);
46 Stream.Emit((unsigned)'C', 8);
47 Stream.Emit(0xC, 4);
48 Stream.Emit(0xF, 4);
49 Stream.Emit(0xE, 4);
50 Stream.Emit(0x0, 4);
51
52 {
53 // Create serializer. Placing it in its own scope assures any necessary
54 // finalization of bits to the buffer in the serializer's dstor.
55 llvm::Serializer Sezr(Stream);
56
57 // Emit the translation unit.
Ted Kremenekdca29272007-12-18 21:44:50 +000058 TU.Emit(Sezr);
Ted Kremenek2f743592007-12-05 21:36:08 +000059 }
60
61 // Write the bits to disk.
62 if (FILE* fp = fopen(Filename.c_str(),"wb")) {
63 fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
64 fclose(fp);
65 return true;
66 }
67
68 return false;
69}
70
71void TranslationUnit::Emit(llvm::Serializer& Sezr) const {
72
73 // ===---------------------------------------------------===/
74 // Serialize the top-level decls.
75 // ===---------------------------------------------------===/
76
77 Sezr.EnterBlock(DeclsBlock);
78
79 // Only serialize the head of a decl chain. The ASTConsumer interfaces
80 // provides us with each top-level decl, including those nested in
81 // a decl chain, so we may be passed decls that are already serialized.
82 for (const_iterator I=begin(), E=end(); I!=E; ++I)
83 if (!Sezr.isRegistered(*I))
84 Sezr.EmitOwnedPtr(*I);
85
86 Sezr.ExitBlock();
87
88 // ===---------------------------------------------------===/
89 // Serialize the "Translation Unit" metadata.
90 // ===---------------------------------------------------===/
91
92 // Emit ASTContext.
93 Sezr.EnterBlock(ASTContextBlock);
94 Sezr.EmitOwnedPtr(Context);
95 Sezr.ExitBlock();
96
97 Sezr.EnterBlock(BasicMetadataBlock);
98
99 // Block for SourceManager, LangOptions, and Target. Allows easy skipping
100 // around to the block for the Selectors during deserialization.
101 Sezr.EnterBlock();
Ted Kremenekfdfc1982007-12-19 22:24:34 +0000102
Ted Kremenek2f743592007-12-05 21:36:08 +0000103 // Emit the SourceManager.
Ted Kremenek7a9d49f2007-12-11 21:27:55 +0000104 Sezr.Emit(Context->getSourceManager());
Ted Kremenek2f743592007-12-05 21:36:08 +0000105
106 // Emit the LangOptions.
107 Sezr.Emit(LangOpts);
108
109 // Emit the Target.
110 Sezr.EmitPtr(&Context->Target);
111 Sezr.EmitCStr(Context->Target.getTargetTriple());
112
113 Sezr.ExitBlock(); // exit "BasicMetadataBlock"
114
115 // Emit the Selectors.
116 Sezr.Emit(Context->Selectors);
117
118 // Emit the Identifier Table.
119 Sezr.Emit(Context->Idents);
120
121 Sezr.ExitBlock(); // exit "ASTContextBlock"
122}
123
Ted Kremeneka1fa3a12007-12-13 00:37:31 +0000124TranslationUnit*
Ted Kremenekdca29272007-12-18 21:44:50 +0000125clang::ReadASTBitcodeFile(const llvm::sys::Path& Filename, FileManager& FMgr) {
Ted Kremenek2f743592007-12-05 21:36:08 +0000126
127 // Create the memory buffer that contains the contents of the file.
128 llvm::scoped_ptr<llvm::MemoryBuffer>
129 MBuffer(llvm::MemoryBuffer::getFile(Filename.c_str(),
130 strlen(Filename.c_str())));
131
132 if (!MBuffer) {
133 // FIXME: Provide diagnostic.
134 return NULL;
135 }
136
137 // Check if the file is of the proper length.
138 if (MBuffer->getBufferSize() & 0x3) {
139 // FIXME: Provide diagnostic: "Length should be a multiple of 4 bytes."
140 return NULL;
141 }
142
143 // Create the bitstream reader.
144 unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
145 llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
146
147 if (Stream.Read(8) != 'B' ||
148 Stream.Read(8) != 'C' ||
149 Stream.Read(4) != 0xC ||
150 Stream.Read(4) != 0xF ||
151 Stream.Read(4) != 0xE ||
152 Stream.Read(4) != 0x0) {
153 // FIXME: Provide diagnostic.
154 return NULL;
155 }
156
157 // Create the deserializer.
158 llvm::Deserializer Dezr(Stream);
159
Ted Kremenekdca29272007-12-18 21:44:50 +0000160 return TranslationUnit::Create(Dezr,FMgr);
Ted Kremenek2f743592007-12-05 21:36:08 +0000161}
162
163TranslationUnit* TranslationUnit::Create(llvm::Deserializer& Dezr,
164 FileManager& FMgr) {
165
166 // Create the translation unit object.
167 TranslationUnit* TU = new TranslationUnit();
168
169 // ===---------------------------------------------------===/
170 // Deserialize the "Translation Unit" metadata.
171 // ===---------------------------------------------------===/
172
173 // Skip to the BasicMetaDataBlock. First jump to ASTContextBlock
174 // (which will appear earlier) and record its location.
175
176 bool FoundBlock = Dezr.SkipToBlock(ASTContextBlock);
177 assert (FoundBlock);
178
179 llvm::Deserializer::Location ASTContextBlockLoc =
180 Dezr.getCurrentBlockLocation();
181
182 FoundBlock = Dezr.SkipToBlock(BasicMetadataBlock);
183 assert (FoundBlock);
Ted Kremenek63ea8632007-12-19 19:27:38 +0000184
Ted Kremenek2f743592007-12-05 21:36:08 +0000185 // Read the SourceManager.
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000186 SourceManager::CreateAndRegister(Dezr,FMgr);
Ted Kremenek2f743592007-12-05 21:36:08 +0000187
188 // Read the LangOptions.
189 TU->LangOpts.Read(Dezr);
190
Ted Kremenekbbced582007-12-12 18:05:32 +0000191 { // Read the TargetInfo.
Ted Kremenek2f743592007-12-05 21:36:08 +0000192 llvm::SerializedPtrID PtrID = Dezr.ReadPtrID();
193 char* triple = Dezr.ReadCStr(NULL,0,true);
Ted Kremenekbbced582007-12-12 18:05:32 +0000194 std::string Triple(triple);
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000195 Dezr.RegisterPtr(PtrID,TargetInfo::CreateTargetInfo(&Triple,
Ted Kremenekbbced582007-12-12 18:05:32 +0000196 &Triple+1));
Ted Kremenek2f743592007-12-05 21:36:08 +0000197 delete [] triple;
Ted Kremenek2f743592007-12-05 21:36:08 +0000198 }
199
200 // For Selectors, we must read the identifier table first because the
201 // SelectorTable depends on the identifiers being already deserialized.
202 llvm::Deserializer::Location SelectorBlkLoc = Dezr.getCurrentBlockLocation();
203 Dezr.SkipBlock();
204
205 // Read the identifier table.
206 IdentifierTable::CreateAndRegister(Dezr);
207
208 // Now jump back and read the selectors.
209 Dezr.JumpTo(SelectorBlkLoc);
210 SelectorTable::CreateAndRegister(Dezr);
211
212 // Now jump back to ASTContextBlock and read the ASTContext.
213 Dezr.JumpTo(ASTContextBlockLoc);
214 TU->Context = Dezr.ReadOwnedPtr<ASTContext>();
215
216 // "Rewind" the stream. Find the block with the serialized top-level decls.
217 Dezr.Rewind();
218 FoundBlock = Dezr.SkipToBlock(DeclsBlock);
219 assert (FoundBlock);
220 llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation();
221
222 while (!Dezr.FinishedBlock(DeclBlockLoc))
223 TU->AddTopLevelDecl(Dezr.ReadOwnedPtr<Decl>());
224
225 return TU;
226}
227