[serialization] Add support for lvalue types and pattern binding decls.

This revealed an issue where a function's pattern may have variables that
depend on the function itself; it's therefore important that the function
decl is recorded in the decl map before its argument patterns are loaded.

We should now support structs, concrete properties, and computed properties.

Swift SVN r5745
This commit is contained in:
Jordan Rose
2013-06-21 17:51:53 +00:00
parent b57c8c4f62
commit c957a28f99
3 changed files with 136 additions and 35 deletions

View File

@@ -336,18 +336,24 @@ Decl *ModuleFile::getDecl(DeclID DID) {
decls_block::ConstructorLayout::readRecord(scratch, parentID, isImplicit, decls_block::ConstructorLayout::readRecord(scratch, parentID, isImplicit,
signatureID, implicitThisID); signatureID, implicitThisID);
Pattern *args = maybeReadPattern(); VarDecl *thisDecl;
assert(args && "missing arguments for constructor"); NominalTypeDecl *parent;
{
auto thisDecl = cast<VarDecl>(getDecl(implicitThisID)); BCOffsetRAII restoreOffset(DeclTypeCursor);
auto parent = cast<NominalTypeDecl>(getDeclContext(parentID)); thisDecl = cast<VarDecl>(getDecl(implicitThisID));
parent = cast<NominalTypeDecl>(getDeclContext(parentID));
}
auto ctor = new (ctx) ConstructorDecl(ctx.getIdentifier("constructor"), auto ctor = new (ctx) ConstructorDecl(ctx.getIdentifier("constructor"),
SourceLoc(), args, thisDecl, SourceLoc(), /*args=*/nullptr,
/*generic params=*/nullptr, thisDecl, /*generic params=*/nullptr,
parent); parent);
declOrOffset = ctor; declOrOffset = ctor;
Pattern *args = maybeReadPattern();
assert(args && "missing arguments for constructor");
ctor->setArguments(args);
ctor->setType(getType(signatureID)); ctor->setType(getType(signatureID));
if (isImplicit) if (isImplicit)
@@ -369,16 +375,10 @@ Decl *ModuleFile::getDecl(DeclID DID) {
auto var = new (ctx) VarDecl(SourceLoc(), getIdentifier(nameID), auto var = new (ctx) VarDecl(SourceLoc(), getIdentifier(nameID),
getType(typeID), nullptr); 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();
// Explicitly set the getter and setter info /before/ recording the VarDecl
// in the map. The functions will check this to know if they are getters or
// setters.
if (getterID || setterID) { if (getterID || setterID) {
var->setProperty(ctx, SourceLoc(), var->setProperty(ctx, SourceLoc(),
cast_or_null<FuncDecl>(getDecl(getterID)), cast_or_null<FuncDecl>(getDecl(getterID)),
@@ -386,6 +386,16 @@ Decl *ModuleFile::getDecl(DeclID DID) {
SourceLoc()); SourceLoc());
} }
declOrOffset = var;
// Explicitly set the DeclContext /after/ recording the VarDecl in the map.
// Sometimes the context has to reference this decl.
var->setDeclContext(getDeclContext(contextID));
var->setNeverUsedAsLValue(isNeverLValue);
if (isImplicit)
var->setImplicit();
var->setOverriddenDecl(cast_or_null<VarDecl>(getDecl(overriddenID))); var->setOverriddenDecl(cast_or_null<VarDecl>(getDecl(overriddenID)));
break; break;
} }
@@ -404,13 +414,24 @@ Decl *ModuleFile::getDecl(DeclID DID) {
isClassMethod, associatedDeclID, isClassMethod, associatedDeclID,
overriddenID); overriddenID);
DeclContext *DC;
FunctionType *signature;
{
BCOffsetRAII restoreOffset(DeclTypeCursor);
DC = getDeclContext(contextID);
signature = cast<FunctionType>(getType(signatureID).getPointer());
}
auto fn = new (ctx) FuncDecl(SourceLoc(), SourceLoc(),
getIdentifier(nameID), SourceLoc(),
/*generic params=*/nullptr, signature,
/*body=*/nullptr, DC);
declOrOffset = fn;
SmallVector<Pattern *, 16> patternBuf; SmallVector<Pattern *, 16> patternBuf;
while (Pattern *pattern = maybeReadPattern()) while (Pattern *pattern = maybeReadPattern())
patternBuf.push_back(pattern); patternBuf.push_back(pattern);
auto DC = getDeclContext(contextID);
auto signature = cast<FunctionType>(getType(signatureID).getPointer());
assert(!patternBuf.empty()); assert(!patternBuf.empty());
size_t patternCount = patternBuf.size() / 2; size_t patternCount = patternBuf.size() / 2;
assert(patternCount * 2 == patternBuf.size() && assert(patternCount * 2 == patternBuf.size() &&
@@ -424,12 +445,7 @@ Decl *ModuleFile::getDecl(DeclID DID) {
argPatterns, bodyPatterns, argPatterns, bodyPatterns,
TypeLoc::withoutLoc(signature->getResult()), TypeLoc::withoutLoc(signature->getResult()),
/*body=*/nullptr, DC); /*body=*/nullptr, DC);
fn->setBody(body);
auto fn = new (ctx) FuncDecl(SourceLoc(), SourceLoc(),
getIdentifier(nameID), SourceLoc(),
/*generic params=*/nullptr, signature,
body, DC);
declOrOffset = fn;
fn->setOverriddenDecl(cast_or_null<FuncDecl>(getDecl(overriddenID))); fn->setOverriddenDecl(cast_or_null<FuncDecl>(getDecl(overriddenID)));
@@ -464,6 +480,26 @@ Decl *ModuleFile::getDecl(DeclID DID) {
break; break;
} }
case decls_block::PATTERN_BINDING_DECL: {
DeclID contextID;
bool isImplicit;
decls_block::PatternBindingLayout::readRecord(scratch, contextID,
isImplicit);
Pattern *pattern = maybeReadPattern();
assert(pattern);
auto binding = new (ctx) PatternBindingDecl(SourceLoc(), pattern,
/*init=*/nullptr,
getDeclContext(contextID));
declOrOffset = binding;
if (isImplicit)
binding->setImplicit();
break;
}
default: default:
// We don't know how to deserialize this kind of decl. // We don't know how to deserialize this kind of decl.
error(); error();
@@ -512,6 +548,8 @@ Type ModuleFile::getType(TypeID TID) {
return nullptr; return nullptr;
} }
ASTContext &ctx = ModuleContext->Ctx;
SmallVector<uint64_t, 64> scratch; SmallVector<uint64_t, 64> scratch;
StringRef blobData; StringRef blobData;
unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
@@ -521,7 +559,6 @@ Type ModuleFile::getType(TypeID TID) {
assert(!blobData.empty() && "missing name in BUILTIN_TYPE record"); assert(!blobData.empty() && "missing name in BUILTIN_TYPE record");
SmallVector<ValueDecl *, 1> lookupResult; SmallVector<ValueDecl *, 1> lookupResult;
ASTContext &ctx = ModuleContext->Ctx;
ctx.TheBuiltinModule->lookupValue({}, ctx.getIdentifier(blobData), ctx.TheBuiltinModule->lookupValue({}, ctx.getIdentifier(blobData),
NLKind::QualifiedLookup, lookupResult); NLKind::QualifiedLookup, lookupResult);
if (lookupResult.empty()) { if (lookupResult.empty()) {
@@ -551,14 +588,14 @@ Type ModuleFile::getType(TypeID TID) {
TypeID parentID; TypeID parentID;
decls_block::StructTypeLayout::readRecord(scratch, structID, parentID); decls_block::StructTypeLayout::readRecord(scratch, structID, parentID);
typeOrOffset = StructType::get(cast<StructDecl>(getDecl(structID)), typeOrOffset = StructType::get(cast<StructDecl>(getDecl(structID)),
getType(parentID), ModuleContext->Ctx); getType(parentID), ctx);
break; break;
} }
case decls_block::PAREN_TYPE: { case decls_block::PAREN_TYPE: {
TypeID underlyingID; TypeID underlyingID;
decls_block::ParenTypeLayout::readRecord(scratch, underlyingID); decls_block::ParenTypeLayout::readRecord(scratch, underlyingID);
typeOrOffset = ParenType::get(ModuleContext->Ctx, getType(underlyingID)); typeOrOffset = ParenType::get(ctx, getType(underlyingID));
break; break;
} }
@@ -589,7 +626,7 @@ Type ModuleFile::getType(TypeID TID) {
} }
} }
typeOrOffset = TupleType::get(elements, ModuleContext->Ctx); typeOrOffset = TupleType::get(elements, ctx);
break; break;
} }
@@ -622,15 +659,29 @@ Type ModuleFile::getType(TypeID TID) {
typeOrOffset = FunctionType::get(getType(inputID), getType(resultID), typeOrOffset = FunctionType::get(getType(inputID), getType(resultID),
autoClosure, blockCompatible, thin, autoClosure, blockCompatible, thin,
callingConvention.getValue(), callingConvention.getValue(), ctx);
ModuleContext->Ctx);
break; break;
} }
case decls_block::METATYPE_TYPE: { case decls_block::METATYPE_TYPE: {
TypeID instanceID; TypeID instanceID;
decls_block::MetaTypeTypeLayout::readRecord(scratch, instanceID); decls_block::MetaTypeTypeLayout::readRecord(scratch, instanceID);
typeOrOffset = MetaTypeType::get(getType(instanceID), ModuleContext->Ctx); typeOrOffset = MetaTypeType::get(getType(instanceID), ctx);
break;
}
case decls_block::LVALUE_TYPE: {
TypeID objectTypeID;
bool isImplicit, isNonSettable;
decls_block::LValueTypeLayout::readRecord(scratch, objectTypeID,
isImplicit, isNonSettable);
LValueType::Qual quals;
if (isImplicit)
quals |= LValueType::Qual::Implicit;
if (isNonSettable)
quals |= LValueType::Qual::NonSettable;
typeOrOffset = LValueType::get(getType(objectTypeID), quals, ctx);
break; break;
} }

View File

@@ -166,12 +166,14 @@ namespace decls_block {
IDENTIFIER_TYPE, IDENTIFIER_TYPE,
FUNCTION_TYPE, FUNCTION_TYPE,
METATYPE_TYPE, METATYPE_TYPE,
LVALUE_TYPE,
TYPE_ALIAS_DECL = 100, TYPE_ALIAS_DECL = 100,
STRUCT_DECL, STRUCT_DECL,
CONSTRUCTOR_DECL, CONSTRUCTOR_DECL,
VAR_DECL, VAR_DECL,
FUNC_DECL, FUNC_DECL,
PATTERN_BINDING_DECL,
PAREN_PATTERN = 200, PAREN_PATTERN = 200,
TUPLE_PATTERN, TUPLE_PATTERN,
@@ -236,6 +238,13 @@ namespace decls_block {
TypeIDField // instance type TypeIDField // instance type
>; >;
using LValueTypeLayout = BCRecordLayout<
LVALUE_TYPE,
TypeIDField, // object type
BCFixed<1>, // implicit?
BCFixed<1> // non-settable?
>;
using TypeAliasLayout = BCRecordLayout< using TypeAliasLayout = BCRecordLayout<
TYPE_ALIAS_DECL, TYPE_ALIAS_DECL,
IdentifierIDField, // name IdentifierIDField, // name
@@ -286,6 +295,13 @@ namespace decls_block {
DeclIDField // overridden function DeclIDField // overridden function
>; >;
using PatternBindingLayout = BCRecordLayout<
PATTERN_BINDING_DECL,
DeclIDField, // context decl
BCFixed<1> // implicit flag
// The pattern trails the record.
>;
using ParenPatternLayout = BCRecordLayout< using ParenPatternLayout = BCRecordLayout<
PAREN_PATTERN PAREN_PATTERN
// The sub-pattern trails the record. // The sub-pattern trails the record.

View File

@@ -327,6 +327,7 @@ static void emitRecordID(llvm::BitstreamWriter &out, unsigned ID,
void Serializer::writeBlockInfoBlock() { void Serializer::writeBlockInfoBlock() {
BCBlockRAII restoreBlock(Out, llvm::bitc::BLOCKINFO_BLOCK_ID, 2); BCBlockRAII restoreBlock(Out, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
#ifndef NDEBUG
SmallVector<unsigned char, 64> nameBuffer; SmallVector<unsigned char, 64> nameBuffer;
#define BLOCK(X) emitBlockID(Out, X ## _ID, #X, nameBuffer) #define BLOCK(X) emitBlockID(Out, X ## _ID, #X, nameBuffer)
#define RECORD(K, X) emitRecordID(Out, K::X, #X, nameBuffer) #define RECORD(K, X) emitRecordID(Out, K::X, #X, nameBuffer)
@@ -347,12 +348,14 @@ void Serializer::writeBlockInfoBlock() {
RECORD(decls_block, IDENTIFIER_TYPE); RECORD(decls_block, IDENTIFIER_TYPE);
RECORD(decls_block, FUNCTION_TYPE); RECORD(decls_block, FUNCTION_TYPE);
RECORD(decls_block, METATYPE_TYPE); RECORD(decls_block, METATYPE_TYPE);
RECORD(decls_block, LVALUE_TYPE);
RECORD(decls_block, TYPE_ALIAS_DECL); RECORD(decls_block, TYPE_ALIAS_DECL);
RECORD(decls_block, STRUCT_DECL); RECORD(decls_block, STRUCT_DECL);
RECORD(decls_block, CONSTRUCTOR_DECL); RECORD(decls_block, CONSTRUCTOR_DECL);
RECORD(decls_block, VAR_DECL); RECORD(decls_block, VAR_DECL);
RECORD(decls_block, FUNC_DECL); RECORD(decls_block, FUNC_DECL);
RECORD(decls_block, PATTERN_BINDING_DECL);
RECORD(decls_block, PAREN_PATTERN); RECORD(decls_block, PAREN_PATTERN);
RECORD(decls_block, TUPLE_PATTERN); RECORD(decls_block, TUPLE_PATTERN);
@@ -375,6 +378,7 @@ void Serializer::writeBlockInfoBlock() {
#undef BLOCK #undef BLOCK
#undef RECORD #undef RECORD
#endif /* NDEBUG */
} }
void Serializer::writeHeader() { void Serializer::writeHeader() {
@@ -483,10 +487,26 @@ bool Serializer::writeDecl(const Decl *D) {
return true; return true;
case DeclKind::Extension: case DeclKind::Extension:
case DeclKind::PatternBinding:
case DeclKind::TopLevelCode:
return false; return false;
case DeclKind::PatternBinding: {
auto binding = cast<PatternBindingDecl>(D);
const Decl *DC = getDeclForContext(binding->getDeclContext());
unsigned abbrCode = DeclTypeAbbrCodes[PatternBindingLayout::Code];
PatternBindingLayout::emitRecord(Out, ScratchRecord, abbrCode,
addDeclRef(DC), binding->isImplicit());
writePattern(binding->getPattern());
// Ignore initializer; external clients don't need to know about it.
return true;
}
case DeclKind::TopLevelCode:
// Top-level code is ignored; external clients don't need to know about it.
return true;
case DeclKind::InfixOperator: case DeclKind::InfixOperator:
case DeclKind::PrefixOperator: case DeclKind::PrefixOperator:
case DeclKind::PostfixOperator: case DeclKind::PostfixOperator:
@@ -807,7 +827,19 @@ bool Serializer::writeType(Type ty) {
return false; return false;
case TypeKind::ProtocolComposition: case TypeKind::ProtocolComposition:
case TypeKind::LValue: return false;
case TypeKind::LValue: {
auto lValueTy = cast<LValueType>(ty.getPointer());
unsigned abbrCode = DeclTypeAbbrCodes[LValueTypeLayout::Code];
LValueTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(lValueTy->getObjectType()),
lValueTy->getQualifiers().isImplicit(),
!lValueTy->getQualifiers().isSettable());
return true;
}
case TypeKind::UnboundGeneric: case TypeKind::UnboundGeneric:
return false; return false;
@@ -835,12 +867,14 @@ void Serializer::writeAllDeclsAndTypes() {
registerDeclTypeAbbr<IdentifierTypeLayout>(); registerDeclTypeAbbr<IdentifierTypeLayout>();
registerDeclTypeAbbr<FunctionTypeLayout>(); registerDeclTypeAbbr<FunctionTypeLayout>();
registerDeclTypeAbbr<MetaTypeTypeLayout>(); registerDeclTypeAbbr<MetaTypeTypeLayout>();
registerDeclTypeAbbr<LValueTypeLayout>();
registerDeclTypeAbbr<TypeAliasLayout>(); registerDeclTypeAbbr<TypeAliasLayout>();
registerDeclTypeAbbr<StructLayout>(); registerDeclTypeAbbr<StructLayout>();
registerDeclTypeAbbr<ConstructorLayout>(); registerDeclTypeAbbr<ConstructorLayout>();
registerDeclTypeAbbr<VarLayout>(); registerDeclTypeAbbr<VarLayout>();
registerDeclTypeAbbr<FuncLayout>(); registerDeclTypeAbbr<FuncLayout>();
registerDeclTypeAbbr<PatternBindingLayout>();
registerDeclTypeAbbr<ParenPatternLayout>(); registerDeclTypeAbbr<ParenPatternLayout>();
registerDeclTypeAbbr<TuplePatternLayout>(); registerDeclTypeAbbr<TuplePatternLayout>();