1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H
17 #define ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H
18
19 #include "ecmascript/compiler/circuit_builder.h"
20 #include "ecmascript/compiler/circuit_builder_helper.h"
21 #include "ecmascript/compiler/share_gate_meta_data.h"
22
23 namespace panda::ecmascript::kungfu {
24
Int8Equal(GateRef x,GateRef y)25 GateRef CircuitBuilder::Int8Equal(GateRef x, GateRef y)
26 {
27 return Equal(x, y);
28 }
29
Int32NotEqual(GateRef x,GateRef y)30 GateRef CircuitBuilder::Int32NotEqual(GateRef x, GateRef y)
31 {
32 return NotEqual(x, y);
33 }
34
Int64NotEqual(GateRef x,GateRef y)35 GateRef CircuitBuilder::Int64NotEqual(GateRef x, GateRef y)
36 {
37 return NotEqual(x, y);
38 }
39
Int64Equal(GateRef x,GateRef y)40 GateRef CircuitBuilder::Int64Equal(GateRef x, GateRef y)
41 {
42 return Equal(x, y);
43 }
44
Int32Equal(GateRef x,GateRef y)45 GateRef CircuitBuilder::Int32Equal(GateRef x, GateRef y)
46 {
47 return Equal(x, y);
48 }
49
IntPtrLessThan(GateRef x,GateRef y)50 GateRef CircuitBuilder::IntPtrLessThan(GateRef x, GateRef y)
51 {
52 return env_->Is32Bit() ? Int32LessThan(x, y) : Int64LessThan(x, y);
53 }
54
IntPtrLessThanOrEqual(GateRef x,GateRef y)55 GateRef CircuitBuilder::IntPtrLessThanOrEqual(GateRef x, GateRef y)
56 {
57 return env_->Is32Bit() ? Int32LessThanOrEqual(x, y) : Int64LessThanOrEqual(x, y);
58 }
59
IntPtrGreaterThan(GateRef x,GateRef y)60 GateRef CircuitBuilder::IntPtrGreaterThan(GateRef x, GateRef y)
61 {
62 return env_->Is32Bit() ? Int32GreaterThan(x, y) : Int64GreaterThan(x, y);
63 }
64
IntPtrGreaterThanOrEqual(GateRef x,GateRef y)65 GateRef CircuitBuilder::IntPtrGreaterThanOrEqual(GateRef x, GateRef y)
66 {
67 return env_->Is32Bit() ? Int32GreaterThanOrEqual(x, y) : Int64GreaterThanOrEqual(x, y);
68 }
69
IntPtrAnd(GateRef x,GateRef y)70 GateRef CircuitBuilder::IntPtrAnd(GateRef x, GateRef y)
71 {
72 return env_->Is32Bit() ? Int32And(x, y) : Int64And(x, y);
73 }
74
IntPtrNot(GateRef x)75 GateRef CircuitBuilder::IntPtrNot(GateRef x)
76 {
77 return env_->Is32Bit() ? Int32Not(x) : Int64Not(x);
78 }
79
IntPtrEqual(GateRef x,GateRef y)80 GateRef CircuitBuilder::IntPtrEqual(GateRef x, GateRef y)
81 {
82 return env_->Is32Bit() ? Int32Equal(x, y) : Int64Equal(x, y);
83 }
84
IntPtrLSR(GateRef x,GateRef y)85 GateRef CircuitBuilder::IntPtrLSR(GateRef x, GateRef y)
86 {
87 auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
88 return BinaryArithmetic(circuit_->Lsr(), ptrSize, x, y);
89 }
90
IntPtrLSL(GateRef x,GateRef y)91 GateRef CircuitBuilder::IntPtrLSL(GateRef x, GateRef y)
92 {
93 auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
94 return BinaryArithmetic(circuit_->Lsl(), ptrSize, x, y);
95 }
96
Int16ToBigEndianInt16(GateRef x)97 GateRef CircuitBuilder::Int16ToBigEndianInt16(GateRef x)
98 {
99 GateRef int16toint32 = ZExtInt16ToInt32(x);
100 GateRef high8bits = Int32LSL(Int32And(int16toint32, Int32(0x00FF)), Int32(8));
101 GateRef low8bits = Int32LSR(Int32And(int16toint32, Int32(0xFF00)), Int32(8));
102 return TruncInt32ToInt16(Int32Add(high8bits, low8bits));
103 }
104
Int32ToBigEndianInt32(GateRef x)105 GateRef CircuitBuilder::Int32ToBigEndianInt32(GateRef x)
106 {
107 GateRef first8bits = Int32LSL(Int32And(x, Int32(0x000000FF)), Int32(24));
108 GateRef second8bits = Int32LSL(Int32And(x, Int32(0x0000FF00)), Int32(8));
109 GateRef third8bits = Int32LSR(Int32And(x, Int32(0x00FF0000)), Int32(8));
110 GateRef fourth8bits = Int32LSR(Int32And(x, Int32(0xFF000000)), Int32(24));
111 GateRef firstHalf = Int32Add(first8bits, second8bits);
112 GateRef secondHalf = Int32Add(third8bits, fourth8bits);
113 return Int32Add(firstHalf, secondHalf);
114 }
115
Int64ToBigEndianInt64(GateRef x)116 GateRef CircuitBuilder::Int64ToBigEndianInt64(GateRef x)
117 {
118 GateRef first8bits = Int64LSL(Int64And(x, Int64(0x00000000000000FF)), Int64(56));
119 GateRef second8bits = Int64LSL(Int64And(x, Int64(0x000000000000FF00)), Int64(40));
120 // 0-16bits
121 GateRef first16bits = Int64Add(first8bits, second8bits);
122 GateRef third8bits = Int64LSL(Int64And(x, Int64(0x0000000000FF0000)), Int64(24));
123 GateRef fourth8bits = Int64LSL(Int64And(x, Int64(0x00000000FF000000)), Int64(8));
124 // 16-32bits
125 GateRef second16bits = Int64Add(third8bits, fourth8bits);
126 // 0-32bits
127 GateRef firstHalf = Int64Add(first16bits, second16bits);
128 GateRef fifth8bits = Int64LSR(Int64And(x, Int64(0x000000FF00000000)), Int64(8));
129 GateRef sixth8bits = Int64LSR(Int64And(x, Int64(0x0000FF0000000000)), Int64(24));
130 //32-48bits
131 GateRef third16bits = Int64Add(fifth8bits, sixth8bits);
132 GateRef seventh8bits = Int64LSR(Int64And(x, Int64(0x00FF000000000000)), Int64(40));
133 GateRef eighth8bits = Int64LSR(Int64And(x, Int64(0xFF00000000000000)), Int64(56));
134 //48-64bits
135 GateRef fourth16bits = Int64Add(seventh8bits, eighth8bits);
136 //32-64bits
137 GateRef secondHalf = Int64Add(third16bits, fourth16bits);
138 //0-64bits
139 return Int64Add(firstHalf, secondHalf);
140 }
141
IntPtrOr(GateRef x,GateRef y)142 GateRef CircuitBuilder::IntPtrOr(GateRef x, GateRef y)
143 {
144 auto ptrsize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
145 return BinaryArithmetic(circuit_->Or(), ptrsize, x, y);
146 }
147
IntPtrAdd(GateRef x,GateRef y)148 GateRef CircuitBuilder::IntPtrAdd(GateRef x, GateRef y)
149 {
150 return env_->Is32Bit() ? Int32Add(x, y) : Int64Add(x, y);
151 }
152
IntPtrSub(GateRef x,GateRef y)153 GateRef CircuitBuilder::IntPtrSub(GateRef x, GateRef y)
154 {
155 return env_->Is32Bit() ? Int32Sub(x, y) : Int64Sub(x, y);
156 }
157
IntPtrMul(GateRef x,GateRef y)158 GateRef CircuitBuilder::IntPtrMul(GateRef x, GateRef y)
159 {
160 return env_->Is32Bit() ? Int32Mul(x, y) : Int64Mul(x, y);
161 }
162
IntPtrDiv(GateRef x,GateRef y)163 GateRef CircuitBuilder::IntPtrDiv(GateRef x, GateRef y)
164 {
165 return env_->Is32Bit() ? Int32Div(x, y) : Int64Div(x, y);
166 }
167
GetInt64OfTInt(GateRef x)168 GateRef CircuitBuilder::GetInt64OfTInt(GateRef x)
169 {
170 GateRef tagged = ChangeTaggedPointerToInt64(x);
171 return Int64And(tagged, Int64(~JSTaggedValue::TAG_MARK));
172 }
173
GetInt32OfTInt(GateRef x)174 GateRef CircuitBuilder::GetInt32OfTInt(GateRef x)
175 {
176 GateRef tagged = ChangeTaggedPointerToInt64(x);
177 return TruncInt64ToInt32(tagged);
178 }
179
GetInt32OfTNumber(GateRef x)180 GateRef CircuitBuilder::GetInt32OfTNumber(GateRef x)
181 {
182 Label subentry(env_);
183 SubCfgEntry(&subentry);
184 Label isInt(env_);
185 Label isDouble(env_);
186 Label exit(env_);
187 DEFVALUE(result, env_, VariableType::INT32(), Int32(0));
188 BRANCH(TaggedIsInt(x), &isInt, &isDouble);
189 Bind(&isInt);
190 {
191 result = GetInt32OfTInt(x);
192 Jump(&exit);
193 }
194 Bind(&isDouble);
195 {
196 result = DoubleCheckINFInRangeInt32(GetDoubleOfTDouble(x));
197 Jump(&exit);
198 }
199 Bind(&exit);
200 GateRef ret = *result;
201 SubCfgExit();
202 return ret;
203 }
204
TaggedCastToIntPtr(GateRef x)205 GateRef CircuitBuilder::TaggedCastToIntPtr(GateRef x)
206 {
207 return env_->Is32Bit() ? GetInt32OfTInt(x) : GetInt64OfTInt(x);
208 }
209
GetDoubleOfTInt(GateRef x)210 GateRef CircuitBuilder::GetDoubleOfTInt(GateRef x)
211 {
212 return ChangeInt32ToFloat64(GetInt32OfTInt(x));
213 }
214
GetDoubleOfTDouble(GateRef x)215 GateRef CircuitBuilder::GetDoubleOfTDouble(GateRef x)
216 {
217 GateRef tagged = ChangeTaggedPointerToInt64(x);
218 GateRef val = Int64Sub(tagged, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
219 return CastInt64ToFloat64(val);
220 }
221
GetBooleanOfTBoolean(GateRef x)222 GateRef CircuitBuilder::GetBooleanOfTBoolean(GateRef x)
223 {
224 GateRef tagged = ChangeTaggedPointerToInt64(x);
225 return TruncInt64ToInt1(tagged);
226 }
227
Int32ToTaggedInt(GateRef x)228 GateRef CircuitBuilder::Int32ToTaggedInt(GateRef x)
229 {
230 GateRef val = SExtInt32ToInt64(x);
231 return Int64Or(val, Int64(JSTaggedValue::TAG_INT));
232 }
233
Int32ToTaggedPtr(GateRef x)234 GateRef CircuitBuilder::Int32ToTaggedPtr(GateRef x)
235 {
236 GateRef val = SExtInt32ToInt64(x);
237 return Int64ToTaggedPtr(Int64Or(val, Int64(JSTaggedValue::TAG_INT)));
238 }
239
Int64ToTaggedPtr(GateRef x)240 GateRef CircuitBuilder::Int64ToTaggedPtr(GateRef x)
241 {
242 return GetCircuit()->NewGate(circuit_->Int64ToTagged(),
243 MachineType::I64, { x }, GateType::TaggedValue());
244 }
245
ToTaggedInt(GateRef x)246 GateRef CircuitBuilder::ToTaggedInt(GateRef x)
247 {
248 return Int64Or(x, Int64(JSTaggedValue::TAG_INT));
249 }
250
ToTaggedIntPtr(GateRef x)251 GateRef CircuitBuilder::ToTaggedIntPtr(GateRef x)
252 {
253 return Int64ToTaggedPtr(Int64Or(x, Int64(JSTaggedValue::TAG_INT)));
254 }
255
DoubleToTaggedDoublePtr(GateRef x)256 GateRef CircuitBuilder::DoubleToTaggedDoublePtr(GateRef x)
257 {
258 GateRef val = CastDoubleToInt64(x);
259 return Int64ToTaggedPtr(Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET)));
260 }
261
DoubleIsImpureNaN(GateRef x)262 GateRef CircuitBuilder::DoubleIsImpureNaN(GateRef x)
263 {
264 GateRef impureNaN = Int64(JSTaggedValue::TAG_INT - JSTaggedValue::DOUBLE_ENCODE_OFFSET);
265 GateRef val = CastDoubleToInt64(x);
266 return Int64UnsignedGreaterThanOrEqual(val, impureNaN);
267 }
268
BooleanToTaggedBooleanPtr(GateRef x)269 GateRef CircuitBuilder::BooleanToTaggedBooleanPtr(GateRef x)
270 {
271 auto val = ZExtInt1ToInt64(x);
272 return Int64ToTaggedPtr(Int64Or(val, Int64(JSTaggedValue::TAG_BOOLEAN_MASK)));
273 }
274
BooleanToInt32(GateRef x)275 GateRef CircuitBuilder::BooleanToInt32(GateRef x)
276 {
277 return ZExtInt1ToInt32(x);
278 }
279
BooleanToFloat64(GateRef x)280 GateRef CircuitBuilder::BooleanToFloat64(GateRef x)
281 {
282 return ChangeInt32ToFloat64(ZExtInt1ToInt32(x));
283 }
284
Float32ToTaggedDoublePtr(GateRef x)285 GateRef CircuitBuilder::Float32ToTaggedDoublePtr(GateRef x)
286 {
287 GateRef val = ExtFloat32ToDouble(x);
288 return DoubleToTaggedDoublePtr(val);
289 }
290
TaggedDoublePtrToFloat32(GateRef x)291 GateRef CircuitBuilder::TaggedDoublePtrToFloat32(GateRef x)
292 {
293 GateRef val = GetDoubleOfTDouble(x);
294 return TruncDoubleToFloat32(val);
295 }
296
TaggedIntPtrToFloat32(GateRef x)297 GateRef CircuitBuilder::TaggedIntPtrToFloat32(GateRef x)
298 {
299 GateRef val = GetInt32OfTInt(x);
300 return ChangeInt32ToFloat32(val);
301 }
302
DoubleToTaggedDouble(GateRef x)303 GateRef CircuitBuilder::DoubleToTaggedDouble(GateRef x)
304 {
305 GateRef val = CastDoubleToInt64(x);
306 return Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
307 }
308
DoubleIsNAN(GateRef x)309 GateRef CircuitBuilder::DoubleIsNAN(GateRef x)
310 {
311 GateRef diff = DoubleEqual(x, x);
312 return Equal(SExtInt1ToInt32(diff), Int32(0));
313 }
314
DoubleToTagged(GateRef x)315 GateRef CircuitBuilder::DoubleToTagged(GateRef x)
316 {
317 GateRef val = CastDoubleToInt64(x);
318 acc_.SetGateType(val, GateType::TaggedValue());
319 return Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
320 }
321
322 template<OpCode Op, MachineType Type>
BinaryOp(GateRef x,GateRef y)323 GateRef CircuitBuilder::BinaryOp(GateRef x, GateRef y)
324 {
325 if (Op == OpCode::ADD) {
326 return BinaryArithmetic(circuit_->Add(), Type, x, y);
327 } else if (Op == OpCode::SUB) {
328 return BinaryArithmetic(circuit_->Sub(), Type, x, y);
329 } else if (Op == OpCode::MUL) {
330 return BinaryArithmetic(circuit_->Mul(), Type, x, y);
331 }
332 UNREACHABLE();
333 return Circuit::NullGate();
334 }
335
336 template<OpCode Op, MachineType Type>
BinaryOpWithOverflow(GateRef x,GateRef y)337 GateRef CircuitBuilder::BinaryOpWithOverflow(GateRef x, GateRef y)
338 {
339 if (Op == OpCode::ADD) {
340 return BinaryArithmetic(circuit_->AddWithOverflow(), Type, x, y);
341 } else if (Op == OpCode::SUB) {
342 return BinaryArithmetic(circuit_->SubWithOverflow(), Type, x, y);
343 } else if (Op == OpCode::MUL) {
344 return BinaryArithmetic(circuit_->MulWithOverflow(), Type, x, y);
345 }
346 UNREACHABLE();
347 return Circuit::NullGate();
348 }
349
Equal(GateRef x,GateRef y,const char * comment)350 GateRef CircuitBuilder::Equal(GateRef x, GateRef y, const char* comment)
351 {
352 auto xType = acc_.GetMachineType(x);
353 switch (xType) {
354 case ARCH:
355 case FLEX:
356 case I1:
357 case I8:
358 case I16:
359 case I32:
360 case I64:
361 return BinaryCmp(circuit_->Icmp(static_cast<uint64_t>(ICmpCondition::EQ)), x, y, comment);
362 case F32:
363 case F64:
364 return BinaryCmp(circuit_->Fcmp(static_cast<uint64_t>(FCmpCondition::OEQ)), x, y, comment);
365 default:
366 LOG_ECMA(FATAL) << "this branch is unreachable";
367 UNREACHABLE();
368 }
369 }
370
NotEqual(GateRef x,GateRef y,const char * comment)371 GateRef CircuitBuilder::NotEqual(GateRef x, GateRef y, const char* comment)
372 {
373 auto xType = acc_.GetMachineType(x);
374 switch (xType) {
375 case ARCH:
376 case FLEX:
377 case I1:
378 case I8:
379 case I16:
380 case I32:
381 case I64:
382 return BinaryCmp(circuit_->Icmp(static_cast<uint64_t>(ICmpCondition::NE)), x, y, comment);
383 case F32:
384 case F64:
385 return BinaryCmp(circuit_->Fcmp(static_cast<uint64_t>(FCmpCondition::ONE)), x, y, comment);
386 default:
387 LOG_ECMA(FATAL) << "this branch is unreachable";
388 UNREACHABLE();
389 }
390 }
391
392 }
393
394 #endif // ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H
395