Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/6c: compiler bug #1315

Closed
rsc opened this issue Nov 30, 2010 · 2 comments
Closed

cmd/6c: compiler bug #1315

rsc opened this issue Nov 30, 2010 · 2 comments

Comments

@rsc
Copy link
Contributor

rsc commented Nov 30, 2010

wreck=; cat x.c
typedef unsigned long long uint64;
typedef unsigned int uint32;

void
f(char *b)
{
    uint32 off;
    
    off = (uint32)(uint64)b & 7;
    if(off) {
        b += 8 - off;
    }
    f(b);
}

wreck=; 6c -S x.c
(x.c:5) TEXT    f+0(SB),$32-8
(x.c:5) MOVQ    b+0(FP),!!DX
(x.c:9) MOVL    DX,!!CX
(x.c:9) ANDL    $7,!!CX
(x.c:10)    CMPL    CX,$0-0
(x.c:10)    JEQ ,!!4(PC)
(x.c:11)    MOVL    $8,!!AX
(x.c:11)    SUBL    CX,!!AX
(x.c:11)    ADDQ    AX,!!DX
(x.c:13)    MOVQ    DX,!!(SP)
(x.c:13)    CALL    ,!!f+0(SB)
(x.c:13)    RET ,!!
(x.c:13)    END ,!!
wreck=; 

That's correct, but note the MOVL DX, CX at x.c:9.
It is doing the & in CX so that DX (= b) can be used later
in the call to f.

wreck=; 6c -S x.c | grep :$(grep -n '(uint32)(uint64)' x.c | awk -F: '{print $1}')
(x.c:9) MOVL    DX,!!CX
(x.c:9) ANDL    $7,!!CX
wreck=; 

If we make the function more complicated, the MOVL
turns around, so that the original register gets used
for the & and the "copy" (only copying the bottom 32 bits)
gets used later as b.

wreck=; cat y.c
typedef unsigned char byte;
typedef int int32;
typedef unsigned long long uint64;
typedef unsigned int uint32;

void throw(char*);
byte *p[2];

void
f(byte *b)
{
    int32 off;
    uint64 *bitp;
    uint64 woff;
    void **vp;

    off = (uint32)(uint64)b & 7;
    if(off)
        b++;

    vp = (void**)b;
    b = vp[1];
    woff = (uint64*)b - (uint64*)p[0];
    bitp = (uint64*)p[0] - woff/2 - 1;
    if((byte*)bitp < (byte*)p[1] || (byte*)bitp >= (byte*)p[0])
        throw("bad bit pointer");
}
wreck=; 6c -S y.c | grep :$(grep -n '(uint32)(uint64)' y.c | awk -F: '{print $1}')
(y.c:17)    MOVL    AX,!!DX
(y.c:17)    ANDL    $7,!!AX
wreck=; 

The "saved" DX gets used later, having lost the top 32 bits.
@rsc
Copy link
Contributor Author

rsc commented Dec 9, 2011

Comment 1:

Labels changed: added priority-later.

@rsc
Copy link
Contributor Author

rsc commented Apr 10, 2012

Comment 3:

This issue was closed by revision e530d6a.

Status changed to Fixed.

@rsc rsc added fixed labels Apr 10, 2012
@rsc rsc assigned ken Apr 10, 2012
@golang golang locked and limited conversation to collaborators Jun 24, 2016
@rsc rsc unassigned ken Jun 22, 2022
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants