llvm.org GIT mirror llvm / 3b3752c
HHVM calling conventions. HHVM calling convention, hhvmcc, is used by HHVM JIT for 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 function calls. One extra 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 of first argument which is passed in RBP (before we use RDI, RSI, etc.) Differential Revision: http://reviews.llvm.org/D12681 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248832 91177308-0d34-0410-b5e6-96231b3b80d8 Maksim Panchenko 4 years ago
16 changed file(s) with 369 addition(s) and 29 deletion(s). Raw diff Collapse all Expand all
146146
147147 /// \brief MSVC calling convention that passes vectors and vector aggregates
148148 /// in SSE registers.
149 X86_VectorCall = 80
149 X86_VectorCall = 80,
150
151 /// \brief Calling convention used by HipHop Virtual Machine (HHVM) to
152 /// perform calls to and from translation cache, and for calling PHP
153 /// functions.
154 /// HHVM calling convention supports tail/sibling call elimination.
155 HHVM = 81,
156
157 /// \brief HHVM calling convention for invoking C/C++ helpers.
158 HHVM_C = 82
150159 };
151160 } // End CallingConv namespace
152161
598598 /// Returns the next integer (mod 2**64) that is greater than or equal to
599599 /// \p Value and is a multiple of \p Align. \p Align must be non-zero.
600600 ///
601 /// If non-zero \p Skew is specified, the return value will be a minimal
602 /// integer that is greater than or equal to \p Value and equal to
603 /// \p Align * N + \p Skew for some integer N. If \p Skew is larger than
604 /// \p Align, its value is adjusted to '\p Skew mod \p Align'.
605 ///
601606 /// Examples:
602607 /// \code
603608 /// RoundUpToAlignment(5, 8) = 8
604609 /// RoundUpToAlignment(17, 8) = 24
605610 /// RoundUpToAlignment(~0LL, 8) = 0
606611 /// RoundUpToAlignment(321, 255) = 510
612 ///
613 /// RoundUpToAlignment(5, 8, 7) = 7
614 /// RoundUpToAlignment(17, 8, 1) = 17
615 /// RoundUpToAlignment(~0LL, 8, 3) = 3
616 /// RoundUpToAlignment(321, 255, 42) = 552
607617 /// \endcode
608 inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) {
609 return (Value + Align - 1) / Align * Align;
618 inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align,
619 uint64_t Skew = 0) {
620 Skew %= Align;
621 return (Value + Align - 1 - Skew) / Align * Align + Skew;
610622 }
611623
612624 /// Returns the offset to the next integer (mod 2**64) that is greater than
9595 return StackRealignable;
9696 }
9797
98 /// Return the skew that has to be applied to stack alignment under
99 /// certain conditions (e.g. stack was adjusted before function \p MF
100 /// was called).
101 virtual unsigned getStackAlignmentSkew(const MachineFunction &MF) const;
102
98103 /// getOffsetOfLocalArea - This method returns the offset of the local area
99104 /// from the stack pointer on entrance to a function.
100105 ///
586586 KEYWORD(preserve_mostcc);
587587 KEYWORD(preserve_allcc);
588588 KEYWORD(ghccc);
589 KEYWORD(hhvmcc);
590 KEYWORD(hhvm_ccc);
589591
590592 KEYWORD(cc);
591593 KEYWORD(c);
15311531 /// ::= 'preserve_mostcc'
15321532 /// ::= 'preserve_allcc'
15331533 /// ::= 'ghccc'
1534 /// ::= 'hhvmcc'
1535 /// ::= 'hhvm_ccc'
15341536 /// ::= 'cc' UINT
15351537 ///
15361538 bool LLParser::ParseOptionalCallingConv(unsigned &CC) {
15591561 case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break;
15601562 case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break;
15611563 case lltok::kw_ghccc: CC = CallingConv::GHC; break;
1564 case lltok::kw_hhvmcc: CC = CallingConv::HHVM; break;
1565 case lltok::kw_hhvm_ccc: CC = CallingConv::HHVM_C; break;
15621566 case lltok::kw_cc: {
15631567 Lex.Lex();
15641568 return ParseUInt32(CC);
9696 kw_webkit_jscc, kw_anyregcc,
9797 kw_preserve_mostcc, kw_preserve_allcc,
9898 kw_ghccc,
99 kw_hhvmcc, kw_hhvm_ccc,
99100
100101 // Attributes:
101102 kw_attributes,
499499 static inline void
500500 AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx,
501501 bool StackGrowsDown, int64_t &Offset,
502 unsigned &MaxAlign) {
502 unsigned &MaxAlign, unsigned Skew) {
503503 // If the stack grows down, add the object size to find the lowest address.
504504 if (StackGrowsDown)
505505 Offset += MFI->getObjectSize(FrameIdx);
511511 MaxAlign = std::max(MaxAlign, Align);
512512
513513 // Adjust to alignment boundary.
514 Offset = RoundUpToAlignment(Offset, Align);
514 Offset = RoundUpToAlignment(Offset, Align, Skew);
515515
516516 if (StackGrowsDown) {
517517 DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n");
529529 AssignProtectedObjSet(const StackObjSet &UnassignedObjs,
530530 SmallSet &ProtectedObjs,
531531 MachineFrameInfo *MFI, bool StackGrowsDown,
532 int64_t &Offset, unsigned &MaxAlign) {
532 int64_t &Offset, unsigned &MaxAlign, unsigned Skew) {
533533
534534 for (StackObjSet::const_iterator I = UnassignedObjs.begin(),
535535 E = UnassignedObjs.end(); I != E; ++I) {
536536 int i = *I;
537 AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
537 AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew);
538538 ProtectedObjs.insert(i);
539539 }
540540 }
561561 assert(LocalAreaOffset >= 0
562562 && "Local area offset should be in direction of stack growth");
563563 int64_t Offset = LocalAreaOffset;
564
565 // Skew to be applied to alignment.
566 unsigned Skew = TFI.getStackAlignmentSkew(Fn);
564567
565568 // If there are fixed sized objects that are preallocated in the local area,
566569 // non-fixed objects can't be allocated right at the start of local area.
592595
593596 unsigned Align = MFI->getObjectAlignment(i);
594597 // Adjust to alignment boundary
595 Offset = RoundUpToAlignment(Offset, Align);
598 Offset = RoundUpToAlignment(Offset, Align, Skew);
596599
597600 MFI->setObjectOffset(i, -Offset); // Set the computed offset
598601 }
601604 for (int i = MaxCSFI; i >= MinCSFI ; --i) {
602605 unsigned Align = MFI->getObjectAlignment(i);
603606 // Adjust to alignment boundary
604 Offset = RoundUpToAlignment(Offset, Align);
607 Offset = RoundUpToAlignment(Offset, Align, Skew);
605608
606609 MFI->setObjectOffset(i, Offset);
607610 Offset += MFI->getObjectSize(i);
623626 RS->getScavengingFrameIndices(SFIs);
624627 for (SmallVectorImpl::iterator I = SFIs.begin(),
625628 IE = SFIs.end(); I != IE; ++I)
626 AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign);
629 AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew);
627630 }
628631
629632 // FIXME: Once this is working, then enable flag will change to a target
634637 unsigned Align = MFI->getLocalFrameMaxAlign();
635638
636639 // Adjust to alignment boundary.
637 Offset = RoundUpToAlignment(Offset, Align);
640 Offset = RoundUpToAlignment(Offset, Align, Skew);
638641
639642 DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
640643
661664 StackObjSet AddrOfObjs;
662665
663666 AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), StackGrowsDown,
664 Offset, MaxAlign);
667 Offset, MaxAlign, Skew);
665668
666669 // Assign large stack objects first.
667670 for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) {
694697 }
695698
696699 AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown,
697 Offset, MaxAlign);
700 Offset, MaxAlign, Skew);
698701 AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown,
699 Offset, MaxAlign);
702 Offset, MaxAlign, Skew);
700703 AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown,
701 Offset, MaxAlign);
704 Offset, MaxAlign, Skew);
702705 }
703706
704707 // Then assign frame offsets to stack objects that are not used to spill
718721 if (ProtectedObjs.count(i))
719722 continue;
720723
721 AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
724 AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew);
722725 }
723726
724727 // Make sure the special register scavenging spill slot is closest to the
728731 RS->getScavengingFrameIndices(SFIs);
729732 for (SmallVectorImpl::iterator I = SFIs.begin(),
730733 IE = SFIs.end(); I != IE; ++I)
731 AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign);
734 AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew);
732735 }
733736
734737 if (!TFI.targetHandlesStackFrameRounding()) {
753756 // If the frame pointer is eliminated, all frame offsets will be relative to
754757 // SP not FP. Align to MaxAlign so this works.
755758 StackAlign = std::max(StackAlign, MaxAlign);
756 Offset = RoundUpToAlignment(Offset, StackAlign);
759 Offset = RoundUpToAlignment(Offset, StackAlign, Skew);
757760 }
758761
759762 // Update frame info to pretend that this is part of the stack...
1616 #include "llvm/CodeGen/MachineFunction.h"
1717 #include "llvm/CodeGen/MachineModuleInfo.h"
1818 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/IR/CallingConv.h"
1920 #include "llvm/IR/Function.h"
2021 #include "llvm/Target/TargetRegisterInfo.h"
2122 #include "llvm/Target/TargetSubtargetInfo.h"
8081 SavedRegs.set(Reg);
8182 }
8283 }
84
85 unsigned TargetFrameLowering::getStackAlignmentSkew(
86 const MachineFunction &MF) const {
87 // When HHVM function is called, the stack is skewed as the return address
88 // is removed from the stack before we enter the function.
89 if (LLVM_UNLIKELY(MF.getFunction()->getCallingConv() == CallingConv::HHVM))
90 return MF.getTarget().getPointerSize();
91
92 return 0;
93 }
318318 case CallingConv::X86_64_Win64: Out << "x86_64_win64cc"; break;
319319 case CallingConv::SPIR_FUNC: Out << "spir_func"; break;
320320 case CallingConv::SPIR_KERNEL: Out << "spir_kernel"; break;
321 case CallingConv::HHVM: Out << "hhvmcc"; break;
322 case CallingConv::HHVM_C: Out << "hhvm_ccc"; break;
321323 }
322324 }
323325
201201 CCCustom<"CC_X86_AnyReg_Error">
202202 ]>;
203203
204 // X86-64 HHVM return-value convention.
205 def RetCC_X86_64_HHVM: CallingConv<[
206 // Promote all types to i64
207 CCIfType<[i8, i16, i32], CCPromoteToType>,
208
209 // Return: could return in any GP register save RSP and R12.
210 CCIfType<[i64], CCAssignToReg<[RBX, RBP, RDI, RSI, RDX, RCX, R8, R9,
211 RAX, R10, R11, R13, R14, R15]>>
212 ]>;
213
204214 // This is the root return-value convention for the X86-32 backend.
205215 def RetCC_X86_32 : CallingConv<[
206216 // If FastCC, use RetCC_X86_32_Fast.
225235 // Handle explicit CC selection
226236 CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo>,
227237 CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo>,
238
239 // Handle HHVM calls.
240 CCIfCC<"CallingConv::HHVM", CCDelegateTo>,
228241
229242 // Mingw64 and native Win64 use Win64 CC
230243 CCIfSubtarget<"isTargetWin64()", CCDelegateTo>,
318331 CCAssignToStack<64, 64>>
319332 ]>;
320333
334 // Calling convention for X86-64 HHVM.
335 def CC_X86_64_HHVM : CallingConv<[
336 // Use all/any GP registers for args, except RSP.
337 CCIfType<[i64], CCAssignToReg<[RBX, R12, RBP, R15,
338 RDI, RSI, RDX, RCX, R8, R9,
339 RAX, R10, R11, R13, R14]>>
340 ]>;
341
342 // Calling convention for helper functions in HHVM.
343 def CC_X86_64_HHVM_C : CallingConv<[
344 // Pass the first argument in RBP.
345 CCIfType<[i64], CCAssignToReg<[RBP]>>,
346
347 // Otherwise it's the same as the regular C calling convention.
348 CCDelegateTo
349 ]>;
350
321351 // Calling convention used on Win64
322352 def CC_X86_Win64_C : CallingConv<[
323353 // FIXME: Handle byval stuff.
733763 CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo>,
734764 CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo>,
735765 CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>,
766 CCIfCC<"CallingConv::HHVM", CCDelegateTo>,
767 CCIfCC<"CallingConv::HHVM_C", CCDelegateTo>,
736768
737769 // Mingw64 and native Win64 use Win64 CC
738770 CCIfSubtarget<"isTargetWin64()", CCDelegateTo>,
803835 def CSR_64_Intel_OCL_BI_AVX512 : CalleeSavedRegs<(add RBX, RDI, RSI, R14, R15,
804836 (sequence "ZMM%u", 16, 31),
805837 K4, K5, K6, K7)>;
838
839 // Only R12 is preserved for PHP calls in HHVM.
840 def CSR_64_HHVM : CalleeSavedRegs<(add R12)>;
24252425 /// supports tail call optimization.
24262426 static bool IsTailCallConvention(CallingConv::ID CC) {
24272427 return (CC == CallingConv::Fast || CC == CallingConv::GHC ||
2428 CC == CallingConv::HiPE);
2428 CC == CallingConv::HiPE || CC == CallingConv::HHVM);
24292429 }
24302430
24312431 /// \brief Return true if the calling convention is a C calling convention.
38993899 /// Callee pop is necessary to support tail calls.
39003900 bool X86::isCalleePop(CallingConv::ID CallingConv,
39013901 bool is64Bit, bool IsVarArg, bool TailCallOpt) {
3902
3903 if (IsTailCallConvention(CallingConv))
3904 return IsVarArg ? false : TailCallOpt;
3905
39023906 switch (CallingConv) {
39033907 default:
39043908 return false;
39063910 case CallingConv::X86_FastCall:
39073911 case CallingConv::X86_ThisCall:
39083912 return !is64Bit;
3909 case CallingConv::Fast:
3910 case CallingConv::GHC:
3911 case CallingConv::HiPE:
3912 if (IsVarArg)
3913 return false;
3914 return TailCallOpt;
39153913 }
39163914 }
39173915
255255 return CSR_64_Intel_OCL_BI_SaveList;
256256 break;
257257 }
258 case CallingConv::HHVM:
259 return CSR_64_HHVM_SaveList;
258260 case CallingConv::Cold:
259261 if (Is64Bit)
260262 return CSR_64_MostRegs_SaveList;
315317 return CSR_64_Intel_OCL_BI_RegMask;
316318 break;
317319 }
320 case CallingConv::HHVM:
321 return CSR_64_HHVM_RegMask;
318322 case CallingConv::Cold:
319323 if (Is64Bit)
320324 return CSR_64_MostRegs_RegMask;
0 ; RUN: llc < %s | FileCheck %s
1
2 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
3 target triple = "x86_64-unknown-linux-gnu"
4
5 declare hhvmcc i64 @bar(i64, i64, i64) nounwind
6
7 ; Simply check we can modify %rbx and %rbp before returning via call to bar.
8 define hhvmcc i64 @foo(i64 %a, i64 %b, i64 %c) nounwind {
9 entry:
10 ; CHECK-LABEL: foo:
11 ; CHECK-DAG: movl $1, %ebx
12 ; CHECK-DAG: movl $3, %ebp
13 ; CHECK: jmp bar
14 %ret = musttail call hhvmcc i64 @bar(i64 1, i64 %b, i64 3)
15 ret i64 %ret
16 }
17
18 ; Check that we can read and modify %rbx returned from PHP function.
19 define hhvmcc i64 @mod_return(i64 %a, i64 %b, i64 %c) nounwind {
20 entry:
21 ; CHECK-LABEL: mod_return:
22 ; CHECK-NEXT: {{^#.*}}
23 ; CHECK-NEXT: callq bar
24 ; CHECK-NEXT: incq %rbx
25 %tmp = call hhvmcc i64 @bar(i64 %a, i64 %b, i64 %c)
26 %retval = add i64 %tmp, 1
27 ret i64 %retval
28 }
29
30 %rettype = type { i64, i64, i64, i64, i64, i64, i64,
31 i64, i64, i64, i64, i64, i64, i64
32 }
33
34 ; Check that we can return up to 14 64-bit args in registers.
35 define hhvmcc %rettype @return_all(i64 %a, i64 %b, i64 %c) nounwind {
36 entry:
37 ; CHECK-LABEL: return_all:
38 ; CHECK-DAG: movl $1, %ebx
39 ; CHECK-DAG: movl $2, %ebp
40 ; CHECK-DAG: movl $3, %edi
41 ; CHECK-DAG: movl $4, %esi
42 ; CHECK-DAG: movl $5, %edx
43 ; CHECK-DAG: movl $6, %ecx
44 ; CHECK-DAG: movl $7, %r8
45 ; CHECK-DAG: movl $8, %r9
46 ; CHECK-DAG: movl $9, %eax
47 ; CHECK-DAG: movl $10, %r10
48 ; CHECK-DAG: movl $11, %r11
49 ; CHECK-DAG: movl $12, %r13
50 ; CHECK-DAG: movl $13, %r14
51 ; CHECK-DAG: movl $14, %r15
52 ; CHECK: retq
53 %r1 = insertvalue %rettype zeroinitializer, i64 1, 0
54 %r2 = insertvalue %rettype %r1, i64 2, 1
55 %r3 = insertvalue %rettype %r2, i64 3, 2
56 %r4 = insertvalue %rettype %r3, i64 4, 3
57 %r5 = insertvalue %rettype %r4, i64 5, 4
58 %r6 = insertvalue %rettype %r5, i64 6, 5
59 %r7 = insertvalue %rettype %r6, i64 7, 6
60 %r8 = insertvalue %rettype %r7, i64 8, 7
61 %r9 = insertvalue %rettype %r8, i64 9, 8
62 %r10 = insertvalue %rettype %r9, i64 10, 9
63 %r11 = insertvalue %rettype %r10, i64 11, 10
64 %r12 = insertvalue %rettype %r11, i64 12, 11
65 %r13 = insertvalue %rettype %r12, i64 13, 12
66 %r14 = insertvalue %rettype %r13, i64 14, 13
67 ret %rettype %r14
68 }
69
70 declare hhvmcc void @return_all_tc(i64, i64, i64, i64, i64, i64, i64, i64,
71 i64, i64, i64, i64, i64, i64, i64)
72
73 ; Check that we can return up to 14 64-bit args in registers via tail call.
74 define hhvmcc void @test_return_all_tc(i64 %a, i64 %b, i64 %c) nounwind {
75 entry:
76 ; CHECK-LABEL: test_return_all_tc:
77 ; CHECK-NEXT: {{^#.*}}
78 ; CHECK-DAG: movl $1, %ebx
79 ; CHECK-DAG: movl $3, %ebp
80 ; CHECK-DAG: movl $4, %r15
81 ; CHECK-DAG: movl $5, %edi
82 ; CHECK-DAG: movl $6, %esi
83 ; CHECK-DAG: movl $7, %edx
84 ; CHECK-DAG: movl $8, %ecx
85 ; CHECK-DAG: movl $9, %r8
86 ; CHECK-DAG: movl $10, %r9
87 ; CHECK-DAG: movl $11, %eax
88 ; CHECK-DAG: movl $12, %r10
89 ; CHECK-DAG: movl $13, %r11
90 ; CHECK-DAG: movl $14, %r13
91 ; CHECK-DAG: movl $15, %r14
92 ; CHECK: jmp return_all_tc
93 tail call hhvmcc void @return_all_tc(
94 i64 1, i64 %b, i64 3, i64 4, i64 5, i64 6, i64 7,
95 i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15)
96 ret void
97 }
98
99 declare hhvmcc {i64, i64} @php_short(i64, i64, i64, i64)
100
101 define hhvmcc i64 @test_php_short(i64 %a, i64 %b, i64 %c) nounwind {
102 entry:
103 ; CHECK-LABEL: test_php_short:
104 ; CHECK-NEXT: {{^#.*}}
105 ; CHECK-NEXT: movl $42, %r15
106 ; CHECK-NEXT: callq php_short
107 ; CHECK-NEXT: leaq (%rbp,%r12), %rbx
108 ; CHECK-NEXT: retq
109 %pair = call hhvmcc {i64, i64} @php_short(i64 %a, i64 %b, i64 %c, i64 42)
110 %fp = extractvalue {i64, i64} %pair, 1
111 %rv = add i64 %fp, %b
112 ret i64 %rv
113 }
114
115 declare hhvmcc %rettype @php_all(i64, i64, i64, i64, i64, i64, i64,
116 i64, i64, i64, i64, i64, i64, i64, i64)
117
118 ; Check that we can pass 15 arguments in registers.
119 ; Also check that %r12 (2nd arg) is not spilled.
120 define hhvmcc i64 @test_php_all(i64 %a, i64 %b, i64 %c) nounwind {
121 entry:
122 ; CHECK-LABEL: test_php_all:
123 ; CHECK-NEXT: {{^#.*}}
124 ; CHECK-NOT: sub
125 ; CHECK-NOT: sub
126 ; CHECK-DAG: movl $1, %ebx
127 ; CHECK-DAG: movl $3, %ebp
128 ; CHECK-DAG: movl $4, %r15
129 ; CHECK-DAG: movl $5, %edi
130 ; CHECK-DAG: movl $6, %esi
131 ; CHECK-DAG: movl $7, %edx
132 ; CHECK-DAG: movl $8, %ecx
133 ; CHECK-DAG: movl $9, %r8
134 ; CHECK-DAG: movl $10, %r9
135 ; CHECK-DAG: movl $11, %eax
136 ; CHECK-DAG: movl $12, %r10
137 ; CHECK-DAG: movl $13, %r11
138 ; CHECK-DAG: movl $14, %r13
139 ; CHECK-DAG: movl $15, %r14
140 ; CHECK: callq php_all
141 %pair = call hhvmcc %rettype @php_all(
142 i64 1, i64 %b, i64 3, i64 4, i64 5, i64 6, i64 7,
143 i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15)
144 %fp = extractvalue %rettype %pair, 1
145 %rv = add i64 %fp, %b
146 ret i64 %rv
147 }
148
149 declare hhvmcc void @svcreq(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64,
150 i64, i64)
151
152 define hhvmcc void @test_svcreq(i64 %a, i64 %b, i64 %c) nounwind {
153 entry:
154 ; CHECK-LABEL: test_svcreq:
155 ; CHECK-DAG: movl $42, %r10
156 ; CHECK-DAG: movl $1, %edi
157 ; CHECK-DAG: movl $2, %esi
158 ; CHECK-DAG: movl $3, %edx
159 ; CHECK-DAG: movl $4, %ecx
160 ; CHECK-DAG: movl $5, %r8
161 ; CHECK-DAG: movl $6, %r9
162 ; CHECK: jmp svcreq
163 tail call hhvmcc void @svcreq(i64 %a, i64 %b, i64 %c, i64 undef, i64 1,
164 i64 2, i64 3, i64 4, i64 5, i64 6, i64 undef,
165 i64 42)
166 ret void
167 }
168
169 declare hhvm_ccc void @helper_short(i64, i64, i64, i64, i64, i64, i64)
170
171 ; Pass all arguments in registers and check that we don't adjust stack
172 ; for the call.
173 define hhvmcc void @test_helper_short(i64 %a, i64 %b, i64 %c) nounwind {
174 entry:
175 ; CHECK-LABEL: test_helper_short:
176 ; CHECK-NOT: push
177 ; CHECK-NOT: sub
178 ; CHECK-DAG: movl $1, %edi
179 ; CHECK-DAG: movl $2, %esi
180 ; CHECK-DAG: movl $3, %edx
181 ; CHECK-DAG: movl $4, %ecx
182 ; CHECK-DAG: movl $5, %r8
183 ; CHECK-DAG: movl $6, %r9
184 ; CHECK: callq helper_short
185 call hhvm_ccc void @helper_short(i64 %c, i64 1, i64 2, i64 3, i64 4,
186 i64 5, i64 6)
187 ret void
188 }
189
190 declare hhvm_ccc void @helper(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64)
191
192 define hhvmcc void @test_helper(i64 %a, i64 %b, i64 %c) nounwind {
193 entry:
194 ; CHECK-LABEL: test_helper:
195 ; CHECK-DAG: movl $1, %edi
196 ; CHECK-DAG: movl $2, %esi
197 ; CHECK-DAG: movl $3, %edx
198 ; CHECK-DAG: movl $4, %ecx
199 ; CHECK-DAG: movl $5, %r8
200 ; CHECK-DAG: movl $6, %r9
201 ; CHECK: callq helper
202 call hhvm_ccc void @helper(i64 %c, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6,
203 i64 7, i64 8, i64 9)
204 ret void
205 }
206
207 ; When we enter function with HHVM calling convention, the stack is aligned
208 ; at 16 bytes. This means we align objects on the stack differently and
209 ; adjust the stack differently for calls.
210 declare hhvm_ccc void @stack_helper(i64, i64, i64)
211 declare hhvm_ccc void @stack_helper2(<2 x double>, i64)
212
213 define hhvmcc void @test_stack_helper(i64 %a, i64 %b, i64 %c) nounwind {
214 entry:
215 ; CHECK-LABEL: test_stack_helper:
216 ; CHECK-NOT: push
217 ; CHECK: subq $32, %rsp
218 ; CHECK: movaps 16(%rsp), %xmm0
219 ; CHECK: callq stack_helper2
220 %t1 = alloca <2 x double>, align 16
221 %t2 = alloca i64, align 8
222 %t3 = alloca i64, align 8
223 %load3 = load i64, i64 *%t3
224 call hhvm_ccc void @stack_helper(i64 %c, i64 %load3, i64 42)
225 %load = load <2 x double>, <2 x double> *%t1
226 %load2 = load i64, i64 *%t2
227 call hhvm_ccc void @stack_helper2(<2 x double> %load, i64 %load2)
228 ret void
229 }
230
231 ; Check that we are not adjusting the stack before calling the helper.
232 define hhvmcc void @test_stack_helper2(i64 %a, i64 %b, i64 %c) nounwind {
233 entry:
234 ; CHECK-LABEL: test_stack_helper2:
235 ; CHECK-NOT: push
236 ; CHECK-NOT: subq
237 call hhvm_ccc void @stack_helper(i64 %c, i64 7, i64 42)
238 ret void
239 }
240
5858 ret void
5959 }
6060
61 declare hhvm_ccc void @hhvm_c_callee()
62
63 define hhvmcc void @hhvm_caller() {
64 call hhvm_ccc void @hhvm_c_callee()
65 ret void
66 }
67
6168 declare i32 @__gxx_personality_v0(...)
182182 EXPECT_EQ(8u, RoundUpToAlignment(5, 8));
183183 EXPECT_EQ(24u, RoundUpToAlignment(17, 8));
184184 EXPECT_EQ(0u, RoundUpToAlignment(~0LL, 8));
185
186 EXPECT_EQ(7u, RoundUpToAlignment(5, 8, 7));
187 EXPECT_EQ(17u, RoundUpToAlignment(17, 8, 1));
188 EXPECT_EQ(3u, RoundUpToAlignment(~0LL, 8, 3));
189 EXPECT_EQ(552u, RoundUpToAlignment(321, 255, 42));
185190 }
186191
187192 }
4141 syn keyword llvmKeyword blockaddress byval c catch cc ccc cleanup coldcc common
4242 syn keyword llvmKeyword constant datalayout declare default define deplibs
4343 syn keyword llvmKeyword distinct dllexport dllimport except extern_weak external
44 syn keyword llvmKeyword externally_initialized fastcc filter gc global hidden
45 syn keyword llvmKeyword initialexec inlinehint inreg intel_ocl_bicc inteldialect
46 syn keyword llvmKeyword internal linkonce linkonce_odr localdynamic localexec
47 syn keyword llvmKeyword minsize module monotonic msp430_intrcc naked nest
44 syn keyword llvmKeyword externally_initialized fastcc filter gc global hhvmcc
45 syn keyword llvmKeyword hhvm_ccc hidden initialexec inlinehint inreg
46 syn keyword llvmKeyword intel_ocl_bicc inteldialect internal linkonce
47 syn keyword llvmKeyword linkonce_odr localdynamic localexec minsize module
48 syn keyword llvmKeyword monotonic msp430_intrcc musttail naked nest
4849 syn keyword llvmKeyword noalias nocapture noimplicitfloat noinline nonlazybind
4950 syn keyword llvmKeyword noredzone noreturn nounwind optnone optsize personality
5051 syn keyword llvmKeyword private protected ptx_device ptx_kernel readnone