• 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 #include "ecmascript/compiler/lcr_circuit_builder.h"
17 
18 #include "ecmascript/compiler/circuit_builder-inl.h"
19 #include "ecmascript/compiler/rt_call_signature.h"
20 #include "ecmascript/compiler/circuit_builder_helper.h"
21 
22 namespace panda::ecmascript::kungfu {
23 
BinaryCmp(const GateMetaData * meta,GateRef left,GateRef right,const char * comment)24 GateRef CircuitBuilder::BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right, const char* comment)
25 {
26     return GetCircuit()->NewGate(meta, MachineType::I1, { left, right }, GateType::NJSValue(), comment);
27 }
28 
GetMachineTypeFromVariableType(VariableType type)29 MachineType CircuitBuilder::GetMachineTypeFromVariableType(VariableType type)
30 {
31     return type.GetMachineType();
32 }
33 
Sqrt(GateRef param)34 GateRef CircuitBuilder::Sqrt(GateRef param)
35 {
36     return GetCircuit()->NewGate(circuit_->Sqrt(), MachineType::F64, {param}, GateType::DoubleType());
37 }
38 
AddWithOverflow(GateRef left,GateRef right)39 GateRef CircuitBuilder::AddWithOverflow(GateRef left, GateRef right)
40 {
41     return GetCircuit()->NewGate(circuit_->AddWithOverflow(), MachineType::I64, {left, right}, GateType::AnyType());
42 }
43 
SubWithOverflow(GateRef left,GateRef right)44 GateRef CircuitBuilder::SubWithOverflow(GateRef left, GateRef right)
45 {
46     return GetCircuit()->NewGate(circuit_->SubWithOverflow(), MachineType::I64, {left, right}, GateType::AnyType());
47 }
48 
MulWithOverflow(GateRef left,GateRef right)49 GateRef CircuitBuilder::MulWithOverflow(GateRef left, GateRef right)
50 {
51     return GetCircuit()->NewGate(circuit_->MulWithOverflow(), MachineType::I64, {left, right}, GateType::AnyType());
52 }
53 
ExtractValue(MachineType mt,GateRef pointer,GateRef index)54 GateRef CircuitBuilder::ExtractValue(MachineType mt, GateRef pointer, GateRef index)
55 {
56     ASSERT(acc_.GetOpCode(index) == OpCode::CONSTANT);
57     ASSERT(acc_.GetMachineType(index) == MachineType::I32);
58     return GetCircuit()->NewGate(circuit_->ExtractValue(), mt, {pointer, index}, GateType::NJSValue());
59 }
60 
ReadSp()61 GateRef CircuitBuilder::ReadSp()
62 {
63     return circuit_->NewGate(circuit_->ReadSp(), MachineType::I64, GateType::NJSValue());
64 }
65 
GetMachineTypeOfValueType(ValueType type)66 MachineType CircuitBuilder::GetMachineTypeOfValueType(ValueType type)
67 {
68     switch (type) {
69         case ValueType::BOOL:
70             return MachineType::I1;
71         case ValueType::INT32:
72         case ValueType::UINT32:
73             return MachineType::I32;
74         case ValueType::FLOAT64:
75             return MachineType::F64;
76         case ValueType::TAGGED_BOOLEAN:
77         case ValueType::TAGGED_INT:
78         case ValueType::TAGGED_DOUBLE:
79         case ValueType::TAGGED_NUMBER:
80         case ValueType::TAGGED_NULL:
81         case ValueType::CHAR:
82         case ValueType::ECMA_STRING:
83         case ValueType::UNDEFINED:
84         case ValueType::HOLE_INT:
85         case ValueType::HOLE_DOUBLE:
86             return MachineType::I64;
87         default:
88             UNREACHABLE();
89             break;
90     }
91     return MachineType::NOVALUE;
92 }
93 
BinaryArithmetic(const GateMetaData * meta,MachineType machineType,GateRef left,GateRef right,GateType gateType,const char * comment)94 GateRef CircuitBuilder::BinaryArithmetic(const GateMetaData* meta, MachineType machineType,
95                                          GateRef left, GateRef right, GateType gateType, const char* comment)
96 {
97     auto circuit = GetCircuit();
98     if (gateType == GateType::Empty()) {
99         gateType = acc_.GetGateType(left);
100     }
101     return circuit->NewGate(meta, machineType, { left, right }, gateType, comment);
102 }
103 
Alloca(size_t size)104 GateRef CircuitBuilder::Alloca(size_t size)
105 {
106     return GetCircuit()->NewGate(circuit_->Alloca(size), MachineType::ARCH, GateType::NJSValue());
107 }
108 
109 // memory
Store(VariableType type,GateRef glue,GateRef base,GateRef offset,GateRef value,MemoryAttribute mAttr)110 void CircuitBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value,
111                            MemoryAttribute mAttr)
112 {
113     auto label = GetCurrentLabel();
114     auto depend = label->GetDepend();
115     auto bit = LoadStoreAccessor::ToValue(mAttr);
116     GateRef result = GetCircuit()->NewGate(circuit_->Store(bit),
117         MachineType::NOVALUE, { depend, glue, base, offset, value }, type.GetGateType());
118     label->SetDepend(result);
119 }
120 
StoreWithoutBarrier(VariableType type,GateRef addr,GateRef value,MemoryAttribute mAttr)121 void CircuitBuilder::StoreWithoutBarrier(VariableType type, GateRef addr, GateRef value, MemoryAttribute mAttr)
122 {
123     auto label = GetCurrentLabel();
124     auto depend = label->GetDepend();
125     auto bit = LoadStoreAccessor::ToValue(mAttr);
126     GateRef result = GetCircuit()->NewGate(circuit_->StoreWithoutBarrier(bit),
127         MachineType::NOVALUE, { depend, addr, value }, type.GetGateType());
128     label->SetDepend(result);
129 }
130 
131 // memory
Load(VariableType type,GateRef base,GateRef offset,MemoryAttribute mAttr)132 GateRef CircuitBuilder::Load(VariableType type, GateRef base, GateRef offset, MemoryAttribute mAttr)
133 {
134     auto label = GetCurrentLabel();
135     auto depend = label->GetDepend();
136     GateRef val = PtrAdd(base, offset);
137     auto bits = LoadStoreAccessor::ToValue(mAttr);
138     GateRef result = GetCircuit()->NewGate(GetCircuit()->Load(bits), type.GetMachineType(),
139                                            { depend, val }, type.GetGateType());
140     label->SetDepend(result);
141     return result;
142 }
143 
Load(VariableType type,GateRef base,GateRef offset,GateRef depend,MemoryAttribute mAttr)144 GateRef CircuitBuilder::Load(VariableType type, GateRef base, GateRef offset, GateRef depend,
145                              MemoryAttribute mAttr)
146 {
147     GateRef val = PtrAdd(base, offset);
148     auto bits = LoadStoreAccessor::ToValue(mAttr);
149     GateRef result = GetCircuit()->NewGate(GetCircuit()->Load(bits), type.GetMachineType(),
150                                            { depend, val }, type.GetGateType());
151     return result;
152 }
153 
Load(VariableType type,GateRef addr,MemoryAttribute mAttr)154 GateRef CircuitBuilder::Load(VariableType type, GateRef addr, MemoryAttribute mAttr)
155 {
156     auto label = GetCurrentLabel();
157     auto depend = label->GetDepend();
158     auto bits = LoadStoreAccessor::ToValue(mAttr);
159     GateRef result = GetCircuit()->NewGate(GetCircuit()->Load(bits), type.GetMachineType(),
160                                            { depend, addr }, type.GetGateType());
161     label->SetDepend(result);
162     return result;
163 }
164 
DoubleTrunc(GateRef gate,GateRef value,const char * comment)165 GateRef CircuitBuilder::DoubleTrunc(GateRef gate, GateRef value, const char* comment)
166 {
167     if (GetCompilationConfig()->IsAArch64()) {
168         return DoubleTrunc(value, comment);
169     }
170 
171     GateRef glue = acc_.GetGlueFromArgList();
172     return CallNGCRuntime(glue, RTSTUB_ID(FloatTrunc), Gate::InvalidGateRef, {value}, gate, comment);
173 }
174 
GetDoubleOfTNumber(GateRef x)175 GateRef CircuitBuilder::GetDoubleOfTNumber(GateRef x)
176 {
177     Label subentry(env_);
178     SubCfgEntry(&subentry);
179     Label isInt(env_);
180     Label isDouble(env_);
181     Label exit(env_);
182     DEFVALUE(result, env_, VariableType::FLOAT64(), Double(0));
183     BRANCH_CIR2(TaggedIsInt(x), &isInt, &isDouble);
184     Bind(&isInt);
185     {
186         result = ChangeInt32ToFloat64(GetInt32OfTInt(x));
187         Jump(&exit);
188     }
189     Bind(&isDouble);
190     {
191         result = GetDoubleOfTDouble(x);
192         Jump(&exit);
193     }
194     Bind(&exit);
195     GateRef ret = *result;
196     SubCfgExit();
197     return ret;
198 }
199 
DoubleToInt(GateRef x,Label * exit)200 GateRef CircuitBuilder::DoubleToInt(GateRef x, Label *exit)
201 {
202     Label overflow(env_);
203 
204     GateRef xInt = ChangeFloat64ToInt32(x);
205     DEFVALUE(result, env_, VariableType::INT32(), xInt);
206 
207     GateRef xInt64 = CastDoubleToInt64(x);
208     // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
209     GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
210     exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
211     exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
212     GateRef bits = Int32(base::INT32_BITS - 1);
213     // exp < 32 - 1
214     BRANCH_CIR2(Int32LessThan(exp, bits), exit, &overflow);
215 
216     Bind(&overflow);
217     {
218         result = CallNGCRuntime(acc_.GetGlueFromArgList(), RTSTUB_ID(DoubleToInt),
219                                 Circuit::NullGate(), { x, IntPtr(base::INT32_BITS) }, Circuit::NullGate());
220         Jump(exit);
221     }
222     Bind(exit);
223     auto ret = *result;
224     return ret;
225 }
226 
DoubleToInt(GateRef glue,GateRef x,size_t typeBits)227 GateRef CircuitBuilder::DoubleToInt(GateRef glue, GateRef x, size_t typeBits)
228 {
229     Label entry(env_);
230     env_->SubCfgEntry(&entry);
231     Label exit(env_);
232     Label overflow(env_);
233 
234     GateRef xInt = ChangeFloat64ToInt32(x);
235     DEFVALUE(result, env_, VariableType::INT32(), xInt);
236 
237     if (env_->IsAmd64()) {
238         // 0x80000000: amd64 overflow return value
239         BRANCH_CIR2(Int32Equal(xInt, Int32(0x80000000)), &overflow, &exit);
240     } else {
241         GateRef xInt64 = CastDoubleToInt64(x);
242         // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
243         GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
244         exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
245         exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
246         GateRef bits = Int32(typeBits - 1);
247         // exp < 32 - 1
248         BRANCH_CIR2(Int32LessThan(exp, bits), &exit, &overflow);
249     }
250     Bind(&overflow);
251     {
252         result = CallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), Circuit::NullGate(), { x, IntPtr(typeBits) },
253                                 Circuit::NullGate());
254         Jump(&exit);
255     }
256     Bind(&exit);
257     auto ret = *result;
258     env_->SubCfgExit();
259     return ret;
260 }
261 
DoubleCheckINFInRangeInt32(GateRef x)262 GateRef CircuitBuilder::DoubleCheckINFInRangeInt32(GateRef x)
263 {
264     Label entry(env_);
265     env_->SubCfgEntry(&entry);
266     Label exit(env_);
267     Label isInfinity(env_);
268     Label positiveInf(env_);
269     Label negativeInf(env_);
270 
271     DEFVALUE(result, env_, VariableType::INT32(), DoubleInRangeInt32(x));
272     GateRef Max = Double(INT32_MAX);
273     GateRef Min = Double(INT32_MIN);
274     GateRef pInfinity = Double(base::POSITIVE_INFINITY);
275     Branch(DoubleIsINF(x), &isInfinity, &exit);
276     Bind(&isInfinity);
277     {
278         Branch(DoubleEqual(x, pInfinity), &positiveInf, &negativeInf);
279         Bind(&positiveInf);
280         {
281             result = ChangeFloat64ToInt32(Max);
282             Jump(&exit);
283         }
284         Bind(&negativeInf);
285         {
286             result = ChangeFloat64ToInt32(Min);
287             Jump(&exit);
288         }
289     }
290     Bind(&exit);
291     auto ret = *result;
292     env_->SubCfgExit();
293     return ret;
294 }
295 
DoubleInRangeInt32(GateRef x)296 GateRef CircuitBuilder::DoubleInRangeInt32(GateRef x)
297 {
298     Label entry(env_);
299     env_->SubCfgEntry(&entry);
300     Label exit(env_);
301     Label overflow(env_);
302     Label checkUnderflow(env_);
303     Label underflow(env_);
304 
305     DEFVALUE(result, env_, VariableType::INT32(), ChangeFloat64ToInt32(x));
306     GateRef Max = Double(INT32_MAX);
307     GateRef Min = Double(INT32_MIN);
308     Branch(DoubleGreaterThan(x, Max), &overflow, &checkUnderflow);
309     Bind(&overflow);
310     {
311         result = ChangeFloat64ToInt32(Max);
312         Jump(&exit);
313     }
314     Bind(&checkUnderflow);
315     {
316         Branch(DoubleLessThan(x, Min), &underflow, &exit);
317         Bind(&underflow);
318         {
319             result = ChangeFloat64ToInt32(Min);
320             Jump(&exit);
321         }
322     }
323     Bind(&exit);
324     auto ret = *result;
325     env_->SubCfgExit();
326     return ret;
327 }
328 }
329