This is an archive of the discontinued LLVM Phabricator instance.

Calling conventions for HHVM
ClosedPublic

Authored by maksfb on Sep 7 2015, 3:53 PM.

Details

Summary

HHVM calling convention, hhvmcc, is used by HHVM JIT for calling
functions in translated cache. We currently support LLVM back end to
generate code for X86-64 and may support other architectures in the
future.

In HHVM calling convention any GP register could be used to pass and
return values, with the exception of R12 which is reserved for
thread-local area and is callee-saved. Other than R12, we always
pass RBX and RBP as args, which are our virtual machine's stack pointer
and frame pointer respectively.

When we enter translation cache via hhvmcc function, we expect
the stack to be aligned at 16 bytes, i.e. skewed by 8 bytes as opposed
to standard ABI alignment. This affects stack object alignment and stack
adjustments for calls.

The second calling convention, hhvm_ccc, is used to call C++ helpers from
HHVM's translation cache. It is almost identical to standard C calling
convention with an exception that we pass our virtual machine's frame pointer
in RBP as the first argument to a function, and then use standard
registers/stack (RDI, RSI, etc.) for the rest of the arguments.

Diff Detail

Event Timeline

maksfb updated this revision to Diff 34060.Sep 7 2015, 3:53 PM
maksfb retitled this revision from to Calling conventions for HHVM.
maksfb updated this object.
maksfb added a subscriber: llvm-commits.
sanjoy edited edge metadata.Sep 7 2015, 4:09 PM

By no means a "proper" review, but two things I noticed on a quick scan:

include/llvm/Support/MathExtras.h
619–622

Should this have a test in Support/MathExtrasTest.cpp?

lib/CodeGen/PrologEpilogInserter.cpp
574

I'd skip the braces for the single line body, like elsewhere in LLVM.

maksfb added inline comments.Sep 7 2015, 4:57 PM
include/llvm/Support/MathExtras.h
619–622

Thanks! Didn't know about it.

lib/CodeGen/PrologEpilogInserter.cpp
574

Sure.

maksfb updated this revision to Diff 34172.Sep 7 2015, 5:08 PM
maksfb edited edge metadata.
This comment was removed by maksfb.
maksfb updated this revision to Diff 34174.Sep 7 2015, 5:16 PM

Restore the diff + suggestions by Sanjoy Das.

mcrosier edited edge metadata.Sep 11 2015, 12:06 PM

Looks to be in pretty good shape, but I'm not confident enough in my review to give the final LGTM. One minor nit.

lib/Target/X86/X86ISelLowering.cpp
3897

While this looks correct, I'm not sure I agree with the refactoring.

Cool. Thanks.

lib/Target/X86/X86ISelLowering.cpp
3897

Which part of it? The logic here is to check for a tail call calling convention, and I thought it'd better to maintain a single list of those.

mcrosier added inline comments.Sep 14 2015, 3:42 PM
lib/Target/X86/X86ISelLowering.cpp
3897

Nevermind. You make a good point. :)

reames edited edge metadata.Sep 16 2015, 6:35 PM

Most of this looks pretty straight forward. The only part which worries me is the Skew implementation and how much that has to touch. Could you give a bit of background on why you need this skew, and why you chose to implement it this way?

Fair warning, I'm not going to be able to sign off on the skew parts. Everything else is in areas I'm familiar with, but that's really not.

include/llvm/IR/CallingConv.h
154

This sentence isn't clear to me. Is this analogous to anyreg where the register allocator can put arguments in any register and the runtime has to parse the stack map to figure out where they are? Or are there defined argument and return registers? If the later, I'd just emit this sentence.

lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
50 ↗(On Diff #34174)

Is this a stray change? Or an unrelated bug fix? If the former, please remove. If the later, please submit separately.

lib/CodeGen/PrologEpilogInserter.cpp
519

It would be cleaner to separate a refactoring change which used the helper function, then extended the argument list later. I'd prefer you did this.

570

I don't have a concrete objection here, but this section feels suspicious. Why do you need to skew each and every element within the frame layout rather than inserting a dummy slot to ensure the skew is respected? Also, do you really want individual arguments passed at Align + Skew? Having an vector argument being passed at align (32) + 8 just seems weird to me.

Thanks for the review. The stack skew is due to the deviation from x64 ABI and is related to the way we enter our translation cache which happens from a piece of assembly code. Typically on a function entry %rsp mod 16 == 8, for us it's %rsp mod 16 == 0. From LLVM point of view all the objects on the stack with alignment over 8 bytes have to be placed differently relative to %rsp. Also, if there happens to be a call to a regular function, we don't have to adjust %rsp when the stack frame is empty (on x64 you have to issue a dummy push or sub 8, %rsp). There's more info in inline comments on why we have to change the alignment rules for implementation.

include/llvm/IR/CallingConv.h
154

Unlike anyreg where LLVM chooses the registers, we'd like to give a similar level of control to the runtime (i.e. HHVM). If you think this sentence is confusing, I will remove it.

lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
50 ↗(On Diff #34174)

Documentation bugfix.

lib/CodeGen/PrologEpilogInserter.cpp
519

Sounds good. I will submit refactoring change separately.

570

That's exactly what we need to do. Inserting dummy object wouldn't give us the same result. On x64 you need to push 8 bytes on a stack before making a call. Our stack have already been adjusted on the entry to HHVM translation cache function, so we can simply do the call without doing the stack adjustment. This changes alignment rules for all the objects on the stack though.

maksfb updated this revision to Diff 35176.Sep 19 2015, 11:46 AM

Updated the patch based on Philip's feedback.

qcolombet accepted this revision.Sep 28 2015, 11:40 AM
qcolombet edited edge metadata.

Hi Maksim,

LGTM with a couple of nitpicks.

Cheers,
-Quentin

include/llvm/Support/MathExtras.h
621

In the comment you said that Skew must be less than Align.
So, this line of code seems useless.
Either keep that line and change the comment to actually reflect what is happening or change that into an assert Skew < Align.

lib/CodeGen/PrologEpilogInserter.cpp
574

I would rather have a target hook for that: getSkew, so that we do not expose (more) target code in the generic part.

This revision is now accepted and ready to land.Sep 28 2015, 11:40 AM

Thanks for the review, Quentin!

include/llvm/Support/MathExtras.h
621

Good point. I'll change the comment.

lib/CodeGen/PrologEpilogInserter.cpp
574

Makes sense. Will move the logic to TargetFrameLowering.

maksfb updated this revision to Diff 35933.EditedSep 28 2015, 6:45 PM
maksfb edited edge metadata.

Updated the patch based on Quentin's feedback, and rebased.

Small nitpicks and questions.

include/llvm/Target/TargetFrameLowering.h
99 ↗(On Diff #35933)

Do not repeat the method name. This was the old style comment.

102 ↗(On Diff #35933)

Should be virtual.

lib/CodeGen/TargetFrameLoweringImpl.cpp
91 ↗(On Diff #35933)

Is HHVM a generic calling convention or is it x86_64 specific.

If the latter, move this code in a x86 frame lowering override.

Thanks!

include/llvm/Target/TargetFrameLowering.h
99 ↗(On Diff #35933)

Ok.

102 ↗(On Diff #35933)

Ok.

lib/CodeGen/TargetFrameLoweringImpl.cpp
91 ↗(On Diff #35933)

It is a generic calling convention and for other architectures we will also have a return address removed from the stack before we enter the function.

maksfb updated this revision to Diff 36024.Sep 29 2015, 12:57 PM

More feedback from Quentin.

Thanks for your patience.

Looks good, please go ahead!

Q.

This revision was automatically updated to reflect the committed changes.