mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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>();
|
||||||
|
|||||||
Reference in New Issue
Block a user