1/*
2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "AirCCallingConvention.h"
28
29#if ENABLE(B3_JIT)
30
31#include "AirCCallSpecial.h"
32#include "AirCode.h"
33#include "B3CCallValue.h"
34#include "B3ValueInlines.h"
35
36namespace JSC { namespace B3 { namespace Air {
37
38namespace {
39
40template<typename BankInfo>
41Arg marshallCCallArgumentImpl(unsigned& argumentCount, unsigned& stackOffset, Value* child)
42{
43 unsigned argumentIndex = argumentCount++;
44 if (argumentIndex < BankInfo::numberOfArgumentRegisters)
45 return Tmp(BankInfo::toArgumentRegister(argumentIndex));
46
47 unsigned slotSize;
48 if (isARM64() && isIOS()) {
49 // Arguments are packed.
50 slotSize = sizeofType(child->type());
51 } else {
52 // Arguments are aligned.
53 slotSize = 8;
54 }
55
56 stackOffset = WTF::roundUpToMultipleOf(slotSize, stackOffset);
57 Arg result = Arg::callArg(stackOffset);
58 stackOffset += slotSize;
59 return result;
60}
61
62Arg marshallCCallArgument(
63 unsigned& gpArgumentCount, unsigned& fpArgumentCount, unsigned& stackOffset, Value* child)
64{
65 switch (bankForType(child->type())) {
66 case GP:
67 return marshallCCallArgumentImpl<GPRInfo>(gpArgumentCount, stackOffset, child);
68 case FP:
69 return marshallCCallArgumentImpl<FPRInfo>(fpArgumentCount, stackOffset, child);
70 }
71 RELEASE_ASSERT_NOT_REACHED();
72 return Arg();
73}
74
75} // anonymous namespace
76
77Vector<Arg> computeCCallingConvention(Code& code, CCallValue* value)
78{
79 Vector<Arg> result;
80 result.append(Tmp(CCallSpecial::scratchRegister));
81 unsigned gpArgumentCount = 0;
82 unsigned fpArgumentCount = 0;
83 unsigned stackOffset = 0;
84 for (unsigned i = 1; i < value->numChildren(); ++i) {
85 result.append(
86 marshallCCallArgument(gpArgumentCount, fpArgumentCount, stackOffset, value->child(i)));
87 }
88 code.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf(stackAlignmentBytes(), stackOffset));
89 return result;
90}
91
92Tmp cCallResult(Type type)
93{
94 switch (type.kind()) {
95 case Void:
96 return Tmp();
97 case Int32:
98 case Int64:
99 return Tmp(GPRInfo::returnValueGPR);
100 case Float:
101 case Double:
102 return Tmp(FPRInfo::returnValueFPR);
103 case Tuple:
104 break;
105 }
106
107 RELEASE_ASSERT_NOT_REACHED();
108 return Tmp();
109}
110
111Inst buildCCall(Code& code, Value* origin, const Vector<Arg>& arguments)
112{
113 Inst inst(Patch, origin, Arg::special(code.cCallSpecial()));
114 inst.args.append(arguments[0]);
115 inst.args.append(Tmp(GPRInfo::returnValueGPR));
116 inst.args.append(Tmp(GPRInfo::returnValueGPR2));
117 inst.args.append(Tmp(FPRInfo::returnValueFPR));
118 for (unsigned i = 1; i < arguments.size(); ++i) {
119 Arg arg = arguments[i];
120 if (arg.isTmp())
121 inst.args.append(arg);
122 }
123 return inst;
124}
125
126} } } // namespace JSC::B3::Air
127
128#endif // ENABLE(B3_JIT)
129
130