//===--- TypeSerialization.cpp - Serialization of Decls ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines methods that implement bitcode serialization for Types. // //===----------------------------------------------------------------------===// #include "clang/AST/Type.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ASTContext.h" #include "llvm/Bitcode/Serialize.h" #include "llvm/Bitcode/Deserialize.h" using namespace clang; using llvm::Serializer; using llvm::Deserializer; using llvm::SerializedPtrID; void QualType::Emit(Serializer& S) const { S.EmitPtr(getTypePtr()); S.EmitInt(getCVRQualifiers()); } QualType QualType::ReadVal(Deserializer& D) { uintptr_t Val; D.ReadUIntPtr(Val, false); return QualType(reinterpret_cast(Val), D.ReadInt()); } void QualType::ReadBackpatch(Deserializer& D) { uintptr_t Val; D.ReadUIntPtr(Val, false); Value.setPointer(reinterpret_cast(Val)); Value.setInt(D.ReadInt()); } //===----------------------------------------------------------------------===// // Type Serialization: Dispatch code to handle specific types. //===----------------------------------------------------------------------===// void Type::Emit(Serializer& S) const { S.EmitInt(getTypeClass()); S.EmitPtr(this); if (!isa(this)) EmitImpl(S); } void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) { Type::TypeClass K = static_cast(D.ReadInt()); SerializedPtrID PtrID = D.ReadPtrID(); switch (K) { default: assert (false && "Deserialization for type not supported."); break; case Type::Builtin: assert (i < Context.getTypes().size()); assert (isa(Context.getTypes()[i])); D.RegisterPtr(PtrID,Context.getTypes()[i]); break; case Type::ExtQual: D.RegisterPtr(PtrID,ExtQualType::CreateImpl(Context,D)); break; case Type::Complex: D.RegisterPtr(PtrID,ComplexType::CreateImpl(Context,D)); break; case Type::ConstantArray: D.RegisterPtr(PtrID,ConstantArrayType::CreateImpl(Context,D)); break; case Type::FunctionNoProto: D.RegisterPtr(PtrID,FunctionNoProtoType::CreateImpl(Context,D)); break; case Type::FunctionProto: D.RegisterPtr(PtrID,FunctionProtoType::CreateImpl(Context,D)); break; case Type::IncompleteArray: D.RegisterPtr(PtrID,IncompleteArrayType::CreateImpl(Context,D)); break; case Type::MemberPointer: D.RegisterPtr(PtrID, MemberPointerType::CreateImpl(Context, D)); break; case Type::Pointer: D.RegisterPtr(PtrID, PointerType::CreateImpl(Context, D)); break; case Type::BlockPointer: D.RegisterPtr(PtrID, BlockPointerType::CreateImpl(Context, D)); break; case Type::Reference: D.RegisterPtr(PtrID, ReferenceType::CreateImpl(Context, D)); break; case Type::Record: case Type::CXXRecord: case Type::Enum: // FIXME: Implement this! assert(false && "Can't deserialize tag types!"); break; case Type::Typedef: D.RegisterPtr(PtrID, TypedefType::CreateImpl(Context, D)); break; case Type::TypeOfExpr: D.RegisterPtr(PtrID, TypeOfExprType::CreateImpl(Context, D)); break; case Type::TypeOf: D.RegisterPtr(PtrID, TypeOfType::CreateImpl(Context, D)); break; case Type::TemplateTypeParm: D.RegisterPtr(PtrID, TemplateTypeParmType::CreateImpl(Context, D)); break; case Type::VariableArray: D.RegisterPtr(PtrID, VariableArrayType::CreateImpl(Context, D)); break; } } //===----------------------------------------------------------------------===// // ExtQualType //===----------------------------------------------------------------------===// void ExtQualType::EmitImpl(Serializer& S) const { S.EmitPtr(getBaseType()); S.EmitInt(getAddressSpace()); } Type* ExtQualType::CreateImpl(ASTContext& Context, Deserializer& D) { QualType BaseTy = QualType::ReadVal(D); unsigned AddressSpace = D.ReadInt(); return Context.getAddrSpaceQualType(BaseTy, AddressSpace).getTypePtr(); } //===----------------------------------------------------------------------===// // BlockPointerType //===----------------------------------------------------------------------===// void BlockPointerType::EmitImpl(Serializer& S) const { S.Emit(getPointeeType()); } Type* BlockPointerType::CreateImpl(ASTContext& Context, Deserializer& D) { return Context.getBlockPointerType(QualType::ReadVal(D)).getTypePtr(); } //===----------------------------------------------------------------------===// // ComplexType //===----------------------------------------------------------------------===// void ComplexType::EmitImpl(Serializer& S) const { S.Emit(getElementType()); } Type* ComplexType::CreateImpl(ASTContext& Context, Deserializer& D) { return Context.getComplexType(QualType::ReadVal(D)).getTypePtr(); } //===----------------------------------------------------------------------===// // ConstantArray //===----------------------------------------------------------------------===// void ConstantArrayType::EmitImpl(Serializer& S) const { S.Emit(getElementType()); S.EmitInt(getSizeModifier()); S.EmitInt(getIndexTypeQualifier()); S.Emit(Size); } Type* ConstantArrayType::CreateImpl(ASTContext& Context, Deserializer& D) { QualType ElTy = QualType::ReadVal(D); ArraySizeModifier am = static_cast(D.ReadInt()); unsigned ITQ = D.ReadInt(); llvm::APInt Size; D.Read(Size); return Context.getConstantArrayType(ElTy,Size,am,ITQ).getTypePtr(); } //===----------------------------------------------------------------------===// // FunctionNoProtoType //===----------------------------------------------------------------------===// void FunctionNoProtoType::EmitImpl(Serializer& S) const { S.Emit(getResultType()); } Type* FunctionNoProtoType::CreateImpl(ASTContext& Context, Deserializer& D) { return Context.getFunctionNoProtoType(QualType::ReadVal(D)).getTypePtr(); } //===----------------------------------------------------------------------===// // FunctionProtoType //===----------------------------------------------------------------------===// void FunctionProtoType::EmitImpl(Serializer& S) const { S.Emit(getResultType()); S.EmitBool(isVariadic()); S.EmitInt(getTypeQuals()); S.EmitInt(getNumArgs()); for (arg_type_iterator I=arg_type_begin(), E=arg_type_end(); I!=E; ++I) S.Emit(*I); } Type* FunctionProtoType::CreateImpl(ASTContext& Context, Deserializer& D) { QualType ResultType = QualType::ReadVal(D); bool isVariadic = D.ReadBool(); unsigned TypeQuals = D.ReadInt(); unsigned NumArgs = D.ReadInt(); llvm::SmallVector Args; for (unsigned j = 0; j < NumArgs; ++j) Args.push_back(QualType::ReadVal(D)); return Context.getFunctionType(ResultType,&*Args.begin(), NumArgs,isVariadic,TypeQuals).getTypePtr(); } //===----------------------------------------------------------------------===// // PointerType //===----------------------------------------------------------------------===// void PointerType::EmitImpl(Serializer& S) const { S.Emit(getPointeeType()); } Type* PointerType::CreateImpl(ASTContext& Context, Deserializer& D) { return Context.getPointerType(QualType::ReadVal(D)).getTypePtr(); } //===----------------------------------------------------------------------===// // ReferenceType //===----------------------------------------------------------------------===// void ReferenceType::EmitImpl(Serializer& S) const { S.Emit(getPointeeType()); } Type* ReferenceType::CreateImpl(ASTContext& Context, Deserializer& D) { return Context.getReferenceType(QualType::ReadVal(D)).getTypePtr(); } //===----------------------------------------------------------------------===// // MemberPointerType //===----------------------------------------------------------------------===// void MemberPointerType::EmitImpl(Serializer& S) const { S.Emit(getPointeeType()); S.Emit(QualType(Class, 0)); } Type* MemberPointerType::CreateImpl(ASTContext& Context, Deserializer& D) { QualType Pointee = QualType::ReadVal(D); QualType Class = QualType::ReadVal(D); return Context.getMemberPointerType(Pointee, Class.getTypePtr()).getTypePtr(); } //===----------------------------------------------------------------------===// // TagType //===----------------------------------------------------------------------===// void TagType::EmitImpl(Serializer& S) const { S.EmitOwnedPtr(getDecl()); } Type* TagType::CreateImpl(ASTContext& Context, Deserializer& D) { std::vector& Types = const_cast&>(Context.getTypes()); // FIXME: This is wrong: we need the subclasses to do the // (de-)serialization. TagType* T = new TagType(Record, NULL,QualType()); Types.push_back(T); // Deserialize the decl. T->decl.setPointer(cast(D.ReadOwnedPtr(Context))); T->decl.setInt(0); return T; } //===----------------------------------------------------------------------===// // TypedefType //===----------------------------------------------------------------------===// void TypedefType::EmitImpl(Serializer& S) const { S.Emit(getCanonicalTypeInternal()); S.EmitPtr(Decl); } Type* TypedefType::CreateImpl(ASTContext& Context, Deserializer& D) { std::vector& Types = const_cast&>(Context.getTypes()); TypedefType* T = new TypedefType(Type::Typedef, NULL, QualType::ReadVal(D)); Types.push_back(T); D.ReadPtr(T->Decl); // May be backpatched. return T; } //===----------------------------------------------------------------------===// // TypeOfExprType //===----------------------------------------------------------------------===// void TypeOfExprType::EmitImpl(llvm::Serializer& S) const { S.EmitOwnedPtr(TOExpr); } Type* TypeOfExprType::CreateImpl(ASTContext& Context, Deserializer& D) { Expr* E = D.ReadOwnedPtr(Context); std::vector& Types = const_cast&>(Context.getTypes()); TypeOfExprType* T = new TypeOfExprType(E, Context.getCanonicalType(E->getType())); Types.push_back(T); return T; } //===----------------------------------------------------------------------===// // TypeOfType //===----------------------------------------------------------------------===// void TypeOfType::EmitImpl(llvm::Serializer& S) const { S.Emit(TOType); } Type* TypeOfType::CreateImpl(ASTContext& Context, Deserializer& D) { QualType TOType = QualType::ReadVal(D); std::vector& Types = const_cast&>(Context.getTypes()); TypeOfType* T = new TypeOfType(TOType, Context.getCanonicalType(TOType)); Types.push_back(T); return T; } //===----------------------------------------------------------------------===// // TemplateTypeParmType //===----------------------------------------------------------------------===// void TemplateTypeParmType::EmitImpl(Serializer& S) const { S.EmitInt(Depth); S.EmitInt(Index); S.EmitPtr(Name); } Type* TemplateTypeParmType::CreateImpl(ASTContext& Context, Deserializer& D) { unsigned Depth = D.ReadInt(); unsigned Index = D.ReadInt(); IdentifierInfo *Name = D.ReadPtr(); return Context.getTemplateTypeParmType(Depth, Index, Name).getTypePtr(); } //===----------------------------------------------------------------------===// // ClassTemplateSpecializationType //===----------------------------------------------------------------------===// void ClassTemplateSpecializationType::EmitImpl(Serializer& S) const { S.Emit(getCanonicalTypeInternal()); S.EmitPtr(Template); S.EmitInt(NumArgs); for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { S.EmitBool(isArgType(Arg)); if (isArgType(Arg)) S.Emit(getArgAsType(Arg)); else S.EmitOwnedPtr(getArgAsExpr(Arg)); } } Type* ClassTemplateSpecializationType:: CreateImpl(ASTContext& Context, Deserializer& D) { llvm::SmallVector Args; llvm::SmallVector ArgIsType; QualType Canon = QualType::ReadVal(D); TemplateDecl *Template = cast(D.ReadPtr()); unsigned NumArgs = D.ReadInt(); for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { bool IsType = D.ReadBool(); ArgIsType.push_back(IsType); if (IsType) Args.push_back( reinterpret_cast(QualType::ReadVal(D).getAsOpaquePtr())); else Args.push_back(reinterpret_cast(D.ReadOwnedPtr(Context))); } return Context.getClassTemplateSpecializationType(Template, NumArgs, &Args[0], &ArgIsType[0], Canon).getTypePtr(); } //===----------------------------------------------------------------------===// // VariableArrayType //===----------------------------------------------------------------------===// void VariableArrayType::EmitImpl(Serializer& S) const { S.Emit(getElementType()); S.EmitInt(getSizeModifier()); S.EmitInt(getIndexTypeQualifier()); S.EmitOwnedPtr(SizeExpr); } Type* VariableArrayType::CreateImpl(ASTContext& Context, Deserializer& D) { QualType ElTy = QualType::ReadVal(D); ArraySizeModifier am = static_cast(D.ReadInt()); unsigned ITQ = D.ReadInt(); Expr* SizeExpr = D.ReadOwnedPtr(Context); return Context.getVariableArrayType(ElTy,SizeExpr,am,ITQ).getTypePtr(); } //===----------------------------------------------------------------------===// // DependentSizedArrayType //===----------------------------------------------------------------------===// void DependentSizedArrayType::EmitImpl(Serializer& S) const { S.Emit(getElementType()); S.EmitInt(getSizeModifier()); S.EmitInt(getIndexTypeQualifier()); S.EmitOwnedPtr(SizeExpr); } Type* DependentSizedArrayType::CreateImpl(ASTContext& Context, Deserializer& D) { QualType ElTy = QualType::ReadVal(D); ArraySizeModifier am = static_cast(D.ReadInt()); unsigned ITQ = D.ReadInt(); Expr* SizeExpr = D.ReadOwnedPtr(Context); return Context.getDependentSizedArrayType(ElTy,SizeExpr,am,ITQ).getTypePtr(); } //===----------------------------------------------------------------------===// // IncompleteArrayType //===----------------------------------------------------------------------===// void IncompleteArrayType::EmitImpl(Serializer& S) const { S.Emit(getElementType()); S.EmitInt(getSizeModifier()); S.EmitInt(getIndexTypeQualifier()); } Type* IncompleteArrayType::CreateImpl(ASTContext& Context, Deserializer& D) { QualType ElTy = QualType::ReadVal(D); ArraySizeModifier am = static_cast(D.ReadInt()); unsigned ITQ = D.ReadInt(); return Context.getIncompleteArrayType(ElTy,am,ITQ).getTypePtr(); }