[llvm] r194428 - Fix the recently added anyregcc convention to handle spilled operands.

Andrew Trick atrick at apple.com
Tue Nov 12 16:42:06 PST 2013


On Nov 12, 2013, at 1:10 PM, Eric Christopher <echristo at gmail.com> wrote:

> On Mon, Nov 11, 2013 at 7:47 PM, Andrew Trick <atrick at apple.com> wrote:
>> 
>> On Nov 11, 2013, at 7:11 PM, Sean Silva <silvas at purdue.edu> wrote:
>> 
>>   StartIdx = isPatchPoint ?
>> -             StartIdx + MI->getOperand(StartIdx+3).getImm() + 5 :
>> +             StartIdx + NumCallArgs + 5 :
>>              StartIdx + 2;
>> 
>> Magic numbers?
>> 
>> 
>> Yes, I absolutely hate referring to operands by position. I was also
>> thinking of fixing this when I fixed the bug today, but haven’t figured out
>> the right way to do it yet.
> 
> Enum along with the instruction?

:) That’s what I’ve done in other compilers. So how do we do it with LLVM target opcodes? Any examples?

> Also the documentation as pointed out by Sean. Please do document the
> cases he describes and probably update the code to fail in some sort
> of spectacular manner.

anyregcc is meant to be used for patching code sequences in place of a call where we just need 2-3 incoming values guaranteed to be in registers. If a JIT does ask for more register args than the platform can handle, which would be completely insane, then they get this spectacular error:

"LLVM ERROR: ran out of registers during register allocation"

If a front end requests anyregcc on a call that is not a patchpoint they get:

"The AnyReg calling convention is only supported by the stackmap and patchpoint intrinsics."

It would be so great to be able to check these docs in:
http://llvm-reviews.chandlerc.com/D1981

You and Sean are the only reviewers I’m not sure about.

-Andy

> 
> -eric
> 
>> -Andy
>> 
>> On Mon, Nov 11, 2013 at 5:40 PM, Andrew Trick <atrick at apple.com> wrote:
>>> 
>>> Author: atrick
>>> Date: Mon Nov 11 16:40:25 2013
>>> New Revision: 194428
>>> 
>>> URL: http://llvm.org/viewvc/llvm-project?rev=194428&view=rev
>>> Log:
>>> Fix the recently added anyregcc convention to handle spilled operands.
>>> 
>>> Fixes <rdar://15432754> [JS] Assertion: "Folded a def to a non-store!"
>>> 
>>> The primary purpose of anyregcc is to prevent a patchpoint's call
>>> arguments and return value from being spilled. They must be available
>>> in a register, although the calling convention does not pin the
>>> register. It's up to the front end to avoid using this convention for
>>> calls with more arguments than allocatable registers.
>> 
>> 
>> What happens otherwise? UB? Do we expose an API to indicate the maximum
>> number available? This sounds ripe for turning into an exploitable
>> vulnerability without some way for the API user to check their assumptions
>> about how many registers LLVM will provide them with.
>> 
>> Also, btw, anyregcc is not documented in LangRef. Please update the
>> documentation.
>> 
>> -- Sean Silva
>> 
>>> 
>>> 
>>> Modified:
>>>    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
>>>    llvm/trunk/test/CodeGen/X86/anyregcc.ll
>>> 
>>> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=194428&r1=194427&r2=194428&view=diff
>>> 
>>> ==============================================================================
>>> --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
>>> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Mon Nov 11 16:40:25 2013
>>> @@ -4207,10 +4207,19 @@ static MachineInstr* foldPatchpoint(Mach
>>>   MachineInstrBuilder MIB(MF, NewMI);
>>> 
>>>   bool isPatchPoint = MI->getOpcode() == TargetOpcode::PATCHPOINT;
>>> +  // For PatchPoint, the call args are not foldable.
>>> +  unsigned NumCallArgs = MI->getOperand(StartIdx+3).getImm();
>>>   StartIdx = isPatchPoint ?
>>> -             StartIdx + MI->getOperand(StartIdx+3).getImm() + 5 :
>>> +             StartIdx + NumCallArgs + 5 :
>>>              StartIdx + 2;
>>> 
>>> +  // Return false if any operands requested for folding are not foldable
>>> (not
>>> +  // part of the stackmap's live values).
>>> +  for (SmallVectorImpl<unsigned>::const_iterator I = Ops.begin(), E =
>>> Ops.end();
>>> +       I != E; ++I) {
>>> +    if (*I < StartIdx)
>>> +      return 0;
>>> +  }
>>>   // No need to fold return, the meta data, and function arguments
>>>   for (unsigned i = 0; i < StartIdx; ++i)
>>>     MIB.addOperand(MI->getOperand(i));
>>> 
>>> Modified: llvm/trunk/test/CodeGen/X86/anyregcc.ll
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/anyregcc.ll?rev=194428&r1=194427&r2=194428&view=diff
>>> 
>>> ==============================================================================
>>> --- llvm/trunk/test/CodeGen/X86/anyregcc.ll (original)
>>> +++ llvm/trunk/test/CodeGen/X86/anyregcc.ll Mon Nov 11 16:40:25 2013
>>> @@ -8,11 +8,11 @@
>>> ; Num Constants
>>> ; CHECK-NEXT:   .long   0
>>> ; Num Callsites
>>> -; CHECK-NEXT:   .long   6
>>> +; CHECK-NEXT:   .long   7
>>> 
>>> ; test
>>> ; CHECK-NEXT:   .long   0
>>> -; CHECK-NEXT:   .long   L{{.*}}-_test
>>> +; CHECK-LABEL:  .long   L{{.*}}-_test
>>> ; CHECK-NEXT:   .short  0
>>> ; 3 locations
>>> ; CHECK-NEXT:   .short  3
>>> @@ -39,7 +39,7 @@ entry:
>>> 
>>> ; property access 1 - %obj is an anyreg call argument and should
>>> therefore be in a register
>>> ; CHECK-NEXT:   .long   1
>>> -; CHECK-NEXT:   .long   L{{.*}}-_property_access1
>>> +; CHECK-LABEL:  .long   L{{.*}}-_property_access1
>>> ; CHECK-NEXT:   .short  0
>>> ; 2 locations
>>> ; CHECK-NEXT:   .short  2
>>> @@ -62,7 +62,7 @@ entry:
>>> 
>>> ; property access 2 - %obj is an anyreg call argument and should
>>> therefore be in a register
>>> ; CHECK-NEXT:   .long   2
>>> -; CHECK-NEXT:   .long   L{{.*}}-_property_access2
>>> +; CHECK-LABEL:  .long   L{{.*}}-_property_access2
>>> ; CHECK-NEXT:   .short  0
>>> ; 2 locations
>>> ; CHECK-NEXT:   .short  2
>>> @@ -86,7 +86,7 @@ entry:
>>> 
>>> ; property access 3 - %obj is a frame index
>>> ; CHECK-NEXT:   .long   3
>>> -; CHECK-NEXT:   .long   L{{.*}}-_property_access3
>>> +; CHECK-LABEL:  .long   L{{.*}}-_property_access3
>>> ; CHECK-NEXT:   .short  0
>>> ; 2 locations
>>> ; CHECK-NEXT:   .short  2
>>> @@ -110,7 +110,7 @@ entry:
>>> 
>>> ; anyreg_test1
>>> ; CHECK-NEXT:   .long   4
>>> -; CHECK-NEXT:   .long   L{{.*}}-_anyreg_test1
>>> +; CHECK-LABEL:  .long   L{{.*}}-_anyreg_test1
>>> ; CHECK-NEXT:   .short  0
>>> ; 14 locations
>>> ; CHECK-NEXT:   .short  14
>>> @@ -193,7 +193,7 @@ entry:
>>> 
>>> ; anyreg_test2
>>> ; CHECK-NEXT:   .long   5
>>> -; CHECK-NEXT:   .long   L{{.*}}-_anyreg_test2
>>> +; CHECK-LABEL:  .long   L{{.*}}-_anyreg_test2
>>> ; CHECK-NEXT:   .short  0
>>> ; 14 locations
>>> ; CHECK-NEXT:   .short  14
>>> @@ -274,6 +274,35 @@ entry:
>>>   ret i64 %ret
>>> }
>>> 
>>> +; Test spilling the return value of an anyregcc call.
>>> +;
>>> +; <rdar://problem/15432754> [JS] Assertion: "Folded a def to a
>>> non-store!"
>>> +;
>>> +; CHECK-LABEL: .long 12
>>> +; CHECK-LABEL: .long L{{.*}}-_patchpoint_spilldef
>>> +; CHECK-NEXT: .short 0
>>> +; CHECK-NEXT: .short 3
>>> +; Loc 0: Register (some register that will be spilled to the stack)
>>> +; CHECK-NEXT: .byte  1
>>> +; CHECK-NEXT: .byte  0
>>> +; CHECK-NEXT: .short {{[0-9]+}}
>>> +; CHECK-NEXT: .long  0
>>> +; Loc 1: Register RDI
>>> +; CHECK-NEXT: .byte  1
>>> +; CHECK-NEXT: .byte  0
>>> +; CHECK-NEXT: .short 5
>>> +; CHECK-NEXT: .long  0
>>> +; Loc 1: Register RSI
>>> +; CHECK-NEXT: .byte  1
>>> +; CHECK-NEXT: .byte  0
>>> +; CHECK-NEXT: .short 4
>>> +; CHECK-NEXT: .long  0
>>> +define i64 @patchpoint_spilldef(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
>>> +entry:
>>> +  %result = tail call anyregcc i64 (i32, i32, i8*, i32, ...)*
>>> @llvm.experimental.patchpoint.i64(i32 12, i32 15, i8* inttoptr (i64 0 to
>>> i8*), i32 2, i64 %p1, i64 %p2)
>>> +  tail call void asm sideeffect "nop",
>>> "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"()
>>> nounwind
>>> +  ret i64 %result
>>> +}
>>> +
>>> declare void @llvm.experimental.patchpoint.void(i32, i32, i8*, i32, ...)
>>> declare i64 @llvm.experimental.patchpoint.i64(i32, i32, i8*, i32, ...)
>>> -
>>> 
>>> 
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>> 
>> 
>> 
>> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131112/a3c083c1/attachment.html>


More information about the llvm-commits mailing list