diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/ASTContext.h | 15 | ||||
| -rw-r--r-- | clang/include/clang/AST/Type.h | 24 | ||||
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 47 | ||||
| -rw-r--r-- | clang/lib/AST/Type.cpp | 33 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 13 | ||||
| -rw-r--r-- | clang/test/Sema/128bitint.c | 6 | 
7 files changed, 125 insertions, 15 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index bc0f191fd6a..3f9e6bf213c 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -78,7 +78,10 @@ class ASTContext {    llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;    llvm::DenseMap<const ObjCInterfaceDecl*,                    const ASTRecordLayout*> ASTObjCInterfaces; -   + +  llvm::DenseMap<unsigned, FixedWidthIntType*> SignedFixedWidthIntTypes; +  llvm::DenseMap<unsigned, FixedWidthIntType*> UnsignedFixedWidthIntTypes; +    // FIXME: Shouldn't ASTRecordForInterface/ASTFieldForIvarRef and    // addRecordToClass/getFieldDecl be part of the backend (i.e. CodeGenTypes and    // CodeGenFunction)? @@ -369,7 +372,9 @@ public:    void setBuiltinVaListType(QualType T);    QualType getBuiltinVaListType() const { return BuiltinVaListType; } -     + +  QualType getFixedWidthIntType(unsigned Width, bool Signed); +  private:    QualType getFromTargetType(unsigned Type) const; @@ -532,6 +537,12 @@ public:    QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,                                                QualType typeDomain) const; +private: +  // Helper for integer ordering +  unsigned getIntegerRank(Type* T); + +public: +    //===--------------------------------------------------------------------===//    //                    Type Compatibility Predicates    //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 39e1495cd92..b93b06ba1e7 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -251,7 +251,8 @@ public:      ObjCInterface, ObjCQualifiedInterface,      ObjCQualifiedId,      TypeOfExp, TypeOfTyp, // GNU typeof extension. -    BlockPointer          // C extension +    BlockPointer,          // C extension +    FixedWidthInt    };  private:    QualType CanonicalType; @@ -537,6 +538,27 @@ public:    static bool classof(const BuiltinType *) { return true; }  }; +/// FixedWidthIntType - Used for arbitrary width types that we either don't +/// want to or can't map to named integer types.  These always have a lower +/// integer rank than builtin types of the same width. +class FixedWidthIntType : public Type { +private: +  unsigned Width; +  bool Signed; +public: +  FixedWidthIntType(unsigned W, bool S) : Type(FixedWidthInt, QualType(), false), +                                          Width(W), Signed(S) {} +   +  unsigned getWidth() const { return Width; } +  bool isSigned() const { return Signed; } +  const char *getName() const; +   +  virtual void getAsStringInternal(std::string &InnerString) const; +   +  static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; } +  static bool classof(const FixedWidthIntType *) { 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.  /// diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c9531508e9f..d4fe26ed678 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -373,6 +373,13 @@ ASTContext::getTypeInfo(const Type *T) {        break;      }      break; +  case Type::FixedWidthInt: +    // FIXME: This isn't precisely correct; the width/alignment should depend +    // on the available types for the target +    Width = cast<FixedWidthIntType>(T)->getWidth(); +    Width = std::max(llvm::NextPowerOf2(Width - 1), 8ULL); +    Align = Width; +    break;    case Type::ASQual:      // FIXME: Pointers into different addr spaces could have different sizes and      // alignment requirements: getPointerInfo should take an AddrSpace. @@ -769,6 +776,14 @@ QualType ASTContext::getComplexType(QualType T) {    return QualType(New, 0);  } +QualType ASTContext::getFixedWidthIntType(unsigned Width, bool Signed) { +  llvm::DenseMap<unsigned, FixedWidthIntType*> &Map = Signed ? +     SignedFixedWidthIntTypes : UnsignedFixedWidthIntTypes; +  FixedWidthIntType *&Entry = Map[Width]; +  if (!Entry) +    Entry = new FixedWidthIntType(Width, Signed); +  return QualType(Entry, 0); +}  /// getPointerType - Return the uniqued reference to the type for a pointer to  /// the specified type. @@ -1599,32 +1614,39 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) {  /// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This  /// routine will assert if passed a built-in type that isn't an integer or enum,  /// or if it is not canonicalized. -static unsigned getIntegerRank(Type *T) { +unsigned ASTContext::getIntegerRank(Type *T) {    assert(T->isCanonical() && "T should be canonicalized"); -  if (isa<EnumType>(T)) -    return 4; -   +  if (EnumType* ET = dyn_cast<EnumType>(T)) +    T = ET->getDecl()->getIntegerType().getTypePtr(); + +  // There are two things which impact the integer rank: the width, and +  // the ordering of builtins.  The builtin ordering is encoded in the +  // bottom three bits; the width is encoded in the bits above that. +  if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) { +    return FWIT->getWidth() << 3; +  } +    switch (cast<BuiltinType>(T)->getKind()) {    default: assert(0 && "getIntegerRank(): not a built-in integer");    case BuiltinType::Bool: -    return 1; +    return 1 + (getIntWidth(BoolTy) << 3);    case BuiltinType::Char_S:    case BuiltinType::Char_U:    case BuiltinType::SChar:    case BuiltinType::UChar: -    return 2; +    return 2 + (getIntWidth(CharTy) << 3);    case BuiltinType::Short:    case BuiltinType::UShort: -    return 3; +    return 3 + (getIntWidth(ShortTy) << 3);    case BuiltinType::Int:    case BuiltinType::UInt: -    return 4; +    return 4 + (getIntWidth(IntTy) << 3);    case BuiltinType::Long:    case BuiltinType::ULong: -    return 5; +    return 5 + (getIntWidth(LongTy) << 3);    case BuiltinType::LongLong:    case BuiltinType::ULongLong: -    return 6; +    return 6 + (getIntWidth(LongLongTy) << 3);    }  } @@ -2718,7 +2740,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {  unsigned ASTContext::getIntWidth(QualType T) {    if (T == BoolTy)      return 1; -  // At the moment, only bool has padding bits +  if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) { +    return FWIT->getWidth(); +  } +  // For builtin types, just use the standard type sizing method    return (unsigned)getTypeSize(T);  } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 24cf8535556..ad5026b98b2 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -510,6 +510,8 @@ bool Type::isIntegerType() const {      // FIXME: In C++, enum types are never integer types.      if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())        return true; +  if (isa<FixedWidthIntType>(CanonicalType)) +    return true;    if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))      return VT->getElementType()->isIntegerType();    if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType)) @@ -525,6 +527,8 @@ bool Type::isIntegralType() const {      if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())        return true;  // Complete enum types are integral.                      // FIXME: In C++, enum types are never integral. +  if (isa<FixedWidthIntType>(CanonicalType)) +    return true;    if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))      return ASQT->getBaseType()->isIntegralType();    return false; @@ -578,6 +582,10 @@ bool Type::isSignedIntegerType() const {    if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))      return ET->getDecl()->getIntegerType()->isSignedIntegerType(); +  if (const FixedWidthIntType *FWIT = +          dyn_cast<FixedWidthIntType>(CanonicalType)) +    return FWIT->isSigned(); +      if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))      return VT->getElementType()->isSignedIntegerType();    if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType)) @@ -598,6 +606,10 @@ bool Type::isUnsignedIntegerType() const {    if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))      return ET->getDecl()->getIntegerType()->isUnsignedIntegerType(); +  if (const FixedWidthIntType *FWIT = +          dyn_cast<FixedWidthIntType>(CanonicalType)) +    return !FWIT->isSigned(); +    if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))      return VT->getElementType()->isUnsignedIntegerType();    if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType)) @@ -635,6 +647,8 @@ bool Type::isRealType() const {             BT->getKind() <= BuiltinType::LongDouble;    if (const TagType *TT = dyn_cast<TagType>(CanonicalType))      return TT->getDecl()->isEnum() && TT->getDecl()->isDefinition(); +  if (isa<FixedWidthIntType>(CanonicalType)) +    return true;    if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))      return VT->getElementType()->isRealType();    if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType)) @@ -650,6 +664,8 @@ bool Type::isArithmeticType() const {      // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).      // If a body isn't seen by the time we get here, return false.      return ET->getDecl()->isDefinition(); +  if (isa<FixedWidthIntType>(CanonicalType)) +    return true;    if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))      return ASQT->getBaseType()->isArithmeticType();    return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType); @@ -667,6 +683,8 @@ bool Type::isScalarType() const {    }    if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))      return ASQT->getBaseType()->isScalarType(); +  if (isa<FixedWidthIntType>(CanonicalType)) +    return true;    return isa<PointerType>(CanonicalType) ||           isa<BlockPointerType>(CanonicalType) ||           isa<MemberPointerType>(CanonicalType) || @@ -1014,6 +1032,21 @@ void BuiltinType::getAsStringInternal(std::string &S) const {    }  } +void FixedWidthIntType::getAsStringInternal(std::string &S) const { +  // FIXME: Once we get bitwidth attribute, write as +  // "int __attribute__((bitwidth(x)))". +  std::string prefix = "__clang_fixedwidth"; +  prefix += llvm::utostr_32(Width); +  prefix += (char)(Signed ? 'S' : 'U'); +  if (S.empty()) { +    S = prefix; +  } else { +    // Prefix the basic type, e.g. 'int X'. +    S = prefix + S; +  } +} + +  void ComplexType::getAsStringInternal(std::string &S) const {    ElementType->getAsStringInternal(S);    S = "_Complex " + S; diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 37b7c5f68cb..5c4b2a5900f 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -216,6 +216,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {      }      break;    } +  case Type::FixedWidthInt: +    return llvm::IntegerType::get(cast<FixedWidthIntType>(T)->getWidth());    case Type::Complex: {      const llvm::Type *EltTy =         ConvertTypeRecursive(cast<ComplexType>(Ty).getElementType()); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c27df2bdeb1..c08634c7889 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1238,7 +1238,12 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {      return;    } -  // FIXME: Need proper fixed-width types +  // FIXME: Sync this with InitializePredefinedMacros; we need to match +  // int8_t and friends, at least with glibc. +  // FIXME: Make sure 32/64-bit integers don't get defined to types of +  // the wrong width on unusual platforms. +  // FIXME: Make sure floating-point mappings are accurate +  // FIXME: Support XF and TF types    QualType NewTy;    switch (DestWidth) {    case 0: @@ -1277,6 +1282,12 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {      else        NewTy = S.Context.UnsignedLongLongTy;      break; +  case 128: +    if (!IntegerMode) { +      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; +      return; +    } +    NewTy = S.Context.getFixedWidthIntType(128, OldTy->isSignedIntegerType());    }    if (!OldTy->getAsBuiltinType()) diff --git a/clang/test/Sema/128bitint.c b/clang/test/Sema/128bitint.c new file mode 100644 index 00000000000..45678e90a9c --- /dev/null +++ b/clang/test/Sema/128bitint.c @@ -0,0 +1,6 @@ +// RUN: clang -fsyntax-only -verify %s +typedef int i128 __attribute__((__mode__(TI))); +typedef unsigned u128 __attribute__((__mode__(TI))); + +int a[((i128)-1 ^ (i128)-2) == 1 ? 1 : -1]; +int a[(u128)-1 > 1LL ? 1 : -1];  | 

