Bugzilla – Bug 94
llvm-gcc tries to add bools
Last modified: 2003-11-06 12:32:45
You need to log in before you can comment on or make changes to this bug.
While trying to build libstdc++ on Mac OS X/PowerPC: 88 cube> cat locale-inst.ii extern bool uppercase; int int_to_char(char *out) { return out[5 + uppercase]; } 89 cube> /Users/brg/cfrontend/build/gcc/xgcc locale-inst.ii gccas: /var/tmp//ccnqZQ7C.s:218: Arithmetic operator requires integer or FP operands! 90 cube> /Users/brg/cfrontend/build/gcc/xgcc -S -o - locale-inst.ii | grep 'add bool' %tmp.3 = add bool %tmp.1, cast (int 5 to bool) ; ty=bool
This is the debugging dump of the array reference: --- <array_ref 0x40e912b8 type <integer_type 0x40e86380 char QI size <integer_cst 0x40e84140 constant 8> unit size <integer_cst 0x40e84154 constant 1> align 8 symtab 0 alias set -1 precision 8 min <integer_cst 0x40e841e0 -128> max <integer_cst 0x40e841f4 127> pointer_to_this <pointer_type 0x40e900e0>> arg 0 <parm_decl 0x40ec4e70 out type <pointer_type 0x40e900e0 type <integer_type 0x40e86380 char> unsigned SI size <integer_cst 0x40e849b0 constant 32> unit size <integer_cst 0x40e84a00 constant 4> align 32 symtab 0 alias set -1> unsigned used SI file locale-inst.ii line 2 size <integer_cst 0x40e849b0 32> unit size <integer_cst 0x40e84a00 4> align 32 context <function_decl 0x40ec4f50 int_to_char> initial <pointer_type 0x40e900e0> arg-type <pointer_type 0x40e900e0>> arg 1 <plus_expr 0x40e912a0 type <integer_type 0x40e864d0 int SI size <integer_cst 0x40e84258 constant 32> unit size <integer_cst 0x40e842e4 constant 4> align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x40e842bc -2147483648> max <integer_cst 0x40e842d0 2147483647> pointer_to_this <pointer_type 0x40e95f50>> arg 0 <var_decl 0x40ec4e00 uppercase type <boolean_type 0x40e86770 bool> unsigned used public external decl_2 SI file locale-inst.ii line 1 size <integer_cst 0x40e84258 32> unit size <integer_cst 0x40e842e4 4> align 32 chain <function_decl 0x40ec4c40 __cxa_call_unexpected>> arg 1 <integer_cst 0x40ebfcd0 constant 5>>>
I will upload the patch I developed for this shortly.
Created an attachment (id=5) [details] proposed patch to fix Bug 94 With this patch, I no longer get an 'add bool' from the testcase. I am curious to know why this never showed up on other platforms, though.
I have no idea how this is happening on OSX: booleans should be promoted to integers for operations like addition. That said, here's the fix (slightly revised from Brian's patch): $ diff -u llvm-representation.h~ llvm-representation.h --- llvm-representation.h~ 2003-10-27 11:34:07.000000000 -0600 +++ llvm-representation.h 2003-11-06 10:10:08.000000000 -0600 @@ -387,6 +387,7 @@ #define llvm_type_is_primitive(TY) (TY->ID < FunctionTyID) #define llvm_type_is_fp(TY) (((TY)->ID == FloatTyID) || ((TY)->ID==DoubleTyID)) #define llvm_type_is_integral(TY) ((TY)->ID >= BoolTyID && (TY)->ID <= LongTyID) +#define llvm_type_is_integer(TY) ((TY)->ID > BoolTyID && (TY)->ID <= LongTyID) #define llvm_type_is_scalar(TY) \ ((TY)->ID == PointerTyID || \ (llvm_type_is_primitive(TY) && (TY)->ID != VoidTyID)) $ diff -u llvm-representation.c~ llvm-representation.c --- llvm-representation.c~ 2003-11-04 23:46:44.000000000 -0600 +++ llvm-representation.c 2003-11-06 10:24:52.000000000 -0600 @@ -536,6 +536,9 @@ if (Opc != O_Shr && Opc != O_Shl) assert(Op1->Ty == Op2->Ty && "Binary operator operands must have compatible types!"); + if (Opc == O_Add || Opc == O_Sub || Opc == O_Mul || Opc == O_Div || + Opc == O_Rem) + assert(Ty != BoolTy && "Cannot perform arith op on boolean!"); return New; } $ diff -u llvm-expand.c~ llvm-expand.c --- llvm-expand.c~ 2003-11-05 10:16:59.000000000 -0600 +++ llvm-expand.c 2003-11-06 10:21:33.000000000 -0600 @@ -5187,7 +5187,7 @@ case EXACT_DIV_EXPR: case PLUS_EXPR: case MINUS_EXPR: case MULT_EXPR: /* Plus, Sub, Mult */ case TRUNC_DIV_EXPR: case TRUNC_MOD_EXPR: case RDIV_EXPR:/* Division, Rem */ - case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: /* Bit operators */ + case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: /* And, Or, Xor */ case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: case TRUTH_XOR_EXPR: /* Bit ops */ case LSHIFT_EXPR: case RSHIFT_EXPR: /* Shifts */ case LT_EXPR: case LE_EXPR: case GT_EXPR: /* Comparisons */ @@ -5212,6 +5212,22 @@ if (V) return V; } + /* If this is a simple arithmetic operator, cast both operands to the result + * type. + */ + switch (TREE_CODE(exp)) { + case PLUS_EXPR: case MINUS_EXPR: case MULT_EXPR: /* Plus, Sub, Mult */ + case TRUNC_DIV_EXPR: case TRUNC_MOD_EXPR: case RDIV_EXPR:/* Div, Rem */ + /* If this is not a logical operator, make sure the operands are not + * bools. + */ + assert(DestTy != BoolTy && "Cannot produce a bool for arithetic ops!"); + case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: /* And, Or, Xor */ + op0 = cast_if_type_not_equal(Fn, op0, DestTy); + op1 = cast_if_type_not_equal(Fn, op1, DestTy); + default: break; + } + /* Attempt to unify the types of the left and right operand... */ if (TREE_CODE(TREE_OPERAND(exp, 1)) == INTEGER_CST) op1 = cast_if_type_not_equal(Fn, op1, op0->Ty); -Chris