//===--- StmtSerialization.cpp - Serialization of Statements --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the type-specific methods for serializing statements
// and expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Expr.h"
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"

using namespace clang;
using llvm::Serializer;
using llvm::Deserializer;

void Stmt::Emit(Serializer& S) const {
  S.FlushRecord();
  S.EmitInt(getStmtClass());
  EmitImpl(S);
  S.FlushRecord();
}  

Stmt* Stmt::Create(Deserializer& D) {
  StmtClass SC = static_cast<StmtClass>(D.ReadInt());
  
  switch (SC) {
    default:  
      assert (false && "Not implemented.");
      return NULL;
    
    case AddrLabelExprClass:
      return AddrLabelExpr::CreateImpl(D);
      
    case ArraySubscriptExprClass:
      return ArraySubscriptExpr::CreateImpl(D);
      
    case AsmStmtClass:
      return AsmStmt::CreateImpl(D);
      
    case BinaryOperatorClass:
      return BinaryOperator::CreateImpl(D);
      
    case BreakStmtClass:
      return BreakStmt::CreateImpl(D);
     
    case CallExprClass:
      return CallExpr::CreateImpl(D);
      
    case CaseStmtClass:
      return CaseStmt::CreateImpl(D);
    
    case CastExprClass:
      return CastExpr::CreateImpl(D);
      
    case CharacterLiteralClass:
      return CharacterLiteral::CreateImpl(D);
      
    case CompoundAssignOperatorClass:
      return CompoundAssignOperator::CreateImpl(D);
      
    case CompoundLiteralExprClass:
      return CompoundLiteralExpr::CreateImpl(D);
      
    case CompoundStmtClass:
      return CompoundStmt::CreateImpl(D);
    
    case ConditionalOperatorClass:
      return ConditionalOperator::CreateImpl(D);
      
    case ContinueStmtClass:
      return ContinueStmt::CreateImpl(D);
      
    case DeclRefExprClass:
      return DeclRefExpr::CreateImpl(D);
      
    case DeclStmtClass:
      return DeclStmt::CreateImpl(D);
      
    case DefaultStmtClass:
      return DefaultStmt::CreateImpl(D);
    
    case DoStmtClass:
      return DoStmt::CreateImpl(D);
      
    case FloatingLiteralClass:
      return FloatingLiteral::CreateImpl(D);

    case ForStmtClass:
      return ForStmt::CreateImpl(D);
    
    case GotoStmtClass:
      return GotoStmt::CreateImpl(D);
      
    case IfStmtClass:
      return IfStmt::CreateImpl(D);
    
    case ImaginaryLiteralClass:
      return ImaginaryLiteral::CreateImpl(D);
      
    case ImplicitCastExprClass:
      return ImplicitCastExpr::CreateImpl(D);
      
    case IndirectGotoStmtClass:
      return IndirectGotoStmt::CreateImpl(D);
      
    case InitListExprClass:
      return InitListExpr::CreateImpl(D);
      
    case IntegerLiteralClass:
      return IntegerLiteral::CreateImpl(D);
      
    case LabelStmtClass:
      return LabelStmt::CreateImpl(D);
      
    case MemberExprClass:
      return MemberExpr::CreateImpl(D);
      
    case NullStmtClass:
      return NullStmt::CreateImpl(D);
      
    case ParenExprClass:
      return ParenExpr::CreateImpl(D);
      
    case PreDefinedExprClass:
      return PreDefinedExpr::CreateImpl(D);
      
    case ReturnStmtClass:
      return ReturnStmt::CreateImpl(D);
    
    case SizeOfAlignOfTypeExprClass:
      return SizeOfAlignOfTypeExpr::CreateImpl(D);
      
    case StmtExprClass:
      return StmtExpr::CreateImpl(D);
      
    case StringLiteralClass:
      return StringLiteral::CreateImpl(D);
      
    case SwitchStmtClass:
      return SwitchStmt::CreateImpl(D);
      
    case UnaryOperatorClass:
      return UnaryOperator::CreateImpl(D);
      
    case WhileStmtClass:
      return WhileStmt::CreateImpl(D);
      
    //==--------------------------------------==//
    //    Objective C
    //==--------------------------------------==//
    
    case ObjCAtCatchStmtClass:
      return ObjCAtCatchStmt::CreateImpl(D);
      
    case ObjCAtFinallyStmtClass:
      return ObjCAtFinallyStmt::CreateImpl(D);
    
    case ObjCAtSynchronizedStmtClass:
      return ObjCAtSynchronizedStmt::CreateImpl(D);
      
    case ObjCAtThrowStmtClass:
      return ObjCAtThrowStmt::CreateImpl(D);
      
    case ObjCAtTryStmtClass:
      return ObjCAtTryStmt::CreateImpl(D);
    
    case ObjCEncodeExprClass:
      return ObjCEncodeExpr::CreateImpl(D);
      
    case ObjCForCollectionStmtClass:
      return ObjCForCollectionStmt::CreateImpl(D);
      
    case ObjCIvarRefExprClass:
      return ObjCIvarRefExpr::CreateImpl(D);
      
    case ObjCSelectorExprClass:
      return ObjCSelectorExpr::CreateImpl(D);
      
    case ObjCStringLiteralClass:
      return ObjCStringLiteral::CreateImpl(D);
  }
}

//===----------------------------------------------------------------------===//
//   C Serialization
//===----------------------------------------------------------------------===//

void AddrLabelExpr::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(AmpAmpLoc);
  S.Emit(LabelLoc);
  S.EmitPtr(Label);
}

AddrLabelExpr* AddrLabelExpr::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  SourceLocation AALoc = SourceLocation::ReadVal(D);
  SourceLocation LLoc = SourceLocation::ReadVal(D);
  AddrLabelExpr* expr = new AddrLabelExpr(AALoc,LLoc,NULL,t);
  D.ReadPtr(expr->Label); // Pointer may be backpatched.
  return expr;
}

void ArraySubscriptExpr::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(RBracketLoc);
  S.BatchEmitOwnedPtrs(getLHS(),getRHS());
}

ArraySubscriptExpr* ArraySubscriptExpr::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  SourceLocation L = SourceLocation::ReadVal(D);
  Expr *LHS, *RHS;
  D.BatchReadOwnedPtrs(LHS,RHS);
  return new ArraySubscriptExpr(LHS,RHS,t,L);  
}

void AsmStmt::EmitImpl(Serializer& S) const {
  S.Emit(AsmLoc);
  
  getAsmString()->EmitImpl(S);
  S.Emit(RParenLoc);  

  S.EmitBool(IsVolatile);
  S.EmitBool(IsSimple);
  S.EmitInt(NumOutputs);
  S.EmitInt(NumInputs);

  unsigned size = NumOutputs + NumInputs;

  for (unsigned i = 0; i < size; ++i)
    S.EmitCStr(Names[i].c_str());
  
  for (unsigned i = 0; i < size; ++i)
    Constraints[i]->EmitImpl(S);

  for (unsigned i = 0; i < size; ++i)
    S.EmitOwnedPtr(Exprs[i]);
  
  S.EmitInt(Clobbers.size());
  for (unsigned i = 0, e = Clobbers.size(); i != e; ++i)
    Clobbers[i]->EmitImpl(S);
}

AsmStmt* AsmStmt::CreateImpl(Deserializer& D) {
  SourceLocation ALoc = SourceLocation::ReadVal(D);
  StringLiteral *AsmStr = StringLiteral::CreateImpl(D);
  SourceLocation PLoc = SourceLocation::ReadVal(D);
  
  bool IsVolatile = D.ReadBool();
  bool IsSimple = D.ReadBool();
  AsmStmt *Stmt = new AsmStmt(ALoc, IsSimple, IsVolatile, 0, 0, 0, 0, 0,  
                              AsmStr, 
                              0, 0, PLoc);  

  Stmt->NumOutputs = D.ReadInt();
  Stmt->NumInputs = D.ReadInt();
  
  unsigned size = Stmt->NumOutputs + Stmt->NumInputs;

  Stmt->Names.reserve(size);
  for (unsigned i = 0; i < size; ++i) {
    std::vector<char> data;
    D.ReadCStr(data, false);

    Stmt->Names.push_back(std::string(data.begin(), data.end()));
  }    

  Stmt->Constraints.reserve(size);
  for (unsigned i = 0; i < size; ++i)
    Stmt->Constraints.push_back(StringLiteral::CreateImpl(D));
  
  Stmt->Exprs.reserve(size);
  for (unsigned i = 0; i < size; ++i)
    Stmt->Exprs.push_back(D.ReadOwnedPtr<Expr>());
  
  unsigned NumClobbers = D.ReadInt();
  Stmt->Clobbers.reserve(NumClobbers);
  for (unsigned i = 0; i < NumClobbers; ++i)
    Stmt->Clobbers.push_back(StringLiteral::CreateImpl(D));
  
  return Stmt;
}

void BinaryOperator::EmitImpl(Serializer& S) const {
  S.EmitInt(Opc);
  S.Emit(OpLoc);;
  S.Emit(getType());
  S.BatchEmitOwnedPtrs(getLHS(),getRHS());
}

BinaryOperator* BinaryOperator::CreateImpl(Deserializer& D) {
  Opcode Opc = static_cast<Opcode>(D.ReadInt());
  SourceLocation OpLoc = SourceLocation::ReadVal(D);
  QualType Result = QualType::ReadVal(D);
  Expr *LHS, *RHS;
  D.BatchReadOwnedPtrs(LHS,RHS);

  return new BinaryOperator(LHS,RHS,Opc,Result,OpLoc);
}

void BreakStmt::EmitImpl(Serializer& S) const {
  S.Emit(BreakLoc);
}

BreakStmt* BreakStmt::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  return new BreakStmt(Loc);
}

void CallExpr::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(RParenLoc);
  S.EmitInt(NumArgs);
  S.BatchEmitOwnedPtrs(NumArgs+1,SubExprs);  
}

CallExpr* CallExpr::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  SourceLocation L = SourceLocation::ReadVal(D);
  unsigned NumArgs = D.ReadInt();
  Expr** SubExprs = new Expr*[NumArgs+1];
  D.BatchReadOwnedPtrs(NumArgs+1,SubExprs);

  return new CallExpr(SubExprs,NumArgs,t,L);  
}

void CaseStmt::EmitImpl(Serializer& S) const {
  S.Emit(CaseLoc);
  S.EmitPtr(getNextSwitchCase());
  S.BatchEmitOwnedPtrs((unsigned) END_EXPR,&SubExprs[0]);
}

CaseStmt* CaseStmt::CreateImpl(Deserializer& D) {
  SourceLocation CaseLoc = SourceLocation::ReadVal(D);
  CaseStmt* stmt = new CaseStmt(NULL,NULL,NULL,CaseLoc);  
  D.ReadPtr(stmt->NextSwitchCase);
  D.BatchReadOwnedPtrs((unsigned) END_EXPR,&stmt->SubExprs[0]);
  return stmt;
}

void CastExpr::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(Loc);
  S.EmitOwnedPtr(Op);
}

CastExpr* CastExpr::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  SourceLocation Loc = SourceLocation::ReadVal(D);
  Expr* Op = D.ReadOwnedPtr<Expr>();
  return new CastExpr(t,Op,Loc);
}
  

void CharacterLiteral::EmitImpl(Serializer& S) const {
  S.Emit(Value);
  S.Emit(Loc);
  S.Emit(getType());
}

CharacterLiteral* CharacterLiteral::CreateImpl(Deserializer& D) {
  unsigned value = D.ReadInt();
  SourceLocation Loc = SourceLocation::ReadVal(D);
  QualType T = QualType::ReadVal(D);
  return new CharacterLiteral(value,T,Loc);
}

void CompoundAssignOperator::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(ComputationType);
  S.Emit(getOperatorLoc());
  S.EmitInt(getOpcode());
  S.BatchEmitOwnedPtrs(getLHS(),getRHS());
}

CompoundAssignOperator* 
CompoundAssignOperator::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  QualType c = QualType::ReadVal(D);
  SourceLocation L = SourceLocation::ReadVal(D);
  Opcode Opc = static_cast<Opcode>(D.ReadInt());
  Expr* LHS, *RHS;
  D.BatchReadOwnedPtrs(LHS,RHS);
  
  return new CompoundAssignOperator(LHS,RHS,Opc,t,c,L);
}

void CompoundLiteralExpr::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(getLParenLoc());
  S.EmitBool(isFileScope());
  S.EmitOwnedPtr(Init);
}

CompoundLiteralExpr* CompoundLiteralExpr::CreateImpl(Deserializer& D) {
  QualType Q = QualType::ReadVal(D);
  SourceLocation L = SourceLocation::ReadVal(D);
  bool fileScope = D.ReadBool();
  Expr* Init = D.ReadOwnedPtr<Expr>();
  return new CompoundLiteralExpr(L, Q, Init, fileScope);
}

void CompoundStmt::EmitImpl(Serializer& S) const {
  S.Emit(LBracLoc);
  S.Emit(RBracLoc);
  S.Emit(Body.size());
  
  for (const_body_iterator I=body_begin(), E=body_end(); I!=E; ++I)
    S.EmitOwnedPtr(*I);
}

CompoundStmt* CompoundStmt::CreateImpl(Deserializer& D) {
  SourceLocation LB = SourceLocation::ReadVal(D);
  SourceLocation RB = SourceLocation::ReadVal(D);
  unsigned size = D.ReadInt();
  
  CompoundStmt* stmt = new CompoundStmt(NULL,0,LB,RB);
  
  stmt->Body.reserve(size);
  
  for (unsigned i = 0; i < size; ++i)
    stmt->Body.push_back(D.ReadOwnedPtr<Stmt>());
  
  return stmt;
}

void ConditionalOperator::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.BatchEmitOwnedPtrs((unsigned) END_EXPR, SubExprs);
}

ConditionalOperator* ConditionalOperator::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  ConditionalOperator* c = new ConditionalOperator(NULL,NULL,NULL,t);
  D.BatchReadOwnedPtrs((unsigned) END_EXPR, c->SubExprs);
  return c;
}

void ContinueStmt::EmitImpl(Serializer& S) const {
  S.Emit(ContinueLoc);
}

ContinueStmt* ContinueStmt::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  return new ContinueStmt(Loc);
}

void DeclStmt::EmitImpl(Serializer& S) const {
  // FIXME: special handling for struct decls.
  S.EmitOwnedPtr(getDecl());  
  S.Emit(StartLoc);
  S.Emit(EndLoc);
}

void DeclRefExpr::EmitImpl(Serializer& S) const {
  S.Emit(Loc);
  S.Emit(getType());
  
  // Some DeclRefExprs can actually hold the owning reference to a FunctionDecl.
  // This occurs when an implicitly defined function is called, and
  // the decl does not appear in the source file.  We thus check if the
  // decl pointer has been registered, and if not, emit an owned pointer.

  // FIXME: While this will work for serialization, it won't work for
  //  memory management.  The only reason this works for serialization is
  //  because we are tracking all serialized pointers.  Either DeclRefExpr
  //  needs an explicit bit indicating that it owns the the object,
  //  or we need a different ownership model.
  
  const Decl* d = getDecl();
  
  if (!S.isRegistered(d)) {
    assert (isa<FunctionDecl>(d) 
     && "DeclRefExpr can only own FunctionDecls for implicitly def. funcs.");

    S.EmitBool(true);
    S.EmitOwnedPtr(d);
  }
  else {
    S.EmitBool(false);
    S.EmitPtr(d);
  }
}

DeclRefExpr* DeclRefExpr::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  QualType T = QualType::ReadVal(D);  
  bool OwnsDecl = D.ReadBool();
  ValueDecl* decl;
  
  if (!OwnsDecl)
    D.ReadPtr(decl,false); // No backpatching.
  else
    decl = cast<ValueDecl>(D.ReadOwnedPtr<Decl>());
  
  return new DeclRefExpr(decl,T,Loc);
}


DeclStmt* DeclStmt::CreateImpl(Deserializer& D) {
  ScopedDecl* decl = cast<ScopedDecl>(D.ReadOwnedPtr<Decl>());
  SourceLocation StartLoc = SourceLocation::ReadVal(D);
  SourceLocation EndLoc = SourceLocation::ReadVal(D);
  return new DeclStmt(decl, StartLoc, EndLoc);
}

void DefaultStmt::EmitImpl(Serializer& S) const {
  S.Emit(DefaultLoc);
  S.EmitOwnedPtr(getSubStmt());
  S.EmitPtr(getNextSwitchCase());
}

DefaultStmt* DefaultStmt::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  Stmt* SubStmt = D.ReadOwnedPtr<Stmt>();
  
  DefaultStmt* stmt = new DefaultStmt(Loc,SubStmt);
  stmt->setNextSwitchCase(D.ReadPtr<SwitchCase>());
  
  return stmt;
}

void DoStmt::EmitImpl(Serializer& S) const {
  S.Emit(DoLoc);
  S.EmitOwnedPtr(getCond());
  S.EmitOwnedPtr(getBody());
}

DoStmt* DoStmt::CreateImpl(Deserializer& D) {
  SourceLocation DoLoc = SourceLocation::ReadVal(D);
  Expr* Cond = D.ReadOwnedPtr<Expr>();
  Stmt* Body = D.ReadOwnedPtr<Stmt>();
  return new DoStmt(Body,Cond,DoLoc);
}

void FloatingLiteral::EmitImpl(Serializer& S) const {
  S.Emit(Loc);
  S.Emit(getType());
  S.EmitBool(isExact());
  S.Emit(Value);
}

FloatingLiteral* FloatingLiteral::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  QualType t = QualType::ReadVal(D);
  bool isExact = D.ReadBool();
  llvm::APFloat Val = llvm::APFloat::ReadVal(D);
  FloatingLiteral* expr = new FloatingLiteral(Val,&isExact,t,Loc);
  return expr;
}

void ForStmt::EmitImpl(Serializer& S) const {
  S.Emit(ForLoc);
  S.EmitOwnedPtr(getInit());
  S.EmitOwnedPtr(getCond());
  S.EmitOwnedPtr(getInc());
  S.EmitOwnedPtr(getBody());
}

ForStmt* ForStmt::CreateImpl(Deserializer& D) {
  SourceLocation ForLoc = SourceLocation::ReadVal(D);
  Stmt* Init = D.ReadOwnedPtr<Stmt>();
  Expr* Cond = D.ReadOwnedPtr<Expr>();
  Expr* Inc = D.ReadOwnedPtr<Expr>();
  Stmt* Body = D.ReadOwnedPtr<Stmt>();
  return new ForStmt(Init,Cond,Inc,Body,ForLoc);
}

void GotoStmt::EmitImpl(Serializer& S) const {
  S.Emit(GotoLoc);
  S.Emit(LabelLoc);
  S.EmitPtr(Label);
}

GotoStmt* GotoStmt::CreateImpl(Deserializer& D) {
  SourceLocation GotoLoc = SourceLocation::ReadVal(D);
  SourceLocation LabelLoc = SourceLocation::ReadVal(D);
  GotoStmt* stmt = new GotoStmt(NULL,GotoLoc,LabelLoc);
  D.ReadPtr(stmt->Label); // This pointer may be backpatched later.
  return stmt;  
}

void IfStmt::EmitImpl(Serializer& S) const {
  S.Emit(IfLoc);
  S.EmitOwnedPtr(getCond());
  S.EmitOwnedPtr(getThen());
  S.EmitOwnedPtr(getElse());
}

IfStmt* IfStmt::CreateImpl(Deserializer& D) {
  SourceLocation L = SourceLocation::ReadVal(D);
  Expr* Cond = D.ReadOwnedPtr<Expr>();
  Stmt* Then = D.ReadOwnedPtr<Stmt>();
  Stmt* Else = D.ReadOwnedPtr<Stmt>();
  return new IfStmt(L,Cond,Then,Else);
}

void ImaginaryLiteral::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.EmitOwnedPtr(Val);    
}

ImaginaryLiteral* ImaginaryLiteral::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  Expr* expr = D.ReadOwnedPtr<Expr>();
  assert (isa<FloatingLiteral>(expr) || isa<IntegerLiteral>(expr));
  return new ImaginaryLiteral(expr,t);
}

void ImplicitCastExpr::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.EmitOwnedPtr(Op);
}

ImplicitCastExpr* ImplicitCastExpr::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  Expr* Op = D.ReadOwnedPtr<Expr>();
  return new ImplicitCastExpr(t,Op);
}

void IndirectGotoStmt::EmitImpl(Serializer& S) const {
  S.EmitOwnedPtr(Target);  
}

IndirectGotoStmt* IndirectGotoStmt::CreateImpl(Deserializer& D) {
  Expr* Target = D.ReadOwnedPtr<Expr>();
  return new IndirectGotoStmt(Target);
}

void InitListExpr::EmitImpl(Serializer& S) const {
  S.Emit(LBraceLoc);
  S.Emit(RBraceLoc);
  S.EmitInt(NumInits);
  S.BatchEmitOwnedPtrs(NumInits,InitExprs);
}

InitListExpr* InitListExpr::CreateImpl(Deserializer& D) {
  InitListExpr* expr = new InitListExpr();
  expr->LBraceLoc = SourceLocation::ReadVal(D);
  expr->RBraceLoc = SourceLocation::ReadVal(D);
  expr->NumInits = D.ReadInt();
  assert(expr->NumInits);
  expr->InitExprs = new Expr*[expr->NumInits];
  D.BatchReadOwnedPtrs(expr->NumInits,expr->InitExprs);
  return expr;
}

void IntegerLiteral::EmitImpl(Serializer& S) const {
  S.Emit(Loc);
  S.Emit(getType());
  S.Emit(getValue());
}

IntegerLiteral* IntegerLiteral::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  QualType T = QualType::ReadVal(D);
  
  // Create a dummy APInt because it is more efficient to deserialize
  // it in place with the deserialized IntegerLiteral. (fewer copies)
  llvm::APInt temp;  
  IntegerLiteral* expr = new IntegerLiteral(temp,T,Loc);
  D.Read(expr->Value);
  
  return expr;
}

void LabelStmt::EmitImpl(Serializer& S) const {
  S.EmitPtr(Label);
  S.Emit(IdentLoc);
  S.EmitOwnedPtr(SubStmt);
}

LabelStmt* LabelStmt::CreateImpl(Deserializer& D) {
  IdentifierInfo* Label = D.ReadPtr<IdentifierInfo>();
  SourceLocation IdentLoc = SourceLocation::ReadVal(D);
  Stmt* SubStmt = D.ReadOwnedPtr<Stmt>();
  return new LabelStmt(IdentLoc,Label,SubStmt);
}

void MemberExpr::EmitImpl(Serializer& S) const {
  S.Emit(MemberLoc);
  S.EmitPtr(MemberDecl);
  S.EmitBool(IsArrow);
  S.Emit(getType());
  S.EmitOwnedPtr(Base);
}

MemberExpr* MemberExpr::CreateImpl(Deserializer& D) {
  SourceLocation L = SourceLocation::ReadVal(D);
  FieldDecl* MemberDecl = cast<FieldDecl>(D.ReadPtr<Decl>());
  bool IsArrow = D.ReadBool();
  QualType T = QualType::ReadVal(D);
  Expr* base = D.ReadOwnedPtr<Expr>();
  
  return new MemberExpr(base,IsArrow,MemberDecl,L,T); 
}

void NullStmt::EmitImpl(Serializer& S) const {
  S.Emit(SemiLoc);
}

NullStmt* NullStmt::CreateImpl(Deserializer& D) {
  SourceLocation SemiLoc = SourceLocation::ReadVal(D);
  return new NullStmt(SemiLoc);
}

void ParenExpr::EmitImpl(Serializer& S) const {
  S.Emit(L);
  S.Emit(R);
  S.EmitOwnedPtr(Val);
}

ParenExpr* ParenExpr::CreateImpl(Deserializer& D) {
  SourceLocation L = SourceLocation::ReadVal(D);
  SourceLocation R = SourceLocation::ReadVal(D);
  Expr* val = D.ReadOwnedPtr<Expr>();  
  return new ParenExpr(L,R,val);
}

void PreDefinedExpr::EmitImpl(Serializer& S) const {
  S.Emit(Loc);
  S.EmitInt(getIdentType());
  S.Emit(getType());  
}

PreDefinedExpr* PreDefinedExpr::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  IdentType it = static_cast<IdentType>(D.ReadInt());
  QualType Q = QualType::ReadVal(D);
  return new PreDefinedExpr(Loc,Q,it);
}

void ReturnStmt::EmitImpl(Serializer& S) const {
  S.Emit(RetLoc);
  S.EmitOwnedPtr(RetExpr);
}

ReturnStmt* ReturnStmt::CreateImpl(Deserializer& D) {
  SourceLocation RetLoc = SourceLocation::ReadVal(D);
  Expr* RetExpr = D.ReadOwnedPtr<Expr>();  
  return new ReturnStmt(RetLoc,RetExpr);
}

void SizeOfAlignOfTypeExpr::EmitImpl(Serializer& S) const {
  S.EmitBool(isSizeof);
  S.Emit(Ty);
  S.Emit(getType());
  S.Emit(OpLoc);
  S.Emit(RParenLoc);
}

SizeOfAlignOfTypeExpr* SizeOfAlignOfTypeExpr::CreateImpl(Deserializer& D) {
  bool isSizeof = D.ReadBool();
  QualType Ty = QualType::ReadVal(D);
  QualType Res = QualType::ReadVal(D);
  SourceLocation OpLoc = SourceLocation::ReadVal(D);
  SourceLocation RParenLoc = SourceLocation::ReadVal(D);
  
  return new SizeOfAlignOfTypeExpr(isSizeof,Ty,Res,OpLoc,RParenLoc);  
}

void StmtExpr::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(LParenLoc);
  S.Emit(RParenLoc);
  S.EmitOwnedPtr(SubStmt);
}

StmtExpr* StmtExpr::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  SourceLocation L = SourceLocation::ReadVal(D);
  SourceLocation R = SourceLocation::ReadVal(D);
  CompoundStmt* SubStmt = cast<CompoundStmt>(D.ReadOwnedPtr<Stmt>());
  return new StmtExpr(SubStmt,t,L,R);
}

void StringLiteral::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(firstTokLoc);
  S.Emit(lastTokLoc);
  S.EmitBool(isWide());
  S.Emit(getByteLength());

  for (unsigned i = 0 ; i < ByteLength; ++i)
    S.EmitInt(StrData[i]);
}

StringLiteral* StringLiteral::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  SourceLocation firstTokLoc = SourceLocation::ReadVal(D);
  SourceLocation lastTokLoc = SourceLocation::ReadVal(D);
  bool isWide = D.ReadBool();
  unsigned ByteLength = D.ReadInt();
  
  StringLiteral* sl = new StringLiteral(NULL,0,isWide,t,firstTokLoc,lastTokLoc);

  char* StrData = new char[ByteLength];
  for (unsigned i = 0; i < ByteLength; ++i)
    StrData[i] = (char) D.ReadInt();

  sl->ByteLength = ByteLength;
  sl->StrData = StrData;
  
  return sl;
}

void SwitchStmt::EmitImpl(Serializer& S) const {
  S.Emit(SwitchLoc);
  S.EmitOwnedPtr(getCond());
  S.EmitOwnedPtr(getBody());
  S.EmitPtr(FirstCase);  
}

SwitchStmt* SwitchStmt::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  Stmt* Cond = D.ReadOwnedPtr<Stmt>();
  Stmt* Body = D.ReadOwnedPtr<Stmt>();
  SwitchCase* FirstCase = cast<SwitchCase>(D.ReadPtr<Stmt>());
  
  SwitchStmt* stmt = new SwitchStmt(cast<Expr>(Cond));
  stmt->setBody(Body,Loc);
  stmt->FirstCase = FirstCase;
  
  return stmt;
}

void UnaryOperator::EmitImpl(Serializer& S) const {
  S.Emit(getType());
  S.Emit(Loc);
  S.EmitInt(Opc);
  S.EmitOwnedPtr(Val);
}

UnaryOperator* UnaryOperator::CreateImpl(Deserializer& D) {
  QualType t = QualType::ReadVal(D);
  SourceLocation L = SourceLocation::ReadVal(D);
  Opcode Opc = static_cast<Opcode>(D.ReadInt());
  Expr* Val = D.ReadOwnedPtr<Expr>();
  return new UnaryOperator(Val,Opc,t,L);
}

void WhileStmt::EmitImpl(Serializer& S) const {
  S.Emit(WhileLoc);
  S.EmitOwnedPtr(getCond());
  S.EmitOwnedPtr(getBody());
}

WhileStmt* WhileStmt::CreateImpl(Deserializer& D) {
  SourceLocation WhileLoc = SourceLocation::ReadVal(D);
  Expr* Cond = D.ReadOwnedPtr<Expr>();
  Stmt* Body = D.ReadOwnedPtr<Stmt>();
  return new WhileStmt(Cond,Body,WhileLoc);
}

//===----------------------------------------------------------------------===//
//   Objective C Serialization
//===----------------------------------------------------------------------===//

void ObjCAtCatchStmt::EmitImpl(Serializer& S) const {
  S.Emit(AtCatchLoc);
  S.Emit(RParenLoc);
  S.BatchEmitOwnedPtrs((unsigned) END_EXPR, &SubExprs[0]);
}

ObjCAtCatchStmt* ObjCAtCatchStmt::CreateImpl(Deserializer& D) {
  SourceLocation AtCatchLoc = SourceLocation::ReadVal(D);
  SourceLocation RParenLoc = SourceLocation::ReadVal(D);
  
  ObjCAtCatchStmt* stmt = new ObjCAtCatchStmt(AtCatchLoc,RParenLoc);
  D.BatchReadOwnedPtrs((unsigned) END_EXPR, &stmt->SubExprs[0]);

  return stmt;
}

void ObjCAtFinallyStmt::EmitImpl(Serializer& S) const {
  S.Emit(AtFinallyLoc);
  S.EmitOwnedPtr(AtFinallyStmt);
}

ObjCAtFinallyStmt* ObjCAtFinallyStmt::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  Stmt* AtFinallyStmt = D.ReadOwnedPtr<Stmt>();
  return new ObjCAtFinallyStmt(Loc,AtFinallyStmt);  
}

void ObjCAtSynchronizedStmt::EmitImpl(Serializer& S) const {
  S.Emit(AtSynchronizedLoc);
  S.BatchEmitOwnedPtrs((unsigned) END_EXPR,&SubStmts[0]);
 }

ObjCAtSynchronizedStmt* ObjCAtSynchronizedStmt::CreateImpl(Deserializer& D) {
  SourceLocation L = SourceLocation::ReadVal(D);
  ObjCAtSynchronizedStmt* stmt = new ObjCAtSynchronizedStmt(L,0,0);
  D.BatchReadOwnedPtrs((unsigned) END_EXPR, &stmt->SubStmts[0]);
  return stmt;
}

void ObjCAtThrowStmt::EmitImpl(Serializer& S) const {
  S.Emit(AtThrowLoc);
  S.EmitOwnedPtr(Throw);
}

ObjCAtThrowStmt* ObjCAtThrowStmt::CreateImpl(Deserializer& D) {
  SourceLocation L = SourceLocation::ReadVal(D);
  Stmt* Throw = D.ReadOwnedPtr<Stmt>();
  return new ObjCAtThrowStmt(L,Throw);  
}
  
void ObjCAtTryStmt::EmitImpl(Serializer& S) const {
  S.Emit(AtTryLoc);
  S.BatchEmitOwnedPtrs((unsigned) END_EXPR, &SubStmts[0]);
}

ObjCAtTryStmt* ObjCAtTryStmt::CreateImpl(Deserializer& D) {
  SourceLocation L = SourceLocation::ReadVal(D);
  ObjCAtTryStmt* stmt = new ObjCAtTryStmt(L,NULL,NULL,NULL);
  D.BatchReadOwnedPtrs((unsigned) END_EXPR, &stmt->SubStmts[0]);
  return stmt;
}

void ObjCEncodeExpr::EmitImpl(Serializer& S) const {
  S.Emit(AtLoc);
  S.Emit(RParenLoc);
  S.Emit(getType());
  S.Emit(EncType);
}

ObjCEncodeExpr* ObjCEncodeExpr::CreateImpl(Deserializer& D) {
  SourceLocation AtLoc = SourceLocation::ReadVal(D);
  SourceLocation RParenLoc = SourceLocation::ReadVal(D);  
  QualType T = QualType::ReadVal(D);
  QualType ET = QualType::ReadVal(D);
  return new ObjCEncodeExpr(T,ET,AtLoc,RParenLoc);
}

void ObjCForCollectionStmt::EmitImpl(Serializer& S) const {
  S.Emit(ForLoc);
  S.Emit(RParenLoc);
  S.BatchEmitOwnedPtrs(getElement(),getCollection(),getBody());
}

ObjCForCollectionStmt* ObjCForCollectionStmt::CreateImpl(Deserializer& D) {
  SourceLocation ForLoc = SourceLocation::ReadVal(D);
  SourceLocation RParenLoc = SourceLocation::ReadVal(D);
  Stmt* Element;
  Expr* Collection;
  Stmt* Body;
  D.BatchReadOwnedPtrs(Element,Collection,Body);  
  return new ObjCForCollectionStmt(Element,Collection,Body,ForLoc, RParenLoc);
}

void ObjCIvarRefExpr::EmitImpl(Serializer& S) const {
  S.Emit(Loc);
  S.Emit(getType());
  S.EmitPtr(getDecl());
}
  
ObjCIvarRefExpr* ObjCIvarRefExpr::CreateImpl(Deserializer& D) {
  SourceLocation Loc = SourceLocation::ReadVal(D);
  QualType T = QualType::ReadVal(D);
  ObjCIvarRefExpr* dr = new ObjCIvarRefExpr(NULL,T,Loc);
  D.ReadPtr(dr->D,false);  
  return dr;
}

void ObjCSelectorExpr::EmitImpl(Serializer& S) const {
  S.Emit(AtLoc);
  S.Emit(RParenLoc);
  S.Emit(getType());
  S.Emit(SelName);
}

ObjCSelectorExpr* ObjCSelectorExpr::CreateImpl(Deserializer& D) {
  SourceLocation AtLoc = SourceLocation::ReadVal(D);
  SourceLocation RParenLoc = SourceLocation::ReadVal(D);
  QualType T = QualType::ReadVal(D);
  Selector SelName = Selector::ReadVal(D);
  
  return new ObjCSelectorExpr(T,SelName,AtLoc,RParenLoc);
}

void ObjCStringLiteral::EmitImpl(Serializer& S) const {
  S.Emit(AtLoc);
  S.Emit(getType());
  S.EmitOwnedPtr(String);
}

ObjCStringLiteral* ObjCStringLiteral::CreateImpl(Deserializer& D) {
  SourceLocation L = SourceLocation::ReadVal(D);
  QualType T = QualType::ReadVal(D);
  StringLiteral* String = cast<StringLiteral>(D.ReadOwnedPtr<Stmt>());
  return new ObjCStringLiteral(String,T,L);
}
