Introduce LValueType.

Swift SVN r1105
This commit is contained in:
John McCall
2012-02-02 00:57:10 +00:00
parent 6d8837dc8d
commit 6ff9afb6f5
8 changed files with 90 additions and 12 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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);