mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[serialization] Serialize DeclContexts, VarDecls, and StructTypes.
Unlike Clang, Swift's DeclContexts are not all Decls. However, I believe each DeclContext that is /serialized/ will be either a decl, a TranslationUnit, or a FuncExpr for a function with an actual declaration. This might turn out to be wrong if (a) SIL needs proper DeclContexts for variables in function bodies, or (b) we need to serialize anonymous closure default arguments. Along with an extension of the ConstructorDecl placeholder code, this allows us to round-trip empty structs. Swift SVN r5532
This commit is contained in:
@@ -81,6 +81,26 @@ StringRef readIdentifier(llvm::BitstreamCursor &Cursor) {
|
||||
return blobData;
|
||||
}
|
||||
|
||||
DeclContext *ModuleFile::getDeclContext(DeclID DID) {
|
||||
if (DID == 0)
|
||||
return ModuleContext;
|
||||
|
||||
Decl *D = getDecl(DID);
|
||||
|
||||
if (auto ND = dyn_cast<NominalTypeDecl>(D))
|
||||
return ND;
|
||||
if (auto ED = dyn_cast<ExtensionDecl>(D))
|
||||
return ED;
|
||||
if (auto CD = dyn_cast<ConstructorDecl>(D))
|
||||
return CD;
|
||||
if (auto DD = dyn_cast<DestructorDecl>(D))
|
||||
return DD;
|
||||
if (auto FD = dyn_cast<FuncDecl>(D))
|
||||
return FD->getBody();
|
||||
|
||||
llvm_unreachable("unknown DeclContext kind");
|
||||
}
|
||||
|
||||
Decl *ModuleFile::getDecl(DeclID DID) {
|
||||
if (DID == 0)
|
||||
return nullptr;
|
||||
@@ -108,15 +128,16 @@ Decl *ModuleFile::getDecl(DeclID DID) {
|
||||
|
||||
switch (recordID) {
|
||||
case decls_block::TYPE_ALIAS_DECL: {
|
||||
DeclID contextID;
|
||||
TypeID underlyingTypeID;
|
||||
bool isGeneric;
|
||||
bool isImplicit;
|
||||
ArrayRef<uint64_t> inheritedIDs;
|
||||
|
||||
decls_block::TypeAliasLayout::readRecord(scratch, underlyingTypeID,
|
||||
decls_block::TypeAliasLayout::readRecord(scratch, contextID,
|
||||
underlyingTypeID,
|
||||
isGeneric, isImplicit,
|
||||
inheritedIDs);
|
||||
assert(inheritedIDs.empty() && "can't handle inherited IDs yet");
|
||||
|
||||
// Deserialize the name.
|
||||
// FIXME: Move this to an identifier table instead of a trailing record.
|
||||
@@ -126,22 +147,40 @@ Decl *ModuleFile::getDecl(DeclID DID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto inherited =
|
||||
MutableArrayRef<TypeLoc>(ctx.Allocate<TypeLoc>(inheritedIDs.size()),
|
||||
inheritedIDs.size());
|
||||
|
||||
TypeLoc *nextInheritedType = inherited.data();
|
||||
for (TypeID TID : inheritedIDs) {
|
||||
auto type = getType(TID);
|
||||
new (nextInheritedType) TypeLoc(TypeLoc::withoutLoc(type));
|
||||
++nextInheritedType;
|
||||
}
|
||||
|
||||
TypeLoc underlyingType = TypeLoc::withoutLoc(getType(underlyingTypeID));
|
||||
declOrOffset = new (ctx) TypeAliasDecl(SourceLoc(),
|
||||
ctx.getIdentifier(name),
|
||||
SourceLoc(),
|
||||
underlyingType,
|
||||
ModuleContext,
|
||||
/*inherited=*/{});
|
||||
auto alias = new (ctx) TypeAliasDecl(SourceLoc(),
|
||||
ctx.getIdentifier(name),
|
||||
SourceLoc(),
|
||||
underlyingType,
|
||||
getDeclContext(contextID),
|
||||
inherited);
|
||||
declOrOffset = alias;
|
||||
|
||||
if (isImplicit)
|
||||
alias->setImplicit();
|
||||
if (isGeneric)
|
||||
alias->setGenericParameter();
|
||||
break;
|
||||
}
|
||||
|
||||
case decls_block::STRUCT_DECL: {
|
||||
DeclID contextID;
|
||||
bool isImplicit;
|
||||
ArrayRef<uint64_t> inheritedIDs;
|
||||
|
||||
decls_block::StructLayout::readRecord(scratch, isImplicit, inheritedIDs);
|
||||
assert(inheritedIDs.empty() && "can't handle inherited IDs yet");
|
||||
decls_block::StructLayout::readRecord(scratch, contextID, isImplicit,
|
||||
inheritedIDs);
|
||||
|
||||
StringRef name = readIdentifier(DeclTypeCursor);
|
||||
if (name.empty()) {
|
||||
@@ -149,6 +188,17 @@ Decl *ModuleFile::getDecl(DeclID DID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto inherited =
|
||||
MutableArrayRef<TypeLoc>(ctx.Allocate<TypeLoc>(inheritedIDs.size()),
|
||||
inheritedIDs.size());
|
||||
|
||||
TypeLoc *nextInheritedType = inherited.data();
|
||||
for (TypeID TID : inheritedIDs) {
|
||||
auto type = getType(TID);
|
||||
new (nextInheritedType) TypeLoc(TypeLoc::withoutLoc(type));
|
||||
++nextInheritedType;
|
||||
}
|
||||
|
||||
ArrayRef<uint64_t> memberIDs;
|
||||
|
||||
auto entry = DeclTypeCursor.advance();
|
||||
@@ -166,11 +216,14 @@ Decl *ModuleFile::getDecl(DeclID DID) {
|
||||
decls_block::DeclContextLayout::readRecord(memberIDBuffer, memberIDs);
|
||||
|
||||
auto theStruct = new (ctx) StructDecl(SourceLoc(), ctx.getIdentifier(name),
|
||||
SourceLoc(), /*inherited=*/{},
|
||||
SourceLoc(), inherited,
|
||||
/*generic params=*/nullptr,
|
||||
ModuleContext);
|
||||
getDeclContext(contextID));
|
||||
declOrOffset = theStruct;
|
||||
|
||||
if (isImplicit)
|
||||
theStruct->setImplicit();
|
||||
|
||||
if (!memberIDs.empty()) {
|
||||
MutableArrayRef<Decl *> members(ctx.Allocate<Decl *>(memberIDs.size()),
|
||||
memberIDs.size());
|
||||
@@ -186,19 +239,72 @@ Decl *ModuleFile::getDecl(DeclID DID) {
|
||||
}
|
||||
|
||||
case decls_block::CONSTRUCTOR_DECL: {
|
||||
DeclID parentID;
|
||||
bool isImplicit;
|
||||
DeclID implicitThisID;
|
||||
|
||||
decls_block::ConstructorLayout::readRecord(scratch, isImplicit,
|
||||
decls_block::ConstructorLayout::readRecord(scratch, parentID, isImplicit,
|
||||
implicitThisID);
|
||||
auto thisDecl = cast<VarDecl>(getDecl(implicitThisID));
|
||||
auto parent = thisDecl->getType()->getAnyNominal();
|
||||
auto parent = cast<NominalTypeDecl>(getDeclContext(parentID));
|
||||
|
||||
auto emptyArgs = TuplePattern::create(ctx, SourceLoc(), {}, SourceLoc());
|
||||
declOrOffset = new (ctx) ConstructorDecl(ctx.getIdentifier("constructor"),
|
||||
SourceLoc(), emptyArgs, thisDecl,
|
||||
/*generic params=*/nullptr,
|
||||
parent);
|
||||
auto ctor = new (ctx) ConstructorDecl(ctx.getIdentifier("constructor"),
|
||||
SourceLoc(), emptyArgs, thisDecl,
|
||||
/*generic params=*/nullptr,
|
||||
parent);
|
||||
declOrOffset = ctor;
|
||||
|
||||
// FIXME: Actually serialize the type instead of reconstructing it here.
|
||||
ctor->setType(FunctionType::get(MetaTypeType::get(thisDecl->getType(),
|
||||
ctx),
|
||||
FunctionType::get(ctx.TheEmptyTupleType,
|
||||
thisDecl->getType(),
|
||||
ctx),
|
||||
ctx));
|
||||
|
||||
if (isImplicit)
|
||||
ctor->setImplicit();
|
||||
break;
|
||||
}
|
||||
|
||||
case decls_block::VAR_DECL: {
|
||||
DeclID contextID;
|
||||
bool isImplicit, isNeverLValue;
|
||||
TypeID typeID;
|
||||
DeclID getterID, setterID;
|
||||
DeclID overriddenID;
|
||||
|
||||
decls_block::VarLayout::readRecord(scratch, contextID, isImplicit,
|
||||
isNeverLValue, typeID, getterID,
|
||||
setterID, overriddenID);
|
||||
|
||||
StringRef name = readIdentifier(DeclTypeCursor);
|
||||
if (name.empty()) {
|
||||
error();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto var = new (ctx) VarDecl(SourceLoc(), ctx.getIdentifier(name),
|
||||
getType(typeID), nullptr);
|
||||
declOrOffset = var;
|
||||
|
||||
// Explicitly set the DeclContext /after/ creating the VarDecl.
|
||||
// Sometimes the context has to reference this decl.
|
||||
var->setDeclContext(getDeclContext(contextID));
|
||||
|
||||
var->setNeverUsedAsLValue(isNeverLValue);
|
||||
if (isImplicit)
|
||||
var->setImplicit();
|
||||
|
||||
if (getterID || setterID) {
|
||||
var->setProperty(ctx, SourceLoc(),
|
||||
cast_or_null<FuncDecl>(getDecl(getterID)),
|
||||
cast_or_null<FuncDecl>(getDecl(setterID)),
|
||||
SourceLoc());
|
||||
}
|
||||
|
||||
var->setOverriddenDecl(cast_or_null<VarDecl>(getDecl(overriddenID)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -264,6 +370,15 @@ Type ModuleFile::getType(TypeID TID) {
|
||||
break;
|
||||
}
|
||||
|
||||
case decls_block::STRUCT_TYPE: {
|
||||
DeclID structID;
|
||||
TypeID parentID;
|
||||
decls_block::StructTypeLayout::readRecord(scratch, structID, parentID);
|
||||
typeOrOffset = StructType::get(cast<StructDecl>(getDecl(structID)),
|
||||
getType(parentID), ModuleContext->Ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// We don't know how to deserialize this kind of type.
|
||||
error();
|
||||
|
||||
Reference in New Issue
Block a user