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