Bugzilla – Bug 131
[llvm-gcc] ?: operator as lvalue not implemented
Last modified: 2003-11-18 17:47:45
You need to log in before you can comment on or make changes to this bug.
Reduced from linux-2.4.22/arch/x86/kernel/pageattr.c % cat pageattr.i typedef struct { unsigned long pgprot; } pgprot_t; void split_large_page(unsigned long addr, pgprot_t prot) { (addr ? prot : ((pgprot_t) { 0x001 } )).pgprot; } % llvm-gcc pageattr.i ERROR: In function c_llvm_expand_lvalue_expr:5607, tree not handled by LLVM yet! <cond_expr 0x40019840 type <record_type 0x40277e00 pgprot_t type_0 SI size <integer_cst 0x4001b7d0 constant 32> unit size <integer_cst 0x4001b7f8 constant 4> align 32 symtab 0 alias set -1 fields <field_decl 0x40277c40 pgprot type <integer_type 0x4001d540 long unsigned int> unsigned SI file pageattr.i line 429 size <integer_cst 0x4001b208 constant 32> unit size <integer_cst 0x4001b294 constant 4> align 32 offset_align 32 offset <integer_cst 0x4001b884 constant 0> bit offset <integer_cst 0x4001b924 constant 0> context <record_type 0x40277cb0> arguments <integer_cst 0x4001b884 0>> context <translation_unit_decl 0x4001d070>> side-effects arg 0 <eq_expr 0x4026a570 type <integer_type 0x4001d3f0 int SI size <integer_cst 0x4001b208 32> unit size <integer_cst 0x4001b294 4> align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x4001b26c -2147483648> max <integer_cst 0x4001b280 2147483647> pointer_to_this <pointer_type 0x4022abd0>> arg 0 <parm_decl 0x40277e70 addr type <integer_type 0x4001d540 long unsigned int> unsigned used SI file pageattr.i line 431 size <integer_cst 0x4001b208 32> unit size <integer_cst 0x4001b294 4> align 32 context <function_decl 0x40279000 split_large_page> result <integer_type 0x4001d540 long unsigned int> initial <integer_type 0x4001d540 long unsigned int> arg-type <integer_type 0x4001d540 long unsigned int> arg-type-as-written <integer_type 0x4001d540 long unsigned int> chain <parm_decl 0x40277ee0 prot>> arg 1 <integer_cst 0x40278c1c constant 0>> arg 1 <compound_literal_expr 0x40278ce4 type <record_type 0x40277e00 pgprot_t> side-effects arg 0 <decl_stmt 0x40278cd0 arg 0 <var_decl 0x40279150>>> arg 2 <parm_decl 0x40277ee0 prot type <record_type 0x40277e00 pgprot_t> used SI file pageattr.i line 431 size <integer_cst 0x4001b7d0 32> unit size <integer_cst 0x4001b7f8 4> align 32 context <function_decl 0x40279000 split_large_page> result <record_type 0x40277e00 pgprot_t> initial <record_type 0x40277e00 pgprot_t> arg-type <record_type 0x40277e00 pgprot_t> arg-type-as-written <record_type 0x40277e00 pgprot_t>>> pageattr.i: In function `split_large_page': pageattr.i:433: internal compiler error: in c_llvm_expand_lvalue_expr, at llvm-expand.c:5607 Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://llvm.cs.uiuc.edu> for instructions.
Fixed. I *LOVE* GCC extensions! Testcase here: test/Regression/CFrontend/2003-11-18-CondExprLValue.c Patch here: $ diff -u llvm-expand.c~ llvm-expand.c --- llvm-expand.c~ 2003-11-18 15:11:50.000000000 -0600 +++ llvm-expand.c 2003-11-18 17:44:00.000000000 -0600 @@ -4825,6 +4825,66 @@ Result = D2V(make_temporary_alloca(Fn, ElTy)); llvm_expand_expr(Fn, exp, Result); break; + + case COND_EXPR: { /* ?: expression */ + /* FIXME: This does not correctly conditionalize CLEANUP expressions because + no scopes are created!!! */ + + /* Allocate a new temporary to hold the result of the expression */ + llvm_basicblock *TrueBlock = llvm_basicblock_new("cond_true"); + llvm_basicblock *FalseBlock = llvm_basicblock_new("cond_false"); + llvm_basicblock *ContinueBlock = llvm_basicblock_new("cond_continue"); + + /* Figure out a place to store the result across blocks. */ + llvm_value *ResultLoc = D2V(make_temporary_alloca(Fn, Ty)); + + /* Expand condition and branch */ + llvm_value *Cond = llvm_expand_expr(Fn, TREE_OPERAND(exp, 0), 0); + Cond = cast_if_type_not_equal(Fn, Cond, BoolTy); + append_inst(Fn, create_cond_branch(Cond, TrueBlock, FalseBlock)); + + /* Add the true block as the fall through */ + llvm_ilist_push_back(llvm_basicblock, Fn->BasicBlocks, TrueBlock); + + /* One branch of the cond can be void, if it never returns. For + example A ? throw : E */ + if (TREE_TYPE(TREE_OPERAND(exp, 1)) != void_type_node) { + unsigned BStart = 0, BSize = 0; + llvm_value *Val = llvm_expand_lvalue_expr(Fn, TREE_OPERAND(exp, 1), + &BStart, &BSize); + assert(BStart == 0 && BSize == 0 && + "Cannot handle lvalue bitfields in condexpr yet!"); + append_inst(Fn, create_store_inst(Val, ResultLoc, 0)); + } else { + llvm_expand_expr(Fn, TREE_OPERAND (exp, 1), 0); + } + + /* Branch to the mainline computation */ + append_inst(Fn, create_uncond_branch(ContinueBlock)); + + /* Add the false block next */ + llvm_ilist_push_back(llvm_basicblock, Fn->BasicBlocks, FalseBlock); + + /* One branch of the cond can be void, if it never returns. For + example A ? throw : E */ + if (TREE_TYPE(TREE_OPERAND(exp, 2)) != void_type_node) { + unsigned BStart = 0, BSize = 0; + llvm_value *Val = llvm_expand_lvalue_expr(Fn, TREE_OPERAND(exp, 2), + &BStart, &BSize); + assert(BStart == 0 && BSize == 0 && + "Cannot handle lvalue bitfields in condexpr yet!"); + append_inst(Fn, create_store_inst(Val, ResultLoc, 0)); + } else { + llvm_expand_expr(Fn, TREE_OPERAND (exp, 2), 0); + } + + /* Add the branch and continue block */ + llvm_emit_label(Fn, ContinueBlock); + + /* Load the result out of the temporary */ + Result = append_inst(Fn, create_load_inst("tmp", ResultLoc, 0)); + break; + } } return cast_if_type_not_equal(Fn, Result, Ty); -Chris