Split complex types out from being members of BuiltinType to being their own

types.

llvm-svn: 39672
This commit is contained in:
Chris Lattner 2007-06-22 20:56:16 +00:00
parent f033c147c9
commit c6395936ae
6 changed files with 106 additions and 66 deletions

View File

@ -132,11 +132,40 @@ void ASTContext::InitBuiltinTypes() {
InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble);
// C99 6.2.5p11.
InitBuiltinType(FloatComplexTy, BuiltinType::FloatComplex);
InitBuiltinType(DoubleComplexTy, BuiltinType::DoubleComplex);
InitBuiltinType(LongDoubleComplexTy, BuiltinType::LongDoubleComplex);
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
LongDoubleComplexTy = getComplexType(LongDoubleTy);
}
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType ASTContext::getComplexType(QualType T) {
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
llvm::FoldingSetNodeID ID;
ComplexType::Profile(ID, T);
void *InsertPos = 0;
if (ComplexType *CT = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(CT, 0);
// If the pointee type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
if (!T->isCanonical()) {
Canonical = getComplexType(T.getCanonicalType());
// Get the new insert position for the node we care about.
ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
ComplexType *New = new ComplexType(T, Canonical);
Types.push_back(New);
ComplexTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
QualType ASTContext::getPointerType(QualType T) {
@ -399,19 +428,16 @@ static int getIntegerRank(QualType t) {
/// getFloatingRank - Return a relative rank for floating point types.
/// This routine will assert if passed a built-in type that isn't a float.
static int getFloatingRank(QualType t) {
switch (cast<BuiltinType>(t.getCanonicalType())->getKind()) {
default:
assert(0 && "getFloatingPointRank(): not a floating type");
case BuiltinType::Float:
case BuiltinType::FloatComplex:
return FloatRank;
case BuiltinType::Double:
case BuiltinType::DoubleComplex:
return DoubleRank;
case BuiltinType::LongDouble:
case BuiltinType::LongDoubleComplex:
return LongDoubleRank;
static int getFloatingRank(QualType T) {
T = T.getCanonicalType();
if (ComplexType *CT = dyn_cast<ComplexType>(T))
return getFloatingRank(CT->getElementType());
switch (cast<BuiltinType>(T)->getKind()) {
default: assert(0 && "getFloatingPointRank(): not a floating type");
case BuiltinType::Float: return FloatRank;
case BuiltinType::Double: return DoubleRank;
case BuiltinType::LongDouble: return LongDoubleRank;
}
}
@ -432,14 +458,10 @@ static int getFloatingRank(QualType t) {
QualType ASTContext::maxComplexType(QualType lt, QualType rt) const {
switch (std::max(getFloatingRank(lt), getFloatingRank(rt))) {
default:
assert(0 && "convertRankToComplex(): illegal value for rank");
case FloatRank:
return FloatComplexTy;
case DoubleRank:
return DoubleComplexTy;
case LongDoubleRank:
return LongDoubleComplexTy;
default: assert(0 && "convertRankToComplex(): illegal value for rank");
case FloatRank: return FloatComplexTy;
case DoubleRank: return DoubleComplexTy;
case LongDoubleRank: return LongDoubleComplexTy;
}
}

View File

@ -252,7 +252,9 @@ bool Type::isUnsignedIntegerType() const {
bool Type::isFloatingType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Float &&
BT->getKind() <= BuiltinType::LongDoubleComplex;
BT->getKind() <= BuiltinType::LongDouble;
if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->isFloatingType();
return false;
}
@ -273,32 +275,27 @@ bool Type::isRealType() const {
}
bool Type::isComplexType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::FloatComplex &&
BT->getKind() <= BuiltinType::LongDoubleComplex;
return false;
return isa<ComplexType>(CanonicalType);
}
bool Type::isArithmeticType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::LongDoubleComplex;
return BT->getKind() != BuiltinType::Void;
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
if (TT->getDecl()->getKind() == Decl::Enum)
return true;
return false;
return isa<ComplexType>(CanonicalType);
}
bool Type::isScalarType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::LongDoubleComplex;
return BT->getKind() != BuiltinType::Void;
if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) {
if (TT->getDecl()->getKind() == Decl::Enum)
return true;
return false;
}
return CanonicalType->getTypeClass() == Pointer;
return isa<PointerType>(CanonicalType) || isa<ComplexType>(CanonicalType);
}
bool Type::isAggregateType() const {
@ -378,9 +375,6 @@ const char *BuiltinType::getName() const {
case Float: return "float";
case Double: return "double";
case LongDouble: return "long double";
case FloatComplex: return "float _Complex";
case DoubleComplex: return "double _Complex";
case LongDoubleComplex: return "long double _Complex";
}
}
@ -458,6 +452,11 @@ void BuiltinType::getAsStringInternal(std::string &S) const {
}
}
void ComplexType::getAsStringInternal(std::string &S) const {
ElementType->getAsStringInternal(S);
S = "_Complex " + S;
}
void PointerType::getAsStringInternal(std::string &S) const {
S = '*' + S;

View File

@ -150,17 +150,13 @@ llvm::Value *CodeGenFunction::ConvertScalarValueToBool(RValue Val, QualType Ty){
Result = Builder.CreateFCmpUNE(Result, Zero, "tobool");
return Result;
}
case BuiltinType::FloatComplex:
case BuiltinType::DoubleComplex:
case BuiltinType::LongDoubleComplex:
assert(0 && "comparisons against complex not implemented yet");
}
} else {
assert((isa<PointerType>(Ty) ||
cast<TagType>(Ty)->getDecl()->getKind() == Decl::Enum) &&
"Unknown scalar type");
} else if (isa<PointerType>(Ty) ||
cast<TagType>(Ty)->getDecl()->getKind() == Decl::Enum) {
// Code below handles this fine.
} else {
assert(isa<ComplexType>(Ty) && "Unknwon type!");
assert(0 && "FIXME: comparisons against complex not implemented yet");
}
// Usual case for integers, pointers, and enums: compare against zero.

View File

@ -63,24 +63,15 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case BuiltinType::LongDouble:
// FIXME: mapping long double onto double.
return llvm::Type::DoubleTy;
case BuiltinType::FloatComplex: {
std::vector<const llvm::Type*> Elts;
Elts.push_back(llvm::Type::FloatTy);
Elts.push_back(llvm::Type::FloatTy);
return llvm::StructType::get(Elts);
}
case BuiltinType::LongDoubleComplex:
// FIXME: mapping long double complex onto double complex.
case BuiltinType::DoubleComplex: {
std::vector<const llvm::Type*> Elts;
Elts.push_back(llvm::Type::DoubleTy);
Elts.push_back(llvm::Type::DoubleTy);
return llvm::StructType::get(Elts);
}
}
break;
}
case Type::Complex: {
std::vector<const llvm::Type*> Elts;
Elts.push_back(ConvertType(cast<ComplexType>(Ty).getElementType()));
Elts.push_back(Elts[0]);
return llvm::StructType::get(Elts);
}
case Type::Pointer: {
const PointerType &P = cast<PointerType>(Ty);
return llvm::PointerType::get(ConvertType(P.getPointeeType()));

View File

@ -26,6 +26,7 @@ namespace clang {
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
std::vector<Type*> Types;
llvm::FoldingSet<ComplexType> ComplexTypes;
llvm::FoldingSet<PointerType> PointerTypes;
llvm::FoldingSet<ReferenceType> ReferenceTypes;
llvm::FoldingSet<ArrayType> ArrayTypes;
@ -52,6 +53,10 @@ public:
~ASTContext();
void PrintStats() const;
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.

View File

@ -179,7 +179,7 @@ namespace clang {
class Type {
public:
enum TypeClass {
Builtin, Pointer, Reference, Array, FunctionNoProto, FunctionProto,
Builtin, Complex, Pointer, Reference, Array, FunctionNoProto, FunctionProto,
TypeName, Tagged
};
private:
@ -188,7 +188,7 @@ private:
/// TypeClass bitfield - Enum that specifies what subclass this belongs to.
/// Note that this should stay at the end of the ivars for Type so that
/// subclasses can pack their bitfields into the same word.
TypeClass TC : 3;
TypeClass TC : 4;
protected:
Type(TypeClass tc, QualType Canonical)
: CanonicalType(Canonical.isNull() ? QualType(this,0) : Canonical), TC(tc){}
@ -293,8 +293,8 @@ public:
Long,
LongLong,
Float, Double, LongDouble,
FloatComplex, DoubleComplex, LongDoubleComplex
Float, Double, LongDouble//,
// FloatComplex, DoubleComplex, LongDoubleComplex
};
private:
Kind TypeKind;
@ -310,6 +310,33 @@ public:
static bool classof(const BuiltinType *) { return true; }
};
/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex
/// types (_Complex float etc) as well as the GCC integer complex extensions.
///
class ComplexType : public Type, public llvm::FoldingSetNode {
QualType ElementType;
ComplexType(QualType Element, QualType CanonicalPtr) :
Type(Complex, CanonicalPtr), ElementType(Element) {
}
friend class ASTContext; // ASTContext creates these.
public:
QualType getElementType() const { return ElementType; }
virtual void getAsStringInternal(std::string &InnerString) const;
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) {
ID.AddPointer(Element.getAsOpaquePtr());
}
static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
static bool classof(const ComplexType *) { return true; }
};
/// PointerType - C99 6.7.5.1 - Pointer Declarators.
///
class PointerType : public Type, public llvm::FoldingSetNode {