blob: 3ad134a2923704be4609fa5999aff9caf1754a06 [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 Kremenekee533642007-12-20 19:47:16 +000023#include "llvm/ADT/OwningPtr.h"
Ted Kremenek2f743592007-12-05 21:36:08 +000024
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
Sam Bishop0f9c72f2008-04-03 14:20:28 +000033TranslationUnit::~TranslationUnit() {
Sam Bishop71de20e2008-04-03 05:35:20 +000034 for (iterator I=begin(), E=end(); I!=E; ++I)
35 delete *I;
36}
Ted Kremenek63ea8632007-12-19 19:27:38 +000037
Ted Kremenekdca29272007-12-18 21:44:50 +000038bool clang::EmitASTBitcodeFile(const TranslationUnit& TU,
39 const llvm::sys::Path& Filename) {
Ted Kremenek2f743592007-12-05 21:36:08 +000040
41 // Reserve 256K for bitstream buffer.
42 std::vector<unsigned char> Buffer;
43 Buffer.reserve(256*1024);
44
45 // Create bitstream.
46 llvm::BitstreamWriter Stream(Buffer);
47
48 // Emit the preamble.
49 Stream.Emit((unsigned)'B', 8);
50 Stream.Emit((unsigned)'C', 8);
51 Stream.Emit(0xC, 4);
52 Stream.Emit(0xF, 4);
53 Stream.Emit(0xE, 4);
54 Stream.Emit(0x0, 4);
55
56 {
57 // Create serializer. Placing it in its own scope assures any necessary
58 // finalization of bits to the buffer in the serializer's dstor.
59 llvm::Serializer Sezr(Stream);
60
61 // Emit the translation unit.
Ted Kremenekdca29272007-12-18 21:44:50 +000062 TU.Emit(Sezr);
Ted Kremenek2f743592007-12-05 21:36:08 +000063 }
64
65 // Write the bits to disk.
66 if (FILE* fp = fopen(Filename.c_str(),"wb")) {
67 fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
68 fclose(fp);
69 return true;
70 }
71
72 return false;
73}
74
75void TranslationUnit::Emit(llvm::Serializer& Sezr) const {
76
77 // ===---------------------------------------------------===/
78 // Serialize the top-level decls.
79 // ===---------------------------------------------------===/
80
81 Sezr.EnterBlock(DeclsBlock);
82
83 // Only serialize the head of a decl chain. The ASTConsumer interfaces
84 // provides us with each top-level decl, including those nested in
85 // a decl chain, so we may be passed decls that are already serialized.
86 for (const_iterator I=begin(), E=end(); I!=E; ++I)
87 if (!Sezr.isRegistered(*I))
88 Sezr.EmitOwnedPtr(*I);
89
90 Sezr.ExitBlock();
91
92 // ===---------------------------------------------------===/
93 // Serialize the "Translation Unit" metadata.
94 // ===---------------------------------------------------===/
95
96 // Emit ASTContext.
97 Sezr.EnterBlock(ASTContextBlock);
98 Sezr.EmitOwnedPtr(Context);
99 Sezr.ExitBlock();
100
101 Sezr.EnterBlock(BasicMetadataBlock);
102
103 // Block for SourceManager, LangOptions, and Target. Allows easy skipping
104 // around to the block for the Selectors during deserialization.
105 Sezr.EnterBlock();
Ted Kremenekfdfc1982007-12-19 22:24:34 +0000106
Ted Kremenek2f743592007-12-05 21:36:08 +0000107 // Emit the SourceManager.
Ted Kremenek7a9d49f2007-12-11 21:27:55 +0000108 Sezr.Emit(Context->getSourceManager());
Ted Kremenek2f743592007-12-05 21:36:08 +0000109
110 // Emit the LangOptions.
111 Sezr.Emit(LangOpts);
112
113 // Emit the Target.
114 Sezr.EmitPtr(&Context->Target);
115 Sezr.EmitCStr(Context->Target.getTargetTriple());
116
117 Sezr.ExitBlock(); // exit "BasicMetadataBlock"
118
119 // Emit the Selectors.
120 Sezr.Emit(Context->Selectors);
121
122 // Emit the Identifier Table.
123 Sezr.Emit(Context->Idents);
124
125 Sezr.ExitBlock(); // exit "ASTContextBlock"
126}
127
Ted Kremeneka1fa3a12007-12-13 00:37:31 +0000128TranslationUnit*
Ted Kremenekdca29272007-12-18 21:44:50 +0000129clang::ReadASTBitcodeFile(const llvm::sys::Path& Filename, FileManager& FMgr) {
Ted Kremenek2f743592007-12-05 21:36:08 +0000130
131 // Create the memory buffer that contains the contents of the file.
Ted Kremenekee533642007-12-20 19:47:16 +0000132 llvm::OwningPtr<llvm::MemoryBuffer>
Chris Lattner35de5122008-04-01 18:04:30 +0000133 MBuffer(llvm::MemoryBuffer::getFile(Filename.c_str()));
Ted Kremenek2f743592007-12-05 21:36:08 +0000134
135 if (!MBuffer) {
136 // FIXME: Provide diagnostic.
137 return NULL;
138 }
139
140 // Check if the file is of the proper length.
141 if (MBuffer->getBufferSize() & 0x3) {
142 // FIXME: Provide diagnostic: "Length should be a multiple of 4 bytes."
143 return NULL;
144 }
145
146 // Create the bitstream reader.
147 unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
148 llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
149
150 if (Stream.Read(8) != 'B' ||
151 Stream.Read(8) != 'C' ||
152 Stream.Read(4) != 0xC ||
153 Stream.Read(4) != 0xF ||
154 Stream.Read(4) != 0xE ||
155 Stream.Read(4) != 0x0) {
156 // FIXME: Provide diagnostic.
157 return NULL;
158 }
159
160 // Create the deserializer.
161 llvm::Deserializer Dezr(Stream);
162
Ted Kremenekdca29272007-12-18 21:44:50 +0000163 return TranslationUnit::Create(Dezr,FMgr);
Ted Kremenek2f743592007-12-05 21:36:08 +0000164}
165
166TranslationUnit* TranslationUnit::Create(llvm::Deserializer& Dezr,
167 FileManager& FMgr) {
168
169 // Create the translation unit object.
170 TranslationUnit* TU = new TranslationUnit();
171
172 // ===---------------------------------------------------===/
173 // Deserialize the "Translation Unit" metadata.
174 // ===---------------------------------------------------===/
175
176 // Skip to the BasicMetaDataBlock. First jump to ASTContextBlock
177 // (which will appear earlier) and record its location.
178
179 bool FoundBlock = Dezr.SkipToBlock(ASTContextBlock);
180 assert (FoundBlock);
181
182 llvm::Deserializer::Location ASTContextBlockLoc =
183 Dezr.getCurrentBlockLocation();
184
185 FoundBlock = Dezr.SkipToBlock(BasicMetadataBlock);
186 assert (FoundBlock);
Ted Kremenek63ea8632007-12-19 19:27:38 +0000187
Ted Kremenek2f743592007-12-05 21:36:08 +0000188 // Read the SourceManager.
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000189 SourceManager::CreateAndRegister(Dezr,FMgr);
Ted Kremenek2f743592007-12-05 21:36:08 +0000190
191 // Read the LangOptions.
192 TU->LangOpts.Read(Dezr);
193
Ted Kremenekbbced582007-12-12 18:05:32 +0000194 { // Read the TargetInfo.
Ted Kremenek2f743592007-12-05 21:36:08 +0000195 llvm::SerializedPtrID PtrID = Dezr.ReadPtrID();
196 char* triple = Dezr.ReadCStr(NULL,0,true);
Chris Lattner42e67372008-03-05 01:18:20 +0000197 Dezr.RegisterPtr(PtrID,TargetInfo::CreateTargetInfo(std::string(triple)));
Ted Kremenek2f743592007-12-05 21:36:08 +0000198 delete [] triple;
Ted Kremenek2f743592007-12-05 21:36:08 +0000199 }
200
201 // For Selectors, we must read the identifier table first because the
202 // SelectorTable depends on the identifiers being already deserialized.
203 llvm::Deserializer::Location SelectorBlkLoc = Dezr.getCurrentBlockLocation();
204 Dezr.SkipBlock();
205
206 // Read the identifier table.
207 IdentifierTable::CreateAndRegister(Dezr);
208
209 // Now jump back and read the selectors.
210 Dezr.JumpTo(SelectorBlkLoc);
211 SelectorTable::CreateAndRegister(Dezr);
212
213 // Now jump back to ASTContextBlock and read the ASTContext.
214 Dezr.JumpTo(ASTContextBlockLoc);
215 TU->Context = Dezr.ReadOwnedPtr<ASTContext>();
216
217 // "Rewind" the stream. Find the block with the serialized top-level decls.
218 Dezr.Rewind();
219 FoundBlock = Dezr.SkipToBlock(DeclsBlock);
220 assert (FoundBlock);
221 llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation();
222
223 while (!Dezr.FinishedBlock(DeclBlockLoc))
224 TU->AddTopLevelDecl(Dezr.ReadOwnedPtr<Decl>());
225
226 return TU;
227}
228