Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT
2 : // This file is part of AsmJit project <https://asmjit.com>
3 : //
4 : // See asmjit.h or LICENSE.md for license and copyright information
5 : // SPDX-License-Identifier: Zlib
6 :
7 : #include "api-build_p.h"
8 : #if !defined(ASMJIT_NO_AARCH64)
9 :
10 : #include "a64func_p.h"
11 : #include "a64operand.h"
12 :
13 : ASMJIT_BEGIN_SUB_NAMESPACE(a64)
14 :
15 : namespace FuncInternal {
16 :
17 : static inline bool shouldThreatAsCDecl(CallConvId ccId) noexcept {
18 : return ccId == CallConvId::kCDecl ||
19 : ccId == CallConvId::kStdCall ||
20 : ccId == CallConvId::kFastCall ||
21 : ccId == CallConvId::kVectorCall ||
22 : ccId == CallConvId::kThisCall ||
23 : ccId == CallConvId::kRegParm1 ||
24 0 : ccId == CallConvId::kRegParm2 ||
25 : ccId == CallConvId::kRegParm3;
26 : }
27 :
28 0 : static RegType regTypeFromFpOrVecTypeId(TypeId typeId) noexcept {
29 0 : if (typeId == TypeId::kFloat32)
30 : return RegType::kARM_VecS;
31 0 : else if (typeId == TypeId::kFloat64)
32 : return RegType::kARM_VecD;
33 : else if (TypeUtils::isVec32(typeId))
34 : return RegType::kARM_VecS;
35 : else if (TypeUtils::isVec64(typeId))
36 : return RegType::kARM_VecD;
37 : else if (TypeUtils::isVec128(typeId))
38 0 : return RegType::kARM_VecV;
39 : else
40 : return RegType::kNone;
41 : }
42 :
43 0 : ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept {
44 : cc.setArch(environment.arch());
45 :
46 : cc.setSaveRestoreRegSize(RegGroup::kGp, 8);
47 : cc.setSaveRestoreRegSize(RegGroup::kVec, 8);
48 : cc.setSaveRestoreAlignment(RegGroup::kGp, 16);
49 : cc.setSaveRestoreAlignment(RegGroup::kVec, 16);
50 : cc.setSaveRestoreAlignment(RegGroup::kExtraVirt2, 1);
51 : cc.setSaveRestoreAlignment(RegGroup::kExtraVirt3, 1);
52 : cc.setPassedOrder(RegGroup::kGp, 0, 1, 2, 3, 4, 5, 6, 7);
53 : cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7);
54 : cc.setNaturalStackAlignment(16);
55 :
56 0 : if (shouldThreatAsCDecl(ccId)) {
57 : // ARM doesn't have that many calling conventions as we can find in X86 world, treat most conventions as __cdecl.
58 : cc.setId(CallConvId::kCDecl);
59 : cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(Gp::kIdOs, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30));
60 : cc.setPreservedRegs(RegGroup::kVec, Support::bitMask(8, 9, 10, 11, 12, 13, 14, 15));
61 : }
62 : else {
63 : cc.setId(ccId);
64 : cc.setSaveRestoreRegSize(RegGroup::kVec, 16);
65 : cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30));
66 : cc.setPreservedRegs(RegGroup::kVec, Support::bitMask(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31));
67 : }
68 :
69 0 : return kErrorOk;
70 : }
71 :
72 0 : ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept {
73 : DebugUtils::unused(signature);
74 :
75 : const CallConv& cc = func.callConv();
76 : uint32_t stackOffset = 0;
77 :
78 : uint32_t i;
79 : uint32_t argCount = func.argCount();
80 :
81 0 : if (func.hasRet()) {
82 0 : for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) {
83 0 : TypeId typeId = func._rets[valueIndex].typeId();
84 :
85 : // Terminate at the first void type (end of the pack).
86 0 : if (typeId == TypeId::kVoid)
87 : break;
88 :
89 0 : switch (typeId) {
90 0 : case TypeId::kInt8:
91 : case TypeId::kInt16:
92 : case TypeId::kInt32: {
93 : func._rets[valueIndex].initReg(RegType::kARM_GpW, valueIndex, TypeId::kInt32);
94 : break;
95 : }
96 :
97 0 : case TypeId::kUInt8:
98 : case TypeId::kUInt16:
99 : case TypeId::kUInt32: {
100 : func._rets[valueIndex].initReg(RegType::kARM_GpW, valueIndex, TypeId::kUInt32);
101 : break;
102 : }
103 :
104 0 : case TypeId::kInt64:
105 : case TypeId::kUInt64: {
106 : func._rets[valueIndex].initReg(RegType::kARM_GpX, valueIndex, typeId);
107 : break;
108 : }
109 :
110 0 : default: {
111 0 : RegType regType = regTypeFromFpOrVecTypeId(typeId);
112 0 : if (regType == RegType::kNone)
113 : return DebugUtils::errored(kErrorInvalidRegType);
114 :
115 0 : func._rets[valueIndex].initReg(regType, valueIndex, typeId);
116 0 : break;
117 : }
118 : }
119 : }
120 : }
121 :
122 0 : switch (cc.strategy()) {
123 : case CallConvStrategy::kDefault: {
124 : uint32_t gpzPos = 0;
125 : uint32_t vecPos = 0;
126 :
127 0 : for (i = 0; i < argCount; i++) {
128 : FuncValue& arg = func._args[i][0];
129 : TypeId typeId = arg.typeId();
130 :
131 0 : if (TypeUtils::isInt(typeId)) {
132 : uint32_t regId = BaseReg::kIdBad;
133 :
134 0 : if (gpzPos < CallConv::kMaxRegArgsPerGroup)
135 0 : regId = cc._passedOrder[RegGroup::kGp].id[gpzPos];
136 :
137 0 : if (regId != BaseReg::kIdBad) {
138 0 : RegType regType = typeId <= TypeId::kUInt32 ? RegType::kARM_GpW : RegType::kARM_GpX;
139 0 : arg.assignRegData(regType, regId);
140 : func.addUsedRegs(RegGroup::kGp, Support::bitMask(regId));
141 0 : gpzPos++;
142 : }
143 : else {
144 : uint32_t size = Support::max<uint32_t>(TypeUtils::sizeOf(typeId), registerSize);
145 0 : arg.assignStackOffset(int32_t(stackOffset));
146 0 : stackOffset += size;
147 : }
148 : continue;
149 0 : }
150 :
151 0 : if (TypeUtils::isFloat(typeId) || TypeUtils::isVec(typeId)) {
152 : uint32_t regId = BaseReg::kIdBad;
153 :
154 0 : if (vecPos < CallConv::kMaxRegArgsPerGroup)
155 0 : regId = cc._passedOrder[RegGroup::kVec].id[vecPos];
156 :
157 0 : if (regId != BaseReg::kIdBad) {
158 0 : RegType regType = regTypeFromFpOrVecTypeId(typeId);
159 0 : if (regType == RegType::kNone)
160 : return DebugUtils::errored(kErrorInvalidRegType);
161 :
162 : arg.initTypeId(typeId);
163 0 : arg.assignRegData(regType, regId);
164 : func.addUsedRegs(RegGroup::kVec, Support::bitMask(regId));
165 0 : vecPos++;
166 : }
167 : else {
168 : uint32_t size = TypeUtils::sizeOf(typeId);
169 0 : arg.assignStackOffset(int32_t(stackOffset));
170 0 : stackOffset += size;
171 : }
172 : continue;
173 0 : }
174 : }
175 : break;
176 : }
177 :
178 : default:
179 : return DebugUtils::errored(kErrorInvalidState);
180 : }
181 :
182 0 : func._argStackSize = stackOffset;
183 0 : return kErrorOk;
184 : }
185 :
186 : } // {FuncInternal}
187 :
188 : ASMJIT_END_SUB_NAMESPACE
189 :
190 : #endif // !ASMJIT_NO_AARCH64
191 :
192 : #endif // __PLUMED_HAS_ASMJIT
|