[cfe-commits] r44631 - in /cfe/trunk/Driver: TranslationUnit.cpp TranslationUnit.h

Ted Kremenek kremenek at apple.com
Wed Dec 5 13:36:08 PST 2007


Author: kremenek
Date: Wed Dec  5 15:36:08 2007
New Revision: 44631

URL: http://llvm.org/viewvc/llvm-project?rev=44631&view=rev
Log:
Added "TranslationUnit" class that will be used to provide an interface
for serializing/deserializing ASTs that is decoupled from the logic
in SerializationTest (which will soon be rewritten to use this interface).

Added:
    cfe/trunk/Driver/TranslationUnit.cpp
    cfe/trunk/Driver/TranslationUnit.h

Added: cfe/trunk/Driver/TranslationUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/TranslationUnit.cpp?rev=44631&view=auto

==============================================================================
--- cfe/trunk/Driver/TranslationUnit.cpp (added)
+++ cfe/trunk/Driver/TranslationUnit.cpp Wed Dec  5 15:36:08 2007
@@ -0,0 +1,229 @@
+//===--- TranslationUnit.cpp - Abstraccction for Translation Units --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Ted Kremenek and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+// FIXME: This should eventually be moved out of the driver, or replaced
+//        with its eventual successor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TranslationUnit.h"
+#include "clang.h"
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/AST/AST.h"
+
+#include "llvm/Bitcode/Serialize.h"
+#include "llvm/Bitcode/Deserialize.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Path.h"
+#include "llvm/ADT/scoped_ptr.h"
+
+#include <stdio.h>
+
+namespace {
+  enum { BasicMetadataBlock = 1,
+         ASTContextBlock = 2,
+         DeclsBlock = 3 };
+}
+
+using namespace clang;
+
+bool TranslationUnit::EmitBitcodeFile(llvm::sys::Path& Filename) const {  
+
+  // Reserve 256K for bitstream buffer.
+  std::vector<unsigned char> Buffer;
+  Buffer.reserve(256*1024);
+  
+  // Create bitstream.
+  llvm::BitstreamWriter Stream(Buffer);
+  
+  // Emit the preamble.
+  Stream.Emit((unsigned)'B', 8);
+  Stream.Emit((unsigned)'C', 8);
+  Stream.Emit(0xC, 4);
+  Stream.Emit(0xF, 4);
+  Stream.Emit(0xE, 4);
+  Stream.Emit(0x0, 4);
+  
+  { 
+    // Create serializer.  Placing it in its own scope assures any necessary
+    // finalization of bits to the buffer in the serializer's dstor.    
+    llvm::Serializer Sezr(Stream);  
+    
+    // Emit the translation unit.
+    Emit(Sezr);
+  }
+  
+  // Write the bits to disk. 
+  if (FILE* fp = fopen(Filename.c_str(),"wb")) {
+    fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
+    fclose(fp);
+    return true;
+  }
+
+  return false;  
+}
+
+void TranslationUnit::Emit(llvm::Serializer& Sezr) const {
+
+  // ===---------------------------------------------------===/
+  //      Serialize the top-level decls.
+  // ===---------------------------------------------------===/  
+  
+  Sezr.EnterBlock(DeclsBlock);
+
+  // Only serialize the head of a decl chain.  The ASTConsumer interfaces
+  // provides us with each top-level decl, including those nested in
+  // a decl chain, so we may be passed decls that are already serialized.  
+  for (const_iterator I=begin(), E=end(); I!=E; ++I) 
+      if (!Sezr.isRegistered(*I))
+        Sezr.EmitOwnedPtr(*I);
+  
+  Sezr.ExitBlock();
+  
+  // ===---------------------------------------------------===/
+  //      Serialize the "Translation Unit" metadata.
+  // ===---------------------------------------------------===/
+
+  // Emit ASTContext.
+  Sezr.EnterBlock(ASTContextBlock);  
+  Sezr.EmitOwnedPtr(Context);  
+  Sezr.ExitBlock();    
+  
+  Sezr.EnterBlock(BasicMetadataBlock);
+  
+  // Block for SourceManager, LangOptions, and Target.  Allows easy skipping
+  // around to the block for the Selectors during deserialization.
+  Sezr.EnterBlock();
+  
+  // Emit the SourceManager.
+  Sezr.Emit(Context->SourceMgr);
+  
+  // Emit the LangOptions.
+  Sezr.Emit(LangOpts);
+  
+  // Emit the Target.
+  Sezr.EmitPtr(&Context->Target);
+  Sezr.EmitCStr(Context->Target.getTargetTriple());
+  
+  Sezr.ExitBlock(); // exit "BasicMetadataBlock"
+  
+  // Emit the Selectors.
+  Sezr.Emit(Context->Selectors);
+  
+  // Emit the Identifier Table.
+  Sezr.Emit(Context->Idents);
+  
+  Sezr.ExitBlock();  // exit "ASTContextBlock"
+}
+
+TranslationUnit* TranslationUnit::ReadBitcodeFile(llvm::sys::Path& Filename,
+                                                  FileManager& FMgr) {
+  
+  // Create the memory buffer that contains the contents of the file.  
+  llvm::scoped_ptr<llvm::MemoryBuffer> 
+    MBuffer(llvm::MemoryBuffer::getFile(Filename.c_str(),
+                                        strlen(Filename.c_str())));
+  
+  if (!MBuffer) {
+    // FIXME: Provide diagnostic.
+    return NULL;
+  }
+  
+  // Check if the file is of the proper length.
+  if (MBuffer->getBufferSize() & 0x3) {
+    // FIXME: Provide diagnostic: "Length should be a multiple of 4 bytes."
+    return NULL;
+  }
+  
+  // Create the bitstream reader.
+  unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
+  llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
+  
+  if (Stream.Read(8) != 'B' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(4) != 0xC ||
+      Stream.Read(4) != 0xF ||
+      Stream.Read(4) != 0xE ||
+      Stream.Read(4) != 0x0) {
+    // FIXME: Provide diagnostic.
+    return NULL;
+  }
+  
+  // Create the deserializer.
+  llvm::Deserializer Dezr(Stream);
+  
+  return Create(Dezr,FMgr);
+}
+
+TranslationUnit* TranslationUnit::Create(llvm::Deserializer& Dezr,
+                                         FileManager& FMgr) {
+  
+  // Create the translation unit object.
+  TranslationUnit* TU = new TranslationUnit();
+  
+  // ===---------------------------------------------------===/
+  //      Deserialize the "Translation Unit" metadata.
+  // ===---------------------------------------------------===/
+  
+  // Skip to the BasicMetaDataBlock.  First jump to ASTContextBlock
+  // (which will appear earlier) and record its location.
+  
+  bool FoundBlock = Dezr.SkipToBlock(ASTContextBlock);
+  assert (FoundBlock);
+  
+  llvm::Deserializer::Location ASTContextBlockLoc =
+  Dezr.getCurrentBlockLocation();
+  
+  FoundBlock = Dezr.SkipToBlock(BasicMetadataBlock);
+  assert (FoundBlock);
+
+  // Read the SourceManager.
+  SourceManager::CreateAndRegister(Dezr,FMgr);
+  
+  // Read the LangOptions.
+  TU->LangOpts.Read(Dezr);
+  
+  { 
+    // Read the TargetInfo.
+    llvm::SerializedPtrID PtrID = Dezr.ReadPtrID();
+    char* triple = Dezr.ReadCStr(NULL,0,true);
+    std::vector<std::string> triples;
+    triples.push_back(triple);
+    delete [] triple;
+    Dezr.RegisterPtr(PtrID,CreateTargetInfo(triples,NULL));
+  }
+  
+  // For Selectors, we must read the identifier table first because the
+  //  SelectorTable depends on the identifiers being already deserialized.
+  llvm::Deserializer::Location SelectorBlkLoc = Dezr.getCurrentBlockLocation();  
+  Dezr.SkipBlock();
+  
+  // Read the identifier table.
+  IdentifierTable::CreateAndRegister(Dezr);
+  
+  // Now jump back and read the selectors.
+  Dezr.JumpTo(SelectorBlkLoc);
+  SelectorTable::CreateAndRegister(Dezr);
+  
+  // Now jump back to ASTContextBlock and read the ASTContext.
+  Dezr.JumpTo(ASTContextBlockLoc);
+  TU->Context = Dezr.ReadOwnedPtr<ASTContext>();
+  
+  // "Rewind" the stream.  Find the block with the serialized top-level decls.
+  Dezr.Rewind();
+  FoundBlock = Dezr.SkipToBlock(DeclsBlock);
+  assert (FoundBlock);
+  llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation();
+  
+  while (!Dezr.FinishedBlock(DeclBlockLoc))
+    TU->AddTopLevelDecl(Dezr.ReadOwnedPtr<Decl>());
+
+  return TU;
+}
+

Added: cfe/trunk/Driver/TranslationUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/TranslationUnit.h?rev=44631&view=auto

==============================================================================
--- cfe/trunk/Driver/TranslationUnit.h (added)
+++ cfe/trunk/Driver/TranslationUnit.h Wed Dec  5 15:36:08 2007
@@ -0,0 +1,75 @@
+//===--- TranslationUnit.h - Abstraction for Translation Units  -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Ted Kremenek and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+// FIXME: This should eventually be moved out of the driver, or replaced
+//        with its eventual successor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TRANSLATION_UNIT_H
+#define LLVM_CLANG_TRANSLATION_UNIT_H
+
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Bitcode/SerializationFwd.h"
+#include "llvm/System/Path.h"
+#include <list>
+
+namespace clang {
+ 
+class FileManager;
+class SourceManager;
+class TargetInfo;
+class IdentifierTable;
+class SelectorTable;
+class ASTContext;
+class Decl;
+  
+class TranslationUnit {
+  LangOptions LangOpts;
+  ASTContext* Context;
+  std::list<Decl*> TopLevelDecls;
+
+  explicit TranslationUnit() : Context(NULL) {}
+  
+public:  
+  explicit TranslationUnit(const LangOptions& lopt, ASTContext& context)
+    : LangOpts(lopt), Context(&context) {}
+
+  /// EmitBitcodeFile - Emit the translation unit to a bitcode file.
+  bool EmitBitcodeFile(llvm::sys::Path& Filename) const;
+  
+  /// Emit - Emit the translation unit to an arbitray bitcode stream.
+  void Emit(llvm::Serializer& S) const;
+  
+  /// Create - Reconsititute a translation unit from a bitcode stream.
+  static TranslationUnit* Create(llvm::Deserializer& D, FileManager& FMgr);
+  
+  /// ReadBitcodeFile - Reconsitute a translation unit from a bitcode file.
+  static TranslationUnit* ReadBitcodeFile(llvm::sys::Path& Filename,
+                                          FileManager& FMgr); 
+  
+  // Accessors
+  const LangOptions& getLangOptions() const { return LangOpts; }
+  ASTContext*        getASTContext() { return Context; }
+  
+  /// AddTopLevelDecl - Add a top-level declaration to the translation unit.
+  void AddTopLevelDecl(Decl* d) {
+    TopLevelDecls.push_back(d);
+  }
+  
+  typedef std::list<Decl*>::iterator iterator;  
+  iterator begin() { return TopLevelDecls.begin(); }
+  iterator end() { return TopLevelDecls.end(); }
+  
+  typedef std::list<Decl*>::const_iterator const_iterator;  
+  const_iterator begin() const { return TopLevelDecls.begin(); }
+  const_iterator end() const { return TopLevelDecls.end(); }  
+};
+  
+} // end namespace clang
+
+#endif





More information about the cfe-commits mailing list