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;
UInt,
ULong,
ULongLong,
+ UInt128, // __uint128_t
Char_S, // This is 'char' for targets where char is signed.
SChar, // This is explicitly qualified signed char.
Int,
Long,
LongLong,
+ Int128, // __int128_t
Float, Double, LongDouble,
/// \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
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
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:
case BuiltinType::LongLong:
case BuiltinType::ULongLong:
return 6 + (getIntWidth(LongLongTy) << 3);
+ case BuiltinType::Int128:
+ case BuiltinType::UInt128:
+ return 7 + (getIntWidth(Int128Ty) << 3);
}
}
encoding =
(const_cast<ASTContext *>(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;
(const_cast<ASTContext *>(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;
return UnsignedLongTy;
case BuiltinType::LongLong:
return UnsignedLongLongTy;
+ case BuiltinType::Int128:
+ return UnsignedInt128Ty;
default:
assert(0 && "Unexpected signed integer type");
return QualType();
bool Type::isIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
- BT->getKind() <= BuiltinType::LongLong;
+ BT->getKind() <= BuiltinType::Int128;
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
// Incomplete enum types are not treated as integer types.
// FIXME: In C++, enum types are never integer types.
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";
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) {
}
// 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);
case BuiltinType::Double:
case BuiltinType::LongDouble:
return getTypeForFormat(Context.getFloatTypeSemantics(T));
+
+ case BuiltinType::UInt128:
+ case BuiltinType::Int128:
+ return llvm::IntegerType::get(128);
}
break;
}
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;
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;
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;
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;
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()) {
--- /dev/null
+// 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;
+}
+
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) { }
// 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);
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;
+}