Here's a patch to give llvm-gcc the ability to specify arbitrary bit widths with a new "bitwidth" attribute. The attribute is used like this:
int __attribute__((bitwidth(17))); int __attribute__((bitwidth(23))) My32BitInt; struct MyStruct { int __attribute__((bitwidth(5))) My5BitField; My32BitInt My32BitField; }; void func(int __attribute__((bitwidth(23))) ) {...} etc. Note that no LLVM backend can currently handle this. I will be working on making either the CBackEnd or LLI handle these correctly. Other targets may or may not get implemented. This patch has not been tested well (just Dejagnu) so please do not apply it. Reid.
Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 248) +++ gcc/tree.h (working copy) @@ -1711,6 +1711,12 @@ #define TYPE_CONTAINS_PLACEHOLDER_INTERNAL(NODE) \ (TYPE_CHECK (NODE)->type.contains_placeholder_bits) +/* APPLE LOCAL begin LLVM bit accurate integer types - ras */ +/* 1 if the bitwidth for this type was requested by "bitwidth" attribute, + 0 if it is the default for this type. */ +#define TYPE_USER_BITWIDTH(NODE) (TYPE_CHECK (NODE)->type.user_bitwidth) +/* APPLE LOCAL end LLVM bit accurate integer types - ras */ + struct die_struct; struct tree_type GTY(()) @@ -1722,7 +1728,7 @@ tree attributes; unsigned int uid; - unsigned int precision : 9; + unsigned int precision : 16; ENUM_BITFIELD(machine_mode) mode : 7; unsigned string_flag : 1; @@ -1741,6 +1747,8 @@ unsigned lang_flag_5 : 1; unsigned lang_flag_6 : 1; unsigned user_align : 1; + /* APPLE LOCAL LLVM bit accurate integer types - ras */ + unsigned user_bitwidth : 1; unsigned int align; tree pointer_to; @@ -2431,6 +2439,12 @@ #define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \ DECL_CHECK (DECL)->decl.gimple_formal_temp +/* APPLE LOCAL begin LLVM bit accurate integer types - ras */ +/* 1 if a bitwidth for this type was requested by "bitwidth" attribute, + 0 if it is the default for this type. */ +#define DECL_USER_BITWIDTH(NODE) (DECL_CHECK (NODE)->decl.user_bitwidth) +/* APPLE LOCAL end LLVM bit accurate integer types - ras */ + /* Enumerate visibility settings. */ #ifndef SYMBOL_VISIBILITY_DEFINED #define SYMBOL_VISIBILITY_DEFINED @@ -2510,6 +2524,9 @@ unsigned iasm_dont_promote_to_static : 1; unsigned int iasm_frame_size; /* APPLE LOCAL end CW asm blocks */ + /* APPLE LOCAL begin LLVM bit accurate integer types - ras */ + unsigned int user_bitwidth : 1; + /* APPLE LOCAL end LLVM bit accurate integer types - ras */ union tree_decl_u1 { /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is Index: gcc/llvm-types.cpp =================================================================== --- gcc/llvm-types.cpp (revision 248) +++ gcc/llvm-types.cpp (working copy) @@ -62,24 +62,15 @@ // Type Conversion Utilities //===----------------------------------------------------------------------===// -static inline const Type *getIntegerType(unsigned Bits, bool isUnsigned) { - switch (Bits*2+isUnsigned) { - default: assert(0 && "Unknown integral type size!"); - case 8*2+0: return Type::Int8Ty; - case 8*2+1: return Type::Int8Ty; - case 16*2+0: return Type::Int16Ty; - case 16*2+1: return Type::Int16Ty; - case 32*2+0: return Type::Int32Ty; - case 32*2+1: return Type::Int32Ty; - case 64*2+0: return Type::Int64Ty; - case 64*2+1: return Type::Int64Ty; - case 128*2+0: - case 128*2+1: +static inline const Type *getIntegerType(unsigned Bits) { + if (Bits > 64) { static bool Warned = false; - if (!Warned) fprintf(stderr, "WARNING: 128-bit integers not supported!\n"); + if (!Warned) fprintf(stderr, + "WARNING: integers > 64 bits not supported yet!\n"); Warned = true; - return isUnsigned ? Type::Int64Ty : Type::Int64Ty; + return Type::Int64Ty; } + return IntegerType::get(Bits); } // isPassedByInvisibleReference - Return true if an argument of the specified @@ -292,7 +283,7 @@ else { // Bools on some platforms take more space than LLVM bool (e.g. PPC). if (const Type *Ty = GET_TYPE_LLVM(type)) return Ty; - const Type *Ty = getIntegerType(TREE_INT_CST_LOW(TYPE_SIZE(type)), true); + const Type *Ty = getIntegerType(TYPE_PRECISION(type)); return SET_TYPE_LLVM(type, Ty); } case ENUMERAL_TYPE: @@ -309,8 +300,7 @@ // FALL THROUGH. case INTEGER_TYPE: if (const Type *Ty = GET_TYPE_LLVM(type)) return Ty; - return SET_TYPE_LLVM(type, getIntegerType(TREE_INT_CST_LOW(TYPE_SIZE(type)), - TYPE_UNSIGNED(type))); + return SET_TYPE_LLVM(type, getIntegerType(TYPE_PRECISION(type))); 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 248) +++ gcc/c-common.c (working copy) @@ -658,6 +658,9 @@ 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 */ +static tree handle_bitwidth_attribute (tree *, tree, tree, int, bool *); +/* 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 +749,10 @@ handle_warn_unused_result_attribute }, { "sentinel", 0, 1, false, true, true, handle_sentinel_attribute }, + /* APPLE LOCAL begin LLVM bit accurate integer types - ras */ + { "bitwidth", 1, 1, false, true, false, + handle_bitwidth_attribute }, + /* APPLE LOCAL end LLVM bit accurate integer types - ras */ { NULL, 0, 0, false, false, false, NULL } }; @@ -5665,6 +5672,97 @@ return NULL_TREE; } + +/* APPLE LOCAL begin LLVM bit accurate integer types - ras */ +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)); + HOST_WIDE_INT num_bits; + + 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) + { + error ("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)) + { + error ("%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 */ + if (num_bits < 1) + { + error("requested bitwidth is too small"); + *no_add_attrs = true; + return NULL_TREE; + } + + if (num_bits > 65535) + { + error("requested bitwidth is too large"); + *no_add_attrs = true; + return NULL_TREE; + } + + + /* Finally, if we don't have an integer type, then you can't apply this + * attribute. */ + if (TREE_CODE(*type) != INTEGER_TYPE) + { + error("bitwidth cannot be applied to this type"); + *no_add_attrs = true; + return NULL_TREE; + } + + /* 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. */ + if (TYPE_UNSIGNED(*type)) + *type = make_unsigned_type(num_bits); + else + *type = make_signed_type(num_bits); + TYPE_USER_BITWIDTH (*type) = 1; + + if (decl != NULL_TREE) { + TREE_TYPE(decl) = *type; + DECL_USER_BITWIDTH (decl) = 1; + } + + return NULL_TREE; +} +/* 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