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 #include "ecmascript/compiler/gate.h"
17 #include "ecmascript/compiler/bytecode_circuit_builder.h"
18
19 namespace panda::ecmascript::kungfu {
20 constexpr size_t ONE_DEPEND = 1;
21 constexpr size_t MANY_DEPEND = 2;
22 constexpr size_t NO_DEPEND = 0;
23 // NOLINTNEXTLINE(readability-function-size)
GetProperties() const24 Properties OpCode::GetProperties() const
25 {
26 // general schema: [STATE]s + [DEPEND]s + [VALUE]s + [ROOT]
27 // GENERAL_STATE for any opcode match in
28 // {IF_TRUE, IF_FALSE, SWITCH_CASE, DEFAULT_CASE, MERGE, LOOP_BEGIN, STATE_ENTRY}
29 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
30 #define STATE(...) (std::make_pair(std::vector<OpCode>{__VA_ARGS__}, false))
31 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
32 #define VALUE(...) (std::make_pair(std::vector<MachineType>{__VA_ARGS__}, false))
33 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
34 #define MANY_STATE(...) (std::make_pair(std::vector<OpCode>{__VA_ARGS__}, true))
35 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
36 #define MANY_VALUE(...) (std::make_pair(std::vector<MachineType>{__VA_ARGS__}, true))
37 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
38 #define NO_STATE (std::nullopt)
39 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
40 #define NO_VALUE (std::nullopt)
41 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
42 #define NO_ROOT (std::nullopt)
43 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
44 #define GENERAL_STATE (NOP)
45 switch (op_) {
46 // SHARED
47 case NOP:
48 case CIRCUIT_ROOT:
49 return {NOVALUE, NO_STATE, NO_DEPEND, NO_VALUE, NO_ROOT};
50 case STATE_ENTRY:
51 case DEPEND_ENTRY:
52 case FRAMESTATE_ENTRY:
53 case RETURN_LIST:
54 case THROW_LIST:
55 case CONSTANT_LIST:
56 case ALLOCA_LIST:
57 case ARG_LIST:
58 return {NOVALUE, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CIRCUIT_ROOT)};
59 case RETURN:
60 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, VALUE(ANYVALUE), OpCode(RETURN_LIST)};
61 case RETURN_VOID:
62 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, NO_VALUE, OpCode(RETURN_LIST)};
63 case THROW:
64 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, VALUE(JSMachineType()), OpCode(THROW_LIST)};
65 case ORDINARY_BLOCK:
66 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, NO_VALUE, NO_ROOT};
67 case IF_BRANCH:
68 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, VALUE(I1), NO_ROOT};
69 case SWITCH_BRANCH:
70 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
71 case IF_TRUE:
72 case IF_FALSE:
73 return {NOVALUE, STATE(OpCode(IF_BRANCH)), NO_DEPEND, NO_VALUE, NO_ROOT};
74 case SWITCH_CASE:
75 case DEFAULT_CASE:
76 return {NOVALUE, STATE(OpCode(SWITCH_BRANCH)), NO_DEPEND, NO_VALUE, NO_ROOT};
77 case MERGE:
78 return {NOVALUE, MANY_STATE(OpCode(GENERAL_STATE)), NO_DEPEND, NO_VALUE, NO_ROOT};
79 case LOOP_BEGIN:
80 return {NOVALUE, STATE(OpCode(GENERAL_STATE), OpCode(LOOP_BACK)), NO_DEPEND, NO_VALUE, NO_ROOT};
81 case LOOP_BACK:
82 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, NO_VALUE, NO_ROOT};
83 case VALUE_SELECTOR:
84 return {FLEX, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, MANY_VALUE(FLEX), NO_ROOT};
85 case DEPEND_SELECTOR:
86 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), MANY_DEPEND, NO_VALUE, NO_ROOT};
87 case DEPEND_RELAY:
88 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, NO_VALUE, NO_ROOT};
89 case DEPEND_AND:
90 return {NOVALUE, NO_STATE, MANY_DEPEND, NO_VALUE, NO_ROOT};
91 // High Level IR
92 case JS_BYTECODE:
93 return {FLEX, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, MANY_VALUE(ANYVALUE), NO_ROOT};
94 case IF_SUCCESS:
95 case IF_EXCEPTION:
96 return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, NO_VALUE, NO_ROOT};
97 case GET_EXCEPTION:
98 return {I64, NO_STATE, ONE_DEPEND, NO_VALUE, NO_ROOT};
99 // Middle Level IR
100 case RUNTIME_CALL:
101 case BYTECODE_CALL:
102 case CALL:
103 return {FLEX, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT};
104 case ALLOCA:
105 return {ARCH, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ALLOCA_LIST)};
106 case ARG:
107 return {FLEX, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ARG_LIST)};
108 case MUTABLE_DATA:
109 case CONST_DATA:
110 return {ARCH, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)};
111 case RELOCATABLE_DATA:
112 return {ARCH, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)};
113 case CONSTANT:
114 return {FLEX, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)};
115 case ZEXT_TO_INT64:
116 return {I64, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
117 case ZEXT_TO_INT32:
118 return {I32, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
119 case ZEXT_TO_INT16:
120 return {I16, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
121 case SEXT_TO_INT64:
122 return {I64, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
123 case SEXT_TO_INT32:
124 return {I32, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
125 case TRUNC_TO_INT32:
126 return {I32, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
127 case TRUNC_TO_INT1:
128 return {I1, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
129 case REV:
130 return {FLEX, NO_STATE, NO_DEPEND, VALUE(FLEX), NO_ROOT};
131 case ADD:
132 case SUB:
133 case MUL:
134 case EXP:
135 case SDIV:
136 case SMOD:
137 case UDIV:
138 case UMOD:
139 case FDIV:
140 case FMOD:
141 case AND:
142 case XOR:
143 case OR:
144 case LSL:
145 case LSR:
146 case ASR:
147 return {FLEX, NO_STATE, NO_DEPEND, VALUE(FLEX, FLEX), NO_ROOT};
148 case SLT:
149 case SLE:
150 case SGT:
151 case SGE:
152 case ULT:
153 case ULE:
154 case UGT:
155 case UGE:
156 case FLT:
157 case FLE:
158 case FGT:
159 case FGE:
160 case EQ:
161 case NE:
162 return {I1, NO_STATE, NO_DEPEND, VALUE(ANYVALUE, ANYVALUE), NO_ROOT};
163 case LOAD:
164 return {FLEX, NO_STATE, ONE_DEPEND, VALUE(ARCH), NO_ROOT};
165 case STORE:
166 return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE, ARCH), NO_ROOT};
167 case TAGGED_TO_INT64:
168 return {I64, NO_STATE, NO_DEPEND, VALUE(I64), NO_ROOT};
169 case INT64_TO_TAGGED:
170 return {I64, NO_STATE, NO_DEPEND, VALUE(I64), NO_ROOT};
171 case SIGNED_INT_TO_FLOAT:
172 case UNSIGNED_INT_TO_FLOAT:
173 return {FLEX, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
174 case FLOAT_TO_SIGNED_INT:
175 case UNSIGNED_FLOAT_TO_INT:
176 return {FLEX, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
177 case BITCAST:
178 return {FLEX, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
179 default:
180 std::cerr << "Please complete OpCode properties (OpCode=" << op_ << ")" << std::endl;
181 UNREACHABLE();
182 }
183 #undef STATE
184 #undef VALUE
185 #undef MANY_STATE
186 #undef MANY_VALUE
187 #undef NO_STATE
188 #undef NO_VALUE
189 #undef NO_ROOT
190 #undef GENERAL_STATE
191 }
192
Str() const193 std::string OpCode::Str() const
194 {
195 const std::map<GateOp, const char *> strMap = {
196 {NOP, "NOP"},
197 {CIRCUIT_ROOT, "CIRCUIT_ROOT"},
198 {STATE_ENTRY, "STATE_ENTRY"},
199 {DEPEND_ENTRY, "DEPEND_ENTRY"},
200 {FRAMESTATE_ENTRY, "FRAMESTATE_ENTRY"},
201 {RETURN_LIST, "RETURN_LIST"},
202 {THROW_LIST, "THROW_LIST"},
203 {CONSTANT_LIST, "CONSTANT_LIST"},
204 {ALLOCA_LIST, "ALLOCA_LIST"},
205 {ARG_LIST, "ARG_LIST"},
206 {RETURN, "RETURN"},
207 {RETURN_VOID, "RETURN_VOID"},
208 {THROW, "THROW"},
209 {ORDINARY_BLOCK, "ORDINARY_BLOCK"},
210 {IF_BRANCH, "IF_BRANCH"},
211 {SWITCH_BRANCH, "SWITCH_BRANCH"},
212 {IF_TRUE, "IF_TRUE"},
213 {IF_FALSE, "IF_FALSE"},
214 {SWITCH_CASE, "SWITCH_CASE"},
215 {DEFAULT_CASE, "DEFAULT_CASE"},
216 {MERGE, "MERGE"},
217 {LOOP_BEGIN, "LOOP_BEGIN"},
218 {LOOP_BACK, "LOOP_BACK"},
219 {VALUE_SELECTOR, "VALUE_SELECTOR"},
220 {DEPEND_SELECTOR, "DEPEND_SELECTOR"},
221 {DEPEND_RELAY, "DEPEND_RELAY"},
222 {DEPEND_AND, "DEPEND_AND"},
223 {JS_BYTECODE, "JS_BYTECODE"},
224 {IF_SUCCESS, "IF_SUCCESS"},
225 {IF_EXCEPTION, "IF_EXCEPTION"},
226 {GET_EXCEPTION, "GET_EXCEPTION"},
227 {RUNTIME_CALL, "RUNTIME_CALL"},
228 {CALL, "CALL"},
229 {BYTECODE_CALL, "BYTECODE_CALL"},
230 {ALLOCA, "ALLOCA"},
231 {ARG, "ARG"},
232 {MUTABLE_DATA, "MUTABLE_DATA"},
233 {RELOCATABLE_DATA, "RELOCATABLE_DATA"},
234 {CONST_DATA, "CONST_DATA"},
235 {CONSTANT, "CONSTANT"},
236 {ZEXT_TO_INT64, "ZEXT_TO_INT64"},
237 {ZEXT_TO_INT32, "ZEXT_TO_INT32"},
238 {ZEXT_TO_INT16, "ZEXT_TO_INT16"},
239 {SEXT_TO_INT64, "SEXT_TO_INT64"},
240 {SEXT_TO_INT32, "SEXT_TO_INT32"},
241 {TRUNC_TO_INT32, "TRUNC_TO_INT32"},
242 {TRUNC_TO_INT1, "TRUNC_TO_INT1"},
243 {REV, "REV"},
244 {ADD, "ADD"},
245 {SUB, "SUB"},
246 {MUL, "MUL"},
247 {EXP, "EXP"},
248 {SDIV, "SDIV"},
249 {SMOD, "SMOD"},
250 {UDIV, "UDIV"},
251 {UMOD, "UMOD"},
252 {FDIV, "FDIV"},
253 {FMOD, "FMOD"},
254 {AND, "AND"},
255 {XOR, "XOR"},
256 {OR, "OR"},
257 {LSL, "LSL"},
258 {LSR, "LSR"},
259 {ASR, "ASR"},
260 {SLT, "SLT"},
261 {SLE, "SLE"},
262 {SGT, "SGT"},
263 {SGE, "SGE"},
264 {ULT, "ULT"},
265 {ULE, "ULE"},
266 {UGT, "UGT"},
267 {UGE, "UGE"},
268 {FLT, "FLT"},
269 {FLE, "FLE"},
270 {FGT, "FGT"},
271 {FGE, "FGE"},
272 {EQ, "EQ"},
273 {NE, "NE"},
274 {LOAD, "LOAD"},
275 {STORE, "STORE"},
276 {TAGGED_TO_INT64, "TAGGED_TO_INT64"},
277 {INT64_TO_TAGGED, "INT64_TO_TAGGED"},
278 {SIGNED_INT_TO_FLOAT, "SIGNED_INT_TO_FLOAT"},
279 {UNSIGNED_INT_TO_FLOAT, "UNSIGNED_INT_TO_FLOAT"},
280 {FLOAT_TO_SIGNED_INT, "FLOAT_TO_SIGNED_INT"},
281 {UNSIGNED_FLOAT_TO_INT, "UNSIGNED_FLOAT_TO_INT"},
282 {BITCAST, "BITCAST"},
283 };
284 if (strMap.count(op_) > 0) {
285 return strMap.at(op_);
286 }
287 return "OP-" + std::to_string(op_);
288 }
289 // 4 : 4 means that there are 4 args in total
GetOpCodeNumInsArray(BitField bitfield) const290 std::array<size_t, 4> OpCode::GetOpCodeNumInsArray(BitField bitfield) const
291 {
292 const size_t manyDepend = 2;
293 auto properties = GetProperties();
294 auto stateProp = properties.statesIn;
295 auto dependProp = properties.dependsIn;
296 auto valueProp = properties.valuesIn;
297 auto rootProp = properties.states;
298 size_t stateSize = stateProp.has_value() ? (stateProp->second ? bitfield : stateProp->first.size()) : 0;
299 size_t dependSize = (dependProp == manyDepend) ? bitfield : dependProp;
300 size_t valueSize = valueProp.has_value() ? (valueProp->second ? bitfield : valueProp->first.size()) : 0;
301 size_t rootSize = rootProp.has_value() ? 1 : 0;
302 return {stateSize, dependSize, valueSize, rootSize};
303 }
304
GetOpCodeNumIns(BitField bitfield) const305 size_t OpCode::GetOpCodeNumIns(BitField bitfield) const
306 {
307 auto numInsArray = GetOpCodeNumInsArray(bitfield);
308 // 0 : 0 means the first element
309 // 1 : 1 means the second element
310 // 2 : 2 means the third element
311 // 3 : 3 means the fourth element
312 return numInsArray[0] + numInsArray[1] + numInsArray[2] + numInsArray[3];
313 }
314
GetMachineType() const315 MachineType OpCode::GetMachineType() const
316 {
317 return GetProperties().returnValue;
318 }
319
GetInMachineType(BitField bitfield,size_t idx) const320 MachineType OpCode::GetInMachineType(BitField bitfield, size_t idx) const
321 {
322 auto numInsArray = GetOpCodeNumInsArray(bitfield);
323 auto valueProp = GetProperties().valuesIn;
324 idx -= numInsArray[0];
325 idx -= numInsArray[1];
326 ASSERT(valueProp.has_value());
327 if (valueProp->second) {
328 return valueProp->first.at(std::min(idx, valueProp->first.size() - 1));
329 }
330 return valueProp->first.at(idx);
331 }
332
GetInStateCode(size_t idx) const333 OpCode OpCode::GetInStateCode(size_t idx) const
334 {
335 auto stateProp = GetProperties().statesIn;
336 ASSERT(stateProp.has_value());
337 if (stateProp->second) {
338 return stateProp->first.at(std::min(idx, stateProp->first.size() - 1));
339 }
340 return stateProp->first.at(idx);
341 }
342
MachineTypeToStr(MachineType machineType)343 std::string MachineTypeToStr(MachineType machineType)
344 {
345 switch (machineType) {
346 case NOVALUE:
347 return "NOVALUE";
348 case ANYVALUE:
349 return "ANYVALUE";
350 case I1:
351 return "I1";
352 case I8:
353 return "I8";
354 case I16:
355 return "I16";
356 case I32:
357 return "I32";
358 case I64:
359 return "I64";
360 case F32:
361 return "F32";
362 case F64:
363 return "F64";
364 default:
365 return "???";
366 }
367 }
368
CheckNullInput() const369 std::optional<std::pair<std::string, size_t>> Gate::CheckNullInput() const
370 {
371 const auto numIns = GetNumIns();
372 for (size_t idx = 0; idx < numIns; idx++) {
373 if (IsInGateNull(idx)) {
374 return std::make_pair("In list contains null", idx);
375 }
376 }
377 return std::nullopt;
378 }
379
CheckStateInput() const380 std::optional<std::pair<std::string, size_t>> Gate::CheckStateInput() const
381 {
382 const auto numInsArray = GetOpCode().GetOpCodeNumInsArray(GetBitField());
383 size_t stateStart = 0;
384 size_t stateEnd = numInsArray[0];
385 for (size_t idx = stateStart; idx < stateEnd; idx++) {
386 auto stateProp = GetOpCode().GetProperties().statesIn;
387 ASSERT(stateProp.has_value());
388 auto expectedIn = GetOpCode().GetInStateCode(idx);
389 auto actualIn = GetInGateConst(idx)->GetOpCode();
390 if (expectedIn == OpCode::NOP) { // general
391 if (!actualIn.IsGeneralState()) {
392 return std::make_pair(
393 "State input does not match (expected:<General State> actual:" + actualIn.Str() + ")", idx);
394 }
395 } else {
396 if (expectedIn != actualIn) {
397 return std::make_pair(
398 "State input does not match (expected:" + expectedIn.Str() + " actual:" + actualIn.Str() + ")",
399 idx);
400 }
401 }
402 }
403 return std::nullopt;
404 }
405
CheckValueInput() const406 std::optional<std::pair<std::string, size_t>> Gate::CheckValueInput() const
407 {
408 const auto numInsArray = GetOpCode().GetOpCodeNumInsArray(GetBitField());
409 size_t valueStart = numInsArray[0] + numInsArray[1];
410 size_t valueEnd = numInsArray[0] + numInsArray[1] + numInsArray[2]; // 2 : 2 means the third element.
411 for (size_t idx = valueStart; idx < valueEnd; idx++) {
412 auto expectedIn = GetOpCode().GetInMachineType(GetBitField(), idx);
413 auto actualIn = GetInGateConst(idx)->GetOpCode().GetMachineType();
414 if (expectedIn == MachineType::FLEX) {
415 expectedIn = GetMachineType();
416 }
417 if (actualIn == MachineType::FLEX) {
418 actualIn = GetInGateConst(idx)->GetMachineType();
419 }
420
421 if ((expectedIn != actualIn) && (expectedIn != ANYVALUE)) {
422 return std::make_pair("Value input does not match (expected: " + MachineTypeToStr(expectedIn) +
423 " actual: " + MachineTypeToStr(actualIn) + ")",
424 idx);
425 }
426 }
427 return std::nullopt;
428 }
429
CheckDependInput() const430 std::optional<std::pair<std::string, size_t>> Gate::CheckDependInput() const
431 {
432 const auto numInsArray = GetOpCode().GetOpCodeNumInsArray(GetBitField());
433 size_t dependStart = numInsArray[0];
434 size_t dependEnd = dependStart + numInsArray[1];
435 for (size_t idx = dependStart; idx < dependEnd; idx++) {
436 if (GetInGateConst(idx)->GetNumInsArray()[1] == 0 &&
437 GetInGateConst(idx)->GetOpCode() != OpCode::DEPEND_ENTRY) {
438 return std::make_pair("Depend input is side-effect free", idx);
439 }
440 }
441 return std::nullopt;
442 }
443
CheckStateOutput() const444 std::optional<std::pair<std::string, size_t>> Gate::CheckStateOutput() const
445 {
446 if (GetOpCode().IsState()) {
447 size_t cnt = 0;
448 const Gate *curGate = this;
449 if (!curGate->IsFirstOutNull()) {
450 const Out *curOut = curGate->GetFirstOutConst();
451 if (curOut->GetGateConst()->GetOpCode().IsState()) {
452 cnt++;
453 }
454 while (!curOut->IsNextOutNull()) {
455 curOut = curOut->GetNextOutConst();
456 if (curOut->GetGateConst()->GetOpCode().IsState()) {
457 cnt++;
458 }
459 }
460 }
461 size_t expected = 0;
462 bool needCheck = true;
463 if (GetOpCode().IsTerminalState()) {
464 expected = 0;
465 } else if (GetOpCode() == OpCode::IF_BRANCH) {
466 expected = 2; // 2: expected number of state out branches
467 } else if (GetOpCode() == OpCode::SWITCH_BRANCH) {
468 needCheck = false;
469 } else {
470 expected = 1;
471 }
472 if (needCheck && cnt != expected) {
473 return std::make_pair("Number of state out branches is not valid (expected:" + std::to_string(expected) +
474 " actual:" + std::to_string(cnt) + ")",
475 -1);
476 }
477 }
478 return std::nullopt;
479 }
480
CheckBranchOutput() const481 std::optional<std::pair<std::string, size_t>> Gate::CheckBranchOutput() const
482 {
483 std::map<std::pair<OpCode, BitField>, size_t> setOfOps;
484 if (GetOpCode() == OpCode::IF_BRANCH || GetOpCode() == OpCode::SWITCH_BRANCH) {
485 size_t cnt = 0;
486 const Gate *curGate = this;
487 if (!curGate->IsFirstOutNull()) {
488 const Out *curOut = curGate->GetFirstOutConst();
489 if (curOut->GetGateConst()->GetOpCode().IsState()) {
490 setOfOps[{curOut->GetGateConst()->GetOpCode(), curOut->GetGateConst()->GetBitField()}]++;
491 cnt++;
492 }
493 while (!curOut->IsNextOutNull()) {
494 curOut = curOut->GetNextOutConst();
495 if (curOut->GetGateConst()->GetOpCode().IsState()) {
496 setOfOps[{curOut->GetGateConst()->GetOpCode(), curOut->GetGateConst()->GetBitField()}]++;
497 cnt++;
498 }
499 }
500 }
501 if (setOfOps.size() != cnt) {
502 return std::make_pair("Duplicate state out branches", -1);
503 }
504 }
505 return std::nullopt;
506 }
507
CheckNOP() const508 std::optional<std::pair<std::string, size_t>> Gate::CheckNOP() const
509 {
510 if (GetOpCode() == OpCode::NOP) {
511 if (!IsFirstOutNull()) {
512 return std::make_pair("NOP gate used by other gates", -1);
513 }
514 }
515 return std::nullopt;
516 }
517
CheckSelector() const518 std::optional<std::pair<std::string, size_t>> Gate::CheckSelector() const
519 {
520 if (GetOpCode() == OpCode::VALUE_SELECTOR || GetOpCode() == OpCode::DEPEND_SELECTOR) {
521 auto stateOp = GetInGateConst(0)->GetOpCode();
522 if (stateOp == OpCode::MERGE || stateOp == OpCode::LOOP_BEGIN) {
523 if (GetInGateConst(0)->GetNumIns() != GetNumIns() - 1) {
524 if (GetOpCode() == OpCode::DEPEND_SELECTOR) {
525 return std::make_pair("Number of depend flows does not match control flows (expected:" +
526 std::to_string(GetInGateConst(0)->GetNumIns()) +
527 " actual:" + std::to_string(GetNumIns() - 1) + ")",
528 -1);
529 } else {
530 return std::make_pair("Number of data flows does not match control flows (expected:" +
531 std::to_string(GetInGateConst(0)->GetNumIns()) +
532 " actual:" + std::to_string(GetNumIns() - 1) + ")",
533 -1);
534 }
535 }
536 } else {
537 return std::make_pair(
538 "State input does not match (expected:[MERGE|LOOP_BEGIN] actual:" + stateOp.Str() + ")", 0);
539 }
540 }
541 return std::nullopt;
542 }
543
CheckRelay() const544 std::optional<std::pair<std::string, size_t>> Gate::CheckRelay() const
545 {
546 if (GetOpCode() == OpCode::DEPEND_RELAY) {
547 auto stateOp = GetInGateConst(0)->GetOpCode();
548 if (!(stateOp == OpCode::IF_TRUE || stateOp == OpCode::IF_FALSE || stateOp == OpCode::SWITCH_CASE ||
549 stateOp == OpCode::DEFAULT_CASE || stateOp == OpCode::IF_SUCCESS || stateOp == OpCode::IF_EXCEPTION)) {
550 return std::make_pair("State input does not match ("
551 "expected:[IF_TRUE|IF_FALSE|SWITCH_CASE|DEFAULT_CASE|IF_SUCCESS|IF_EXCEPTION] actual:" +
552 stateOp.Str() + ")", 0);
553 }
554 }
555 return std::nullopt;
556 }
557
SpecialCheck() const558 std::optional<std::pair<std::string, size_t>> Gate::SpecialCheck() const
559 {
560 {
561 auto ret = CheckNOP();
562 if (ret.has_value()) {
563 return ret;
564 }
565 }
566 {
567 auto ret = CheckSelector();
568 if (ret.has_value()) {
569 return ret;
570 }
571 }
572 {
573 auto ret = CheckRelay();
574 if (ret.has_value()) {
575 return ret;
576 }
577 }
578 return std::nullopt;
579 }
580
Verify() const581 bool Gate::Verify() const
582 {
583 std::string errorString;
584 size_t highlightIdx = -1;
585 bool failed = false;
586 {
587 auto ret = CheckNullInput();
588 if (ret.has_value()) {
589 failed = true;
590 std::tie(errorString, highlightIdx) = ret.value();
591 }
592 }
593 if (!failed) {
594 auto ret = CheckStateInput();
595 if (ret.has_value()) {
596 failed = true;
597 std::tie(errorString, highlightIdx) = ret.value();
598 }
599 }
600 if (!failed) {
601 auto ret = CheckValueInput();
602 if (ret.has_value()) {
603 failed = true;
604 std::tie(errorString, highlightIdx) = ret.value();
605 }
606 }
607 if (!failed) {
608 auto ret = CheckDependInput();
609 if (ret.has_value()) {
610 failed = true;
611 std::tie(errorString, highlightIdx) = ret.value();
612 }
613 }
614 if (!failed) {
615 auto ret = CheckStateOutput();
616 if (ret.has_value()) {
617 failed = true;
618 std::tie(errorString, highlightIdx) = ret.value();
619 }
620 }
621 if (!failed) {
622 auto ret = CheckBranchOutput();
623 if (ret.has_value()) {
624 failed = true;
625 std::tie(errorString, highlightIdx) = ret.value();
626 }
627 }
628 if (!failed) {
629 auto ret = SpecialCheck();
630 if (ret.has_value()) {
631 failed = true;
632 std::tie(errorString, highlightIdx) = ret.value();
633 }
634 }
635 if (failed) {
636 std::cerr << "[Verifier][Error] Gate level input list schema verify failed" << std::endl;
637 Print("", true, highlightIdx);
638 std::cerr << "Note: " << errorString << std::endl;
639 }
640 return !failed;
641 }
642
JSMachineType()643 MachineType JSMachineType()
644 {
645 return MachineType::I64;
646 }
647
GetOpCodeNumIns(OpCode opcode,BitField bitfield)648 size_t GetOpCodeNumIns(OpCode opcode, BitField bitfield)
649 {
650 return opcode.GetOpCodeNumIns(bitfield);
651 }
652
SetNextOut(const Out * ptr)653 void Out::SetNextOut(const Out *ptr)
654 {
655 nextOut_ =
656 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
657 static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
658 }
659
GetNextOut()660 Out *Out::GetNextOut()
661 {
662 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
663 return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + nextOut_);
664 }
665
GetNextOutConst() const666 const Out *Out::GetNextOutConst() const
667 {
668 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
669 return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + nextOut_);
670 }
671
SetPrevOut(const Out * ptr)672 void Out::SetPrevOut(const Out *ptr)
673 {
674 prevOut_ =
675 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
676 static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
677 }
678
GetPrevOut()679 Out *Out::GetPrevOut()
680 {
681 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
682 return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + prevOut_);
683 }
684
GetPrevOutConst() const685 const Out *Out::GetPrevOutConst() const
686 {
687 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
688 return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + prevOut_);
689 }
690
SetIndex(OutIdx idx)691 void Out::SetIndex(OutIdx idx)
692 {
693 idx_ = idx;
694 }
695
GetIndex() const696 OutIdx Out::GetIndex() const
697 {
698 return idx_;
699 }
700
GetGate()701 Gate *Out::GetGate()
702 {
703 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
704 return reinterpret_cast<Gate *>(&this[idx_ + 1]);
705 }
706
GetGateConst() const707 const Gate *Out::GetGateConst() const
708 {
709 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
710 return reinterpret_cast<const Gate *>(&this[idx_ + 1]);
711 }
712
SetPrevOutNull()713 void Out::SetPrevOutNull()
714 {
715 prevOut_ = 0;
716 }
717
IsPrevOutNull() const718 bool Out::IsPrevOutNull() const
719 {
720 return prevOut_ == 0;
721 }
722
SetNextOutNull()723 void Out::SetNextOutNull()
724 {
725 nextOut_ = 0;
726 }
727
IsNextOutNull() const728 bool Out::IsNextOutNull() const
729 {
730 return nextOut_ == 0;
731 }
732
SetGate(const Gate * ptr)733 void In::SetGate(const Gate *ptr)
734 {
735 gatePtr_ =
736 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
737 static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
738 }
739
GetGate()740 Gate *In::GetGate()
741 {
742 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
743 return reinterpret_cast<Gate *>((reinterpret_cast<uint8_t *>(this)) + gatePtr_);
744 }
745
GetGateConst() const746 const Gate *In::GetGateConst() const
747 {
748 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
749 return reinterpret_cast<const Gate *>((reinterpret_cast<const uint8_t *>(this)) + gatePtr_);
750 }
751
SetGateNull()752 void In::SetGateNull()
753 {
754 gatePtr_ = 0;
755 }
756
IsGateNull() const757 bool In::IsGateNull() const
758 {
759 return gatePtr_ == 0;
760 }
761
762 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
Gate(GateId id,OpCode opcode,MachineType bitValue,BitField bitfield,Gate * inList[],GateType type,MarkCode mark)763 Gate::Gate(GateId id, OpCode opcode, MachineType bitValue, BitField bitfield, Gate *inList[], GateType type,
764 MarkCode mark)
765 : id_(id), opcode_(opcode), bitValue_(bitValue), type_(type), stamp_(1), mark_(mark), bitfield_(bitfield),
766 firstOut_(0)
767 {
768 auto numIns = GetNumIns();
769 for (size_t idx = 0; idx < numIns; idx++) {
770 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
771 auto in = inList[idx];
772 if (in == nullptr) {
773 GetIn(idx)->SetGateNull();
774 } else {
775 NewIn(idx, in);
776 }
777 auto curOut = GetOut(idx);
778 curOut->SetIndex(idx);
779 }
780 }
781
Gate(GateId id,OpCode opcode,BitField bitfield,Gate * inList[],GateType type,MarkCode mark)782 Gate::Gate(GateId id, OpCode opcode, BitField bitfield, Gate *inList[], GateType type, MarkCode mark)
783 : id_(id), opcode_(opcode), type_(type), stamp_(1), mark_(mark), bitfield_(bitfield), firstOut_(0)
784 {
785 auto numIns = GetNumIns();
786 for (size_t idx = 0; idx < numIns; idx++) {
787 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
788 auto in = inList[idx];
789 if (in == nullptr) {
790 GetIn(idx)->SetGateNull();
791 } else {
792 NewIn(idx, in);
793 }
794 auto curOut = GetOut(idx);
795 curOut->SetIndex(idx);
796 }
797 }
798
GetOutListSize(size_t numIns)799 size_t Gate::GetOutListSize(size_t numIns)
800 {
801 return numIns * sizeof(Out);
802 }
803
GetOutListSize() const804 size_t Gate::GetOutListSize() const
805 {
806 return Gate::GetOutListSize(GetNumIns());
807 }
808
GetInListSize(size_t numIns)809 size_t Gate::GetInListSize(size_t numIns)
810 {
811 return numIns * sizeof(In);
812 }
813
GetInListSize() const814 size_t Gate::GetInListSize() const
815 {
816 return Gate::GetInListSize(GetNumIns());
817 }
818
GetGateSize(size_t numIns)819 size_t Gate::GetGateSize(size_t numIns)
820 {
821 return Gate::GetOutListSize(numIns) + Gate::GetInListSize(numIns) + sizeof(Gate);
822 }
823
GetGateSize() const824 size_t Gate::GetGateSize() const
825 {
826 return Gate::GetGateSize(GetNumIns());
827 }
828
NewIn(size_t idx,Gate * in)829 void Gate::NewIn(size_t idx, Gate *in)
830 {
831 GetIn(idx)->SetGate(in);
832 auto curOut = GetOut(idx);
833 if (in->IsFirstOutNull()) {
834 curOut->SetNextOutNull();
835 } else {
836 curOut->SetNextOut(in->GetFirstOut());
837 in->GetFirstOut()->SetPrevOut(curOut);
838 }
839 curOut->SetPrevOutNull();
840 in->SetFirstOut(curOut);
841 }
842
ModifyIn(size_t idx,Gate * in)843 void Gate::ModifyIn(size_t idx, Gate *in)
844 {
845 DeleteIn(idx);
846 NewIn(idx, in);
847 }
848
DeleteIn(size_t idx)849 void Gate::DeleteIn(size_t idx)
850 {
851 if (!GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) {
852 GetOut(idx)->GetPrevOut()->SetNextOut(GetOut(idx)->GetNextOut());
853 GetOut(idx)->GetNextOut()->SetPrevOut(GetOut(idx)->GetPrevOut());
854 } else if (GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) {
855 GetOut(idx)->GetPrevOut()->SetNextOutNull();
856 } else if (!GetOut(idx)->IsNextOutNull()) { // then GetOut(idx)->IsPrevOutNull() is true
857 GetIn(idx)->GetGate()->SetFirstOut(GetOut(idx)->GetNextOut());
858 GetOut(idx)->GetNextOut()->SetPrevOutNull();
859 } else { // only this out now
860 GetIn(idx)->GetGate()->SetFirstOutNull();
861 }
862 GetIn(idx)->SetGateNull();
863 }
864
DeleteGate()865 void Gate::DeleteGate()
866 {
867 auto numIns = GetNumIns();
868 for (size_t idx = 0; idx < numIns; idx++) {
869 DeleteIn(idx);
870 }
871 SetOpCode(OpCode(OpCode::NOP));
872 }
873
GetOut(size_t idx)874 Out *Gate::GetOut(size_t idx)
875 {
876 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
877 return &reinterpret_cast<Out *>(this)[-1 - idx];
878 }
879
GetFirstOut()880 Out *Gate::GetFirstOut()
881 {
882 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
883 return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + firstOut_);
884 }
885
GetFirstOutConst() const886 const Out *Gate::GetFirstOutConst() const
887 {
888 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
889 return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + firstOut_);
890 }
891
SetFirstOutNull()892 void Gate::SetFirstOutNull()
893 {
894 firstOut_ = 0;
895 }
896
IsFirstOutNull() const897 bool Gate::IsFirstOutNull() const
898 {
899 return firstOut_ == 0;
900 }
901
SetFirstOut(const Out * firstOut)902 void Gate::SetFirstOut(const Out *firstOut)
903 {
904 firstOut_ =
905 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
906 static_cast<GateRef>(reinterpret_cast<const uint8_t *>(firstOut) - reinterpret_cast<const uint8_t *>(this));
907 }
908
GetIn(size_t idx)909 In *Gate::GetIn(size_t idx)
910 {
911 #ifndef NDEBUG
912 if (idx >= GetNumIns()) {
913 std::cerr << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")" << std::endl;
914 Print();
915 ASSERT(false);
916 }
917 #endif
918 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
919 return &reinterpret_cast<In *>(this + 1)[idx];
920 }
921
GetInConst(size_t idx) const922 const In *Gate::GetInConst(size_t idx) const
923 {
924 #ifndef NDEBUG
925 if (idx >= GetNumIns()) {
926 std::cerr << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")" << std::endl;
927 Print();
928 ASSERT(false);
929 }
930 #endif
931 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
932 return &reinterpret_cast<const In *>(this + 1)[idx];
933 }
934
GetInGate(size_t idx)935 Gate *Gate::GetInGate(size_t idx)
936 {
937 return GetIn(idx)->GetGate();
938 }
939
GetInGateConst(size_t idx) const940 const Gate *Gate::GetInGateConst(size_t idx) const
941 {
942 return GetInConst(idx)->GetGateConst();
943 }
944
IsInGateNull(size_t idx) const945 bool Gate::IsInGateNull(size_t idx) const
946 {
947 return GetInConst(idx)->IsGateNull();
948 }
949
GetId() const950 GateId Gate::GetId() const
951 {
952 return id_;
953 }
954
GetOpCode() const955 OpCode Gate::GetOpCode() const
956 {
957 return opcode_;
958 }
959
GetMachineType() const960 MachineType Gate::GetMachineType() const
961 {
962 return bitValue_;
963 }
964
SetMachineType(MachineType MachineType)965 void Gate::SetMachineType(MachineType MachineType)
966 {
967 bitValue_ = MachineType;
968 }
969
SetOpCode(OpCode opcode)970 void Gate::SetOpCode(OpCode opcode)
971 {
972 opcode_ = opcode;
973 }
974
GetGateType() const975 GateType Gate::GetGateType() const
976 {
977 return type_;
978 }
979
SetGateType(GateType type)980 void Gate::SetGateType(GateType type)
981 {
982 type_ = type;
983 }
984
GetNumIns() const985 size_t Gate::GetNumIns() const
986 {
987 return GetOpCodeNumIns(GetOpCode(), GetBitField());
988 }
989
GetNumInsArray() const990 std::array<size_t, 4> Gate::GetNumInsArray() const // 4 : 4 means that there are 4 args.
991 {
992 return GetOpCode().GetOpCodeNumInsArray(GetBitField());
993 }
994
GetBitField() const995 BitField Gate::GetBitField() const
996 {
997 return bitfield_;
998 }
999
SetBitField(BitField bitfield)1000 void Gate::SetBitField(BitField bitfield)
1001 {
1002 bitfield_ = bitfield;
1003 }
1004
MachineTypeStr(MachineType machineType) const1005 std::string Gate::MachineTypeStr(MachineType machineType) const
1006 {
1007 const std::map<MachineType, const char *> strMap = {
1008 {NOVALUE, "NOVALUE"},
1009 {ANYVALUE, "ANYVALUE"},
1010 {ARCH, "ARCH"},
1011 {FLEX, "FLEX"},
1012 {I1, "I1"},
1013 {I8, "I8"},
1014 {I16, "I16"},
1015 {I32, "I32"},
1016 {I64, "I64"},
1017 {F32, "F32"},
1018 {F64, "F64"},
1019 };
1020 if (strMap.count(machineType) > 0) {
1021 return strMap.at(machineType);
1022 }
1023 return "MachineType-" + std::to_string(machineType);
1024 }
1025
GateTypeStr(GateType gateType) const1026 std::string Gate::GateTypeStr(GateType gateType) const
1027 {
1028 const std::map<GateType, const char *> strMap = {
1029 {C_VALUE, "C_VALUE"},
1030 {TAGGED_VALUE, "TAGGED_VALUE"},
1031 {TAGGED_POINTER, "TAGGED_POINTER"},
1032 {TAGGED_NO_POINTER, "TAGGED_NO_POINTER"},
1033 {EMPTY, "EMPTY"},
1034 {JS_ANY, "JS_ANY"},
1035 };
1036
1037 if (strMap.count(gateType) > 0) {
1038 return strMap.at(gateType);
1039 }
1040 return "GateType-" + std::to_string(gateType);
1041 }
1042
Print(std::string bytecode,bool inListPreview,size_t highlightIdx) const1043 void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) const
1044 {
1045 if (GetOpCode() != OpCode::NOP) {
1046 std::cerr << std::dec << "("
1047 << "id=" << id_ << ", "
1048 << "op=" << GetOpCode().Str() << ", "
1049 << ((bytecode.compare("") == 0) ? "" : "bytecode=") << bytecode
1050 << ((bytecode.compare("") == 0) ? "" : ", ")
1051 << "machineType=" << MachineTypeStr(GetMachineType()) << ", "
1052 << "bitfield=" << std::to_string(bitfield_) << ", "
1053 << "type=" << GateTypeStr(type_) << ", "
1054 << "stamp=" << static_cast<uint32_t>(stamp_) << ", "
1055 << "mark=" << static_cast<uint32_t>(mark_) << ", ";
1056 std::cerr << "in="
1057 << "[";
1058 auto numInsArray = GetOpCode().GetOpCodeNumInsArray(GetBitField());
1059 size_t idx = 0;
1060 auto stateSize = numInsArray[0];
1061 auto dependSize = numInsArray[1];
1062 auto valueSize = numInsArray[2]; // 2 : 2 means the third element.
1063 auto rootSize = numInsArray[3]; // 3 : 3 means the four element.
1064 idx = PrintInGate(stateSize, idx, 0, inListPreview, highlightIdx);
1065 idx = PrintInGate(stateSize + dependSize, idx, stateSize, inListPreview, highlightIdx);
1066 idx = PrintInGate(stateSize + dependSize + valueSize, idx, stateSize + dependSize, inListPreview, highlightIdx);
1067 PrintInGate(stateSize + dependSize + valueSize + rootSize, idx, stateSize + dependSize + valueSize,
1068 inListPreview, highlightIdx, true);
1069
1070 std::cerr << "]"
1071 << ", ";
1072 std::cerr << "out="
1073 << "[";
1074 if (!IsFirstOutNull()) {
1075 const Out *curOut = GetFirstOutConst();
1076 std::cerr << std::dec << ""
1077 << std::to_string(curOut->GetGateConst()->GetId()) +
1078 (inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str()) : std::string(""));
1079 while (!curOut->IsNextOutNull()) {
1080 curOut = curOut->GetNextOutConst();
1081 std::cerr << std::dec << " "
1082 << std::to_string(curOut->GetGateConst()->GetId()) +
1083 (inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str())
1084 : std::string(""));
1085 }
1086 }
1087 std::cerr << "]"
1088 << ")" << std::endl;
1089 }
1090 }
1091
PrintInGate(size_t numIns,size_t idx,size_t size,bool inListPreview,size_t highlightIdx,bool isEnd) const1092 size_t Gate::PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPreview, size_t highlightIdx,
1093 bool isEnd) const
1094 {
1095 std::cerr << "[";
1096 for (; idx < numIns; idx++) {
1097 std::cerr << std::dec << ((idx == size) ? "" : " ") << ((idx == highlightIdx) ? "\033[4;31m" : "")
1098 << ((IsInGateNull(idx)
1099 ? "N"
1100 : (std::to_string(GetInGateConst(idx)->GetId()) +
1101 (inListPreview ? std::string(":" + GetInGateConst(idx)->GetOpCode().Str())
1102 : std::string("")))))
1103 << ((idx == highlightIdx) ? "\033[0m" : "");
1104 }
1105 std::cerr << "]"
1106 << ((isEnd) ? "" : ", ");
1107 return idx;
1108 }
1109
PrintByteCode(std::string bytecode) const1110 void Gate::PrintByteCode(std::string bytecode) const
1111 {
1112 Print(bytecode);
1113 }
1114
GetMark(TimeStamp stamp) const1115 MarkCode Gate::GetMark(TimeStamp stamp) const
1116 {
1117 return (stamp_ == stamp) ? mark_ : MarkCode::NO_MARK;
1118 }
1119
SetMark(MarkCode mark,TimeStamp stamp)1120 void Gate::SetMark(MarkCode mark, TimeStamp stamp)
1121 {
1122 stamp_ = stamp;
1123 mark_ = mark;
1124 }
1125
IsRoot() const1126 bool OpCode::IsRoot() const
1127 {
1128 return (GetProperties().states == OpCode::CIRCUIT_ROOT) || (op_ == OpCode::CIRCUIT_ROOT);
1129 }
1130
IsProlog() const1131 bool OpCode::IsProlog() const
1132 {
1133 return (GetProperties().states == OpCode::ARG_LIST);
1134 }
1135
IsFixed() const1136 bool OpCode::IsFixed() const
1137 {
1138 return (GetOpCodeNumInsArray(1)[0] > 0) &&
1139 ((GetMachineType() != NOVALUE) ||
1140 ((GetOpCodeNumInsArray(1)[1] > 0) && (GetOpCodeNumInsArray(1)[2] == 0) &&
1141 (GetOpCodeNumInsArray(1)[3] == 0)));
1142 }
1143
IsSchedulable() const1144 bool OpCode::IsSchedulable() const
1145 {
1146 return (op_ != OpCode::NOP) && (!IsProlog()) && (!IsRoot()) && (!IsFixed()) &&
1147 (GetOpCodeNumInsArray(1)[0] == 0);
1148 }
1149
IsState() const1150 bool OpCode::IsState() const
1151 {
1152 return (op_ != OpCode::NOP) && (!IsProlog()) && (!IsRoot()) && (!IsFixed()) &&
1153 (GetOpCodeNumInsArray(1)[0] > 0);
1154 }
1155
IsGeneralState() const1156 bool OpCode::IsGeneralState() const
1157 {
1158 return ((op_ == OpCode::IF_TRUE) || (op_ == OpCode::IF_FALSE) || (op_ == OpCode::IF_SUCCESS) ||
1159 (op_ == OpCode::IF_EXCEPTION) || (op_ == OpCode::SWITCH_CASE) ||
1160 (op_ == OpCode::DEFAULT_CASE) || (op_ == OpCode::MERGE) || (op_ == OpCode::LOOP_BEGIN) ||
1161 (op_ == OpCode::ORDINARY_BLOCK) || (op_ == OpCode::STATE_ENTRY));
1162 }
1163
IsTerminalState() const1164 bool OpCode::IsTerminalState() const
1165 {
1166 return ((op_ == OpCode::RETURN) || (op_ == OpCode::THROW) || (op_ == OpCode::RETURN_VOID));
1167 }
1168
IsCFGMerge() const1169 bool OpCode::IsCFGMerge() const
1170 {
1171 return (op_ == OpCode::MERGE) || (op_ == OpCode::LOOP_BEGIN);
1172 }
1173
IsControlCase() const1174 bool OpCode::IsControlCase() const
1175 {
1176 return (op_ == OpCode::IF_BRANCH) || (op_ == OpCode::SWITCH_BRANCH) || (op_ == OpCode::IF_TRUE) ||
1177 (op_ == OpCode::IF_FALSE) || (op_ == OpCode::IF_SUCCESS) || (op_ == OpCode::IF_EXCEPTION) ||
1178 (op_ == OpCode::SWITCH_CASE) || (op_ == OpCode::DEFAULT_CASE);
1179 }
1180
IsLoopHead() const1181 bool OpCode::IsLoopHead() const
1182 {
1183 return (op_ == OpCode::LOOP_BEGIN);
1184 }
1185
IsNop() const1186 bool OpCode::IsNop() const
1187 {
1188 return (op_ == OpCode::NOP);
1189 }
1190 } // namespace panda::ecmascript::kungfu
1191