1 /* 2 * Copyright (c) 2021 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_CIRCUIT_BUILDER_H 17 #define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H 18 19 #include "ecmascript/base/number_helper.h" 20 #include "ecmascript/compiler/builtins/builtins_call_signature.h" 21 #include "ecmascript/compiler/circuit.h" 22 #include "ecmascript/compiler/call_signature.h" 23 #include "ecmascript/compiler/gate.h" 24 #include "ecmascript/compiler/gate_accessor.h" 25 #include "ecmascript/compiler/variable_type.h" 26 #include "ecmascript/global_env_constants.h" 27 #include "ecmascript/jspandafile/constpool_value.h" 28 #include "ecmascript/js_hclass.h" 29 #include "ecmascript/js_tagged_value.h" 30 #include "ecmascript/platform/elf.h" 31 #include "ecmascript/tagged_array.h" 32 33 namespace panda::ecmascript::kungfu { 34 using namespace panda::ecmascript; 35 #define DEFVAlUE(varname, cirBuilder, type, val) \ 36 Variable varname(cirBuilder, type, cirBuilder->NextVariableId(), val) 37 38 class Environment; 39 class Label; 40 class Variable; 41 42 #define BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V) \ 43 V(Int16Add, Add, MachineType::I16) \ 44 V(Int32Add, Add, MachineType::I32) \ 45 V(Int64Add, Add, MachineType::I64) \ 46 V(DoubleAdd, Add, MachineType::F64) \ 47 V(PtrAdd, Add, MachineType::ARCH) \ 48 V(Int16Sub, Sub, MachineType::I16) \ 49 V(Int32Sub, Sub, MachineType::I32) \ 50 V(Int64Sub, Sub, MachineType::I64) \ 51 V(DoubleSub, Sub, MachineType::F64) \ 52 V(PtrSub, Sub, MachineType::ARCH) \ 53 V(Int32Mul, Mul, MachineType::I32) \ 54 V(Int64Mul, Mul, MachineType::I64) \ 55 V(DoubleMul, Mul, MachineType::F64) \ 56 V(PtrMul, Mul, MachineType::ARCH) \ 57 V(Int32Div, Sdiv, MachineType::I32) \ 58 V(Int64Div, Sdiv, MachineType::I64) \ 59 V(DoubleDiv, Fdiv, MachineType::F64) \ 60 V(Int32Mod, Smod, MachineType::I32) \ 61 V(DoubleMod, Smod, MachineType::F64) \ 62 V(BoolAnd, And, MachineType::I1) \ 63 V(Int8And, And, MachineType::I8) \ 64 V(Int32And, And, MachineType::I32) \ 65 V(Int64And, And, MachineType::I64) \ 66 V(BoolOr, Or, MachineType::I1) \ 67 V(Int32Or, Or, MachineType::I32) \ 68 V(Int64Or, Or, MachineType::I64) \ 69 V(Int32Xor, Xor, MachineType::I32) \ 70 V(Int64Xor, Xor, MachineType::I64) \ 71 V(Int16LSL, Lsl, MachineType::I16) \ 72 V(Int32LSL, Lsl, MachineType::I32) \ 73 V(Int64LSL, Lsl, MachineType::I64) \ 74 V(Int8LSR, Lsr, MachineType::I8) \ 75 V(Int32LSR, Lsr, MachineType::I32) \ 76 V(Int64LSR, Lsr, MachineType::I64) \ 77 V(Int32ASR, Asr, MachineType::I32) 78 79 #define UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V) \ 80 V(BoolNot, Rev, MachineType::I1) \ 81 V(Int32Not, Rev, MachineType::I32) \ 82 V(Int64Not, Rev, MachineType::I64) \ 83 V(CastDoubleToInt64, Bitcast, MachineType::I64) \ 84 V(CastInt64ToFloat64, Bitcast, MachineType::F64) \ 85 V(SExtInt32ToInt64, Sext, MachineType::I64) \ 86 V(SExtInt1ToInt64, Sext, MachineType::I64) \ 87 V(SExtInt1ToInt32, Sext, MachineType::I32) \ 88 V(ZExtInt8ToInt16, Zext, MachineType::I16) \ 89 V(ZExtInt32ToInt64, Zext, MachineType::I64) \ 90 V(ZExtInt1ToInt64, Zext, MachineType::I64) \ 91 V(ZExtInt1ToInt32, Zext, MachineType::I32) \ 92 V(ZExtInt8ToInt32, Zext, MachineType::I32) \ 93 V(ZExtInt8ToInt64, Zext, MachineType::I64) \ 94 V(ZExtInt8ToPtr, Zext, MachineType::ARCH) \ 95 V(ZExtInt16ToPtr, Zext, MachineType::ARCH) \ 96 V(ZExtInt32ToPtr, Zext, MachineType::ARCH) \ 97 V(SExtInt32ToPtr, Sext, MachineType::ARCH) \ 98 V(ZExtInt16ToInt32, Zext, MachineType::I32) \ 99 V(ZExtInt16ToInt64, Zext, MachineType::I64) \ 100 V(TruncInt16ToInt8, Trunc, MachineType::I8) \ 101 V(TruncInt64ToInt32, Trunc, MachineType::I32) \ 102 V(TruncPtrToInt32, Trunc, MachineType::I32) \ 103 V(TruncInt64ToInt1, Trunc, MachineType::I1) \ 104 V(TruncInt64ToInt16, Trunc, MachineType::I16) \ 105 V(TruncInt32ToInt1, Trunc, MachineType::I1) \ 106 V(TruncInt32ToInt16, Trunc, MachineType::I16) \ 107 V(TruncFloatToInt64, TruncFloatToInt64, MachineType::I64) \ 108 V(ExtFloat32ToDouble, Fext, MachineType::F64) \ 109 V(TruncDoubleToFloat32, Ftrunc, MachineType::F32) \ 110 V(ChangeTaggedPointerToInt64, TaggedToInt64, MachineType::I64) \ 111 V(ChangeInt32ToFloat64, SignedIntToFloat, MachineType::F64) \ 112 V(ChangeInt32ToFloat32, SignedIntToFloat, MachineType::F32) \ 113 V(ChangeUInt32ToFloat64, UnsignedIntToFloat, MachineType::F64) \ 114 V(ChangeFloat64ToInt32, FloatToSignedInt, MachineType::I32) \ 115 V(SExtInt16ToInt64, Sext, MachineType::I64) \ 116 V(SExtInt16ToInt32, Sext, MachineType::I32) \ 117 V(SExtInt8ToInt64, Sext, MachineType::I64) \ 118 119 #define BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(V) \ 120 V(DoubleLessThan, Fcmp, static_cast<BitField>(FCmpCondition::OLT)) \ 121 V(DoubleLessThanOrEqual, Fcmp, static_cast<BitField>(FCmpCondition::OLE)) \ 122 V(DoubleGreaterThan, Fcmp, static_cast<BitField>(FCmpCondition::OGT)) \ 123 V(DoubleGreaterThanOrEqual, Fcmp, static_cast<BitField>(FCmpCondition::OGE)) \ 124 V(Int32LessThan, Icmp, static_cast<BitField>(ICmpCondition::SLT)) \ 125 V(Int32LessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SLE)) \ 126 V(Int32GreaterThan, Icmp, static_cast<BitField>(ICmpCondition::SGT)) \ 127 V(Int32GreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SGE)) \ 128 V(Int32UnsignedLessThan, Icmp, static_cast<BitField>(ICmpCondition::ULT)) \ 129 V(Int32UnsignedGreaterThan, Icmp, static_cast<BitField>(ICmpCondition::UGT)) \ 130 V(Int32UnsignedGreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::UGE)) \ 131 V(Int64LessThan, Icmp, static_cast<BitField>(ICmpCondition::SLT)) \ 132 V(Int64LessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SLE)) \ 133 V(Int64GreaterThan, Icmp, static_cast<BitField>(ICmpCondition::SGT)) \ 134 V(Int64GreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SGE)) \ 135 V(Int64UnsignedLessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::ULE)) 136 137 class CompilationConfig { 138 public: 139 explicit CompilationConfig(const std::string &triple, bool enablePGOProfiler = false, bool isTraceBC = false, 140 bool profiling = false) triple_(GetTripleFromString (triple))141 : triple_(GetTripleFromString(triple)), isTraceBc_(isTraceBC), enablePGOProfiler_(enablePGOProfiler), 142 profiling_(profiling) 143 { 144 } 145 ~CompilationConfig() = default; 146 Is32Bit()147 inline bool Is32Bit() const 148 { 149 return triple_ == Triple::TRIPLE_ARM32; 150 } 151 IsAArch64()152 inline bool IsAArch64() const 153 { 154 return triple_ == Triple::TRIPLE_AARCH64; 155 } 156 IsAmd64()157 inline bool IsAmd64() const 158 { 159 return triple_ == Triple::TRIPLE_AMD64; 160 } 161 Is64Bit()162 inline bool Is64Bit() const 163 { 164 return IsAArch64() || IsAmd64(); 165 } 166 GetTriple()167 Triple GetTriple() const 168 { 169 return triple_; 170 } 171 IsTraceBC()172 bool IsTraceBC() const 173 { 174 return isTraceBc_; 175 } 176 IsEnablePGOProfiler()177 bool IsEnablePGOProfiler() const 178 { 179 return enablePGOProfiler_; 180 } 181 IsProfiling()182 bool IsProfiling() const 183 { 184 return profiling_; 185 } 186 187 private: GetTripleFromString(const std::string & triple)188 inline Triple GetTripleFromString(const std::string &triple) 189 { 190 if (triple.compare("x86_64-unknown-linux-gnu") == 0) { 191 return Triple::TRIPLE_AMD64; 192 } 193 194 if (triple.compare("aarch64-unknown-linux-gnu") == 0) { 195 return Triple::TRIPLE_AARCH64; 196 } 197 198 if (triple.compare("arm-unknown-linux-gnu") == 0) { 199 return Triple::TRIPLE_ARM32; 200 } 201 UNREACHABLE(); 202 } 203 Triple triple_; 204 bool isTraceBc_; 205 bool enablePGOProfiler_; 206 bool profiling_; 207 }; 208 209 class CircuitBuilder { 210 public: CircuitBuilder(Circuit * circuit)211 explicit CircuitBuilder(Circuit *circuit) : circuit_(circuit), acc_(circuit) {} CircuitBuilder(Circuit * circuit,CompilationConfig * cmpCfg)212 explicit CircuitBuilder(Circuit *circuit, CompilationConfig *cmpCfg) 213 : circuit_(circuit), acc_(circuit), cmpCfg_(cmpCfg) 214 { 215 } 216 ~CircuitBuilder() = default; 217 NO_MOVE_SEMANTIC(CircuitBuilder); 218 NO_COPY_SEMANTIC(CircuitBuilder); 219 // low level interface 220 template<TypedUnOp Op> 221 inline GateRef Int32OverflowCheck(GateRef gate); 222 GateRef ArrayCheck(GateRef gate); 223 GateRef StableArrayCheck(GateRef gate); 224 GateRef TypedArrayCheck(GateType type, GateRef gate); 225 GateRef IndexCheck(GateType type, GateRef gate, GateRef index); 226 GateRef ObjectTypeCheck(GateType type, GateRef gate, GateRef hclassOffset); 227 GateRef PrimitiveTypeCheck(GateType type, GateRef gate); 228 GateRef CallTargetCheck(GateRef function, GateRef id, GateRef param); 229 GateRef DeoptCheck(GateRef condition, GateRef frameState, DeoptType type = DeoptType::NOTCHECK); 230 GateRef TypedBinaryOperator(MachineType type, TypedBinOp binOp, GateType typeLeft, GateType typeRight, 231 std::vector<GateRef> inList, GateType gateType); 232 GateRef TypedCallOperator(MachineType type, const std::initializer_list<GateRef>& args); 233 inline GateRef TypedCallBuiltin(GateRef x, BuiltinsStubCSigns::ID id); 234 GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList); 235 GateRef TypedUnaryOperator(MachineType type, TypedUnOp unaryOp, GateType typeVal, 236 const std::vector<GateRef>& inList, GateType gateType); 237 GateRef TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState); 238 GateRef TypedSuperAllocateThis(GateRef superCtor, GateRef newTarget, GateRef frameState); 239 GateRef GetSuperConstructor(GateRef ctor); 240 GateRef Arguments(size_t index); 241 GateRef Merge(const std::vector<GateRef> &inList); 242 GateRef Selector(OpCode opcode, MachineType machineType, GateRef control, const std::vector<GateRef> &values, 243 int valueCounts, VariableType type = VariableType::VOID()); 244 GateRef Selector(OpCode opcode, GateRef control, const std::vector<GateRef> &values, 245 int valueCounts, VariableType type = VariableType::VOID()); 246 GateRef Int8(int8_t val); 247 GateRef Int16(int16_t val); 248 GateRef Int32(int32_t value); 249 GateRef Int64(int64_t value); 250 GateRef IntPtr(int64_t val); 251 GateRef Boolean(bool value); 252 GateRef Double(double value); 253 GateRef UndefineConstant(); 254 GateRef HoleConstant(); 255 GateRef NullConstant(); 256 GateRef ExceptionConstant(); 257 GateRef RelocatableData(uint64_t val); 258 GateRef Alloca(size_t size); 259 GateRef Branch(GateRef state, GateRef condition); 260 GateRef SwitchBranch(GateRef state, GateRef index, int caseCounts); 261 GateRef Return(GateRef state, GateRef depend, GateRef value); 262 GateRef ReturnVoid(GateRef state, GateRef depend); 263 GateRef Goto(GateRef state); 264 GateRef LoopBegin(GateRef state); 265 GateRef LoopEnd(GateRef state); 266 GateRef IfTrue(GateRef ifBranch); 267 GateRef IfFalse(GateRef ifBranch); 268 GateRef SwitchCase(GateRef switchBranch, int64_t value); 269 GateRef DefaultCase(GateRef switchBranch); 270 GateRef DependRelay(GateRef state, GateRef depend); 271 GateRef DependAnd(std::initializer_list<GateRef> args); 272 GateRef BinaryArithmetic(const GateMetaData* meta, MachineType machineType, 273 GateRef left, GateRef right); 274 GateRef BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right); 275 static MachineType GetMachineTypeFromVariableType(VariableType type); 276 GateRef GetCallBuiltinId(GateRef method); GetCircuit()277 Circuit *GetCircuit() const 278 { 279 return circuit_; 280 } 281 // constant 282 inline GateRef True(); 283 inline GateRef False(); 284 inline GateRef Undefined(); 285 286 // call operation 287 GateRef CallBCHandler(GateRef glue, GateRef target, const std::vector<GateRef> &args); 288 GateRef CallBCDebugger(GateRef glue, GateRef target, const std::vector<GateRef> &args); 289 GateRef CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args); 290 GateRef CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args); 291 GateRef CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv); 292 GateRef CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args); 293 GateRef CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args); 294 GateRef CallStub(GateRef glue, int index, const std::vector<GateRef> &args); 295 GateRef CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args, bool isNew = false); 296 GateRef Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend, 297 const std::vector<GateRef> &args); 298 299 // memory 300 inline GateRef Load(VariableType type, GateRef base, GateRef offset); 301 void Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value); 302 303 #define ARITHMETIC_BINARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID) \ 304 inline GateRef NAME(GateRef x, GateRef y) \ 305 { \ 306 return BinaryArithmetic(circuit_->OPCODEID(), MACHINETYPEID, x, y); \ 307 } 308 309 BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(ARITHMETIC_BINARY_OP_WITH_BITWIDTH) 310 #undef ARITHMETIC_BINARY_OP_WITH_BITWIDTH 311 312 #define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID) \ 313 inline GateRef NAME(GateRef x) \ 314 { \ 315 return circuit_->NewGate(circuit_->OPCODEID(), MACHINETYPEID, { x }, GateType::NJSValue()); \ 316 } 317 318 UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(ARITHMETIC_UNARY_OP_WITH_BITWIDTH) 319 #undef ARITHMETIC_UNARY_OP_WITH_BITWIDTH 320 321 #define CMP_BINARY_OP_WITHOUT_BITWIDTH(NAME, OPCODEID, CONDITION) \ 322 inline GateRef NAME(GateRef x, GateRef y) \ 323 { \ 324 return BinaryCmp(circuit_->OPCODEID(static_cast<uint64_t>(CONDITION)), x, y); \ 325 } 326 327 BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(CMP_BINARY_OP_WITHOUT_BITWIDTH) 328 #undef CMP_BINARY_OP_WITHOUT_BITWIDTH 329 330 inline GateRef Equal(GateRef x, GateRef y); 331 inline GateRef NotEqual(GateRef x, GateRef y); 332 333 // js world 334 // cast operation 335 inline GateRef GetInt64OfTInt(GateRef x); 336 inline GateRef GetInt32OfTInt(GateRef x); 337 inline GateRef TaggedCastToIntPtr(GateRef x); 338 inline GateRef GetDoubleOfTDouble(GateRef x); 339 inline GateRef GetDoubleOfTNumber(GateRef x); 340 inline GateRef Int32ToTaggedPtr(GateRef x); 341 inline GateRef Int64ToTaggedPtr(GateRef x); 342 inline GateRef Int32ToTaggedInt(GateRef x); 343 // bit operation 344 inline GateRef IsSpecial(GateRef x, JSTaggedType type); 345 inline GateRef TaggedIsInt(GateRef x); 346 inline GateRef TaggedIsDouble(GateRef x); 347 inline GateRef TaggedIsObject(GateRef x); 348 inline GateRef TaggedIsNumber(GateRef x); 349 inline GateRef TaggedIsNumeric(GateRef x); 350 inline GateRef TaggedIsNotHole(GateRef x); 351 inline GateRef TaggedIsHole(GateRef x); 352 inline GateRef TaggedIsUndefined(GateRef x); 353 inline GateRef TaggedIsException(GateRef x); 354 inline GateRef TaggedIsSpecial(GateRef x); 355 inline GateRef TaggedIsHeapObject(GateRef x); 356 inline GateRef TaggedIsAsyncGeneratorObject(GateRef x); 357 inline GateRef TaggedIsGeneratorObject(GateRef x); 358 inline GateRef TaggedIsPropertyBox(GateRef x); 359 inline GateRef TaggedIsWeak(GateRef x); 360 inline GateRef TaggedIsPrototypeHandler(GateRef x); 361 inline GateRef TaggedIsTransitionHandler(GateRef x); 362 inline GateRef TaggedIsStoreTSHandler(GateRef x); 363 inline GateRef TaggedIsTransWithProtoHandler(GateRef x); 364 inline GateRef TaggedIsUndefinedOrNull(GateRef x); 365 inline GateRef TaggedIsTrue(GateRef x); 366 inline GateRef TaggedIsFalse(GateRef x); 367 inline GateRef TaggedIsNull(GateRef x); 368 inline GateRef TaggedIsBoolean(GateRef x); 369 inline GateRef IsAOTLiteralInfo(GateRef x); 370 inline GateRef TaggedGetInt(GateRef x); 371 inline GateRef ToTaggedInt(GateRef x); 372 inline GateRef ToTaggedIntPtr(GateRef x); 373 inline GateRef DoubleToTaggedDoublePtr(GateRef x); 374 inline GateRef BooleanToTaggedBooleanPtr(GateRef x); 375 inline GateRef Float32ToTaggedDoublePtr(GateRef x); 376 inline GateRef TaggedDoublePtrToFloat32(GateRef x); 377 inline GateRef TaggedIntPtrToFloat32(GateRef x); 378 inline GateRef DoubleToTaggedDouble(GateRef x); 379 inline GateRef DoubleToTagged(GateRef x); 380 inline GateRef DoubleIsNAN(GateRef x); 381 inline GateRef TaggedTrue(); 382 inline GateRef TaggedFalse(); 383 // Pointer/Arithmetic/Logic Operations 384 inline GateRef IntPtrDiv(GateRef x, GateRef y); 385 inline GateRef IntPtrOr(GateRef x, GateRef y); 386 inline GateRef IntPtrLSL(GateRef x, GateRef y); 387 inline GateRef IntPtrLSR(GateRef x, GateRef y); 388 inline GateRef Int64NotEqual(GateRef x, GateRef y); 389 inline GateRef Int32NotEqual(GateRef x, GateRef y); 390 inline GateRef Int64Equal(GateRef x, GateRef y); 391 inline GateRef DoubleEqual(GateRef x, GateRef y); 392 inline GateRef DoubleNotEqual(GateRef x, GateRef y); 393 inline GateRef Int8Equal(GateRef x, GateRef y); 394 inline GateRef Int32Equal(GateRef x, GateRef y); 395 inline GateRef IntPtrGreaterThan(GateRef x, GateRef y); 396 template<OpCode Op, MachineType Type> 397 inline GateRef BinaryOp(GateRef x, GateRef y); 398 inline GateRef GetValueFromTaggedArray(GateRef array, GateRef index); 399 inline void SetValueToTaggedArray(VariableType valType, GateRef glue, GateRef array, GateRef index, GateRef val); 400 GateRef TaggedIsString(GateRef obj); 401 GateRef TaggedIsStringOrSymbol(GateRef obj); 402 inline GateRef GetGlobalConstantString(ConstantIndex index); 403 404 GateRef IsJSHClass(GateRef obj); 405 GateRef HasPendingException(GateRef glue); 406 407 // middle ir: operations with any type 408 template<TypedBinOp Op> 409 inline GateRef TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType); 410 template<TypedUnOp Op> 411 inline GateRef TypedUnaryOp(GateRef x, GateType xType, GateType gateType); 412 413 // middle ir: Number operations 414 template<TypedBinOp Op> 415 inline GateRef NumberBinaryOp(GateRef x, GateRef y); 416 inline GateRef PrimitiveToNumber(GateRef x, VariableType type); 417 418 // middle ir: object operations 419 GateRef ToLength(GateRef receiver); 420 template<TypedLoadOp Op> 421 GateRef LoadElement(GateRef receiver, GateRef index); 422 template<TypedStoreOp Op> 423 GateRef StoreElement(GateRef receiver, GateRef index, GateRef value); 424 GateRef LoadProperty(GateRef receiver, GateRef offset); 425 GateRef StoreProperty(GateRef receiver, GateRef offset, GateRef value); 426 GateRef LoadArrayLength(GateRef array); 427 GateRef HeapAlloc(GateRef initialHClass, GateType type, RegionSpaceFlag flag); 428 GateRef Construct(std::vector<GateRef> args); 429 430 // Object Operations 431 inline GateRef LoadHClass(GateRef object); 432 inline GateRef IsDictionaryMode(GateRef object); 433 inline void StoreHClass(GateRef glue, GateRef object, GateRef hClass); 434 inline GateRef IsJsType(GateRef object, JSType type); 435 inline GateRef GetObjectType(GateRef hClass); 436 inline GateRef IsDictionaryModeByHClass(GateRef hClass); 437 inline GateRef DoubleIsINF(GateRef x); 438 inline GateRef IsDictionaryElement(GateRef hClass); 439 inline GateRef IsClassConstructor(GateRef object); 440 inline GateRef IsClassPrototype(GateRef object); 441 inline GateRef IsExtensible(GateRef object); 442 inline GateRef TaggedObjectIsEcmaObject(GateRef obj); 443 inline GateRef IsJSObject(GateRef obj); 444 inline GateRef TaggedObjectBothAreString(GateRef x, GateRef y); 445 inline GateRef IsCallable(GateRef obj); 446 inline GateRef IsCallableFromBitField(GateRef bitfield); 447 inline GateRef LogicAnd(GateRef x, GateRef y); 448 inline GateRef LogicOr(GateRef x, GateRef y); 449 inline GateRef BothAreString(GateRef x, GateRef y); 450 inline GateRef GetObjectSizeFromHClass(GateRef hClass); 451 GateRef GetGlobalObject(GateRef glue); 452 GateRef GetMethodFromFunction(GateRef function); 453 GateRef GetModuleFromFunction(GateRef function); 454 GateRef GetHomeObjectFromFunction(GateRef function); 455 GateRef FunctionIsResolved(GateRef function); 456 GateRef GetLengthFromString(GateRef value); 457 GateRef GetHashcodeFromString(GateRef glue, GateRef value); 458 GateRef IsUtf16String(GateRef string); 459 GateRef TaggedIsBigInt(GateRef obj); 460 void SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value); 461 GateRef GetFunctionLexicalEnv(GateRef function); 462 void SetModuleToFunction(GateRef glue, GateRef function, GateRef value); 463 void SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass, 464 GateRef value, GateRef attrOffset, VariableType type); 465 void SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value); 466 GateRef GetConstPool(GateRef jsFunc); 467 GateRef GetObjectFromConstPool(GateRef glue, GateRef jsFunc, GateRef index, ConstPoolType type); 468 GateRef GetObjectFromConstPool(GateRef glue, GateRef constPool, GateRef module, GateRef index, 469 ConstPoolType type); SetEnvironment(Environment * env)470 void SetEnvironment(Environment *env) 471 { 472 env_ = env; 473 } GetCurrentEnvironment()474 Environment *GetCurrentEnvironment() const 475 { 476 return env_; 477 } SetCompilationConfig(CompilationConfig * cmpCfg)478 void SetCompilationConfig(CompilationConfig *cmpCfg) 479 { 480 cmpCfg_ = cmpCfg; 481 } GetCompilationConfig()482 CompilationConfig *GetCompilationConfig() const 483 { 484 return cmpCfg_; 485 } 486 // label related 487 void NewEnvironment(GateRef hir); 488 void DeleteCurrentEnvironment(); 489 inline int NextVariableId(); 490 inline void HandleException(GateRef result, Label *success, Label *exception, Label *exit); 491 inline void HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal); 492 inline void SubCfgEntry(Label *entry); 493 inline void SubCfgExit(); 494 inline GateRef Return(GateRef value); 495 inline GateRef Return(); 496 inline void Bind(Label *label); 497 inline void Bind(Label *label, bool justSlowPath); 498 void Jump(Label *label); 499 void Branch(GateRef condition, Label *trueLabel, Label *falseLabel); 500 void Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys); 501 void LoopBegin(Label *loopHead); 502 void LoopEnd(Label *loopHead); 503 inline Label *GetCurrentLabel() const; 504 inline GateRef GetState() const; 505 inline GateRef GetDepend() const; 506 inline void SetDepend(GateRef depend); 507 inline void SetState(GateRef state); 508 509 GateRef GetGlobalEnvValue(VariableType type, GateRef env, size_t index); 510 GateRef GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index); 511 GateRef IsBase(GateRef ctor); 512 513 private: 514 Circuit *circuit_ {nullptr}; 515 GateAccessor acc_; 516 Environment *env_ {nullptr}; 517 CompilationConfig *cmpCfg_ {nullptr}; 518 }; 519 520 class Label { 521 public: 522 explicit Label() = default; 523 explicit Label(Environment *env); 524 explicit Label(CircuitBuilder *cirBuilder); 525 ~Label() = default; 526 Label(Label const &label) = default; 527 Label &operator=(Label const &label) = default; 528 Label(Label &&label) = default; 529 Label &operator=(Label &&label) = default; 530 inline void Seal(); WriteVariable(Variable * var,GateRef value)531 inline void WriteVariable(Variable *var, GateRef value) 532 { 533 impl_->WriteVariable(var, value); 534 } ReadVariable(Variable * var)535 inline GateRef ReadVariable(Variable *var) 536 { 537 return impl_->ReadVariable(var); 538 } 539 inline void Bind(); 540 inline void MergeAllControl(); 541 inline void MergeAllDepend(); 542 inline void AppendPredecessor(const Label *predecessor); 543 inline std::vector<Label> GetPredecessors() const; 544 inline void SetControl(GateRef control); 545 inline void SetPreControl(GateRef control); 546 inline void MergeControl(GateRef control); 547 inline GateRef GetControl() const; 548 inline GateRef GetDepend() const; 549 inline void SetDepend(GateRef depend); 550 551 private: 552 class LabelImpl { 553 public: LabelImpl(Environment * env,GateRef control)554 LabelImpl(Environment *env, GateRef control) 555 : env_(env), control_(control), predeControl_(-1), isSealed_(false) 556 { 557 } 558 ~LabelImpl() = default; 559 NO_MOVE_SEMANTIC(LabelImpl); 560 NO_COPY_SEMANTIC(LabelImpl); 561 void Seal(); 562 void WriteVariable(Variable *var, GateRef value); 563 GateRef ReadVariable(Variable *var); 564 void Bind(); 565 void MergeAllControl(); 566 void MergeAllDepend(); 567 void AppendPredecessor(LabelImpl *predecessor); GetPredecessors()568 std::vector<LabelImpl *> GetPredecessors() const 569 { 570 return predecessors_; 571 } SetControl(GateRef control)572 void SetControl(GateRef control) 573 { 574 control_ = control; 575 } SetPreControl(GateRef control)576 void SetPreControl(GateRef control) 577 { 578 predeControl_ = control; 579 } MergeControl(GateRef control)580 void MergeControl(GateRef control) 581 { 582 if (predeControl_ == -1) { 583 predeControl_ = control; 584 control_ = predeControl_; 585 } else { 586 otherPredeControls_.push_back(control); 587 } 588 } GetControl()589 GateRef GetControl() const 590 { 591 return control_; 592 } SetDepend(GateRef depend)593 void SetDepend(GateRef depend) 594 { 595 depend_ = depend; 596 } GetDepend()597 GateRef GetDepend() const 598 { 599 return depend_; 600 } 601 602 private: 603 bool IsNeedSeal() const; IsSealed()604 bool IsSealed() const 605 { 606 return isSealed_; 607 } 608 bool IsLoopHead() const; 609 bool IsControlCase() const; 610 GateRef ReadVariableRecursive(Variable *var); 611 Environment *env_; 612 GateRef control_; 613 GateRef predeControl_ {-1}; 614 GateRef dependRelay_ {-1}; 615 GateRef depend_ {-1}; 616 GateRef loopDepend_ {-1}; 617 std::vector<GateRef> otherPredeControls_; 618 bool isSealed_ {false}; 619 std::map<Variable *, GateRef> valueMap_; 620 std::vector<GateRef> phi; 621 std::vector<LabelImpl *> predecessors_; 622 std::map<Variable *, GateRef> incompletePhis_; 623 }; 624 Label(LabelImpl * impl)625 explicit Label(LabelImpl *impl) : impl_(impl) {} 626 friend class Environment; GetRawLabel()627 LabelImpl *GetRawLabel() const 628 { 629 return impl_; 630 } 631 LabelImpl *impl_ {nullptr}; 632 }; 633 634 class Environment { 635 public: 636 using LabelImpl = Label::LabelImpl; 637 Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder); 638 Environment(GateRef stateEntry, GateRef dependEntry, std::vector<GateRef>& inlist, 639 Circuit *circuit, CircuitBuilder *builder); 640 Environment(size_t arguments, CircuitBuilder *builder); 641 ~Environment(); GetCurrentLabel()642 Label *GetCurrentLabel() const 643 { 644 return currentLabel_; 645 } SetCurrentLabel(Label * label)646 void SetCurrentLabel(Label *label) 647 { 648 currentLabel_ = label; 649 } GetBuilder()650 CircuitBuilder *GetBuilder() const 651 { 652 return circuitBuilder_; 653 } GetCircuit()654 Circuit *GetCircuit() const 655 { 656 return circuit_; 657 } NextVariableId()658 int NextVariableId() 659 { 660 return nextVariableId_++; 661 } SetCompilationConfig(const CompilationConfig * cfg)662 void SetCompilationConfig(const CompilationConfig *cfg) 663 { 664 ccfg_ = cfg; 665 } GetCompilationConfig()666 const CompilationConfig *GetCompilationConfig() const 667 { 668 return ccfg_; 669 } Is32Bit()670 inline bool Is32Bit() const 671 { 672 return ccfg_->Is32Bit(); 673 } IsAArch64()674 inline bool IsAArch64() const 675 { 676 return ccfg_->IsAArch64(); 677 } IsAmd64()678 inline bool IsAmd64() const 679 { 680 return ccfg_->IsAmd64(); 681 } IsArch64Bit()682 inline bool IsArch64Bit() const 683 { 684 return ccfg_->IsAmd64() || ccfg_->IsAArch64(); 685 } IsAsmInterp()686 inline bool IsAsmInterp() const 687 { 688 return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME; 689 } IsArch32Bit()690 inline bool IsArch32Bit() const 691 { 692 return ccfg_->Is32Bit(); 693 } GetArgument(size_t index)694 inline GateRef GetArgument(size_t index) const 695 { 696 return arguments_.at(index); 697 } IsEnablePGOProfiler()698 inline bool IsEnablePGOProfiler() const 699 { 700 return ccfg_->IsEnablePGOProfiler(); 701 } 702 703 inline Label GetLabelFromSelector(GateRef sel); 704 inline void AddSelectorToLabel(GateRef sel, Label label); 705 inline LabelImpl *NewLabel(Environment *env, GateRef control = -1); 706 inline void SubCfgEntry(Label *entry); 707 inline void SubCfgExit(); 708 inline GateRef GetInput(size_t index) const; 709 710 private: 711 Label *currentLabel_ {nullptr}; 712 Circuit *circuit_ {nullptr}; 713 CircuitBuilder *circuitBuilder_ {nullptr}; 714 std::unordered_map<GateRef, LabelImpl *> phiToLabels_; 715 std::vector<GateRef> inputList_; 716 Label entry_; 717 std::vector<LabelImpl *> rawLabels_; 718 std::stack<Label *> stack_; 719 int nextVariableId_ {0}; 720 std::vector<GateRef> arguments_; 721 const CompilationConfig *ccfg_ {nullptr}; 722 }; 723 724 class Variable { 725 public: Variable(Environment * env,VariableType type,uint32_t id,GateRef value)726 Variable(Environment *env, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), env_(env) 727 { 728 Bind(value); 729 env_->GetCurrentLabel()->WriteVariable(this, value); 730 } Variable(CircuitBuilder * cirbuilder,VariableType type,uint32_t id,GateRef value)731 Variable(CircuitBuilder *cirbuilder, VariableType type, uint32_t id, GateRef value) 732 : id_(id), type_(type), env_(cirbuilder->GetCurrentEnvironment()) 733 { 734 Bind(value); 735 env_->GetCurrentLabel()->WriteVariable(this, value); 736 } 737 ~Variable() = default; 738 NO_MOVE_SEMANTIC(Variable); 739 NO_COPY_SEMANTIC(Variable); Bind(GateRef value)740 void Bind(GateRef value) 741 { 742 currentValue_ = value; 743 } Value()744 GateRef Value() const 745 { 746 return currentValue_; 747 } Type()748 VariableType Type() const 749 { 750 return type_; 751 } IsBound()752 bool IsBound() const 753 { 754 return currentValue_ != 0; 755 } 756 Variable &operator=(const GateRef value) 757 { 758 env_->GetCurrentLabel()->WriteVariable(this, value); 759 Bind(value); 760 return *this; 761 } 762 GateRef operator*() 763 { 764 return env_->GetCurrentLabel()->ReadVariable(this); 765 } ReadVariable()766 GateRef ReadVariable() 767 { 768 return env_->GetCurrentLabel()->ReadVariable(this); 769 } WriteVariable(GateRef value)770 void WriteVariable(GateRef value) 771 { 772 env_->GetCurrentLabel()->WriteVariable(this, value); 773 Bind(value); 774 } 775 GateRef AddPhiOperand(GateRef val); 776 GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in); 777 GateRef TryRemoveTrivialPhi(GateRef phi); GetId()778 uint32_t GetId() const 779 { 780 return id_; 781 } 782 783 private: GetCircuit()784 Circuit* GetCircuit() const 785 { 786 return env_->GetCircuit(); 787 } 788 789 uint32_t id_; 790 VariableType type_; 791 GateRef currentValue_ {0}; 792 Environment *env_; 793 }; 794 } // namespace panda::ecmascript::kungfu 795 796 #endif // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H 797