• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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