[cfe-dev] Patch for arbitrary fixed-width integer types

Chris Lattner clattner at apple.com
Sat Feb 7 18:47:51 PST 2009


On Feb 6, 2009, at 8:28 PM, Eli Friedman wrote:

> Patch attached.  The reason I'm sending this to cfe-dev rather than
> just committing it is that it's a substantial new chunk of code, and I
> want to make sure it's something we really want; the potential users
> are rather limited.

Nifty.

In  lib/Sema/SemaDeclAttr.cpp, it seems that you could simplify the  
code by doing something like this before the switch:

if (IntegerMode) {
   NewTy = S.Context.getFixedWidthIntType(size, OldTy- 
 >isSignedIntegerType());
} else {
   switch ()...

> The attached patch adds one user for the new fixed-width types: the
> implementation of the mode attribute.  That said, this is probably
> overkill for that particular use, and it might confuse code that uses
> function overloading.

This sounds like a good use for it.  I'm not too concerned with C++  
overloading for attribute(mode).  I have never seen attribute mode  
used with C++ code.

> Another possible use is that there was a request on the list a while
> ago for a way to declare integer types of arbitrary width; this patch
> would make implementing that relatively easy.

Yes, it would.  attribute(bitwidth(42)) would be nice to support.   
This would also give you something to pretty print to with:

+void FixedWidthIntType::getAsStringInternal(std::string &S) const {
+  if (S.empty()) {
+    S = llvm::utostr_32(Width);
+  } else {
+    // Prefix the basic type, e.g. 'int X'.
+    S = ' ' + S;
+    S = llvm::utostr_32(Width) + S;
+  }
+}

> Also, we could use this for gcc compatibility for testcases like the
> following, although I'm not sure it's worthwhile:
> struct {unsigned long long x : 33;} x;
> unsigned long long a(void) {return x.x+1;}

This would also be very nice.  We really should support this case at  
the very least, because this is a silent miscompilation otherwise.   
How does "x" act w.r.t to overloading in this case with gcc?

+++ lib/AST/ASTContext.cpp	(working copy)
@@ -373,6 +373,13 @@
        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;

This should probably follow the same logic that TargetData has on the  
LLVM IR  side of things.



+QualType ASTContext::getFixedWidthIntType(unsigned Width, bool  
Signed) {
+  if (Signed) {
+    if (!SignedFixedWidthIntTypes.count(Width)) {
+      SignedFixedWidthIntTypes[Width] = new FixedWidthIntType(Width,  
true);
+    }
+    return QualType(SignedFixedWidthIntTypes[Width], 0);
+  }
+  if (!UnsignedFixedWidthIntTypes.count(Width)) {
+    UnsignedFixedWidthIntTypes[Width] = new FixedWidthIntType(Width,  
false);
+  }
+  return QualType(UnsignedFixedWidthIntTypes[Width], 0);
+}

Instead of doing two/three lookups (one for count one for return and  
one for the insert), please just do one:

   llvm::DenseMap<unsigned, FixedWidthIntType*> &Map = Signed ?  
SignedFixedWidthIntTypes : UnsignedFixedWidthIntTypes;

   FixedWidthIntType *&Entry = Map[Width];
   if (Entry) return Entry;
   return Entry = new ...
}

I'm not sure how this fits in with ranking and C++ overload, but this  
is very cool.

-Chris





More information about the cfe-dev mailing list