First Last Prev Next    No search results available
Details
: [llvmg++] call through array of pointers to member functi...
Bug#: 165
: tools
: llvm-g++
Status: RESOLVED
Resolution: FIXED
: All
: All
: 1.0
: P2
: normal
: 1.1

:
: compile-fail
:
:
  Show dependency tree - Show dependency graph
People
Reporter: Brian R. Gaeke <gaeke+bugs@uiuc.edu>
Assigned To: Chris Lattner <sabre@nondot.org>

Attachments


Note

You need to log in before you can comment on or make changes to this bug.

Related actions


Description:   Opened: 2003-12-07 23:32
The following test program involving a call through a pointer-to-member function
 fails an assertion in llvm-g++ of the "tree not handled yet" flavor. The tree
it prints is a SAVE_EXPR. It looks to me as though c_llvm_expand_lvalue_expr()
needs to be extended to allow for a SAVE_EXPR lvalue. 

I noted that if I take out the call to opcode(), the assert no longer fails.

/**********************************/
extern "C" void abort();
class Evil {
public:
 void fun () { abort (); }
 void step (unsigned int instr);
 unsigned short opcode (const unsigned int instr) const;
};
typedef void (Evil::*memfunptr) ();
void Evil::step (unsigned int instr) {
 static const memfunptr jumpTable[] = { &Evil::fun };
 (this->*jumpTable[opcode (instr)]) ();
}
/************************/

The resulting long and tedious llvm-g++ barf is as follows:

ERROR: In function c_llvm_expand_lvalue_expr:5926, tree not handled by LLVM yet!
 <save_expr 0x40018340
    type <record_type 0x40190e00 readonly DI
        size <integer_cst 0x4001a618 constant 64>
        unit size <integer_cst 0x4001a99c constant 8>
        align 32 symtab 0 alias set -1
        fields <field_decl 0x40190cb0 __pfn type <pointer_type 0x401904d0>
            unsigned SI file cpu.ii line 10
            size <integer_cst 0x4001a9b0 constant 32>
            unit size <integer_cst 0x4001a9d8 constant 4>
            align 32 offset_align 32
            offset <integer_cst 0x4001aa64 constant 0>
            bit offset <integer_cst 0x4001ab04 constant 0> context <record_type
0x40190b60> arguments <integer_cst 0x4001aa64 0> chain <field_decl 0x40190d20
__delta>>
        ptrmemfunc fn type <pointer_type 0x401904d0 type <method_type 0x4018d230>
            readonly unsigned SI size <integer_cst 0x4001a9b0 32> unit size
<integer_cst 0x4001a9d8 4>
            align 32 symtab 0 alias set -1>
        pointer_to_this <pointer_type 0x40191000>>
    side-effects readonly
    arg 0 <array_ref 0x401584c8 type <record_type 0x40190e00>
        side-effects readonly
        arg 0 <var_decl 0x40190ee0 jumpTable type <array_type 0x40190e70>
            readonly addressable asm_written used static tree_1 decl_6 DI file
cpu.ii line 10 size <integer_cst 0x4001a618 64> unit size <integer_cst 0x4001a99c 8>
            align 32 context <function_decl 0x4018d5b0 step> initial
<constructor 0x4018ea14>>
        arg 1 <nop_expr 0x4018eb54 type <integer_type 0x4001c4d0 int>
            side-effects
            arg 0 <call_expr 0x401584b0 type <integer_type 0x4001c460 short
unsigned int>
                side-effects
                arg 0 <addr_expr 0x4018eb40 type <pointer_type 0x401915b0>
                    constant arg 0 <function_decl 0x4018d850 opcode>>
                arg 1 <tree_list 0x4018eb18
                    value <nop_expr 0x4018eb04 type <pointer_type 0x4018d000>
                        readonly
                        arg 0 <nop_expr 0x4018eaf0 type <pointer_type 0x4018d000>
                            readonly arg 0 <parm_decl 0x40190310 this>>>
                    chain <tree_list 0x4018eb2c value <parm_decl 0x40190150
instr>>>>>>
    arg 1 <function_decl 0x4018d5b0 step
        type <method_type 0x4018d540 type <void_type 0x40023bd0 void>
            DI size <integer_cst 0x4001a618 64> unit size <integer_cst 0x4001a99c 8>
            align 32 symtab 0 alias set -1 method basetype <record_type
0x4018bee0 Evil>
            arg-types <tree_list 0x40186e10 value <pointer_type 0x4018d000>
                chain <tree_list 0x40186dfc value <integer_type 0x4001c540
unsigned int>
                    chain <tree_list 0x4015a8e8 tree_2 value <void_type
0x40023bd0 void>>>>>
        asm_written public static decl_5 QI file cpu.ii line 9 context
<record_type 0x4018bee0 Evil>
        arguments <parm_decl 0x40190310 this type <pointer_type 0x4018d310>
            readonly unsigned SI file cpu.ii line 9 size <integer_cst 0x4001a9b0
32> unit size <integer_cst 0x4001a9d8 4>
            align 32 context <function_decl 0x4018d5b0 step> initial
<pointer_type 0x4018d310> arg-type <pointer_type 0x4018d310> chain <parm_decl
0x40190150 instr>>
        result <result_decl 0x40190380 type <void_type 0x40023bd0 void>
            VOID file cpu.ii line 9
            align 8 context <function_decl 0x4018d5b0 step>> initial <block
0x40184de8>
       
        chain <function_decl 0x4018d850 opcode type <method_type 0x4018d930>
            addressable used public external QI file cpu.ii line 6 context
<record_type 0x4018bee0 Evil> arguments <parm_decl 0x4018da80 this>
           >>
    rtl 2 (nil)

    rtl 3 (nil)
>
cpu.ii: In member function `void Evil::step(unsigned int)':
cpu.ii:11: internal compiler error: in c_llvm_expand_lvalue_expr, at
llvm-expand.c:5926
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://llvm.cs.uiuc.edu> for instructions.
------- Comment #1 From Chris Lattner 2003-12-08 00:14:10 -------
Cute.  This is definitely a bug, and should be relatively easy to fix.  Nice 1.1
fodder.  :)

-Chris
------- Comment #2 From Brian R. Gaeke 2003-12-08 00:19:31 -------
Minor fix to summary.  Procrastinate, procrastinate.
------- Comment #3 From Chris Lattner 2003-12-08 00:32:20 -------
Fixed.

Testcase here: test/Regression/C++Frontend/2003-12-08-ArrayOfPtrToMemberFunc.cpp

Patch here:

$ diff -u llvm-expand.c~ llvm-expand.c
--- llvm-expand.c~      Fri Nov 28 22:21:26 2003
+++ llvm-expand.c       Mon Dec  8 00:27:54 2003
@@ -5044,6 +5044,37 @@
     llvm_expand_expr(Fn, exp, Result);
     break;
 
+  case SAVE_EXPR:
+    /* Return the innermost context enclosing DECL that is a FUNCTION_DECL, or
+       zero if none.  */
+    context = decl_function_context (exp);
+
+    /* If this SAVE_EXPR was at global context, assume we are an
+       initialization function and move it into our context.  */
+    if (context == 0)
+      SAVE_EXPR_CONTEXT (exp) = current_function_decl;
+
+    /* We treat inline_function_decl as an alias for the current function
+       because that is the inline function whose vars, types, etc.
+       are being merged into the current function.
+       See expand_inline_function.  */
+    if (context == current_function_decl)
+      context = 0;
+
+    /* If this is non-local, handle it.  */
+    if (context) LLVM_TODO_TREE(exp);  /* Don't handle nested functions yet! */
+
+    /* If the expression has not been computed yet... */
+    if (SAVE_EXPR_LLVM(exp) == 0) {
+      /* Expand the saved expression. This does not handle bit-fields yet. */
+      Result = llvm_expand_lvalue_expr(Fn, TREE_OPERAND(exp, 0), 0, 0);
+      SAVE_EXPR_LLVM(exp) = Result;
+      TREE_USED(exp) = 1;
+    } else {
+      Result = SAVE_EXPR_LLVM(exp);
+    }
+    break;
+
   case COND_EXPR: {      /* ?: expression */
     /* Allocate a new temporary to hold the result of the expression */
     llvm_basicblock *TrueBlock = llvm_basicblock_new("cond_true");

Thanks for the bug report!

-Chris
------- Comment #4 From Chris Lattner 2003-12-08 00:35:45 -------
whoops, I thought the midair collision was just due to fixing pointers, which I
had covered. fix my bogus fix

First Last Prev Next    No search results available