From 2df9ced9fd1e8c7d7b38443db07e0e811de22571 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 30 Apr 2009 02:43:43 +0000 Subject: [PATCH] initial support for __[u]int128_t, which should be basically compatible with VC++ and GCC. The codegen/mangling angle hasn't been fully ironed out yet. Note that we accept int128_t even in 32-bit mode, unlike gcc. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70464 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 4 ++-- include/clang/AST/Type.h | 2 ++ include/clang/Frontend/PCHBitCodes.h | 6 +++++- lib/AST/ASTContext.cpp | 18 ++++++++++++++++++ lib/AST/Type.cpp | 4 +++- lib/CodeGen/CGCall.cpp | 4 +++- lib/CodeGen/CodeGenTypes.cpp | 4 ++++ lib/CodeGen/Mangle.cpp | 2 ++ lib/Frontend/PCHReader.cpp | 2 ++ lib/Frontend/PCHWriter.cpp | 2 ++ lib/Sema/Sema.cpp | 12 ++++++++++++ test/CodeGen/uint128_t.c | 18 ++++++++++++++++++ test/CodeGenCXX/mangle.cpp | 5 ++++- test/CodeGenObjC/encode-test-5.m | 7 ++++++- test/Sema/types.c | 11 +++++++++++ 15 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 test/CodeGen/uint128_t.c diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index f4a01c4cf0..8cb1056110 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -174,9 +174,9 @@ public: QualType BoolTy; QualType CharTy; QualType WCharTy; // [C++ 3.9.1p5], integer type in C99. - QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy; + QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; - QualType UnsignedLongLongTy; + QualType UnsignedLongLongTy, UnsignedInt128Ty; QualType FloatTy, DoubleTy, LongDoubleTy; QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; QualType VoidPtrTy; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 5374c00949..3e8d024d72 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -537,6 +537,7 @@ public: UInt, ULong, ULongLong, + UInt128, // __uint128_t Char_S, // This is 'char' for targets where char is signed. SChar, // This is explicitly qualified signed char. @@ -545,6 +546,7 @@ public: Int, Long, LongLong, + Int128, // __int128_t Float, Double, LongDouble, diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index a4da704386..bb5c91b8e0 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -315,7 +315,11 @@ namespace clang { /// \brief The placeholder type for overloaded function sets. PREDEF_TYPE_OVERLOAD_ID = 19, /// \brief The placeholder type for dependent types. - PREDEF_TYPE_DEPENDENT_ID = 20 + PREDEF_TYPE_DEPENDENT_ID = 20, + /// \brief The '__uint128_t' type. + PREDEF_TYPE_UINT128_ID = 21, + /// \brief The '__int128_t' type. + PREDEF_TYPE_INT128_ID = 22 }; /// \brief The number of predefined type IDs that are reserved for diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 58fc42b036..6cd016cab8 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -251,6 +251,10 @@ void ASTContext::InitBuiltinTypes() { InitBuiltinType(DoubleTy, BuiltinType::Double); InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble); + // GNU extension, 128-bit integers. + InitBuiltinType(Int128Ty, BuiltinType::Int128); + InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); + if (LangOpts.CPlusPlus) // C++ 3.9.1p5 InitBuiltinType(WCharTy, BuiltinType::WChar); else // C99 @@ -421,6 +425,13 @@ ASTContext::getTypeInfo(const Type *T) { Width = Target.getLongDoubleWidth(); Align = Target.getLongDoubleAlign(); break; + case BuiltinType::Int128: + case BuiltinType::UInt128: + Width = 128; + + // FIXME: Is this correct for all targets? + Align = 128; + break; } break; case Type::FixedWidthInt: @@ -1923,6 +1934,9 @@ unsigned ASTContext::getIntegerRank(Type *T) { case BuiltinType::LongLong: case BuiltinType::ULongLong: return 6 + (getIntWidth(LongLongTy) << 3); + case BuiltinType::Int128: + case BuiltinType::UInt128: + return 7 + (getIntWidth(Int128Ty) << 3); } } @@ -2291,6 +2305,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, encoding = (const_cast(this))->getIntWidth(T) == 32 ? 'L' : 'Q'; break; + case BuiltinType::UInt128: encoding = 'T'; break; case BuiltinType::ULongLong: encoding = 'Q'; break; case BuiltinType::Char_S: case BuiltinType::SChar: encoding = 'c'; break; @@ -2301,6 +2316,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, (const_cast(this))->getIntWidth(T) == 32 ? 'l' : 'q'; break; case BuiltinType::LongLong: encoding = 'q'; break; + case BuiltinType::Int128: encoding = 't'; break; case BuiltinType::Float: encoding = 'f'; break; case BuiltinType::Double: encoding = 'd'; break; case BuiltinType::LongDouble: encoding = 'd'; break; @@ -3244,6 +3260,8 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) { return UnsignedLongTy; case BuiltinType::LongLong: return UnsignedLongLongTy; + case BuiltinType::Int128: + return UnsignedInt128Ty; default: assert(0 && "Unexpected signed integer type"); return QualType(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 0331bbf40d..d6cf4bd0c3 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -584,7 +584,7 @@ Type::getAsTemplateSpecializationType() const { bool Type::isIntegerType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::LongLong; + BT->getKind() <= BuiltinType::Int128; if (const TagType *TT = dyn_cast(CanonicalType)) // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. @@ -901,11 +901,13 @@ const char *BuiltinType::getName() const { case Int: return "int"; case Long: return "long"; case LongLong: return "long long"; + case Int128: return "__int128_t"; case UChar: return "unsigned char"; case UShort: return "unsigned short"; case UInt: return "unsigned int"; case ULong: return "unsigned long"; case ULongLong: return "unsigned long long"; + case UInt128: return "__uint128_t"; case Float: return "float"; case Double: return "double"; case LongDouble: return "long double"; diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 07663bfaea..a6439fcb03 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -640,6 +640,9 @@ void X86_64ABIInfo::classify(QualType Ty, if (k == BuiltinType::Void) { Current = NoClass; + } else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) { + Lo = Memory; + Hi = Memory; } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) { Current = Integer; } else if (k == BuiltinType::Float || k == BuiltinType::Double) { @@ -650,7 +653,6 @@ void X86_64ABIInfo::classify(QualType Ty, } // FIXME: _Decimal32 and _Decimal64 are SSE. // FIXME: _float128 and _Decimal128 are (SSE, SSEUp). - // FIXME: __int128 is (Integer, Integer). } else if (const EnumType *ET = Ty->getAsEnumType()) { // Classify the underlying integer type. classify(ET->getDecl()->getIntegerType(), Context, OffsetBase, Lo, Hi); diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index f0bc6f6961..a3f79d3d59 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -256,6 +256,10 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case BuiltinType::Double: case BuiltinType::LongDouble: return getTypeForFormat(Context.getFloatTypeSemantics(T)); + + case BuiltinType::UInt128: + case BuiltinType::Int128: + return llvm::IntegerType::get(128); } break; } diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 3a7fe9c1f7..e6d643f7ca 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -508,12 +508,14 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::UInt: Out << 'j'; break; case BuiltinType::ULong: Out << 'm'; break; case BuiltinType::ULongLong: Out << 'y'; break; + case BuiltinType::UInt128: Out << 'o'; break; case BuiltinType::SChar: Out << 'a'; break; case BuiltinType::WChar: Out << 'w'; break; case BuiltinType::Short: Out << 's'; break; case BuiltinType::Int: Out << 'i'; break; case BuiltinType::Long: Out << 'l'; break; case BuiltinType::LongLong: Out << 'x'; break; + case BuiltinType::Int128: Out << 'n'; break; case BuiltinType::Float: Out << 'f'; break; case BuiltinType::Double: Out << 'd'; break; case BuiltinType::LongDouble: Out << 'e'; break; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index ead6dcc101..9323620938 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1663,12 +1663,14 @@ QualType PCHReader::GetType(pch::TypeID ID) { case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break; case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break; case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break; + case pch::PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break; case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break; case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break; case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break; case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break; case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break; case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break; + case pch::PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break; case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break; case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break; case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break; diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 8374e092a5..b28d0c8cf9 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1829,6 +1829,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break; case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break; case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break; + case BuiltinType::UInt128: ID = pch::PREDEF_TYPE_UINT128_ID; break; case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break; case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break; case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break; @@ -1836,6 +1837,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break; case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break; case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break; + case BuiltinType::Int128: ID = pch::PREDEF_TYPE_INT128_ID; break; case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break; case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break; case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break; diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 367c9f5756..8ce3ce0be6 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -108,6 +108,18 @@ static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) { void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { TUScope = S; PushDeclContext(S, Context.getTranslationUnitDecl()); + + // Install [u]int128_t. + PushOnScopeChains(TypedefDecl::Create(Context, CurContext, + SourceLocation(), + &Context.Idents.get("__int128_t"), + Context.Int128Ty), TUScope); + PushOnScopeChains(TypedefDecl::Create(Context, CurContext, + SourceLocation(), + &Context.Idents.get("__uint128_t"), + Context.UnsignedInt128Ty), TUScope); + + if (!PP.getLangOptions().ObjC1) return; if (Context.getObjCSelType().isNull()) { diff --git a/test/CodeGen/uint128_t.c b/test/CodeGen/uint128_t.c new file mode 100644 index 0000000000..b3261dd687 --- /dev/null +++ b/test/CodeGen/uint128_t.c @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -emit-llvm -o - + +typedef unsigned long long uint64_t; +extern uint64_t numer; +extern uint64_t denom; + +uint64_t +f(uint64_t val) +{ + __uint128_t tmp; + + tmp = val; + tmp *= numer; + tmp /= denom; + + return tmp; +} + diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 0f13527023..5540a6868f 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -46,5 +46,8 @@ namespace N { int i; } namespace N { int f(int, int) { static int b; return b; } } // RUN: grep "_ZZN1N1gEvE1a =" %t | count 1 && -// RUN: grep "_ZGVZN1N1gEvE1a =" %t | count 1 +// RUN: grep "_ZGVZN1N1gEvE1a =" %t | count 1 && namespace N { int h(); void g() { static int a = h(); } } + +// RUN: grep "_Z1fno" %t | count 1 +void f(__int128_t, __uint128_t) { } diff --git a/test/CodeGenObjC/encode-test-5.m b/test/CodeGenObjC/encode-test-5.m index 970df3da87..bf1a0a6725 100644 --- a/test/CodeGenObjC/encode-test-5.m +++ b/test/CodeGenObjC/encode-test-5.m @@ -6,6 +6,11 @@ char *a = @encode(_Complex int); // RUN: grep jf %t | count 1 && char *b = @encode(_Complex float); -// RUN: grep jd %t | count 1 +// RUN: grep jd %t | count 1 && char *c = @encode(_Complex double); +// RUN: grep "t.00" %t | count 1 && +char *e = @encode(__int128_t); + +// RUN: grep "T.00" %t | count 1 +char *f = @encode(__uint128_t); diff --git a/test/Sema/types.c b/test/Sema/types.c index 40dfd89c4f..d1e9fcc052 100644 --- a/test/Sema/types.c +++ b/test/Sema/types.c @@ -8,3 +8,14 @@ typedef int *S[2]; restrict S y; // expected-error {{restrict requires a pointer or reference ('S' (aka 'int *[2]') is invalid)}} + +// int128_t is available. +int a() { + __int128_t s; + __uint128_t t; +} +// but not a keyword +int b() { + int __int128_t; + int __uint128_t; +} -- 2.40.0