[LLVMbugs] [Bug 166] NEW: [llvmg++] Code generated to call through a pointer to member function is nasty

bugzilla-daemon at zion.cs.uiuc.edu bugzilla-daemon at zion.cs.uiuc.edu
Sun Dec 7 22:59:26 PST 2003


http://llvm.cs.uiuc.edu/bugs/show_bug.cgi?id=166

           Summary: [llvmg++] Code generated to call through a pointer to
                    member function is nasty
           Product: tools
           Version: 1.0
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: llvm-g++
        AssignedTo: sabre at nondot.org
        ReportedBy: sabre at nondot.org


Consider a slightly simplified version of Brian's testcase for Bug 165:

----
struct Evil {
 void fun ();
};
typedef void (Evil::*memfunptr) ();

memfunptr ptr = &Evil::fun;

void Evil::fun() {
 (this->*ptr) ();
}
----

We currently generate the following LLVM code:

----
        %struct.Evil = type { ubyte }
%ptr = global { void (%struct.Evil*)*, int } { void (%struct.Evil*)*
%_ZN4Evil3funEv, int 0 }           ; <{ void (%struct.Evil*)*, int }*> [#uses=1]

implementation   ; Functions:

void %_ZN4Evil3funEv(%struct.Evil* %this) {
entry:
        %tmp.1 = load void (%struct.Evil*)** getelementptr ({ void
(%struct.Evil*)*, int }* %ptr, long 0, ubyte 0)              ; <void
(%struct.Evil*)*> [#uses=2]
        %tmp.2 = cast void (%struct.Evil*)* %tmp.1 to int               ; <int>
[#uses=2]
        %tmp.3 = and int %tmp.2, 1              ; <int> [#uses=1]
        %tmp.4 = seteq int %tmp.3, 0            ; <bool> [#uses=1]
        br bool %tmp.4, label %cond_true, label %cond_false

cond_true:              ; preds = %entry
        %tmp.351 = load int* getelementptr ({ void (%struct.Evil*)*, int }*
%ptr, long 0, ubyte 1)              ; <int> [#uses=1]
        %tmp.372 = cast int %tmp.351 to long            ; <long> [#uses=1]
        %tmp.363 = getelementptr %struct.Evil* %this, long %tmp.372            
; <%struct.Evil*> [#uses=1]
        call void %tmp.1( %struct.Evil* %tmp.363 )
        ret void

cond_false:             ; preds = %entry
        %tmp.10 = load int* getelementptr ({ void (%struct.Evil*)*, int }* %ptr,
long 0, ubyte 1)               ; <int> [#uses=1]
        %tmp.12 = cast int %tmp.10 to long              ; <long> [#uses=1]
        %tmp.11 = getelementptr %struct.Evil* %this, long %tmp.12              
; <%struct.Evil*> [#uses=2]
        %tmp.13 = cast %struct.Evil* %tmp.11 to int (...)***            ; <int
(...)***> [#uses=1]
        %tmp.14 = load int (...)*** %tmp.13             ; <int (...)**> [#uses=1]
        %tmp.18 = cast int %tmp.2 to int (...)**                ; <int (...)**>
[#uses=1]
        %tmp.19 = cast int (...)** %tmp.14 to long              ; <long> [#uses=1]
        %tmp.20 = cast int (...)** %tmp.18 to long              ; <long> [#uses=1]
        %tmp.21 = add long %tmp.19, %tmp.20             ; <long> [#uses=1]
        %tmp.22 = cast long %tmp.21 to int (...)**              ; <int (...)**>
[#uses=1]
        %tmp.26 = cast int (...)** %tmp.22 to long              ; <long> [#uses=1]
        %tmp.28 = add long %tmp.26, -1          ; <long> [#uses=1]
        %tmp.29 = cast long %tmp.28 to void (%struct.Evil*)**           ; <void
(%struct.Evil*)**> [#uses=1]
        %tmp.31 = load void (%struct.Evil*)** %tmp.29           ; <void
(%struct.Evil*)*> [#uses=1]
        call void %tmp.31( %struct.Evil* %tmp.11 )
        ret void
}
----

This is gratuitously non-type-safe, and _might_ not actually even work if the
adjustment offset is non-zero (I'm not sure).  This directly caused by the
non-LLVM C++ front-end code, so I'm not sure exactly how to fix it (I think
there is a target hook or something which controls this).  In any case, masking
off the low bit of the function pointer seems like an extremely bad idea.

-Chris



------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.



More information about the llvm-bugs mailing list