kavon / ghc-llvm

improvements to llvm to support functional-language compilers, e.g., ghc
Other
4 stars 0 forks source link

Undef Arguments to a CPS Call #5

Open kavon opened 7 years ago

kavon commented 7 years ago

As you can see below, if one of the arguments to the CPSCALL is an undef, or in MBB speak IMPLICIT_DEF value, we're free to eliminate that binding, which leaves the TCRETURN referencing an unbound register.

I think the solution to this is to use the call-sequence start/end instructions to protect the physical register bindings. I have a feeling that's part of what their purpose is.

handleOverflow:
  %retFromGC = call ghccc {i8**, i64} @doGC(i8** %newSP, i64 undef), !cps.retpt !0

==================================================================

BB#6: derived from LLVM BB %handleOverflow
    Predecessors according to CFG: BB#5
    ADJCALLSTACKDOWN64 0, 0, 0, %RSP<imp-def,dead>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
    %R13<def> = COPY %vreg9; GR64:%vreg9
    %vreg24<def> = IMPLICIT_DEF; GR64:%vreg24
    %RBP<def> = COPY %vreg24; GR64:%vreg24
    CPSCALLd64 <ga:@doGC>, <regmask>, %RSP<imp-use>, %R13<imp-use>, %RBP<imp-use>, %RSP<imp-def>, %R13<imp-def>, %RBP<imp-def>
    ADJCALLSTACKUP64 0, 0, %RSP<imp-def,dead>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
    %vreg25<def> = COPY %R13; GR64:%vreg25
    %vreg26<def> = COPY %RBP; GR64:%vreg26
    %vreg10<def> = COPY %vreg25; GR64:%vreg10,%vreg25
    %vreg11<def> = COPY %vreg26; GR64:%vreg11,%vreg26
    JMP_1 <BB#5>
    Successors according to CFG: BB#5(?%)

=======================================================================

BB#6: derived from LLVM BB %handleOverflow
    Predecessors according to CFG: BB#5
    ADJCALLSTACKDOWN64 0, 0, 0, %RSP<imp-def,dead>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
    %R13<def> = COPY %vreg9; GR64:%vreg9
    %vreg24<def> = IMPLICIT_DEF; GR64:%vreg24
    %RBP<def> = COPY %vreg24; GR64:%vreg24
    ADJCALLSTACKUP64 0, 0, %RSP<imp-def>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
    %vreg30<def> = LEA64r %RIP, 1, %noreg, <MCSym=LretptStandin2>, %noreg; GR64:%vreg30
    MOV64mr %RBP, 1, %noreg, 52, %noreg, %vreg30<kill>; GR64:%vreg30
    TCRETURNdi64 <ga:@doGC>, 0, %RSP<imp-use>, %R13<imp-use>, %RBP<imp-use>
    Successors according to CFG: BB#12(?%)

BB#12: EH LANDING PAD
    Live Ins: %R13 %RBP
    Predecessors according to CFG: BB#6
    EH_LABEL <MCSym=LretptStandin2>
    %vreg25<def> = COPY %R13<kill>; GR64:%vreg25
    %vreg26<def> = COPY %RBP<kill>; GR64:%vreg26
    %vreg10<def> = COPY %vreg25; GR64:%vreg10,%vreg25
    %vreg11<def> = COPY %vreg26; GR64:%vreg11,%vreg26
    JMP_1 <BB#5>
    Successors according to CFG: BB#5(0x80000000 / 0x80000000 = 100.00%)

========================================================================

BB#10: derived from LLVM BB %handleOverflow
    Predecessors according to CFG: BB#8
    ADJCALLSTACKDOWN64 0, 0, 0, %RSP<imp-def,dead>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
    %R13<def> = COPY %vreg9; GR64:%vreg9
    ADJCALLSTACKUP64 0, 0, %RSP<imp-def>, %EFLAGS<imp-def,dead>, %RSP<imp-use>
    %vreg30<def> = LEA64r %RIP, 1, %noreg, <MCSym=LretptStandin2>, %noreg; GR64:%vreg30
    MOV64mr %RBP<undef>, 1, %noreg, 52, %noreg, %vreg30; GR64:%vreg30
    TCRETURNdi64 <ga:@doGC>, 0, %RSP<imp-use>, %R13<imp-use>, %RBP<imp-use>
    Successors according to CFG: BB#11(?%)

========================================================================

*** Bad machine code: Using an undefined physical register ***
- function:    foo
- basic block: BB#10 handleOverflow (0x7fcb2b8153c8)
- instruction: TCRETURNdi64
- operand 4:   %RBP<imp-use>
LLVM ERROR: Found 1 machine code errors.
kavon commented 7 years ago

Actually, the problem only crops up if the SP_ARGNUM argument is undef, because we get the following code:

%vreg3<def> = IMPLICIT_DEF; GR64:%vreg3
%RBP<def> = COPY %vreg3; GR64:%vreg3
%vreg6<def> = LEA64r %RIP, 1, %noreg, <MCSym=LCAFE0>, %noreg; GR64:%vreg6
MOV64mr %RBP, 1, %noreg, 17, %noreg, %vreg6<kill>; GR64:%vreg6

which turns into

%vreg6<def> = LEA64r %RIP, 1, %noreg, <MCSym=LCAFE0>, %noreg; GR64:%vreg6
MOV64mr %RBP<undef>, 1, %noreg, 17, %noreg, %vreg6; GR64:%vreg6

which makes no sense as RBP was not defined. I think this might make sense if we had started with the following instead:

%vreg3<def> = IMPLICIT_DEF; GR64:%vreg3
%RBP<def> = COPY %vreg3; GR64:%vreg3
%vreg6<def> = LEA64r %RIP, 1, %noreg, <MCSym=LCAFE0>, %noreg; GR64:%vreg6
MOV64mr %vreg3, 1, %noreg, 17, %noreg, %vreg6<kill>; GR64:%vreg6

All of the above instructions would probably be deleted safely then.

Overall, I'm not concerned with this bug right now. If there's a way to check that the value is not undef/posion during verification (see #7 ) that'd be nice.