Hi Eli,
Sorry for latency.
As you remember this patch should correct 'mode' attr implementation.
You proposed to use generic way of type detection for each target: just
scan for target types and select one with suitable width.
Unfortunately I can't commit patch with generic implementation. I got
test failure for clang. And I expect more failures for another targets.
The reason is next.
The target could still keep mode unsupported even if it has type of
suitable width. I mean the next.
For example this string should cause error for i686 machines (128 bit
float):
typedef float f128ibm __attribute__ ((mode (TF)));
But in case of generic approach for all targets it would be passed.
In this case virtual functions allows to implement exceptions.
In this case 'getIntTypeByWidth' may be a bit confusing name. Instead it
is supposed to return type for some particular mode, not by width.
Something like getInt/RealTypeForMode(width, sign).
Though, currently I kept the original name.
-Stepan.
Eli Friedman wrote:
On Sun, Aug 25, 2013 at 9:34 AM, Stepan Dyatkovskiy <[email protected]
<mailto:[email protected]>> wrote:
Hi Eli,
Thanks for review!
>
enum RealType {
+ NoFloat = 255,
Float = 0,
Double,
- LongDouble
+ LongDouble,
};
Unless I'm missing something, there isn't any reason not to make
NoFloat 0.
Yes, there is. Since there types could be encoded, and Float is
supposed to be encoded as 0. It couses several crashes:
Clang :: CodeGenObjC/fpret.m
Clang :: CodeGenObjC/metadata-symbols-__64.m
Clang :: Sema/attr-mode.c
Oh, okay, that's fine.
+ /// \brief Return integer type with specified width.
+ virtual IntType getIntTypeByWidth(unsigned BitWidth, bool
IsSigned) const;
+
+ /// \brief Return floating point type with specified width.
+ virtual RealType getRealTypeByWidth(unsigned BitWidth) const;
Instead of making these virtual, would it be possible to make these
figure out the appropriate types based on the widths etc. we already
compute? e.g. for the integer types, something like so:
TargetInfo::IntType TargetInfo::getIntTypeByWidth(
unsigned BitWidth, bool IsSigned) const {
if (getCharWidth() == BitWidth)
return IsSigned ? SignedChar : UnsignedChar;
if (getShortWidth() == BitWidth)
return IsSigned ? SignedShort : UnsignedShort;
if (getIntWidth() == BitWidth)
return IsSigned ? SignedInt : UnsignedInt;
if (getLongWidth() == BitWidth)
return IsSigned ? SignedLong : UnsignedLong;
if (getLongLongWidth() == BitWidth)
return IsSigned ? SignedLongLong : UnsignedLongLong;
return NoInt;
}
I'd prefer to make things as simple as possible for people
adding new targets.
OK. I did it. The reason was to keep current implementation but in
better form, so everybody could customize it. Implementation you
proposed could work differently, though I can watch for buildbots
after commit and reject it if something went wrong.
Sorry it took a little while to get to reviewing this.
Sorry me to. I was on vocation :-)
- LongDouble
+ LongDouble,
};
I don't recall whether all the compilers we care about accept this
without complaining; please leave out the extra comma.
Otherwise, LGTM.
-Eli
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 6f27fbe..377282f 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -480,6 +480,17 @@ public:
const TargetInfo &getTargetInfo() const { return *Target; }
+ /// getIntTypeForBitwidth -
+ /// sets integer QualTy according to specified details:
+ /// bitwidth, signed/unsigned.
+ /// Returns empty type if there is no appropriate target types.
+ QualType getIntTypeForBitwidth(unsigned DestWidth,
+ unsigned Signed) const;
+ /// getRealTypeForBitwidth -
+ /// sets floating point QualTy according to specified bitwidth.
+ /// Returns empty type if there is no appropriate target types.
+ QualType getRealTypeForBitwidth(unsigned DestWidth) const;
+
bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const;
const LangOptions& getLangOpts() const { return LangOpts; }
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 1073711..1466cc2 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -112,6 +112,8 @@ public:
///===---- Target Data Type Query Methods -------------------------------===//
enum IntType {
NoInt = 0,
+ SignedChar,
+ UnsignedChar,
SignedShort,
UnsignedShort,
SignedInt,
@@ -123,6 +125,7 @@ public:
};
enum RealType {
+ NoFloat = 255,
Float = 0,
Double,
LongDouble
@@ -220,6 +223,12 @@ public:
/// For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
+ /// \brief Return integer type with specified width.
+ virtual IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
+
+ /// \brief Return floating point type with specified width.
+ virtual RealType getRealTypeByWidth(unsigned BitWidth) const;
+
/// \brief Return the alignment (in bits) of the specified integer type enum.
///
/// For example, SignedInt -> getIntAlign().
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 94d9e91..85ac734 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -6314,6 +6314,8 @@ ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
CanQualType ASTContext::getFromTargetType(unsigned Type) const {
switch (Type) {
case TargetInfo::NoInt: return CanQualType();
+ case TargetInfo::SignedChar: return SignedCharTy;
+ case TargetInfo::UnsignedChar: return UnsignedCharTy;
case TargetInfo::SignedShort: return ShortTy;
case TargetInfo::UnsignedShort: return UnsignedShortTy;
case TargetInfo::SignedInt: return IntTy;
@@ -7990,6 +7992,38 @@ size_t ASTContext::getSideTableAllocatedMemory() const {
llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
}
+/// getIntTypeForBitwidth -
+/// sets integer QualTy according to specified details:
+/// bitwidth, signed/unsigned.
+/// Returns empty type if there is no appropriate target types.
+QualType ASTContext::getIntTypeForBitwidth(unsigned DestWidth,
+ unsigned Signed) const {
+ TargetInfo::IntType Ty = getTargetInfo().getIntTypeByWidth(DestWidth, Signed);
+ CanQualType QualTy = getFromTargetType(Ty);
+ if (!QualTy && DestWidth == 128)
+ return Signed ? Int128Ty : UnsignedInt128Ty;
+ return QualTy;
+}
+
+/// getRealTypeForBitwidth -
+/// sets floating point QualTy according to specified bitwidth.
+/// Returns empty type if there is no appropriate target types.
+QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const {
+ TargetInfo::RealType Ty = getTargetInfo().getRealTypeByWidth(DestWidth);
+ switch (Ty) {
+ case TargetInfo::Float:
+ return FloatTy;
+ case TargetInfo::Double:
+ return DoubleTy;
+ case TargetInfo::LongDouble:
+ return LongDoubleTy;
+ case TargetInfo::NoFloat:
+ return QualType();
+ }
+
+ llvm_unreachable("Unhandled TargetInfo::RealType value");
+}
+
void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) {
if (Number > 1)
MangleNumbers[ND] = Number;
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index f8c10d1..f2dc66e 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -102,6 +102,8 @@ TargetInfo::~TargetInfo() {}
const char *TargetInfo::getTypeName(IntType T) {
switch (T) {
default: llvm_unreachable("not an integer!");
+ case SignedChar: return "char";
+ case UnsignedChar: return "unsigned char";
case SignedShort: return "short";
case UnsignedShort: return "unsigned short";
case SignedInt: return "int";
@@ -118,10 +120,12 @@ const char *TargetInfo::getTypeName(IntType T) {
const char *TargetInfo::getTypeConstantSuffix(IntType T) {
switch (T) {
default: llvm_unreachable("not an integer!");
+ case SignedChar:
case SignedShort:
case SignedInt: return "";
case SignedLong: return "L";
case SignedLongLong: return "LL";
+ case UnsignedChar:
case UnsignedShort:
case UnsignedInt: return "U";
case UnsignedLong: return "UL";
@@ -134,6 +138,8 @@ const char *TargetInfo::getTypeConstantSuffix(IntType T) {
unsigned TargetInfo::getTypeWidth(IntType T) const {
switch (T) {
default: llvm_unreachable("not an integer!");
+ case SignedChar:
+ case UnsignedChar: return getCharWidth();
case SignedShort:
case UnsignedShort: return getShortWidth();
case SignedInt:
@@ -145,11 +151,50 @@ unsigned TargetInfo::getTypeWidth(IntType T) const {
};
}
+TargetInfo::IntType TargetInfo::getIntTypeByWidth(
+ unsigned BitWidth, bool IsSigned) const {
+ switch (BitWidth) {
+ case 8:
+ return IsSigned ? SignedChar : UnsignedChar;
+ case 16:
+ return IsSigned ? SignedShort : UnsignedShort;
+ case 32:
+ return IsSigned ? SignedInt : UnsignedInt;
+ case 64:
+ if (getLongWidth() == 64)
+ return IsSigned ? SignedLong : UnsignedLong;
+ return IsSigned ? SignedLongLong : UnsignedLongLong;
+ case 128:
+ // Currently Int128 is not in IntType enumeration.
+ return NoInt;
+ }
+ return NoInt;
+}
+
+TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
+ switch (BitWidth) {
+ case 32:
+ return Float;
+ case 64:
+ return Double;
+ case 96:
+ return LongDouble;
+ case 128:
+ if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble) {
+ return LongDouble;
+ }
+ break;
+ }
+ return NoFloat;
+}
+
/// getTypeAlign - Return the alignment (in bits) of the specified integer type
/// enum. For example, SignedInt -> getIntAlign().
unsigned TargetInfo::getTypeAlign(IntType T) const {
switch (T) {
default: llvm_unreachable("not an integer!");
+ case SignedChar:
+ case UnsignedChar: return getCharAlign();
case SignedShort:
case UnsignedShort: return getShortAlign();
case SignedInt:
@@ -166,11 +211,13 @@ unsigned TargetInfo::getTypeAlign(IntType T) const {
bool TargetInfo::isTypeSigned(IntType T) {
switch (T) {
default: llvm_unreachable("not an integer!");
+ case SignedChar:
case SignedShort:
case SignedInt:
case SignedLong:
case SignedLongLong:
return true;
+ case UnsignedChar:
case UnsignedShort:
case UnsignedInt:
case UnsignedLong:
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 2eb74e0..0d76069 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -497,7 +497,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far");
Builder.defineMacro("__CHAR_BIT__", "8");
- DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Builder);
+ DefineTypeSize("__SCHAR_MAX__", TargetInfo::SignedChar, TI, Builder);
DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Builder);
DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Builder);
DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder);
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 00f8af9..6167c60 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -3637,77 +3637,24 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// 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:
+ if (!DestWidth) {
S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
return;
- default:
+ }
+
+ QualType NewTy;
+
+ if (IntegerMode)
+ NewTy = S.Context.getIntTypeForBitwidth(DestWidth,
+ OldTy->isSignedIntegerType());
+ else
+ NewTy = S.Context.getRealTypeForBitwidth(DestWidth);
+
+ if (NewTy.isNull()) {
S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
return;
- case 8:
- if (!IntegerMode) {
- S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
- return;
- }
- if (OldTy->isSignedIntegerType())
- NewTy = S.Context.SignedCharTy;
- else
- NewTy = S.Context.UnsignedCharTy;
- break;
- case 16:
- if (!IntegerMode) {
- S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
- return;
- }
- if (OldTy->isSignedIntegerType())
- NewTy = S.Context.ShortTy;
- else
- NewTy = S.Context.UnsignedShortTy;
- break;
- case 32:
- if (!IntegerMode)
- NewTy = S.Context.FloatTy;
- else if (OldTy->isSignedIntegerType())
- NewTy = S.Context.IntTy;
- else
- NewTy = S.Context.UnsignedIntTy;
- break;
- case 64:
- if (!IntegerMode)
- NewTy = S.Context.DoubleTy;
- else if (OldTy->isSignedIntegerType())
- if (S.Context.getTargetInfo().getLongWidth() == 64)
- NewTy = S.Context.LongTy;
- else
- NewTy = S.Context.LongLongTy;
- else
- if (S.Context.getTargetInfo().getLongWidth() == 64)
- NewTy = S.Context.UnsignedLongTy;
- else
- NewTy = S.Context.UnsignedLongLongTy;
- break;
- case 96:
- NewTy = S.Context.LongDoubleTy;
- break;
- case 128:
- if (!IntegerMode && &S.Context.getTargetInfo().getLongDoubleFormat() !=
- &llvm::APFloat::PPCDoubleDouble) {
- S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
- return;
- }
- if (IntegerMode) {
- if (OldTy->isSignedIntegerType())
- NewTy = S.Context.Int128Ty;
- else
- NewTy = S.Context.UnsignedInt128Ty;
- } else
- NewTy = S.Context.LongDoubleTy;
- break;
}
if (ComplexMode) {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits