mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Introduce LValueType.
Swift SVN r1105
This commit is contained in:
@@ -50,10 +50,11 @@ public:
|
||||
void *TupleTypes; // llvm::FoldingSet<TupleType>
|
||||
void *MetaTypeTypes; // DenseMap<TypeAliasDecl*, MetaTypeType*>
|
||||
void *ModuleTypes; // DenseMap<Module*, ModuleType*>
|
||||
void *FunctionTypes; // DenseMap<std::pair<Type*, Type*>, FunctionType*>
|
||||
void *ArrayTypes; // DenseMap<std::pair<Type*, uint64_t>, ArrayType*>
|
||||
void *FunctionTypes; // DenseMap<std::pair<Type, Type>, FunctionType*>
|
||||
void *ArrayTypes; // DenseMap<std::pair<Type, uint64_t>, ArrayType*>
|
||||
void *IntegerTypes; // DenseMap<unsigned, BuiltinIntegerType>
|
||||
void *ParenTypes; // DenseMap<Type*, ParenType*>
|
||||
void *ParenTypes; // DenseMap<Type, ParenType*>
|
||||
void *LValueTypes; // DenseMap<Type, LValueType*>
|
||||
public:
|
||||
|
||||
ASTContext(llvm::SourceMgr &SourceMgr, DiagnosticEngine &Diags);
|
||||
|
||||
@@ -59,6 +59,7 @@ ALWAYS_CANONICAL_TYPE(Module, Type)
|
||||
TYPE(Function, Type)
|
||||
TYPE(Array, Type)
|
||||
ALWAYS_CANONICAL_TYPE(Protocol, Type)
|
||||
TYPE(LValue, Type)
|
||||
|
||||
#undef UNCHECKED_TYPE
|
||||
#undef SUGARED_TYPE
|
||||
|
||||
@@ -619,6 +619,46 @@ private:
|
||||
TypeAliasDecl *TheDecl);
|
||||
};
|
||||
|
||||
/// LValueType - An l-value is a handle to a physical object. The
|
||||
/// type of that object uniquely determines the type of an l-value
|
||||
/// for it.
|
||||
///
|
||||
/// L-values are not fully first-class in Swift:
|
||||
///
|
||||
/// A type is said to "carry" an l-value if
|
||||
/// - it is an l-value type or
|
||||
/// - it is a tuple and at least one of its element types
|
||||
/// carries an l-value.
|
||||
///
|
||||
/// The type of a function argument may carry an l-value. This
|
||||
/// is done by annotating the bound variable with the [byref]
|
||||
/// attribute.
|
||||
///
|
||||
/// The type of a return value, local variable, or field may not
|
||||
/// carry an l-value.
|
||||
///
|
||||
/// When inferring a value type from an expression whose type
|
||||
/// carries an l-value, the carried l-value types are converted
|
||||
/// to their object type.
|
||||
class LValueType : public TypeBase {
|
||||
Type ObjectTy;
|
||||
|
||||
LValueType(Type objectTy) : TypeBase(TypeKind::LValue), ObjectTy(objectTy) {}
|
||||
|
||||
public:
|
||||
static LValueType *get(Type type, ASTContext &C);
|
||||
|
||||
Type getObjectType() const { return ObjectTy; }
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const LValueType *type) { return true; }
|
||||
static bool classof(const TypeBase *type) {
|
||||
return type->getKind() == TypeKind::LValue;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,9 @@ typedef llvm::DenseMap<unsigned, BuiltinIntegerType*> IntegerTypesMapTy;
|
||||
/// ParenTypesMapTy - This is the actual type underlying 'ParenTypes'.
|
||||
typedef llvm::DenseMap<Type, ParenType*> ParenTypesMapTy;
|
||||
|
||||
/// LValueTypesMapTy - This is the actual type underlying 'LValueTypes'.
|
||||
typedef llvm::DenseMap<Type, LValueType*> LValueTypesMapTy;
|
||||
|
||||
ASTContext::ASTContext(llvm::SourceMgr &sourcemgr, DiagnosticEngine &Diags)
|
||||
: Allocator(new llvm::BumpPtrAllocator()),
|
||||
IdentifierTable(new IdentifierTableMapTy(*Allocator)),
|
||||
@@ -57,6 +60,7 @@ ASTContext::ASTContext(llvm::SourceMgr &sourcemgr, DiagnosticEngine &Diags)
|
||||
ArrayTypes(new ArrayTypesMapTy()),
|
||||
IntegerTypes(new IntegerTypesMapTy()),
|
||||
ParenTypes(new ParenTypesMapTy()),
|
||||
LValueTypes(new LValueTypesMapTy()),
|
||||
SourceMgr(sourcemgr),
|
||||
Diags(Diags),
|
||||
TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)),
|
||||
@@ -81,6 +85,7 @@ ASTContext::~ASTContext() {
|
||||
delete (IdentifierTableMapTy*)IdentifierTable; IdentifierTable = 0;
|
||||
delete (IntegerTypesMapTy*)IntegerTypes; IntegerTypes = 0;
|
||||
delete (ParenTypesMapTy*)ParenTypes; ParenTypes = 0;
|
||||
delete (LValueTypesMapTy*)LValueTypes; LValueTypes = 0;
|
||||
delete Allocator; Allocator = 0;
|
||||
}
|
||||
|
||||
@@ -272,3 +277,8 @@ ProtocolType::ProtocolType(SourceLoc ProtocolLoc, ArrayRef<ValueDecl*> Elts,
|
||||
ProtocolLoc(ProtocolLoc), Elements(Elts), TheDecl(TheDecl) {
|
||||
}
|
||||
|
||||
LValueType *LValueType::get(Type objectTy, ASTContext &C) {
|
||||
LValueType *&entry = (*(LValueTypesMapTy*)C.LValueTypes)[objectTy];
|
||||
if (!entry) entry = new (C) LValueType(objectTy);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,12 @@ TypeBase *TypeBase::getCanonicalType() {
|
||||
break;
|
||||
}
|
||||
|
||||
case TypeKind::LValue: {
|
||||
Type objectType = cast<LValueType>(this)->getObjectType();
|
||||
objectType = objectType->getCanonicalType();
|
||||
Result = LValueType::get(objectType, objectType->getASTContext());
|
||||
break;
|
||||
}
|
||||
case TypeKind::Function: {
|
||||
FunctionType *FT = cast<FunctionType>(this);
|
||||
Type In = FT->getInput()->getCanonicalType();
|
||||
@@ -94,6 +100,7 @@ TypeBase *TypeBase::getCanonicalType() {
|
||||
Result = ArrayType::get(EltTy, AT->getSize(), EltTy->getASTContext());
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Cache the canonical type for future queries.
|
||||
assert(Result && "Case not implemented!");
|
||||
@@ -111,6 +118,7 @@ TypeBase *TypeBase::getDesugaredType() {
|
||||
case TypeKind::Tuple:
|
||||
case TypeKind::Function:
|
||||
case TypeKind::Array:
|
||||
case TypeKind::LValue:
|
||||
// None of these types have sugar at the outer level.
|
||||
return this;
|
||||
case TypeKind::Paren:
|
||||
@@ -377,3 +385,7 @@ void ProtocolType::print(raw_ostream &OS) const {
|
||||
OS << '}';
|
||||
}
|
||||
|
||||
void LValueType::print(raw_ostream &OS) const {
|
||||
OS << "[byref] ";
|
||||
getObjectType()->print(OS);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
|
||||
#include "GenType.h"
|
||||
#include "IRGenFunction.h"
|
||||
@@ -177,6 +178,8 @@ const TypeInfo *TypeConverter::convertType(IRGenModule &IGM, Type T) {
|
||||
return new PrimitiveTypeInfo(llvm::IntegerType::get(Ctx, BitWidth),
|
||||
Size(ByteSize), Alignment(ByteSize));
|
||||
}
|
||||
case TypeKind::LValue:
|
||||
return convertLValueType(IGM, cast<LValueType>(TB));
|
||||
case TypeKind::Tuple:
|
||||
return convertTupleType(IGM, cast<TupleType>(TB));
|
||||
case TypeKind::OneOf:
|
||||
@@ -191,6 +194,14 @@ const TypeInfo *TypeConverter::convertType(IRGenModule &IGM, Type T) {
|
||||
llvm_unreachable("bad type kind");
|
||||
}
|
||||
|
||||
const TypeInfo *TypeConverter::convertLValueType(IRGenModule &IGM,
|
||||
LValueType *T) {
|
||||
const TypeInfo &objectTI = IGM.getFragileTypeInfo(T->getObjectType());
|
||||
return new PrimitiveTypeInfo(objectTI.StorageType->getPointerTo(),
|
||||
Size(IGM.TargetData.getPointerSize()),
|
||||
Alignment(IGM.TargetData.getPointerABIAlignment()));
|
||||
}
|
||||
|
||||
/// emitTypeAlias - Emit a type alias. You wouldn't think that these
|
||||
/// would need IR support, but we apparently want to emit struct and
|
||||
/// oneof declarations as these instead of as their own declarations.
|
||||
@@ -222,4 +233,3 @@ void IRGenModule::getExplosionSchema(Type type, ExplosionSchema &schema) {
|
||||
// Okay, that didn't work; just do the general thing.
|
||||
getFragileTypeInfo(type).getExplosionSchema(schema);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace llvm {
|
||||
namespace swift {
|
||||
class ArrayType;
|
||||
class FunctionType;
|
||||
class LValueType;
|
||||
class OneOfType;
|
||||
class TupleType;
|
||||
class Type;
|
||||
@@ -133,6 +134,7 @@ class TypeConverter {
|
||||
static const TypeInfo *convertOneOfType(IRGenModule &IGM, OneOfType *T);
|
||||
static const TypeInfo *convertFunctionType(IRGenModule &IGM, FunctionType *T);
|
||||
static const TypeInfo *convertArrayType(IRGenModule &IGM, ArrayType *T);
|
||||
static const TypeInfo *convertLValueType(IRGenModule &IGM, LValueType *T);
|
||||
|
||||
public:
|
||||
TypeConverter();
|
||||
|
||||
@@ -207,15 +207,17 @@ void Mangler::mangleType(Type type, ExplosionKind explosion,
|
||||
Buffer << "i" << cast<BuiltinIntegerType>(type)->getBitWidth();
|
||||
return;
|
||||
|
||||
case TypeKind::NameAlias:
|
||||
return mangleType(cast<NameAliasType>(base)->getDecl()->getUnderlyingType(),
|
||||
explosion, uncurryLevel);
|
||||
case TypeKind::Identifier:
|
||||
return mangleType(cast<IdentifierType>(base)->getMappedType(),
|
||||
explosion, uncurryLevel);
|
||||
case TypeKind::Paren:
|
||||
return mangleType(cast<ParenType>(base)->getUnderlyingType(),
|
||||
#define SUGARED_TYPE(id, parent) \
|
||||
case TypeKind::id: \
|
||||
return mangleType(cast<id##Type>(base)->getDesugaredType(), \
|
||||
explosion, uncurryLevel);
|
||||
#define TYPE(id, parent)
|
||||
#include "swift/AST/TypeNodes.def"
|
||||
|
||||
case TypeKind::LValue:
|
||||
Buffer << 'R';
|
||||
return mangleType(cast<LValueType>(base)->getObjectType(),
|
||||
ExplosionKind::Minimal, 0);
|
||||
|
||||
case TypeKind::Tuple: {
|
||||
TupleType *tuple = cast<TupleType>(base);
|
||||
|
||||
Reference in New Issue
Block a user