blob: 2507d244a18d57c12656fc36e6cd384b1efee87d [file] [log] [blame]
Ted Kremenek27cc3c22007-12-13 17:54:02 +00001//===--- TranslationUnit.cpp - Abstraction for Translation Units ----------===//
Ted Kremenek6f046da2007-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
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
Ted Kremenek397de012007-12-13 00:37:31 +000036bool TranslationUnit::EmitBitcodeFile(const llvm::sys::Path& Filename) const {
Ted Kremenek6f046da2007-12-05 21:36:08 +000037
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.
Ted Kremenekb3ee1932007-12-11 21:27:55 +0000105 Sezr.Emit(Context->getSourceManager());
Ted Kremenek6f046da2007-12-05 21:36:08 +0000106
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
Ted Kremenek397de012007-12-13 00:37:31 +0000125TranslationUnit*
126TranslationUnit::ReadBitcodeFile(const llvm::sys::Path& Filename,
127 FileManager& FMgr) {
Ted Kremenek6f046da2007-12-05 21:36:08 +0000128
129 // Create the memory buffer that contains the contents of the file.
130 llvm::scoped_ptr<llvm::MemoryBuffer>
131 MBuffer(llvm::MemoryBuffer::getFile(Filename.c_str(),
132 strlen(Filename.c_str())));
133
134 if (!MBuffer) {
135 // FIXME: Provide diagnostic.
136 return NULL;
137 }
138
139 // Check if the file is of the proper length.
140 if (MBuffer->getBufferSize() & 0x3) {
141 // FIXME: Provide diagnostic: "Length should be a multiple of 4 bytes."
142 return NULL;
143 }
144
145 // Create the bitstream reader.
146 unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
147 llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
148
149 if (Stream.Read(8) != 'B' ||
150 Stream.Read(8) != 'C' ||
151 Stream.Read(4) != 0xC ||
152 Stream.Read(4) != 0xF ||
153 Stream.Read(4) != 0xE ||
154 Stream.Read(4) != 0x0) {
155 // FIXME: Provide diagnostic.
156 return NULL;
157 }
158
159 // Create the deserializer.
160 llvm::Deserializer Dezr(Stream);
161
162 return Create(Dezr,FMgr);
163}
164
165TranslationUnit* TranslationUnit::Create(llvm::Deserializer& Dezr,
166 FileManager& FMgr) {
167
168 // Create the translation unit object.
169 TranslationUnit* TU = new TranslationUnit();
170
171 // ===---------------------------------------------------===/
172 // Deserialize the "Translation Unit" metadata.
173 // ===---------------------------------------------------===/
174
175 // Skip to the BasicMetaDataBlock. First jump to ASTContextBlock
176 // (which will appear earlier) and record its location.
177
178 bool FoundBlock = Dezr.SkipToBlock(ASTContextBlock);
179 assert (FoundBlock);
180
181 llvm::Deserializer::Location ASTContextBlockLoc =
182 Dezr.getCurrentBlockLocation();
183
184 FoundBlock = Dezr.SkipToBlock(BasicMetadataBlock);
185 assert (FoundBlock);
186
187 // Read the SourceManager.
Ted Kremenekd7f64cd2007-12-12 22:39:36 +0000188 SourceManager::CreateAndRegister(Dezr,FMgr);
Ted Kremenek6f046da2007-12-05 21:36:08 +0000189
190 // Read the LangOptions.
191 TU->LangOpts.Read(Dezr);
192
Ted Kremenek38591a22007-12-12 18:05:32 +0000193 { // Read the TargetInfo.
Ted Kremenek6f046da2007-12-05 21:36:08 +0000194 llvm::SerializedPtrID PtrID = Dezr.ReadPtrID();
195 char* triple = Dezr.ReadCStr(NULL,0,true);
Ted Kremenek38591a22007-12-12 18:05:32 +0000196 std::string Triple(triple);
Ted Kremenekd7f64cd2007-12-12 22:39:36 +0000197 Dezr.RegisterPtr(PtrID,TargetInfo::CreateTargetInfo(&Triple,
Ted Kremenek38591a22007-12-12 18:05:32 +0000198 &Triple+1));
Ted Kremenek6f046da2007-12-05 21:36:08 +0000199 delete [] triple;
Ted Kremenek6f046da2007-12-05 21:36:08 +0000200 }
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