Devang,

Please find attached the latest bitwidth attribute patch. This is a
candidate for committing to llvm-gcc if it passes your review. The
differences between this patch and the one you reviewed are:

1. All six of the bit reduction builtins have been removed (not needed).
2. I've hacked on the C++ part of llvm-gcc to get it to handle the three
remaining
   builtins much like C does. This was a lot more involved than just
modifying the
   typeck.c file. semantics.c and call.c had to be modified too.

The main thing needing review are the changes to gcc/cp/*.c. The rest
you've already reviewed. If it looks good, please consider committing
it.

Thanks,

Reid.
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 276)
+++ gcc/tree.h	(working copy)
@@ -1711,6 +1711,21 @@
 #define TYPE_CONTAINS_PLACEHOLDER_INTERNAL(NODE) \
   (TYPE_CHECK (NODE)->type.contains_placeholder_bits)
 
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+/* 1 if the bitwidth for this type was set with the "bitwidth" attribute,
+   0 otherwise.  */
+#define TYPE_USER_BITWIDTH(NODE) (TYPE_CHECK (NODE)->type.user_bitwidth)
+/* Extracts the bitwidth field that holds the user's requested
+ * bitwidth from the bitwidth attribute. Depending on the usage this
+ * may or may not be honored due to limitations of how the type is
+ * used. See the handle_bitwidth_attribute function in c-common.c for
+ * details. Note that this field always contains the bitwidth requested
+ * in the attribute but that may differ from the precision used by the type.*/
+#define TYPE_BITWIDTH(NODE) (TYPE_CHECK (NODE)->type.bitwidth)
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
+
 struct die_struct;
 
 struct tree_type GTY(())
@@ -1741,6 +1756,10 @@
   unsigned lang_flag_5 : 1;
   unsigned lang_flag_6 : 1;
   unsigned user_align : 1;
+  /* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+  unsigned user_bitwidth : 1;
+  unsigned bitwidth : 23;
+  /* APPLE LOCAL end LLVM bit accurate integer types - ras */
 
   unsigned int align;
   tree pointer_to;
Index: gcc/llvm.h
===================================================================
--- gcc/llvm.h	(revision 276)
+++ gcc/llvm.h	(working copy)
@@ -92,6 +92,12 @@
 /* llvm_asm_file_end - Finish the .s file. */
 void llvm_asm_file_end(void);
 
+/* A function that can be used to see if a function is one of the LLVM
+ * pseudo_builtin functions that permits integer arguments of any size.
+ * A non-negative result indicates which pseudo-builtin it is. A 
+ * negative result indicates it is not a pseudo-builtin. */
+int llvm_get_pseudo_builtin_index(const char *);
+
 #endif /* ENABLE_LLVM */
 
 #endif
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 276)
+++ gcc/cp/typeck.c	(working copy)
@@ -42,6 +42,11 @@
 #include "target.h"
 #include "convert.h"
 #include "c-common.h"
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+#include "llvm.h"
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
 
 static tree convert_for_assignment (tree, tree, const char *, tree, int);
 static tree cp_pointer_int_sum (enum tree_code, tree, tree);
@@ -2620,6 +2625,12 @@
   tree result = NULL_TREE;
   const char *called_thing = 0;
   int i = 0;
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+  const char *fname = 0;
+  int is_pseudo_builtin = 0;
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
 
   /* Argument passing is always copy-initialization.  */
   flags |= LOOKUP_ONLYCONVERTING;
@@ -2635,7 +2646,18 @@
 	    called_thing = "member function";
 	}
       else
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+        {
+          is_pseudo_builtin = 
+            llvm_get_pseudo_builtin_index(IDENTIFIER_POINTER(DECL_NAME(fndecl)))
+              >= 0;
+          called_thing = "function";
+        }
+#else
 	called_thing = "function";
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
     }
 
   for (valtail = values, typetail = typelist;
@@ -2683,6 +2705,18 @@
       if (val == error_mark_node)
 	return error_mark_node;
 
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+      /* If its a pseudo-builtin function, just defeat all the type checking
+         below and tack the value on to the result. The type is checked later
+         in llvm-convert.cpp when the builtin is handled. */
+      if (is_pseudo_builtin) 
+        {
+	  result = tree_cons (NULL_TREE, val, result);
+        } 
+      else
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
       if (type != 0)
 	{
 	  /* Formal parm type is specified by a function prototype.  */
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 276)
+++ gcc/cp/call.c	(working copy)
@@ -39,6 +39,11 @@
 #include "intl.h"
 #include "target.h"
 #include "convert.h"
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+#include "llvm.h"
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
 
 /* The various kinds of conversion.  */
 
@@ -326,6 +331,12 @@
       mark_used (decl);
     }
 
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+  if (llvm_get_pseudo_builtin_index(IDENTIFIER_POINTER(DECL_NAME(decl))) < 0)
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
+
   /* Don't pass empty class objects by value.  This is useful
      for tags in STL, which are used to control overload resolution.
      We don't need to handle other cases of copying empty classes.  */
@@ -4857,6 +4868,19 @@
       ++i;
       is_method = 1;
     }
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+  /* For llvm, if this function is a pseudo-builtin, we want to defeat any
+   * kind of argument conversion. The llvm-convert.cpp file will handle it. */
+  if (llvm_get_pseudo_builtin_index(IDENTIFIER_POINTER(DECL_NAME(fn))) >= 0) 
+    {
+      for (; arg ; arg = TREE_CHAIN(arg))
+        converted_args = tree_cons(NULL_TREE, TREE_VALUE(arg), converted_args);
+    }
+  else
+    {
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
 
   for (; arg && parm;
        parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
@@ -4899,6 +4923,11 @@
       converted_args = tree_cons (NULL_TREE, a, converted_args);
     }
 
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+    }
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
   converted_args = nreverse (converted_args);
 
   check_function_arguments (TYPE_ATTRIBUTES (TREE_TYPE (fn)),
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 276)
+++ gcc/cp/mangle.c	(working copy)
@@ -1751,6 +1751,22 @@
       else
 	{
 	  size_t itk;
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+          /* Check for bit-accurate integer types that don't use the shared
+           * integer type modes. */
+          unsigned Bits = TYPE_USER_BITWIDTH(type) ? TYPE_BITWIDTH(type) :
+                            TREE_INT_CST_LOW(TYPE_SIZE(type));
+          if ((Bits > HOST_BITS_PER_WIDE_INT * 2) ||
+              (Bits != 8 && Bits != 16 && Bits != 32 && 
+               Bits != 64 && Bits != 128)) {
+            char tmpbuf[32];
+            write_char('q');
+            sprintf(tmpbuf, "%d", Bits);
+            write_string(tmpbuf);
+            break;
+          }
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
+
 	  /* Assume TYPE is one of the shared integer type nodes.  Find
 	     it in the array of these nodes.  */
 	iagain:
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 276)
+++ gcc/cp/semantics.c	(working copy)
@@ -47,6 +47,11 @@
 #include "tree-iterator.h"
 #include "vec.h"
 #include "target.h"
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+#include "llvm.h"
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
 
 /* There routines provide a modular interface to perform many parsing
    operations.  They may therefore be used during actual parsing, or
@@ -1706,6 +1711,22 @@
       identifier = DECL_NAME (fn);
     }
 
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+  /* Avoid Koenig lookup if its a pseudo-builtin function */
+  if (llvm_get_pseudo_builtin_index(IDENTIFIER_POINTER(identifier)) >= 0) {
+    /* Just make up a function prototype of int X(...) for this */
+    tree ftype = build_function_type(integer_type_node, NULL_TREE);
+    /* Create the function decl */
+    tree func = build_lang_decl (FUNCTION_DECL, identifier, ftype);
+    /* Make sure its an 'extern "C"' function so it doesn't get mangled */
+    SET_DECL_LANGUAGE(func, lang_c);
+    TREE_NOTHROW(func) = 0;
+    return func;
+  }
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
+
   /* A call to a namespace-scope function using an unqualified name.
 
      Do Koenig lookup -- unless any of the arguments are
Index: gcc/llvm-convert.cpp
===================================================================
--- gcc/llvm-convert.cpp	(revision 276)
+++ gcc/llvm-convert.cpp	(working copy)
@@ -1877,10 +1877,49 @@
                     ConvertType(TREE_TYPE(exp))); 
 }
 
+static int builtin_functions_comparator(const void* X1, const void* X2) {
+  const char** S1 = (const char**) X1;
+  const char** S2 = (const char**) X2;
+  return strcmp(*S1, *S2);
+}
+
+/// This is an external function that c-typeck.c and cp/typeck.c use to 
+/// determine if it should promote operands to the function or not. Its 
+/// also used in EmitCALL_EXPR to detect the pseudo-builtin functions and 
+/// emit them directly. These functions cannot be "normal" builtin gcc 
+/// functions because their arguments and results can be any integer bit 
+/// width and gcc builtins can't handle that.
+int llvm_get_pseudo_builtin_index(const char * key) {
+  // Make sure we have a valid key
+  if (!key)
+    return -1;
+
+  // Define a sorted array of the pseudo-builtin function names.
+  // NOTE: Keep this in sorted order and in sync with the switch statement
+  // NOTE: in EmitCALL_EXPR, below.
+  static const char* pseudo_builtin_functions[] = {
+    "__builtin_bit_concat",      // concatenate two bit strings into one
+    "__builtin_bit_part_select", // Select a range of bits
+    "__builtin_bit_select",      // select a single bit
+  }; 
+
+  // Use bsearch to see if the function name is one in the list
+  const char **item = (const char**) bsearch(&key, pseudo_builtin_functions,
+      sizeof(pseudo_builtin_functions)/sizeof(pseudo_builtin_functions[0]),
+      sizeof(pseudo_builtin_functions[0]), builtin_functions_comparator);
+  // if we didn't find one, return failure
+  if (!item)
+    return -1;
+  // Otherwise, return the index of the item we found.
+  return (item - &pseudo_builtin_functions[0]);
+}
+
 Value *TreeToLLVM::EmitCALL_EXPR(tree exp, Value *DestLoc) {
-  // Check for a built-in function call.  If we can lower it directly, do so
-  // now.
+  // Get the function declaration
   tree fndecl = get_callee_fndecl(exp);
+
+  // Check for a real built-in function call.  If we can lower it directly, 
+  // do so now.
   if (fndecl && DECL_BUILT_IN(fndecl) &&
       DECL_BUILT_IN_CLASS(fndecl) != BUILT_IN_FRONTEND) {
     Value *Res = 0;
@@ -1888,8 +1927,29 @@
       return Res;
   }
 
+  // Get the callee value.
   Value *Callee = Emit(TREE_OPERAND(exp, 0), 0);
 
+  if (Callee) {
+    // Handle arbitrary precision integer bit manipulation builtins
+    Value* Res = 0;
+    Function* Func = 0;
+    if (ConstantExpr* CE = dyn_cast<ConstantExpr>(Callee)) {
+      if (CE->getOpcode() == Instruction::BitCast)
+        Func = dyn_cast<Function>(CE->getOperand(0));
+    } else 
+      Func = dyn_cast<Function>(Callee);
+    if (Func) {
+      switch (llvm_get_pseudo_builtin_index(Func->getName().c_str())) {
+        default: assert(0 && "Unexpected pseudo-builtin index");
+        case -1: break; /* not found */
+        case 0: if (EmitBuiltinBitConcat(exp, Res)) return Res; break; 
+        case 1: if (EmitBuiltinBitPartSelect(exp, Res)) return Res; break;
+        case 2: if (EmitBuiltinBitSelect(exp, Res)) return Res; break;
+      }
+    }
+  }
+
   if (TREE_OPERAND(exp, 2)) {
     // This is a direct call to a function using a static chain.  We need to
     // change the function type to one with an extra parameter for the chain.
@@ -2269,9 +2329,9 @@
   Value *RetVal = RHS;
   RHS = CastToAnyType(RHS, Op1Signed, OldVal->getType(), Op0Signed);
   if (LV.BitStart)
-    RHS = BinaryOperator::createShl(RHS,
-                        ConstantInt::get(RHS->getType(), LV.BitStart),
-                        "tmp", CurBB);
+    RHS = BinaryOperator::createShl(RHS, ConstantInt::get(RHS->getType(), 
+                                    LV.BitStart), "tmp", CurBB);
+
   // Next, if this doesn't touch the top bit, mask out any bits that shouldn't
   // be set in the result.
   uint64_t MaskVal = ((1ULL << LV.BitSize)-1) << LV.BitStart;
@@ -3483,6 +3543,8 @@
                             Result, "tmp", CurBB);
     return true;
   }
+
+
 #undef HANDLE_UNARY_INT
 #undef HANDLE_UNARY_FP
 
@@ -3913,7 +3975,238 @@
   return true;
 }
 
+// Convert the __builtin_bit_select pseudo-builtin. This pseudo-builtin requires
+// two integer operands of arbitrary bit width. The first operand is the value 
+// from which the bit will be selected. The second operand is the bit number, 
+// counted from the least significant bit, that will be selected. The result 
+// is an i1 value.
+// See IEEE 1666-2005, System C, Section 7.2.5, pg 175. 
+bool TreeToLLVM::EmitBuiltinBitSelect(tree exp, Value *&Result) {
+  tree arglist = TREE_OPERAND(exp, 1);
+  
+  // Get the Value and bit operands
+  Value* Val = Emit(TREE_VALUE(arglist), 0);
+  Value* Bit = Emit(TREE_VALUE(TREE_CHAIN(arglist)), 0);
 
+  // Make sure they are integers.
+  if (!Val->getType()->isInteger() || !Bit->getType()->isInteger()) {
+    error("All arguments to __builtin_bit_select must be integer typed");
+    return false;
+  }
+
+  // If the Bit index argument isn't the same width as the Val, make it so.
+  if (Val->getType() != Bit->getType())
+    Bit = CastInst::createIntegerCast(Bit, Val->getType(), false, "tmp", CurBB);
+
+  // Shift the bits down to the one of interest.
+  Instruction* Shift = 
+    BinaryOperator::createLShr(Val, Bit, "bit_select", CurBB);
+
+  // Truncate down to an i1
+  Result = new TruncInst(Shift, Type::Int1Ty, "bit_select", CurBB);
+
+  // Set the result type on the expression
+  // FIXME: For some reason if we set the type of this expression, the type of
+  // "main" and all its variables become i1 too. This is a complete mystery. In
+  // the bit_concat.c test case, this function is called from a function that
+  // main calls. There's no way that "exp" refers to "main". How could it?
+  // ***BOGGLE***
+  // llvm_set_type(TREE_TYPE(exp), Result->getType());
+
+  return true;
+}
+
+// Convert the __builtin_part_select pseudo-builtin. This pseudo-builtin takes 
+// three integer operands of arbitrary bit width. The first operand is the 
+// value from which to select the bits. The second and third operands define a 
+// range of bits to select.  The result is the bits selected and has a 
+// corresponding width of Left-Right (second operand - third operand).
+// See IEEE 1666-2005, System C, Section 7.2.6, pg 175. 
+bool TreeToLLVM::EmitBuiltinBitPartSelect(tree exp, Value *&Result) {
+  tree arglist = TREE_OPERAND(exp, 1);
+  
+  // Get the operands to the function
+  Value* Val = Emit(TREE_VALUE(arglist), 0);
+  Value* Left = Emit(TREE_VALUE(TREE_CHAIN(arglist)), 0);
+  Value* Right = Emit(TREE_VALUE(TREE_CHAIN(TREE_CHAIN(arglist))), 0);
+
+  // Make sure we have integers for all
+  if (!Val->getType()->isInteger() || !Left->getType()->isInteger() ||
+      !Right->getType()->isInteger()) {
+    error("All arguments to __builtin_part_select must be integer typed");
+    return false;
+  }
+
+  // Cast Left and Right to the size of Val so the widths are all the same
+  if (Left->getType() != Val->getType())
+    Left = CastInst::createIntegerCast(Left, Val->getType(), false, 
+                                       "tmp", CurBB);
+  if (Right->getType() != Val->getType())
+    Right = CastInst::createIntegerCast(Right, Val->getType(), false, 
+                                        "tmp", CurBB);
+
+  // We want to select a range of bits here such that [Left, Right] is shifted
+  // down to the low bits. However, it is quite possible that Left is smaller
+  // than Right in which case the bits have to be reversed. 
+  
+  // Create the blocks we will need for the two cases (forward, reverse)
+  BasicBlock *RevSize = new BasicBlock("revsize", CurBB->getParent());
+  BasicBlock *FwdSize = new BasicBlock("fwdsize", CurBB->getParent());
+  BasicBlock *Compute = new BasicBlock("compute", CurBB->getParent());
+  BasicBlock *Reverse = new BasicBlock("reverse", CurBB->getParent());
+  BasicBlock *RsltBlk = new BasicBlock("result",  CurBB->getParent());
+
+  // Compute a few things that both cases will need, up front.
+  Constant* Zero = ConstantInt::get(Val->getType(), 0);
+  Constant* One = ConstantInt::get(Val->getType(), 1);
+  Constant* AllOnes = ConstantInt::getAllOnesValue(Val->getType());
+
+  // Compare the Left and Right bit positions. This is used to determine 
+  // which case we have (forward or reverse)
+  ICmpInst *Cmp = new ICmpInst(ICmpInst::ICMP_ULT, Left, Right, "less", CurBB);
+  new BranchInst(RevSize, FwdSize, Cmp, CurBB);
+
+  // First, copmute the number of bits in the forward case.
+  Instruction* FBitSize = 
+    BinaryOperator::createSub(Left, Right,"fbits", FwdSize);
+  new BranchInst(Compute, FwdSize);
+
+  // Second, compute the number of bits in the reverse case.
+  Instruction* RBitSize = 
+    BinaryOperator::createSub(Right, Left, "rbits", RevSize);
+  new BranchInst(Compute, RevSize);
+
+  // Now, compute the bit range. Start by getting the bitsize and the shift
+  // amount (either Left or Right) from PHI nodes. Then we compute a mask for 
+  // the number of bits we want in the range. We shift the bits down to the 
+  // least significant bits, apply the mask to zero out unwanted high bits, and
+  // we have computed the "forward" result. It may still need to be reversed.
+
+  // Get the BitSize from one of the two subtractions
+  PHINode *BitSize = new PHINode(Val->getType(), "bits", Compute);
+  BitSize->reserveOperandSpace(2);
+  BitSize->addIncoming(FBitSize, FwdSize);
+  BitSize->addIncoming(RBitSize, RevSize);
+
+  // Get the ShiftAmount as the smaller of Left/Right
+  PHINode *ShiftAmt = new PHINode(Val->getType(), "shiftamt", Compute);
+  ShiftAmt->reserveOperandSpace(2);
+  ShiftAmt->addIncoming(Right, FwdSize);
+  ShiftAmt->addIncoming(Left, RevSize);
+
+  // Increment the bit size
+  Instruction *BitSizePlusOne = 
+    BinaryOperator::createAdd(BitSize, One, "bits", Compute);
+
+  // Create a Mask to zero out the high order bits.
+  Instruction* Mask = 
+    BinaryOperator::createShl(AllOnes, BitSizePlusOne, "mask", Compute);
+  Mask = BinaryOperator::createNot(Mask, "mask", Compute);
+
+  // Shift the bits down and apply the mask
+  Instruction* FRes = BinaryOperator::createLShr(Val, ShiftAmt, "fres",Compute);
+  FRes = BinaryOperator::createAnd(FRes, Mask, "fres", Compute);
+  new BranchInst(Reverse, RsltBlk, Cmp, Compute);
+
+  // In the Reverse block we have the mask already in FRes but we must reverse 
+  // it by shifting FRes bits right and putting them in RRes by shifting them 
+  // in from left.
+
+  // First set up our loop counters
+  PHINode *Count = new PHINode(Val->getType(), "count", Reverse);
+  Count->reserveOperandSpace(2);
+  Count->addIncoming(BitSizePlusOne, Compute);
+
+  // Next, get the value that we are shifting.
+  PHINode *BitsToShift   = new PHINode(Val->getType(), "val", Reverse);
+  BitsToShift->reserveOperandSpace(2);
+  BitsToShift->addIncoming(FRes, Compute);
+
+  // Finally, get the result of the last computation
+  PHINode *RRes  = new PHINode(Val->getType(), "rres", Reverse);
+  RRes->reserveOperandSpace(2);
+  RRes->addIncoming(Zero, Compute);
+
+  // Decrement the counter
+  Instruction *Decr = BinaryOperator::createSub(Count, One, "decr", Reverse);
+  Count->addIncoming(Decr, Reverse);
+
+  // Compute the Bit that we want to move
+  Instruction *Bit = 
+    BinaryOperator::createAnd(BitsToShift, One, "bit", Reverse);
+
+  // Compute the new value for next iteration.
+  Instruction *NewVal = 
+    BinaryOperator::createLShr(BitsToShift, One, "rshift", Reverse);
+  BitsToShift->addIncoming(NewVal, Reverse);
+
+  // Shift the bit into the low bits of the result.
+  Instruction *NewRes = BinaryOperator::createShl(RRes, One, "lshift", Reverse);
+  NewRes = BinaryOperator::createOr(NewRes, Bit, "addbit", Reverse);
+  RRes->addIncoming(NewRes, Reverse);
+  
+  // Terminate loop if we've moved all the bits.
+  ICmpInst *Cond = new ICmpInst(ICmpInst::ICMP_EQ, Decr, Zero, "cond", Reverse);
+  new BranchInst(RsltBlk, Reverse, Cond, Reverse);
+
+  // Finally, in the result block, select one of the two results with a PHI
+  // node and return the result;
+  CurBB = RsltBlk;
+  PHINode *BitSelect = new PHINode(Val->getType(), "part_select", CurBB);
+  BitSelect->reserveOperandSpace(2);
+  BitSelect->addIncoming(FRes, Compute);
+  BitSelect->addIncoming(NewRes, Reverse);
+  Result = BitSelect;
+
+  // Set the result type on the expression since it might be > i32.
+  llvm_set_type(TREE_TYPE(exp), Result->getType());
+
+  return true;
+}
+
+// Convert the __builtin_bit_concat pseudo-builtin. This builtin requires two 
+// integer operands (of arbitrary bit width). It concatenates the bits to 
+// produce an integer from the union of the corresponding bit width. The first 
+// operand (LHS) occupies the high-order bits while the second operand (RHS) 
+// occupies the low order bits.  
+// See IEEE 1666-2005, System C, Section 7.2.7, pg 176. 
+bool TreeToLLVM::EmitBuiltinBitConcat(tree exp, Value *&Result) {
+  tree arglist = TREE_OPERAND(exp, 1);
+  
+  // Get the operands to the function
+  Value* High = Emit(TREE_VALUE(arglist), 0);
+  Value* Low = Emit(TREE_VALUE(TREE_CHAIN(arglist)), 0);
+
+  // Make sure we have integers for all
+  if (!High->getType()->isInteger() || !Low->getType()->isInteger()) {
+    error("All arguments to __builtin_bit_concat must be integer typed");
+    return false;
+  }
+
+  const IntegerType* HighTy = cast<IntegerType>(High->getType());
+  const IntegerType* LowTy = cast<IntegerType>(Low->getType());
+  const IntegerType* ResultTy = IntegerType::get(HighTy->getBitWidth() +
+                                                 LowTy->getBitWidth());
+    
+  // Get the shift amount for the high bits
+  ConstantInt *Shift = ConstantInt::get(ResultTy, LowTy->getBitWidth());
+
+  // Extend both values to the concatenated bit width
+  Instruction *HighZExt = new ZExtInst(High, ResultTy, "zext", CurBB);
+  Instruction *LowZExt  = new ZExtInst(Low,  ResultTy, "zext", CurBB);
+
+  // Shift the high bits up
+  Instruction *New = BinaryOperator::createShl(HighZExt, Shift, "shift", CurBB);
+
+  // Or in the low bits to form the result.
+  Result = BinaryOperator::createOr(New, LowZExt, "concat", CurBB);
+
+  // Set the result type on the expression since it might be != i32.
+  llvm_set_type(TREE_TYPE(exp), Result->getType());
+
+  return true;
+}
+
 //===----------------------------------------------------------------------===//
 //                      ... Complex Math Expressions ...
 //===----------------------------------------------------------------------===//
Index: gcc/llvm-internal.h
===================================================================
--- gcc/llvm-internal.h	(revision 276)
+++ gcc/llvm-internal.h	(working copy)
@@ -455,6 +455,9 @@
   bool EmitBuiltinReturnAddr(tree_node *exp, Value *&Result, bool isFrame);
   bool EmitBuiltinStackSave(tree_node *exp, Value *&Result);
   bool EmitBuiltinStackRestore(tree_node *exp);
+  bool EmitBuiltinBitSelect(tree_node* exp, Value *&Result);
+  bool EmitBuiltinBitPartSelect(tree_node* exp, Value *&Result);
+  bool EmitBuiltinBitConcat(tree_node* exp, Value *&Result);
 
   // Complex Math Expressions.
   void EmitLoadFromComplex(Value *&Real, Value *&Imag, Value *SrcComplex,
@@ -519,5 +522,7 @@
   static Constant *EmitLV_ARRAY_REF(tree_node *exp);
 };
 
+extern const Type * llvm_set_type(tree_node* Tr, const Type *Ty);
+
 #endif
 /* APPLE LOCAL end LLVM (ENTIRE FILE!)  */
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 276)
+++ gcc/c-typeck.c	(working copy)
@@ -44,6 +44,9 @@
 #include "tree-iterator.h"
 #include "tree-gimple.h"
 #include "tree-flow.h"
+#ifdef ENABLE_LLVM
+#include "llvm.h"
+#endif
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -2270,6 +2273,12 @@
   tree selector;
   /* APPLE LOCAL mainline 2005-04-14 */
   const char *invalid_func_diag;
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+  const char *fname = 0;
+  int is_pseudo_builtin = 0;
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
 
   /* Change pointer to function to the function itself for
      diagnostics.  */
@@ -2280,6 +2289,15 @@
   /* Handle an ObjC selector specially for diagnostics.  */
   selector = objc_message_selector ();
 
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+  if (TREE_CODE (function) == FUNCTION_DECL) {
+    fname = IDENTIFIER_POINTER(DECL_NAME(function));
+    is_pseudo_builtin = llvm_get_pseudo_builtin_index(fname) >= 0;
+  }
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
+  
   /* Scan the given expressions and types, producing individual
      converted arguments and pushing them on RESULT in reverse order.  */
 
@@ -2317,6 +2335,16 @@
 
       val = require_complete_type (val);
 
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+      if (is_pseudo_builtin) 
+        {
+          result = tree_cons (NULL_TREE, val, result);
+        } 
+      else
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
+
       if (type != 0)
 	{
 	  /* Formal parm type is specified by a function prototype.  */
@@ -2921,7 +2949,7 @@
 	  return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
 				  TREE_OPERAND (arg, 1), 1);
 	}
-#endif ENABLE_LLVM
+#endif
       /* APPLE LOCAL end LLVM */
 
       /* Anything not already handled and not a true memory reference
Index: gcc/llvm-types.cpp
===================================================================
--- gcc/llvm-types.cpp	(revision 276)
+++ gcc/llvm-types.cpp	(working copy)
@@ -70,7 +70,7 @@
 #define SET_TYPE_SYMTAB_LLVM(NODE, index) (TYPE_CHECK (NODE)->type.symtab.llvm = index)
 
 // Note down LLVM type for GCC tree node.
-static const Type * llvm_set_type(tree Tr, const Type *Ty) {
+const Type * llvm_set_type(tree Tr, const Type *Ty) {
 
   unsigned &TypeSlot = LTypesMap[Ty];
   if (TypeSlot) {
@@ -428,27 +428,20 @@
       return TypeDB.setType(type, Ty);
     }
     // FALL THROUGH.
-  case INTEGER_TYPE:
-    if (const Type *Ty = GET_TYPE_LLVM(type)) return Ty;
-
-    // FIXME: eliminate this when 128-bit integer types in LLVM work.
-    switch (TREE_INT_CST_LOW(TYPE_SIZE(type))) {
-    case 1:
-    case 8:
-    case 16:
-    case 32:
-    case 64:
-      break;
-    default:
+  case INTEGER_TYPE: {
+    const Type *Ty = GET_TYPE_LLVM(type); 
+    if (Ty)
+      return Ty;
+    unsigned Bits = TYPE_USER_BITWIDTH(type) ? TYPE_BITWIDTH(type) :
+                       TREE_INT_CST_LOW(TYPE_SIZE(type));
+    if (Bits > 64) {
       static bool Warned = false;
-      if (!Warned)
-        fprintf(stderr, "WARNING: %d-bit integers not supported!\n",
-                (int)TREE_INT_CST_LOW(TYPE_SIZE(type)));
+      if (!Warned) fprintf(stderr, 
+                           "WARNING: integers > 64 bits not supported yet!\n");
       Warned = true;
-      return Type::Int64Ty;
     }
-    return SET_TYPE_LLVM(type, 
-                         IntegerType::get(TREE_INT_CST_LOW(TYPE_SIZE(type))));
+    return SET_TYPE_LLVM(type, IntegerType::get(Bits));
+  }
   case REAL_TYPE:
     if (const Type *Ty = GET_TYPE_LLVM(type)) return Ty;
     switch (TYPE_PRECISION(type)) {
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 276)
+++ gcc/c-common.c	(working copy)
@@ -658,6 +658,11 @@
 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
 						 bool *);
 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+static tree handle_bitwidth_attribute (tree *, tree, tree, int, bool *);
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
 
 static void check_function_nonnull (tree, tree);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -746,6 +751,12 @@
 			      handle_warn_unused_result_attribute },
   { "sentinel",               0, 1, false, true, true,
 			      handle_sentinel_attribute },
+  /* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+  { "bitwidth",               1, 1, false, true, false,
+			      handle_bitwidth_attribute },
+#endif 
+  /* APPLE LOCAL end LLVM bit accurate integer types - ras */
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
@@ -5665,6 +5676,163 @@
   
   return NULL_TREE;
 }
+
+/* APPLE LOCAL begin LLVM bit accurate integer types - ras */
+#ifdef ENABLE_LLVM
+static tree
+handle_bitwidth_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+			   int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  tree decl = NULL_TREE;
+  tree *type = NULL;
+  int is_type = 0;
+  tree bitwidth_expr = (args ? TREE_VALUE (args) 
+                        : size_int (INT_TYPE_SIZE * BITS_PER_UNIT));
+  unsigned num_bits = 0, gcc_bits = 0, precision_bits = 0;
+
+  if (DECL_P (*node))
+    {
+      decl = *node;
+      type = &TREE_TYPE (decl);
+      is_type = TREE_CODE (*node) == TYPE_DECL;
+    }
+  else if (TYPE_P (*node))
+    type = node, is_type = 1;
+
+  /* Strip any NOPs of any kind.  */
+  while (TREE_CODE (bitwidth_expr) == NOP_EXPR
+	 || TREE_CODE (bitwidth_expr) == CONVERT_EXPR
+	 || TREE_CODE (bitwidth_expr) == NON_LVALUE_EXPR)
+    bitwidth_expr = TREE_OPERAND (bitwidth_expr, 0);
+
+  if (TREE_CODE (bitwidth_expr) != INTEGER_CST)
+    {
+      warning ("bitwidth attribute ignored because requested bitwidth "
+                "is not an integer constant");
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  if (!is_type && (TREE_CODE (decl) != VAR_DECL) 
+         && (TREE_CODE (decl) != FIELD_DECL)
+         && (TREE_CODE (decl) != CONST_DECL)
+         && (TREE_CODE (decl) != RESULT_DECL)
+         && (TREE_CODE (decl) != PARM_DECL))
+    {
+      warning ("bitwidth attribute ignored because %Jbitwidth may "
+               "not be specified for %qD", decl, decl);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* Get the bitwidth value */
+  num_bits = int_cst_value(bitwidth_expr);
+
+  /* Check the range for the number of bits. The bitwidth must be at least 1*/
+  if (num_bits < 1) 
+    {
+      warning("bitwidth attribute ignored because requested bitwidth "
+              "is too small");
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* The tree_type structure (tree.h) reserves 23 bits for the bitwidth field.
+   * Consequently we must ensure that the value provided fits within 23 bits.
+   * The number 23 is an artifact of LLVM's implementation of arbitrary 
+   * precision integer types as there were 23 bits left over in the Type class.
+   * (see include/llvm/Type.h). 2^23 > 8 million which should be sufficient 
+   * for any foreseeable application.
+   */
+  if (num_bits > (1 << 23) - 1 )
+    {
+      warning("bitwidth attribute ignored because requested bitwidth "
+              "is too large");
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* We can only apply this to an INTEGER_TYPE or ENUMERAL_TYPE. The bitwidth
+   * doesn't make sense for other types. Note that BOOL_TYPE is not included
+   * because it is either 1 bit or has target-specific size that must be
+   * followed. Controlling the size of a bool is not useful anyway. */
+  if (TREE_CODE(*type) != INTEGER_TYPE && TREE_CODE(*type) != ENUMERAL_TYPE)
+    {
+      warning("bitwidth attribute ignored because it cannot be "
+              "applied to this type");
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* Compute how many bits should be used for gcc's purposes. This computation
+   * ensures that an even number of bytes are reserved for the type. This allows
+   * bitwidth types to match other types for gcc's purposes (but not llvm's). */
+  gcc_bits = (num_bits <= CHAR_TYPE_SIZE ? CHAR_TYPE_SIZE : 
+      (num_bits <= SHORT_TYPE_SIZE ? SHORT_TYPE_SIZE :
+       (num_bits <= INT_TYPE_SIZE ? INT_TYPE_SIZE :
+        (num_bits <= LONG_TYPE_SIZE ? LONG_TYPE_SIZE : LONG_LONG_TYPE_SIZE))));
+
+  /* The PRECISION field needs the accurate number of bits, but only up to a
+   * specific width (see below). */
+  precision_bits = num_bits;
+
+  /* The requested bit width may be too large for GCC to handle. The 
+   * value HOST_BITS_PER_WIDE_INT*2 is used by the make_*_type functions as an
+   * upper limit on the bit width. Since it will truncate to that limit, we just
+   * generate a warning about this situation. */
+  gcc_bits = num_bits;
+  if (num_bits > HOST_BITS_PER_WIDE_INT * 2) {
+    /* Generate a warning message about exceeding this bit width limit */
+    location_t this_location;
+
+    if (EXPR_HAS_LOCATION (*node))
+      this_location = EXPR_LOCATION (*node);
+    else
+      this_location = input_location;
+    warning("%Hbitwidth of %u exceeds maximum of %d for some uses",
+            &this_location, num_bits, HOST_BITS_PER_WIDE_INT * 2);
+
+    /* GCC can only handle bit widths up to a fixed limit so adjust to that
+     * limit if we're exceeding it */
+    gcc_bits = precision_bits = HOST_BITS_PER_WIDE_INT * 2;
+  }
+
+  /* Okay, we've taken care of all the error cases and we now have a valid
+   * node upon which we can confer the bit width. */
+
+  /* Construct the signed or unsigned integer type based on the num_bits we
+   * extracted from the attribute. Note that these two functions will truncate
+   * large values for num_bits down to HOST_BITS_PER_WIDE_INT*2, hence the
+   * preceding warning. */
+  if (TREE_CODE(*type) == ENUMERAL_TYPE)
+    *type = build_variant_type_copy(*type);
+  else if (TYPE_UNSIGNED(*type))
+    *type = make_unsigned_type(gcc_bits);
+  else
+    *type = make_signed_type(gcc_bits);
+
+  /* Set the precision field in case it differs from gcc_bits */
+  TYPE_PRECISION(*type) = precision_bits;
+
+  /* Set the requested bit width in the bitwidth field. */
+  TYPE_BITWIDTH(*type) = num_bits;
+
+  /* Indicate to everyone that the TYPE_BITWIDTH field has been set. This 
+   * allows users of this type to pick either TYPE_PRECISION or TYPE_BITWIDTH
+   * depending on whether TYPE_USER_BITWIDTH is set or not. */
+  TYPE_USER_BITWIDTH(*type) = 1;
+
+  /* Finally, make sure the original declaration (if there was one) gets the
+   * new type we just constructed */
+  if (decl != NULL_TREE) {
+    TREE_TYPE(decl) = *type;
+  }
+
+  return NULL_TREE;
+}
+#endif
+/* APPLE LOCAL end LLVM bit accurate integer types - ras */
+
 
 /* Check for valid arguments being passed to a function.  */
 void
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to