• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 <codecvt>
17 #include <cstdarg>
18 #include <iostream>
19 #include <locale>
20 #include <string>
21 #include <unistd.h>
22 
23 #include "assembly-type.h"
24 #include "assembly-program.h"
25 #include "assembly-emitter.h"
26 #include "json/json.h"
27 #include "securec.h"
28 #include "ts2abc_options.h"
29 #include "ts2abc.h"
30 #include "protobufSnapshotGenerator.h"
31 
32 #ifdef ENABLE_BYTECODE_OPT
33 #include "optimize_bytecode.h"
34 #endif
35 
36 namespace panda::ts2abc {
37 // pandasm definitions
38 constexpr const auto LANG_EXT = panda::pandasm::extensions::Language::ECMASCRIPT;
39 const std::string WHOLE_LINE;
40 bool g_isMergeAbc = false;
41 bool g_debugModeEnabled = false;
42 bool g_debugLogEnabled = false;
43 int g_optLevel = 0;
44 bool g_enableTypeinfo = false;
45 bool g_displayTypeinfo = false;
46 bool g_isDtsFile = false;
47 std::string g_optLogLevel = "error";
48 uint32_t g_literalArrayCount = 0;
49 int32_t g_newLiteralArrayIndex = -1;
50 static constexpr const char* TSTYPE_ANNO_RECORD_NAME = "_ESTypeAnnotation";
51 static constexpr const char* TSTYPE_ANNO_ELEMENT_NAME = "_TypeOfInstruction";
52 std::string g_compilerOutputProto = "";
53 std::string g_recordName = "";
54 std::string g_outputFileName = "";
55 bool g_isStartDollar = true;
56 constexpr uint32_t LITERALBUFFERINDEXOFFSET = 100;
57 uint32_t MAX_UINT8 = static_cast<uint32_t>(std::numeric_limits<uint8_t>::max());
58 bool g_isOutputProto = false;
59 static constexpr const char* PROTO_BIN_SUFFIX = "protoBin";
60 
61 constexpr std::size_t BOUND_LEFT = 0;
62 constexpr std::size_t BOUND_RIGHT = 0;
63 constexpr std::size_t LINE_NUMBER = 0;
64 constexpr bool IS_DEFINED = true;
65 int g_opCodeIndex = 0;
66 std::unordered_map<int, panda::pandasm::Opcode> g_opcodeMap = {
67 #define OPLIST(opcode, name, optype, width, flags, def_idx, use_idxs) {g_opCodeIndex++, panda::pandasm::Opcode::opcode},
68     PANDA_INSTRUCTION_LIST(OPLIST)
69 #undef OPLIST
70     {-1, panda::pandasm::Opcode::INVALID},
71 };
72 
73 // pandasm helpers
MakeRecordDefinition(const std::string & name)74 static panda::pandasm::Record MakeRecordDefinition(const std::string &name)
75 {
76     auto record = panda::pandasm::Record(name, LANG_EXT);
77     return record;
78 }
79 
MakeFuncDefintion(const std::string & name,const std::string & returnType)80 static panda::pandasm::Function MakeFuncDefintion(const std::string &name, const std::string &returnType)
81 {
82     auto function = panda::pandasm::Function(
83         name,
84         LANG_EXT,
85         BOUND_LEFT,
86         BOUND_RIGHT,
87         WHOLE_LINE,
88         IS_DEFINED,
89         LINE_NUMBER);
90 
91     function.return_type = panda::pandasm::Type(returnType.c_str(), 0);
92     return function;
93 };
94 
MakeLabel(const std::string & name)95 static panda::pandasm::Label MakeLabel(const std::string &name)
96 {
97     auto label = panda::pandasm::Label(
98         name,
99         BOUND_LEFT,
100         BOUND_RIGHT,
101         WHOLE_LINE,
102         IS_DEFINED,
103         LINE_NUMBER);
104 
105     return label;
106 };
107 
108 
IsValidInt32(double value)109 static bool IsValidInt32(double value)
110 {
111     return (value <= static_cast<double>(std::numeric_limits<int>::max()) &&
112         value >= static_cast<double>(std::numeric_limits<int>::min()));
113 }
114 
GetDebugLog()115 bool GetDebugLog()
116 {
117     return g_debugLogEnabled;
118 }
119 
SetDebugLog(bool debugLog)120 static void SetDebugLog(bool debugLog)
121 {
122     g_debugLogEnabled = debugLog;
123 }
124 
GetDebugModeEnabled()125 bool GetDebugModeEnabled()
126 {
127     return g_debugModeEnabled;
128 }
129 
SetDebugModeEnabled(bool value)130 static void SetDebugModeEnabled(bool value)
131 {
132     g_debugModeEnabled = value;
133 }
134 
135 // Unified interface for debug log print
Logd(const char * format,...)136 static void Logd(const char *format, ...)
137 {
138     const int logBufferSize = 1024;
139     if (GetDebugLog()) {
140         va_list valist;
141         va_start(valist, format);
142         char logMsg[logBufferSize];
143         int ret = vsnprintf_s(logMsg, sizeof(logMsg), sizeof(logMsg) - 1, format, valist);
144         if (ret == -1) {
145             va_end(valist);
146             return;
147         }
148         std::cout << logMsg << std::endl;
149         va_end(valist);
150     }
151 }
152 
ConvertUtf8ToUtf16(const std::string & data)153 static std::u16string ConvertUtf8ToUtf16(const std::string &data)
154 {
155     std::u16string u16Data = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(data);
156     return u16Data;
157 }
158 
ConvertUtf16ToMUtf8(const uint16_t * u16Data,size_t u16DataSize)159 static std::string ConvertUtf16ToMUtf8(const uint16_t *u16Data, size_t u16DataSize)
160 {
161     size_t mutf8DataLen = panda::utf::Utf16ToMUtf8Size(u16Data, u16DataSize);
162     std::vector<uint8_t> mutf8Data(mutf8DataLen);
163 
164     panda::utf::ConvertRegionUtf16ToMUtf8(u16Data, mutf8Data.data(), u16DataSize, mutf8DataLen - 1, 0);
165 
166     std::string ret = std::string(reinterpret_cast<char *>(mutf8Data.data()));
167     return ret;
168 }
169 
ConvertUtf8ToMUtf8(const std::string & data)170 static std::string ConvertUtf8ToMUtf8(const std::string &data)
171 {
172     // WARN: std::u16string is set of uint_least16_t characters.
173     std::u16string u16String = ConvertUtf8ToUtf16(data);
174     uint16_t *u16Data = reinterpret_cast<uint16_t *>(u16String.data());
175     size_t u16DataSize = u16String.size();
176     return ConvertUtf16ToMUtf8(u16Data, u16DataSize);
177 }
178 
GetLiteralId(int64_t index)179 static std::string GetLiteralId(int64_t index)
180 {
181     return g_recordName + "_" + std::to_string(index);
182 }
183 
IsFuncMain0(std::string funcName)184 static bool IsFuncMain0(std::string funcName)
185 {
186     std::string expectedName = "func_main_0";
187     if (g_isMergeAbc) {
188         expectedName = g_recordName + "." + expectedName;
189     }
190     return funcName == expectedName;
191 }
192 
ParseUnicodeEscapeString(const std::string & data)193 static std::string ParseUnicodeEscapeString(const std::string &data)
194 {
195     const int unicodeEscapeSymbolLen = 2;
196     const int unicodeCharacterLen = 4;
197     const int base = 16;
198     std::string::size_type startIdx = 0;
199     std::string newData = "";
200     std::string::size_type len = data.length();
201     while (true) {
202         std::string unicodeStr = "\\u";
203         std::string::size_type index = data.find(unicodeStr, startIdx);
204         if (index == std::string::npos) {
205             break;
206         }
207         if (index != 0 && data[index - 1] == '\\') {
208             std::string tmpStr = data.substr(startIdx, index - 1 - startIdx) +
209                                 data.substr(index, unicodeEscapeSymbolLen); // delete a '\\'
210             newData += ConvertUtf8ToMUtf8(tmpStr);
211             startIdx = index + unicodeEscapeSymbolLen;
212         } else {
213             std::string tmpStr = data.substr(startIdx, index - startIdx);
214             newData += ConvertUtf8ToMUtf8(tmpStr);
215             std::string uStr = data.substr(index + unicodeEscapeSymbolLen, unicodeCharacterLen);
216             uint16_t u16Data = static_cast<uint16_t>(std::stoi(uStr.c_str(), NULL, base));
217             newData += ConvertUtf16ToMUtf8(&u16Data, 1);
218             startIdx = index + unicodeEscapeSymbolLen + unicodeCharacterLen;
219         }
220     }
221     if (startIdx != len) {
222         std::string tmpStr = data.substr(startIdx);
223         newData += ConvertUtf8ToMUtf8(tmpStr);
224     }
225     return newData;
226 }
227 
ParseString(const std::string & data)228 std::string ParseString(const std::string &data)
229 {
230     if (data.find("\\u") != std::string::npos) {
231         return ParseUnicodeEscapeString(data);
232     }
233 
234     return ConvertUtf8ToMUtf8(data);
235 }
236 
ParseLiteral(const Json::Value & literal,std::vector<panda::pandasm::LiteralArray::Literal> & literalArray)237 static void ParseLiteral(const Json::Value &literal, std::vector<panda::pandasm::LiteralArray::Literal> &literalArray)
238 {
239     panda::pandasm::LiteralArray::Literal tagLiteral;
240     panda::pandasm::LiteralArray::Literal valueLiteral;
241 
242     uint8_t tagValue = static_cast<uint8_t>(literal["t"].asUInt());
243 
244     tagLiteral.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
245     tagLiteral.value_ = tagValue;
246     literalArray.emplace_back(tagLiteral);
247 
248     switch (tagValue) {
249         case static_cast<uint8_t>(panda::panda_file::LiteralTag::BOOL): {
250             valueLiteral.tag_ = panda::panda_file::LiteralTag::BOOL;
251             valueLiteral.value_ = literal["v"].asBool();
252             break;
253         }
254         case static_cast<uint8_t>(panda::panda_file::LiteralTag::INTEGER): {
255             valueLiteral.tag_ = panda::panda_file::LiteralTag::INTEGER;
256             valueLiteral.value_ = static_cast<uint32_t>(literal["v"].asInt());
257             break;
258         }
259         case static_cast<uint8_t>(panda::panda_file::LiteralTag::DOUBLE): {
260             valueLiteral.tag_ = panda::panda_file::LiteralTag::DOUBLE;
261             valueLiteral.value_ = literal["v"].asDouble();
262             break;
263         }
264         case static_cast<uint8_t>(panda::panda_file::LiteralTag::STRING): {
265             valueLiteral.tag_ = panda::panda_file::LiteralTag::STRING;
266             valueLiteral.value_ = ParseString(literal["v"].asString());
267             break;
268         }
269         case static_cast<uint8_t>(panda::panda_file::LiteralTag::METHOD): {
270             valueLiteral.tag_ = panda::panda_file::LiteralTag::METHOD;
271             valueLiteral.value_ = ParseString(literal["v"].asString());
272             break;
273         }
274         case static_cast<uint8_t>(panda::panda_file::LiteralTag::GENERATORMETHOD): {
275             valueLiteral.tag_ = panda::panda_file::LiteralTag::GENERATORMETHOD;
276             valueLiteral.value_ = ParseString(literal["v"].asString());
277             break;
278         }
279         case static_cast<uint8_t>(panda::panda_file::LiteralTag::ACCESSOR): {
280             valueLiteral.tag_ = panda::panda_file::LiteralTag::ACCESSOR;
281             valueLiteral.value_ = static_cast<uint8_t>(0);
282             break;
283         }
284         case static_cast<uint8_t>(panda::panda_file::LiteralTag::METHODAFFILIATE): {
285             valueLiteral.tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE;
286             valueLiteral.value_ = static_cast<uint16_t>(literal["v"].asUInt());
287             break;
288         }
289         case static_cast<uint8_t>(panda::panda_file::LiteralTag::LITERALBUFFERINDEX): {
290             UNREACHABLE();
291         }
292         case static_cast<uint8_t>(panda::panda_file::LiteralTag::LITERALARRAY): {
293             valueLiteral.tag_ = panda::panda_file::LiteralTag::LITERALARRAY;
294             valueLiteral.value_ = ParseString(literal["v"].asString());
295             break;
296         }
297         case static_cast<uint8_t>(panda::panda_file::LiteralTag::BUILTINTYPEINDEX): {
298             valueLiteral.tag_ = panda::panda_file::LiteralTag::BUILTINTYPEINDEX;
299             valueLiteral.value_ = static_cast<uint8_t>(literal["v"].asInt());
300             break;
301         }
302         case static_cast<uint8_t>(panda::panda_file::LiteralTag::NULLVALUE): {
303             valueLiteral.tag_ = panda::panda_file::LiteralTag::NULLVALUE;
304             valueLiteral.value_ = static_cast<uint8_t>(0);
305             break;
306         }
307         default:
308             break;
309     }
310 
311     literalArray.emplace_back(valueLiteral);
312 }
313 
ParseRecord(const Json::Value & record)314 static panda::pandasm::Record ParseRecord(const Json::Value &record)
315 {
316     std::string recordName = "";
317     if (record.isMember("name") && record["name"].isString()) {
318         recordName = record["name"].asString();
319     }
320 
321     auto pandaRecord = MakeRecordDefinition(recordName);
322 
323     if (record.isMember("metadata") && record["metadata"].isObject()) {
324         auto metadata = record["metadata"];
325         if (metadata.isMember("attribute") && metadata["attribute"].isString()) {
326             std::string metAttribute = metadata["attribute"].asString();
327             if (metAttribute.length() > 0) {
328                 pandaRecord.metadata->SetAttribute(metAttribute);
329             }
330         }
331     }
332 
333     return pandaRecord;
334 }
335 
ParseInstructionOpCode(const Json::Value & ins,panda::pandasm::Ins & pandaIns)336 static void ParseInstructionOpCode(const Json::Value &ins, panda::pandasm::Ins &pandaIns)
337 {
338     if (ins.isMember("o") && ins["o"].isInt()) {
339         auto opcode = ins["o"].asInt();
340         if (g_opcodeMap.find(opcode) != g_opcodeMap.end()) {
341             pandaIns.opcode = g_opcodeMap[opcode];
342         }
343     }
344 }
345 
ParseInstructionRegs(const Json::Value & ins,panda::pandasm::Ins & pandaIns)346 static void ParseInstructionRegs(const Json::Value &ins, panda::pandasm::Ins &pandaIns)
347 {
348     if (ins.isMember("r") && ins["r"].isArray()) {
349         auto regs = ins["r"];
350         for (Json::ArrayIndex i = 0; i < regs.size(); ++i) {
351             pandaIns.regs.emplace_back(regs[i].asUInt());
352         }
353     }
354 }
355 
ParseInstructionIds(const Json::Value & ins,panda::pandasm::Ins & pandaIns)356 static void ParseInstructionIds(const Json::Value &ins, panda::pandasm::Ins &pandaIns)
357 {
358     if (ins.isMember("id") && ins["id"].isArray()) {
359         auto ids = ins["id"];
360         for (Json::ArrayIndex i = 0; i < ids.size(); ++i) {
361             if (ids[i].isString()) {
362                 pandaIns.ids.emplace_back(ParseString(ids[i].asString()));
363             }
364         }
365     }
366 }
367 
ParseInstructionImms(const Json::Value & ins,panda::pandasm::Ins & pandaIns)368 static void ParseInstructionImms(const Json::Value &ins, panda::pandasm::Ins &pandaIns)
369 {
370     if (ins.isMember("im") && ins["im"].isArray()) {
371         auto imms = ins["im"];
372         for (Json::ArrayIndex i = 0; i < imms.size(); ++i) {
373             double imsValue = imms[i].asDouble();
374             Logd("imm: %lf ", imsValue);
375             double intpart;
376             if (std::modf(imsValue, &intpart) == 0.0 && IsValidInt32(imsValue)) {
377                 pandaIns.imms.emplace_back(static_cast<int64_t>(imsValue));
378             } else {
379                 pandaIns.imms.emplace_back(imsValue);
380             }
381         }
382     }
383 }
384 
ParseInstructionLabel(const Json::Value & ins,panda::pandasm::Ins & pandaIns)385 static void ParseInstructionLabel(const Json::Value &ins, panda::pandasm::Ins &pandaIns)
386 {
387     if (ins.isMember("l") && ins["l"].isString()) {
388         std::string label = ins["l"].asString();
389         if (label.length() != 0) {
390             Logd("label:\t%s", label.c_str());
391             pandaIns.set_label = true;
392             pandaIns.label = label;
393             Logd("pandaIns.label:\t%s", pandaIns.label.c_str());
394         }
395     }
396 }
397 
ParseInstructionDebugInfo(const Json::Value & ins,panda::pandasm::Ins & pandaIns)398 static void ParseInstructionDebugInfo(const Json::Value &ins, panda::pandasm::Ins &pandaIns)
399 {
400     panda::pandasm::debuginfo::Ins insDebug;
401     if (ins.isMember("d") && ins["d"].isObject()) {
402         auto debugPosInfo = ins["d"];
403         if (GetDebugModeEnabled()) {
404             if (debugPosInfo.isMember("bl") && debugPosInfo["bl"].isInt()) {
405                 insDebug.bound_left = debugPosInfo["bl"].asUInt();
406             }
407 
408             if (debugPosInfo.isMember("br") && debugPosInfo["br"].isInt()) {
409                 insDebug.bound_right = debugPosInfo["br"].asUInt();
410             }
411 
412             // whole line
413             if (debugPosInfo.isMember("w") && debugPosInfo["w"].isString()) {
414                 insDebug.whole_line = debugPosInfo["w"].asString();
415             }
416 
417             // column number
418             if (debugPosInfo.isMember("c") && debugPosInfo["c"].isInt()) {
419                 insDebug.column_number = debugPosInfo["c"].asInt();
420             }
421         }
422 
423         // line number
424         if (debugPosInfo.isMember("l") && debugPosInfo["l"].isInt()) {
425             insDebug.line_number = debugPosInfo["l"].asInt();
426         }
427     }
428 
429     pandaIns.ins_debug = insDebug;
430 }
431 
ParseInstruction(const Json::Value & ins)432 static panda::pandasm::Ins ParseInstruction(const Json::Value &ins)
433 {
434     panda::pandasm::Ins pandaIns;
435     ParseInstructionOpCode(ins, pandaIns);
436     ParseInstructionRegs(ins, pandaIns);
437     ParseInstructionIds(ins, pandaIns);
438     ParseInstructionImms(ins, pandaIns);
439     ParseInstructionLabel(ins, pandaIns);
440     ParseInstructionDebugInfo(ins, pandaIns);
441     return pandaIns;
442 }
443 
ParseVariablesDebugInfo(const Json::Value & function,panda::pandasm::Function & pandaFunc)444 static int ParseVariablesDebugInfo(const Json::Value &function, panda::pandasm::Function &pandaFunc)
445 {
446     if (!GetDebugModeEnabled()) {
447         return RETURN_SUCCESS;
448     }
449 
450     if (function.isMember("v") && function["v"].isArray()) {
451         for (Json::ArrayIndex i = 0; i < function["v"].size(); ++i) {
452             if (!function["v"][i].isObject()) {
453                 continue;
454             }
455 
456             panda::pandasm::debuginfo::LocalVariable variableDebug;
457             auto variable = function["v"][i];
458             if (variable.isMember("n") && variable["n"].isString()) {
459                 variableDebug.name = variable["n"].asString();  // name
460             }
461 
462             if (variable.isMember("s") && variable["s"].isString()) {
463                 variableDebug.signature = variable["s"].asString();  // signature
464             }
465 
466             if (variable.isMember("st") && variable["st"].isString()) {
467                 variableDebug.signature_type = variable["st"].asString();  // signature type
468             }
469 
470             if (variable.isMember("r") && variable["r"].isInt()) {
471                 variableDebug.reg = variable["r"].asInt();  // regs
472             }
473 
474             if (variable.isMember("start") && variable["start"].isInt()) {
475                 variableDebug.start = variable["start"].asUInt();  // start
476             }
477 
478             if (variable.isMember("len") && variable["len"].isInt()) {
479                 variableDebug.length = variable["len"].asUInt();  // length
480             }
481 
482             pandaFunc.local_variable_debug.push_back(variableDebug);
483         }
484     }
485 
486     return RETURN_SUCCESS;
487 }
488 
ParseSourceFileInfo(const Json::Value & function,panda::pandasm::Function & pandaFunc)489 static int ParseSourceFileInfo(const Json::Value &function, panda::pandasm::Function &pandaFunc)
490 {
491     if (function.isMember("sf") && function["sf"].isString()) {
492         pandaFunc.source_file = function["sf"].asString();
493     }
494 
495     if (function.isMember("sc") && function["sc"].isString()) {
496         pandaFunc.source_code = function["sc"].asString();
497     }
498 
499     return RETURN_SUCCESS;
500 }
501 
ParsecatchBlock(const Json::Value & catch_block)502 static panda::pandasm::Function::CatchBlock ParsecatchBlock(const Json::Value &catch_block)
503 {
504     panda::pandasm::Function::CatchBlock pandaCatchBlock;
505 
506     if (catch_block.isMember("tb_lab") && catch_block["tb_lab"].isString()) {
507         pandaCatchBlock.try_begin_label = catch_block["tb_lab"].asString();
508     }
509 
510     if (catch_block.isMember("te_lab") && catch_block["te_lab"].isString()) {
511         pandaCatchBlock.try_end_label = catch_block["te_lab"].asString();
512     }
513 
514     if (catch_block.isMember("cb_lab") && catch_block["cb_lab"].isString()) {
515         pandaCatchBlock.catch_begin_label = catch_block["cb_lab"].asString();
516         pandaCatchBlock.catch_end_label = catch_block["cb_lab"].asString();
517     }
518 
519     return pandaCatchBlock;
520 }
521 
GetFunctionDefintion(const Json::Value & function)522 panda::pandasm::Function GetFunctionDefintion(const Json::Value &function)
523 {
524     std::string funcName = "";
525     if (function.isMember("n") && function["n"].isString()) {
526         funcName = function["n"].asString();
527     }
528 
529     std::string funcRetType = "";
530     auto params = std::vector<panda::pandasm::Function::Parameter>();
531     if (function.isMember("s") && function["s"].isObject()) {
532         auto signature = function["s"];
533         if (signature.isMember("rt") && signature["rt"].isString()) {
534             funcRetType = signature["rt"].asString();
535         } else {
536             funcRetType = "any";
537         }
538 
539         Logd("parsing function: %s return type: %s \n", funcName.c_str(), funcRetType.c_str());
540 
541         if (signature.isMember("p") && signature["p"].isInt()) {
542             auto paramNum = signature["p"].asUInt();
543             for (Json::ArrayIndex i = 0; i < paramNum; ++i) {
544                 params.emplace_back(panda::pandasm::Type("any", 0), LANG_EXT);
545             }
546         }
547     }
548 
549     uint32_t regsNum = 0;
550     if (function.isMember("r") && function["r"].isInt()) {
551         regsNum = function["r"].asUInt();
552     }
553 
554     auto pandaFunc = MakeFuncDefintion(funcName, funcRetType);
555     pandaFunc.params = std::move(params);
556     pandaFunc.regs_num = regsNum;
557 
558     return pandaFunc;
559 }
560 
ParseFunctionInstructions(const Json::Value & function,panda::pandasm::Function & pandaFunc)561 static void ParseFunctionInstructions(const Json::Value &function, panda::pandasm::Function &pandaFunc)
562 {
563     if (function.isMember("i") && function["i"].isArray()) {
564         auto ins = function["i"];
565         for (Json::ArrayIndex i = 0; i < ins.size(); ++i) {
566             if (!ins[i].isObject()) {
567                 continue;
568             }
569 
570             auto paIns = ParseInstruction(ins[i]);
571             Logd("instruction:\t%s", paIns.ToString().c_str());
572             pandaFunc.ins.push_back(paIns);
573         }
574     }
575 }
576 
ParseFunctionLabels(const Json::Value & function,panda::pandasm::Function & pandaFunc)577 static void ParseFunctionLabels(const Json::Value &function, panda::pandasm::Function &pandaFunc)
578 {
579     if (function.isMember("l") && function["l"].isArray()) {
580         auto labels = function["l"];
581         for (Json::ArrayIndex i = 0; i < labels.size(); ++i) {
582             auto labelName = labels[i].asString();
583             auto pandaLabel = MakeLabel(labelName);
584 
585             Logd("label_name:\t%s", labelName.c_str());
586             pandaFunc.label_table.emplace(labelName, pandaLabel);
587         }
588     }
589 }
590 
ParseFunctionCatchTables(const Json::Value & function,panda::pandasm::Function & pandaFunc)591 static void ParseFunctionCatchTables(const Json::Value &function, panda::pandasm::Function &pandaFunc)
592 {
593     if (function.isMember("ca_tab") && function["ca_tab"].isArray()) {
594         auto catchTables = function["ca_tab"];
595         for (Json::ArrayIndex i = 0; i < catchTables.size(); ++i) {
596             auto catchTable = catchTables[i];
597             if (!catchTable.isObject()) {
598                 continue;
599             }
600 
601             auto pandaCatchBlock = ParsecatchBlock(catchTable);
602             pandaFunc.catch_blocks.push_back(pandaCatchBlock);
603         }
604     }
605 }
606 
GetInstTypeMap(const Json::Value & function,panda::pandasm::Function & pandaFunc)607 static std::vector<std::pair<int32_t, uint32_t>> GetInstTypeMap(const Json::Value &function,
608                                                                 panda::pandasm::Function &pandaFunc)
609 {
610     constexpr const char* TYPE_INFO = "ti";
611     std::vector<std::pair<int32_t, uint32_t>> instTypeMap;
612     if (!function.isMember(TYPE_INFO) || !function[TYPE_INFO].isArray()) {
613         return instTypeMap;
614     }
615 
616     // must be instidx <-> typeidx pair
617     auto sourceTypeMap = function[TYPE_INFO];
618     constexpr size_t TYPE_MAP_ELEMENT_SIZE = 2;
619     ASSERT(sourceTypeMap.size() % TYPE_MAP_ELEMENT_SIZE == 0);
620     instTypeMap.reserve(sourceTypeMap.size() / TYPE_MAP_ELEMENT_SIZE);
621 
622     // fix inst index since invalid inst won't be emit
623     int32_t start = 0;
624     int32_t remove = 0;
625     for (Json::ArrayIndex i = 0; i < sourceTypeMap.size(); i += TYPE_MAP_ELEMENT_SIZE) {
626         auto instIndex = sourceTypeMap[i].asInt();
627         auto typeIndex = sourceTypeMap[i + 1].asUInt();
628         if (instIndex < 0) { // para
629             instTypeMap.emplace_back(instIndex, typeIndex);
630             continue;
631         }
632 
633         // remove the invalid instruction
634         for (; start < instIndex; start++) {
635             if (pandaFunc.ins[start].opcode == panda::pandasm::Opcode::INVALID) {
636                 remove++;
637             }
638         }
639         instTypeMap.emplace_back(instIndex - remove, typeIndex);
640     }
641 
642     if (g_displayTypeinfo) {
643         std::cout << "Handle types for function: " << pandaFunc.name << std::endl;
644         std::cout << "(instruction order, type): ";
645         for (auto &it : instTypeMap) {
646             std::cout << "(" << it.first << ", " << it.second << "), ";
647         }
648         std::cout << std::endl;
649     }
650 
651     return instTypeMap;
652 }
653 
ParseFunctionTypeInfo(const Json::Value & function,panda::pandasm::Function & pandaFunc,panda::pandasm::Program & prog)654 static void ParseFunctionTypeInfo(const Json::Value &function, panda::pandasm::Function &pandaFunc,
655                                   panda::pandasm::Program &prog)
656 {
657     auto instTypeMap = GetInstTypeMap(function, pandaFunc);
658     if (!instTypeMap.empty()) {
659         std::vector<panda::pandasm::LiteralArray::Literal> literalArray;
660         for (auto &it : instTypeMap) {
661             panda::pandasm::LiteralArray::Literal instTagLiteral;
662             panda::pandasm::LiteralArray::Literal instValueLiteral;
663             instTagLiteral.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
664             ASSERT(static_cast<uint32_t>(panda::panda_file::LiteralTag::INTEGER) <= MAX_UINT8);
665             instTagLiteral.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::INTEGER);
666             literalArray.emplace_back(instTagLiteral);
667             instValueLiteral.tag_ = panda::panda_file::LiteralTag::INTEGER;
668             instValueLiteral.value_ = static_cast<uint32_t>(it.first);
669             literalArray.emplace_back(instValueLiteral);
670 
671             panda::pandasm::LiteralArray::Literal typeTagLiteral;
672             panda::pandasm::LiteralArray::Literal typeValueLiteral;
673             typeTagLiteral.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
674             auto type = it.second;
675             if (type < LITERALBUFFERINDEXOFFSET) {
676                 ASSERT(static_cast<uint32_t>(panda::panda_file::LiteralTag::BUILTINTYPEINDEX) <= MAX_UINT8);
677                 typeTagLiteral.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::BUILTINTYPEINDEX);
678                 typeValueLiteral.tag_ = panda::panda_file::LiteralTag::BUILTINTYPEINDEX;
679                 ASSERT(type <= MAX_UINT8);
680                 typeValueLiteral.value_ = static_cast<uint8_t>(type);
681             } else {
682                 ASSERT(static_cast<uint32_t>(panda::panda_file::LiteralTag::LITERALARRAY) <= MAX_UINT8);
683                 typeTagLiteral.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::LITERALARRAY);
684                 typeValueLiteral.tag_ = panda::panda_file::LiteralTag::LITERALARRAY;
685                 std::string typeId = GetLiteralId(type - LITERALBUFFERINDEXOFFSET);
686                 typeValueLiteral.value_ = typeId;
687             }
688             literalArray.emplace_back(typeTagLiteral);
689             literalArray.emplace_back(typeValueLiteral);
690         }
691 
692         std::string litId = GetLiteralId(g_newLiteralArrayIndex--);
693         auto literalarrayInstance = panda::pandasm::LiteralArray(literalArray);
694         prog.literalarray_table.emplace(litId, std::move(literalarrayInstance));
695 
696         panda::pandasm::AnnotationData funcAnnotation(TSTYPE_ANNO_RECORD_NAME);
697         panda::pandasm::AnnotationElement typeOfVregElement(
698             TSTYPE_ANNO_ELEMENT_NAME, std::make_unique<panda::pandasm::ScalarValue>(
699             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(litId)));
700         funcAnnotation.AddElement(std::move(typeOfVregElement));
701         const_cast<std::vector<panda::pandasm::AnnotationData>&>(pandaFunc.metadata->GetAnnotations()).push_back(
702             std::move(funcAnnotation));
703     }
704 }
705 
CreateLiteralArrayForType(const Json::Value & types,panda::pandasm::Program & prog)706 static std::string CreateLiteralArrayForType(const Json::Value &types, panda::pandasm::Program &prog)
707 {
708     std::vector<panda::pandasm::LiteralArray::Literal> literalArray;
709     for (Json::ArrayIndex i = 0; i < types.size(); i++) {
710         auto type = types[i];
711         if (!type.isObject()) {
712             continue;
713         }
714 
715         panda::pandasm::LiteralArray::Literal symbolTagLiteral;
716         panda::pandasm::LiteralArray::Literal symbolValueLiteral;
717         std::string symbol = "";
718         if (type.isMember("symbol") && type["symbol"].isString()) {
719             symbol = type["symbol"].asString();
720         }
721         symbolTagLiteral.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
722         ASSERT(static_cast<uint32_t>(panda::panda_file::LiteralTag::STRING) <= MAX_UINT8);
723         symbolTagLiteral.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::STRING);
724         symbolValueLiteral.tag_ = panda::panda_file::LiteralTag::STRING;
725         symbolValueLiteral.value_ = symbol;
726         literalArray.emplace_back(symbolTagLiteral);
727         literalArray.emplace_back(symbolValueLiteral);
728 
729         panda::pandasm::LiteralArray::Literal typeTagLiteral;
730         panda::pandasm::LiteralArray::Literal typeValueLiteral;
731         uint32_t typeIndex = 0;
732         if (type.isMember("type") && type["type"].isInt()) {
733             typeIndex = type["type"].asUInt();
734         }
735         typeTagLiteral.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
736         if (typeIndex < LITERALBUFFERINDEXOFFSET) {
737             ASSERT(static_cast<uint32_t>(panda::panda_file::LiteralTag::BUILTINTYPEINDEX) <= MAX_UINT8);
738             typeTagLiteral.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::BUILTINTYPEINDEX);
739             typeValueLiteral.tag_ = panda::panda_file::LiteralTag::BUILTINTYPEINDEX;
740             ASSERT(typeIndex <= MAX_UINT8);
741             typeValueLiteral.value_ = static_cast<uint8_t>(typeIndex);
742         } else {
743             ASSERT(static_cast<uint32_t>(panda::panda_file::LiteralTag::LITERALARRAY) <= MAX_UINT8);
744             typeTagLiteral.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::LITERALARRAY);
745             typeValueLiteral.tag_ = panda::panda_file::LiteralTag::LITERALARRAY;
746             std::string litId = GetLiteralId(typeIndex - LITERALBUFFERINDEXOFFSET);
747             typeValueLiteral.value_ = litId;
748         }
749 
750         literalArray.emplace_back(typeTagLiteral);
751         literalArray.emplace_back(typeValueLiteral);
752     }
753 
754     std::string litId = GetLiteralId(g_newLiteralArrayIndex--);
755     auto literalarrayInstance = panda::pandasm::LiteralArray(literalArray);
756     prog.literalarray_table.emplace(litId, std::move(literalarrayInstance));
757     return litId;
758 }
759 
ParseFunctionExportedType(const Json::Value & function,panda::pandasm::Function & pandaFunc,panda::pandasm::Program & prog)760 static void ParseFunctionExportedType(const Json::Value &function, panda::pandasm::Function &pandaFunc,
761                                       panda::pandasm::Program &prog)
762 {
763     std::string funcName = "";
764     if (function.isMember("n") && function["n"].isString()) {
765         funcName = function["n"].asString();
766         if (!IsFuncMain0(funcName)) {
767             return;
768         }
769     }
770 
771     if (function.isMember("es2t") && function["es2t"].isArray()) {
772         auto exportedTypes = function["es2t"];
773         panda::pandasm::AnnotationData funcAnnotation(TSTYPE_ANNO_RECORD_NAME);
774         std::string litId = CreateLiteralArrayForType(exportedTypes, prog);
775 
776         std::string symbolTypeAnnotationName = "exportedSymbolTypes";
777         panda::pandasm::AnnotationElement exportedSymbolTypesElement(symbolTypeAnnotationName,
778             std::make_unique<panda::pandasm::ScalarValue>(
779                 panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(litId)));
780         funcAnnotation.AddElement(std::move(exportedSymbolTypesElement));
781 
782         const_cast<std::vector<panda::pandasm::AnnotationData>&>(
783             pandaFunc.metadata->GetAnnotations()).push_back(std::move(funcAnnotation));
784     }
785 }
786 
ParseFunctionDeclaredType(const Json::Value & function,panda::pandasm::Function & pandaFunc,panda::pandasm::Program & prog)787 static void ParseFunctionDeclaredType(const Json::Value &function, panda::pandasm::Function &pandaFunc,
788                                       panda::pandasm::Program &prog)
789 {
790     std::string funcName = "";
791     if (function.isMember("n") && function["n"].isString()) {
792         funcName = function["n"].asString();
793         if (!IsFuncMain0(funcName)) {
794             return;
795         }
796     }
797 
798     if (function.isMember("ds2t") && function["ds2t"].isArray()) {
799         auto declaredTypes = function["ds2t"];
800         panda::pandasm::AnnotationData funcAnnotation(TSTYPE_ANNO_RECORD_NAME);
801         std::string litId = CreateLiteralArrayForType(declaredTypes, prog);
802 
803         std::string symbolTypeAnnotationName = "declaredSymbolTypes";
804         panda::pandasm::AnnotationElement declaredSymbolTypesElement(symbolTypeAnnotationName,
805             std::make_unique<panda::pandasm::ScalarValue>(
806                 panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(litId)));
807         funcAnnotation.AddElement(std::move(declaredSymbolTypesElement));
808 
809         const_cast<std::vector<panda::pandasm::AnnotationData>&>(pandaFunc.metadata->GetAnnotations()).push_back(
810             std::move(funcAnnotation));
811     }
812 }
813 
ParseFunctionKind(const Json::Value & function,panda::pandasm::Function & pandaFunc)814 static void ParseFunctionKind(const Json::Value &function, panda::pandasm::Function &pandaFunc) {
815     panda::panda_file::FunctionKind funcKind {};
816     if (function.isMember("kind") && function["kind"].isInt()) {
817         funcKind = static_cast<panda::panda_file::FunctionKind>(function["kind"].asUInt());
818         pandaFunc.SetFunctionKind(funcKind);
819     }
820 }
821 
ParseFunctionIcSize(const Json::Value & function,panda::pandasm::Function & pandaFunc)822 static void ParseFunctionIcSize(const Json::Value &function, panda::pandasm::Function &pandaFunc) {
823     if (function.isMember("icSize") && function["icSize"].isInt()) {
824         size_t icSize = static_cast<size_t>(function["icSize"].asUInt());
825         pandaFunc.SetSlotsNum(icSize);
826     }
827 }
828 
ParseFunction(const Json::Value & function,panda::pandasm::Program & prog)829 static panda::pandasm::Function ParseFunction(const Json::Value &function, panda::pandasm::Program &prog)
830 {
831     auto pandaFunc = GetFunctionDefintion(function);
832     ParseFunctionInstructions(function, pandaFunc);
833     ParseVariablesDebugInfo(function, pandaFunc);
834     ParseSourceFileInfo(function, pandaFunc);
835     ParseFunctionLabels(function, pandaFunc);
836     ParseFunctionCatchTables(function, pandaFunc);
837     ParseFunctionTypeInfo(function, pandaFunc, prog);
838     ParseFunctionExportedType(function, pandaFunc, prog);
839     ParseFunctionDeclaredType(function, pandaFunc, prog);
840     ParseFunctionKind(function, pandaFunc);
841     ParseFunctionIcSize(function, pandaFunc);
842 
843     if (g_isDtsFile && !IsFuncMain0(pandaFunc.name)) {
844         pandaFunc.metadata->SetAttribute("external");
845     }
846 
847     return pandaFunc;
848 }
849 
GenerateESCallTypeAnnotationRecord(panda::pandasm::Program & prog)850 static void GenerateESCallTypeAnnotationRecord(panda::pandasm::Program &prog)
851 {
852     auto callTypeAnnotationRecord = panda::pandasm::Record("_ESCallTypeAnnotation", LANG_EXT);
853     callTypeAnnotationRecord.metadata->SetAttribute("external");
854     callTypeAnnotationRecord.metadata->SetAccessFlags(panda::ACC_ANNOTATION);
855     prog.record_table.emplace(callTypeAnnotationRecord.name, std::move(callTypeAnnotationRecord));
856 }
GenerateESTypeAnnotationRecord(panda::pandasm::Program & prog)857 static void GenerateESTypeAnnotationRecord(panda::pandasm::Program &prog)
858 {
859     auto tsTypeAnnotationRecord = panda::pandasm::Record(TSTYPE_ANNO_RECORD_NAME, LANG_EXT);
860     tsTypeAnnotationRecord.metadata->SetAttribute("external");
861     tsTypeAnnotationRecord.metadata->SetAccessFlags(panda::ACC_ANNOTATION);
862     prog.record_table.emplace(tsTypeAnnotationRecord.name, std::move(tsTypeAnnotationRecord));
863 }
864 
GenerateESModuleRecord(panda::pandasm::Program & prog)865 static void GenerateESModuleRecord(panda::pandasm::Program &prog)
866 {
867     auto ecmaModuleRecord = panda::pandasm::Record("_ESModuleRecord", LANG_EXT);
868     ecmaModuleRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC);
869     prog.record_table.emplace(ecmaModuleRecord.name, std::move(ecmaModuleRecord));
870 }
871 
GenerateCommonJsRecord(panda::pandasm::Program & prog,bool isCommonJs)872 static void GenerateCommonJsRecord(panda::pandasm::Program &prog, bool isCommonJs)
873 {
874     // when multi-abc file get merged, field should be inserted in abc's own record
875     auto commonjsRecord = panda::pandasm::Record("_CommonJsRecord", LANG_EXT);
876     commonjsRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC);
877     auto isCommonJsField = panda::pandasm::Field(LANG_EXT);
878     isCommonJsField.name = "isCommonJs";
879     isCommonJsField.type = panda::pandasm::Type("u8", 0);
880     isCommonJsField.metadata->SetValue(panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(
881         static_cast<uint8_t>(isCommonJs)));
882     commonjsRecord.field_list.emplace_back(std::move(isCommonJsField));
883 
884     prog.record_table.emplace(commonjsRecord.name, std::move(commonjsRecord));
885 }
886 
SetCommonjsField(panda::pandasm::Program & prog,bool isCommonjs)887 static void SetCommonjsField(panda::pandasm::Program &prog, bool isCommonjs)
888 {
889     auto iter = prog.record_table.find(g_recordName);
890     if (iter != prog.record_table.end()) {
891         auto &rec = iter->second;
892         auto isCommonJsField = panda::pandasm::Field(LANG_EXT);
893         isCommonJsField.name = "isCommonjs";
894         isCommonJsField.type = panda::pandasm::Type("u8", 0);
895         isCommonJsField.metadata->SetValue(
896             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(static_cast<uint8_t>(isCommonjs)));
897         rec.field_list.emplace_back(std::move(isCommonJsField));
898     }
899 }
900 
AddModuleRecord(panda::pandasm::Program & prog,const std::string & moduleName)901 static void AddModuleRecord(panda::pandasm::Program &prog, const std::string &moduleName)
902 {
903     std::string moduleRecordName = g_isMergeAbc ? g_recordName : "_ESModuleRecord";
904     std::string fieldName = g_isMergeAbc ? "moduleRecordIdx" : moduleName;
905     auto iter = prog.record_table.find(moduleRecordName);
906     if (iter != prog.record_table.end()) {
907         auto &rec = iter->second;
908         auto moduleIdxField = panda::pandasm::Field(LANG_EXT);
909         moduleIdxField.name = fieldName;
910         moduleIdxField.type = panda::pandasm::Type("u32", 0);
911         std::string moduleId = GetLiteralId(g_newLiteralArrayIndex);
912         moduleIdxField.metadata->SetValue(
913             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(moduleId));
914 
915         rec.field_list.emplace_back(std::move(moduleIdxField));
916     }
917 }
918 
ParseJson(const std::string & data,Json::Value & rootValue)919 int ParseJson(const std::string &data, Json::Value &rootValue)
920 {
921     JSONCPP_STRING errs;
922     Json::CharReaderBuilder readerBuilder;
923 
924     std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
925     bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &rootValue, &errs);
926     if (!res || !errs.empty()) {
927         std::cerr << "ParseJson err. " << errs.c_str() << std::endl;
928         return RETURN_FAILED;
929     }
930 
931     if (!rootValue.isObject()) {
932         std::cerr << "The parsed json data is not one object" << std::endl;
933         return RETURN_FAILED;
934     }
935 
936     return RETURN_SUCCESS;
937 }
938 
ParseMergeAbcMode(const Json::Value & rootValue)939 static void ParseMergeAbcMode(const Json::Value &rootValue)
940 {
941     Logd("---------------parse is_merge_abc----------------");
942     if (rootValue.isMember("merge_abc") && rootValue["merge_abc"].isBool()) {
943         g_isMergeAbc = rootValue["merge_abc"].asBool();
944     }
945 }
946 
ParseModuleMode(const Json::Value & rootValue,panda::pandasm::Program & prog)947 static void ParseModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog)
948 {
949     Logd("----------------parse module_mode-----------------");
950     if (rootValue.isMember("module_mode") && rootValue["module_mode"].isBool()) {
951         if (rootValue["module_mode"].asBool() && !g_isMergeAbc) {
952             GenerateESModuleRecord(prog);
953         }
954     }
955 }
956 
ParseCommonJsModuleMode(const Json::Value & rootValue,panda::pandasm::Program & prog)957 static void ParseCommonJsModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog)
958 {
959     Logd("------------parse commonjs_module_mode-------------");
960     if (rootValue.isMember("commonjs_module") && rootValue["commonjs_module"].isBool()) {
961         if (g_isMergeAbc) {
962             SetCommonjsField(prog, rootValue["commonjs_module"].asBool());
963         } else {
964             if (rootValue["commonjs_module"].asBool()) {
965                 GenerateCommonJsRecord(prog, true);
966             }
967         }
968     }
969 }
970 
ParseLogEnable(const Json::Value & rootValue)971 void ParseLogEnable(const Json::Value &rootValue)
972 {
973     if (rootValue.isMember("log_enabled") && rootValue["log_enabled"].isBool()) {
974         SetDebugLog(rootValue["log_enabled"].asBool());
975     }
976 }
977 
ParseDebugMode(const Json::Value & rootValue)978 void ParseDebugMode(const Json::Value &rootValue)
979 {
980     Logd("-----------------parse debug_mode-----------------");
981     if (rootValue.isMember("debug_mode") && rootValue["debug_mode"].isBool()) {
982         SetDebugModeEnabled(rootValue["debug_mode"].asBool());
983     }
984 }
985 
ParseOptLevel(const Json::Value & rootValue)986 static void ParseOptLevel(const Json::Value &rootValue)
987 {
988     Logd("-----------------parse opt level-----------------");
989     if (rootValue.isMember("opt_level") && rootValue["opt_level"].isInt()) {
990         g_optLevel = rootValue["opt_level"].asInt();
991     }
992     if (GetDebugModeEnabled()) {
993         g_optLevel = 0;
994     }
995 }
996 
ParseDisplayTypeinfo(const Json::Value & rootValue)997 static void ParseDisplayTypeinfo(const Json::Value &rootValue)
998 {
999     Logd("-----------------parse enable_typeinfo-----------------");
1000     if (rootValue.isMember("display_typeinfo") && rootValue["display_typeinfo"].isBool()) {
1001         g_displayTypeinfo = rootValue["display_typeinfo"].asBool();
1002     }
1003 }
1004 
ParseOptLogLevel(const Json::Value & rootValue)1005 static void ParseOptLogLevel(const Json::Value &rootValue)
1006 {
1007     Logd("-----------------parse opt log level-----------------");
1008     if (rootValue.isMember("opt_log_level") && rootValue["opt_log_level"].isString()) {
1009         g_optLogLevel = rootValue["opt_log_level"].asString();
1010     }
1011 }
1012 
ParseIsDtsFile(const Json::Value & rootValue)1013 static void ParseIsDtsFile(const Json::Value &rootValue)
1014 {
1015     Logd("-----------------parse is dts file-----------------");
1016     if (rootValue.isMember("is_dts_file") && rootValue["is_dts_file"].isBool()) {
1017         g_isDtsFile = rootValue["is_dts_file"].asBool();
1018     }
1019 }
1020 
ParseEnableTypeInfo(const Json::Value & rootValue)1021 static void ParseEnableTypeInfo(const Json::Value &rootValue)
1022 {
1023     Logd("-----------------parse enable type info-----------------");
1024     if (rootValue.isMember("record_type") && rootValue["record_type"].isBool()) {
1025         g_enableTypeinfo = rootValue["record_type"].asBool();
1026     }
1027 }
1028 
ParseCompilerOutputProto(const Json::Value & rootValue)1029 static void ParseCompilerOutputProto(const Json::Value &rootValue)
1030 {
1031     Logd("-----------------parse compiler output proto-----------------");
1032     if (rootValue.isMember("output-proto") && rootValue["output-proto"].isBool()) {
1033         g_isOutputProto = rootValue["output-proto"].asBool();
1034     }
1035 }
1036 
ReplaceAllDistinct(std::string & str,const std::string & oldValue,const std::string & newValue)1037 static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, const std::string &newValue)
1038 {
1039     for (std::string::size_type pos(0); pos != std::string::npos; pos += newValue.length()) {
1040         if ((pos = str.find(oldValue, pos)) != std::string::npos) {
1041             str.replace(pos, oldValue.length(), newValue);
1042         } else {
1043             break;
1044         }
1045     }
1046 }
1047 
ParseOptions(const Json::Value & rootValue,panda::pandasm::Program & prog)1048 static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program &prog)
1049 {
1050     GenerateESCallTypeAnnotationRecord(prog);
1051     GenerateESTypeAnnotationRecord(prog);
1052     ParseMergeAbcMode(rootValue);
1053     ParseModuleMode(rootValue, prog);
1054     ParseCommonJsModuleMode(rootValue, prog);
1055     ParseLogEnable(rootValue);
1056     ParseDebugMode(rootValue);
1057     ParseOptLevel(rootValue);
1058     ParseDisplayTypeinfo(rootValue);
1059     ParseOptLogLevel(rootValue);
1060     ParseIsDtsFile(rootValue);
1061     ParseEnableTypeInfo(rootValue);
1062     ParseCompilerOutputProto(rootValue);
1063 }
1064 
ParseSingleFunc(const Json::Value & rootValue,panda::pandasm::Program & prog)1065 static void ParseSingleFunc(const Json::Value &rootValue, panda::pandasm::Program &prog)
1066 {
1067     auto function = ParseFunction(rootValue["fb"], prog);
1068     prog.function_table.emplace(function.name.c_str(), std::move(function));
1069 }
1070 
ParseRec(const Json::Value & rootValue,panda::pandasm::Program & prog)1071 static void ParseRec(const Json::Value &rootValue, panda::pandasm::Program &prog)
1072 {
1073     auto record = ParseRecord(rootValue["rb"]);
1074     g_recordName = record.name;
1075     prog.record_table.emplace(record.name.c_str(), std::move(record));
1076 }
1077 
SetPackageName(const std::string & packageName,panda::pandasm::Program & prog)1078 static void SetPackageName(const std::string &packageName, panda::pandasm::Program &prog)
1079 {
1080     auto iter = prog.record_table.find(g_recordName);
1081     if (iter != prog.record_table.end()) {
1082         auto &rec = iter->second;
1083         auto pkgNameField = panda::pandasm::Field(LANG_EXT);
1084         pkgNameField.name = "pkgName@" + packageName;
1085         pkgNameField.type = panda::pandasm::Type("u8", 0);
1086         pkgNameField.metadata->SetValue(
1087             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(static_cast<uint8_t>(0)));
1088 
1089         rec.field_list.emplace_back(std::move(pkgNameField));
1090     }
1091 }
1092 
ParseInputJsonFileContent(const Json::Value & rootValue,panda::pandasm::Program & prog)1093 static void ParseInputJsonFileContent(const Json::Value &rootValue, panda::pandasm::Program &prog)
1094 {
1095     auto iter = prog.record_table.find(g_recordName);
1096     if (iter != prog.record_table.end()) {
1097         auto &rec = iter->second;
1098 
1099         auto inputJsonFileContentField = panda::pandasm::Field(LANG_EXT);
1100         inputJsonFileContentField.name = "jsonFileContent";
1101         inputJsonFileContentField.type = panda::pandasm::Type("u32", 0);
1102         inputJsonFileContentField.metadata->SetValue(
1103             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::STRING>(
1104             static_cast<std::string_view>(rootValue["ijfc"].asString())));
1105         rec.field_list.emplace_back(std::move(inputJsonFileContentField));
1106     }
1107 }
1108 
ParseSingleStr(const Json::Value & rootValue,panda::pandasm::Program & prog)1109 static void ParseSingleStr(const Json::Value &rootValue, panda::pandasm::Program &prog)
1110 {
1111     auto strArr = rootValue["s"];
1112     for (Json::ArrayIndex i = 0; i < strArr.size(); ++i) {
1113         prog.strings.insert(ParseString(strArr[i].asString()));
1114     }
1115 }
1116 
ParseSingleLiteralBuf(const Json::Value & rootValue,panda::pandasm::Program & prog)1117 static void ParseSingleLiteralBuf(const Json::Value &rootValue, panda::pandasm::Program &prog)
1118 {
1119     std::vector<panda::pandasm::LiteralArray::Literal> literalArray;
1120     auto literalBuffer = rootValue["lit_arr"];
1121     auto literals = literalBuffer["lb"];
1122     for (Json::ArrayIndex i = 0; i < literals.size(); ++i) {
1123         ParseLiteral(literals[i], literalArray);
1124     }
1125 
1126     auto literalarrayInstance = panda::pandasm::LiteralArray(literalArray);
1127     auto litId = literalBuffer["k"].asString();
1128     prog.literalarray_table.emplace(litId, std::move(literalarrayInstance));
1129 }
1130 
ParseModuleRequests(const Json::Value & moduleRequests,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1131 static void ParseModuleRequests(const Json::Value &moduleRequests,
1132                                 std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1133 {
1134     panda::pandasm::LiteralArray::Literal moduleSize = {
1135         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(moduleRequests.size())};
1136     moduleLiteralArray.emplace_back(moduleSize);
1137     for (Json::ArrayIndex i = 0; i < moduleRequests.size(); ++i) {
1138         panda::pandasm::LiteralArray::Literal moduleRequest = {
1139             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(moduleRequests[i].asString())};
1140         moduleLiteralArray.emplace_back(moduleRequest);
1141     }
1142 }
1143 
ParseRegularImportEntries(const Json::Value & regularImportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1144 static void ParseRegularImportEntries(const Json::Value &regularImportEntries,
1145                                       std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1146 {
1147     panda::pandasm::LiteralArray::Literal entrySize = {
1148         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(regularImportEntries.size())};
1149     moduleLiteralArray.emplace_back(entrySize);
1150     for (Json::ArrayIndex i = 0; i < regularImportEntries.size(); ++i) {
1151         auto entry = regularImportEntries[i];
1152         panda::pandasm::LiteralArray::Literal localName = {
1153             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["localName"].asString())};
1154         moduleLiteralArray.emplace_back(localName);
1155         panda::pandasm::LiteralArray::Literal importName = {
1156             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["importName"].asString())};
1157         moduleLiteralArray.emplace_back(importName);
1158         panda::pandasm::LiteralArray::Literal moduleRequest = {
1159             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
1160             .value_ = static_cast<uint16_t>(entry["moduleRequest"].asUInt())};
1161         moduleLiteralArray.emplace_back(moduleRequest);
1162     }
1163 }
1164 
ParseNamespaceImportEntries(const Json::Value & namespaceImportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1165 static void ParseNamespaceImportEntries(const Json::Value &namespaceImportEntries,
1166                                         std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1167 {
1168     panda::pandasm::LiteralArray::Literal entrySize = {
1169         .tag_ = panda::panda_file::LiteralTag::INTEGER,
1170         .value_ = static_cast<uint32_t>(namespaceImportEntries.size())};
1171     moduleLiteralArray.emplace_back(entrySize);
1172     for (Json::ArrayIndex i = 0; i < namespaceImportEntries.size(); ++i) {
1173         auto entry = namespaceImportEntries[i];
1174         panda::pandasm::LiteralArray::Literal localName = {
1175             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["localName"].asString())};
1176         moduleLiteralArray.emplace_back(localName);
1177         panda::pandasm::LiteralArray::Literal moduleRequest = {
1178             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
1179             .value_ = static_cast<uint16_t>(entry["moduleRequest"].asUInt())};
1180         moduleLiteralArray.emplace_back(moduleRequest);
1181     }
1182 }
1183 
ParseLocalExportEntries(const Json::Value & localExportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1184 static void ParseLocalExportEntries(const Json::Value &localExportEntries,
1185                                     std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1186 {
1187     panda::pandasm::LiteralArray::Literal entrySize = {
1188         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(localExportEntries.size())};
1189     moduleLiteralArray.emplace_back(entrySize);
1190     for (Json::ArrayIndex i = 0; i < localExportEntries.size(); ++i) {
1191         auto entry = localExportEntries[i];
1192         panda::pandasm::LiteralArray::Literal localName = {
1193             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["localName"].asString())};
1194         moduleLiteralArray.emplace_back(localName);
1195         panda::pandasm::LiteralArray::Literal exportName = {
1196             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["exportName"].asString())};
1197         moduleLiteralArray.emplace_back(exportName);
1198     }
1199 }
1200 
ParseIndirectExportEntries(const Json::Value & indirectExportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1201 static void ParseIndirectExportEntries(const Json::Value &indirectExportEntries,
1202                                        std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1203 {
1204     panda::pandasm::LiteralArray::Literal entrySize = {
1205         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(indirectExportEntries.size())};
1206     moduleLiteralArray.emplace_back(entrySize);
1207     for (Json::ArrayIndex i = 0; i < indirectExportEntries.size(); ++i) {
1208         auto entry = indirectExportEntries[i];
1209         panda::pandasm::LiteralArray::Literal exportName = {
1210             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["exportName"].asString())};
1211         moduleLiteralArray.emplace_back(exportName);
1212         panda::pandasm::LiteralArray::Literal importName = {
1213             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["importName"].asString())};
1214         moduleLiteralArray.emplace_back(importName);
1215         panda::pandasm::LiteralArray::Literal moduleRequest = {
1216             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
1217             .value_ = static_cast<uint16_t>(entry["moduleRequest"].asUInt())};
1218         moduleLiteralArray.emplace_back(moduleRequest);
1219     }
1220 }
1221 
ParseStarExportEntries(const Json::Value & starExportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1222 static void ParseStarExportEntries(const Json::Value &starExportEntries,
1223                                    std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1224 {
1225     panda::pandasm::LiteralArray::Literal entrySize = {
1226         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(starExportEntries.size())};
1227     moduleLiteralArray.emplace_back(entrySize);
1228     for (Json::ArrayIndex i = 0; i < starExportEntries.size(); ++i) {
1229         panda::pandasm::LiteralArray::Literal moduleRequest = {
1230             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
1231             .value_ = static_cast<uint16_t>(starExportEntries[i].asUInt())};
1232         moduleLiteralArray.emplace_back(moduleRequest);
1233     }
1234 }
1235 
ParseSingleModule(const Json::Value & rootValue,panda::pandasm::Program & prog)1236 static void ParseSingleModule(const Json::Value &rootValue, panda::pandasm::Program &prog)
1237 {
1238     std::vector<panda::pandasm::LiteralArray::Literal> moduleLiteralArray;
1239 
1240     auto moduleRecord = rootValue["mod"];
1241     ParseModuleRequests(moduleRecord["moduleRequests"], moduleLiteralArray);
1242     ParseRegularImportEntries(moduleRecord["regularImportEntries"], moduleLiteralArray);
1243     ParseNamespaceImportEntries(moduleRecord["namespaceImportEntries"], moduleLiteralArray);
1244     ParseLocalExportEntries(moduleRecord["localExportEntries"], moduleLiteralArray);
1245     ParseIndirectExportEntries(moduleRecord["indirectExportEntries"], moduleLiteralArray);
1246     ParseStarExportEntries(moduleRecord["starExportEntries"], moduleLiteralArray);
1247 
1248     std::string moduleName = ParseString(moduleRecord["moduleName"].asString());
1249     AddModuleRecord(prog, moduleName);
1250     std::string moduleId = GetLiteralId(g_newLiteralArrayIndex--);
1251 
1252     auto moduleLiteralarrayInstance = panda::pandasm::LiteralArray(moduleLiteralArray);
1253     prog.literalarray_table.emplace(moduleId, std::move(moduleLiteralarrayInstance));
1254 }
1255 
ParseSingleTypeInfo(const Json::Value & rootValue,panda::pandasm::Program & prog)1256 static void ParseSingleTypeInfo(const Json::Value &rootValue, panda::pandasm::Program &prog)
1257 {
1258     auto typeInfoRecord = rootValue["ti"];
1259     auto typeFlag = typeInfoRecord["tf"].asBool();
1260     auto typeSummaryIndex = typeInfoRecord["tsi"].asString();
1261 
1262     if (g_isMergeAbc) {
1263         auto iter = prog.record_table.find(g_recordName);
1264         if (iter != prog.record_table.end()) {
1265             auto &rec = iter->second;
1266 
1267             auto typeFlagField = panda::pandasm::Field(LANG_EXT);
1268             typeFlagField.name = "typeFlag";
1269             typeFlagField.type = panda::pandasm::Type("u8", 0);
1270             typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(
1271             static_cast<uint8_t>(typeFlag)));
1272             rec.field_list.emplace_back(std::move(typeFlagField));
1273 
1274             if (g_enableTypeinfo) {
1275                 auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT);
1276                 typeSummaryIndexField.name = "typeSummaryOffset";
1277                 typeSummaryIndexField.type = panda::pandasm::Type("u32", 0);
1278                 typeSummaryIndexField.metadata->SetValue(
1279                     panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(typeSummaryIndex));
1280                 rec.field_list.emplace_back(std::move(typeSummaryIndexField));
1281             }
1282         }
1283         return;
1284     }
1285     auto ecmaTypeInfoRecord = panda::pandasm::Record("_ESTypeInfoRecord", LANG_EXT);
1286     ecmaTypeInfoRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC);
1287 
1288     auto typeFlagField = panda::pandasm::Field(LANG_EXT);
1289     typeFlagField.name = "typeFlag";
1290     typeFlagField.type = panda::pandasm::Type("u8", 0);
1291     typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(
1292     static_cast<uint8_t>(typeFlag)));
1293     ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeFlagField));
1294 
1295     if (g_enableTypeinfo) {
1296         auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT);
1297         typeSummaryIndexField.name = "typeSummaryOffset";
1298         typeSummaryIndexField.type = panda::pandasm::Type("u32", 0);
1299         typeSummaryIndexField.metadata->SetValue(
1300             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(typeSummaryIndex));
1301         ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeSummaryIndexField));
1302     }
1303 
1304     prog.record_table.emplace(ecmaTypeInfoRecord.name, std::move(ecmaTypeInfoRecord));
1305 }
1306 
ParseSmallPieceJson(const std::string & subJson,panda::pandasm::Program & prog)1307 static int ParseSmallPieceJson(const std::string &subJson, panda::pandasm::Program &prog)
1308 {
1309     Json::Value rootValue;
1310     if (ParseJson(subJson, rootValue)) {
1311         std::cerr <<" Fail to parse json by JsonCPP" << std::endl;
1312         return RETURN_FAILED;
1313     }
1314     int type = -1;
1315     if (rootValue.isMember("t") && rootValue["t"].isInt()) {
1316         type = rootValue["t"].asInt();
1317     }
1318     switch (type) {
1319         case static_cast<int>(JsonType::FUNCTION): {
1320             if (rootValue.isMember("fb") && rootValue["fb"].isObject()) {
1321                 ParseSingleFunc(rootValue, prog);
1322             }
1323             break;
1324         }
1325         case static_cast<int>(JsonType::RECORD): {
1326             if (rootValue.isMember("rb") && rootValue["rb"].isObject()) {
1327                 ParseRec(rootValue, prog);
1328             }
1329             if (rootValue.isMember("pn") && rootValue["pn"].isString()) {
1330                 std::string packageName = rootValue["pn"].asString();
1331                 SetPackageName(packageName, prog);
1332             }
1333             break;
1334         }
1335         case static_cast<int>(JsonType::STRING): {
1336             if (rootValue.isMember("s") && rootValue["s"].isArray()) {
1337                 ParseSingleStr(rootValue, prog);
1338             }
1339             break;
1340         }
1341         case static_cast<int>(JsonType::LITERALBUFFER): {
1342             if (rootValue.isMember("lit_arr") && rootValue["lit_arr"].isObject()) {
1343                 ParseSingleLiteralBuf(rootValue, prog);
1344             }
1345             break;
1346         }
1347         case static_cast<int>(JsonType::MODULE): {
1348             if (rootValue.isMember("mod") && rootValue["mod"].isObject()) {
1349                 ParseSingleModule(rootValue, prog);
1350             }
1351             break;
1352         }
1353         case static_cast<int>(JsonType::OPTIONS): {
1354             ParseOptions(rootValue, prog);
1355             break;
1356         }
1357         case static_cast<int>(JsonType::TYPEINFO): {
1358             if (rootValue.isMember("ti") && rootValue["ti"].isObject()) {
1359                 ParseSingleTypeInfo(rootValue, prog);
1360             }
1361             break;
1362         }
1363         case static_cast<int>(JsonType::RECORDNAME): {
1364             if (rootValue.isMember("rn") && rootValue["rn"].isString()) {
1365                 g_recordName = rootValue["rn"].asString();
1366             }
1367             break;
1368         }
1369         case static_cast<int>(JsonType::OUTPUTFILENAME): {
1370             if (rootValue.isMember("ofn") && rootValue["ofn"].isString()) {
1371                 g_outputFileName = rootValue["ofn"].asString();
1372             }
1373             break;
1374         }
1375         case static_cast<int>(JsonType::INPUTJSONFILECONTENT): {
1376             if (rootValue.isMember("ijfc") && rootValue["ijfc"].isString()) {
1377                 ParseInputJsonFileContent(rootValue, prog);
1378             }
1379             break;
1380         }
1381         default: {
1382             std::cerr << "Unreachable json type: " << type << std::endl;
1383             return RETURN_FAILED;
1384         }
1385     }
1386     return RETURN_SUCCESS;
1387 }
1388 
ParseData(const std::string & data,panda::pandasm::Program & prog)1389 static bool ParseData(const std::string &data, panda::pandasm::Program &prog)
1390 {
1391     if (data.empty()) {
1392         std::cerr << "the stringify json is empty" << std::endl;
1393         return false;
1394     }
1395 
1396     size_t pos = 0;
1397 
1398     for (size_t idx = 0; idx < data.size(); idx++) {
1399         if (data[idx] == '$' && (idx == 0 || data[idx - 1] != '#')) {
1400             if (g_isStartDollar) {
1401                 pos = idx + 1;
1402                 g_isStartDollar = false;
1403                 continue;
1404             }
1405 
1406             std::string subJson = data.substr(pos, idx - pos);
1407             ReplaceAllDistinct(subJson, "#$", "$");
1408             ReplaceAllDistinct(subJson, "#*", "*");
1409             if (ParseSmallPieceJson(subJson, prog)) {
1410                 std::cerr << "fail to parse stringify json" << std::endl;
1411                 return false;
1412             }
1413             g_isStartDollar = true;
1414         }
1415     }
1416 
1417     return true;
1418 }
1419 
IsStartOrEndPosition(int idx,char * buff,const std::string & data)1420 static bool IsStartOrEndPosition(int idx, char *buff, const std::string &data)
1421 {
1422     if (buff[idx] != '$') {
1423         return false;
1424     }
1425 
1426     if (idx == 0 && (data.empty() || data.back() != '#')) {
1427         return true;
1428     }
1429 
1430     if (idx != 0 && buff[idx - 1] != '#') {
1431         return true;
1432     }
1433 
1434     return false;
1435 }
1436 
EmitProgram(const std::string & output,int optLevel,std::string optLogLevel,panda::pandasm::Program & prog)1437 static bool EmitProgram(const std::string &output, int optLevel, std::string optLogLevel, panda::pandasm::Program &prog)
1438 {
1439     if (g_isOutputProto) {
1440         g_compilerOutputProto = output.substr(0, output.find_last_of(".") + 1).append(PROTO_BIN_SUFFIX);
1441     }
1442     std::string convertedFilePath = panda::os::file::File::GetExtendedFilePath(output);
1443 
1444 #ifdef ENABLE_BYTECODE_OPT
1445     if (g_optLevel != static_cast<int>(OptLevel::O_LEVEL0) || optLevel != static_cast<int>(OptLevel::O_LEVEL0)) {
1446         optLogLevel = (optLogLevel != "error") ? optLogLevel : g_optLogLevel;
1447 
1448         if (g_optLogLevel != "error") {
1449             panda::Logger::ComponentMask mask;
1450             mask.set(panda::Logger::Component::ASSEMBLER);
1451             mask.set(panda::Logger::Component::BYTECODE_OPTIMIZER);
1452             mask.set(panda::Logger::Component::COMPILER);
1453             panda::Logger::InitializeStdLogging(panda::Logger::LevelFromString(optLogLevel), mask);
1454         }
1455 
1456         bool emitDebugInfo = true;
1457         std::map<std::string, size_t> stat;
1458         std::map<std::string, size_t> *statp = nullptr;
1459         panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
1460         panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps* mapsp = &maps;
1461 
1462         if (!panda::pandasm::AsmEmitter::Emit(convertedFilePath, prog, statp, mapsp, emitDebugInfo)) {
1463             std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl;
1464             return false;
1465         }
1466 
1467         panda::bytecodeopt::OptimizeBytecode(&prog, mapsp, convertedFilePath, true);
1468 
1469         if (g_compilerOutputProto.size() > 0) {
1470             panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, g_compilerOutputProto);
1471             return true;
1472         }
1473 
1474         if (!panda::pandasm::AsmEmitter::Emit(convertedFilePath, prog, statp, mapsp, emitDebugInfo)) {
1475             std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl;
1476             return false;
1477         }
1478         return true;
1479     }
1480 #endif
1481     if (g_compilerOutputProto.size() > 0) {
1482         panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, g_compilerOutputProto);
1483         return true;
1484     }
1485 
1486     if (!panda::pandasm::AsmEmitter::Emit(convertedFilePath, prog, nullptr)) {
1487         std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl;
1488         return false;
1489     }
1490 
1491     Logd("Successfully generated: %s\n", output.c_str());
1492     return true;
1493 }
1494 
EmitAndRestoreProgram(panda::pandasm::Program & prog,const panda::ts2abc::Options & options)1495 static bool EmitAndRestoreProgram(panda::pandasm::Program &prog, const panda::ts2abc::Options &options)
1496 {
1497     if (!EmitProgram(g_outputFileName, options.GetOptLevelArg(), options.GetOptLogLevelArg(), prog)) {
1498         std::cerr << "fail to emit porgram " << g_outputFileName << " in HandleBuffer" << std::endl;
1499         return false;
1500     }
1501     prog = panda::pandasm::Program();
1502     prog.lang = panda::pandasm::extensions::Language::ECMASCRIPT;
1503     g_newLiteralArrayIndex = -1;
1504     return true;
1505 }
1506 
HandleBuffer(const int & ret,char * buff,std::string & data,panda::pandasm::Program & prog,const panda::ts2abc::Options & options)1507 static bool HandleBuffer(const int &ret, char *buff, std::string &data, panda::pandasm::Program &prog,
1508                          const panda::ts2abc::Options &options)
1509 {
1510     uint32_t startPos = 0;
1511     if (options.IsMultiProgramsPipe() && ((buff[0] == '*' && data.back() != '#') ||
1512                                           (buff[0] == '\n' && buff[1] == '*'))) {
1513         if (!EmitAndRestoreProgram(prog, options)) {
1514             std::cerr << "fail to emit and restore program" << std::endl;
1515             return false;
1516         }
1517     }
1518 
1519     for (int idx = 0; idx < ret; idx++) {
1520         if (IsStartOrEndPosition(idx, buff, data)) {
1521             if (g_isStartDollar) {
1522                 startPos = idx + 1;
1523                 g_isStartDollar = false;
1524                 continue;
1525             }
1526 
1527             std::string substr(buff + startPos, buff + idx);
1528             data += substr;
1529             ReplaceAllDistinct(data, "#$", "$");
1530             ReplaceAllDistinct(data, "#*", "*");
1531             if (ParseSmallPieceJson(data, prog)) {
1532                 std::cerr << "fail to parse stringify json" << std::endl;
1533                 return false;
1534             }
1535             g_isStartDollar = true;
1536             // clear data after parsing
1537             data.clear();
1538             // idx: $, then idx + 1:'\n', so comparing buff[idx + 2] with '*'
1539             if (options.IsMultiProgramsPipe() && idx < ret - 2 && buff[idx + 2] == '*' &&
1540                 !EmitAndRestoreProgram(prog, options)) {
1541                 std::cerr << "fail to emit and restore program" << std::endl;
1542                 return false;
1543             }
1544         }
1545     }
1546 
1547     if (!g_isStartDollar) {
1548         std::string substr(buff + startPos, buff + ret);
1549         data += substr;
1550     }
1551 
1552     return true;
1553 }
1554 
ReadFromPipe(panda::pandasm::Program & prog,panda::ts2abc::Options options)1555 static bool ReadFromPipe(panda::pandasm::Program &prog, panda::ts2abc::Options options)
1556 {
1557     std::string data;
1558     const size_t bufSize = 4096;
1559     // the parent process open a pipe to this child process with fd of 3
1560     const size_t fd = 3;
1561 
1562     char buff[bufSize + 1];
1563     int ret = 0;
1564 
1565     while ((ret = read(fd, buff, bufSize)) != 0) {
1566         if (ret < 0) {
1567             std::cerr << "Read pipe error" << std::endl;
1568             return false;
1569         }
1570         buff[ret] = '\0';
1571 
1572         if (!HandleBuffer(ret, buff, data, prog, options)) {
1573             std::cerr << "fail to handle buffer" << std::endl;
1574             return false;
1575         }
1576     }
1577 
1578     Logd("finish parsing from pipe");
1579     return true;
1580 }
1581 
GenerateProgramsFromPipe(const panda::ts2abc::Options & options)1582 bool GenerateProgramsFromPipe(const panda::ts2abc::Options &options)
1583 {
1584     panda::pandasm::Program prog = panda::pandasm::Program();
1585     prog.lang = panda::pandasm::extensions::Language::ECMASCRIPT;
1586 
1587     if (!ReadFromPipe(prog, options)) {
1588         std::cerr << "fail to parse programs from Pipe!" << std::endl;
1589         return false;
1590     }
1591 
1592     return true;
1593 }
1594 
GenerateProgram(const std::string & data,const std::string & output,panda::ts2abc::Options options)1595 bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string &output,
1596                      panda::ts2abc::Options options)
1597 {
1598     bool isParsingFromPipe = options.GetCompileByPipeArg();
1599     int optLevel = options.GetOptLevelArg();
1600     std::string optLogLevel = options.GetOptLogLevelArg();
1601     panda::pandasm::Program prog = panda::pandasm::Program();
1602     prog.lang = panda::pandasm::extensions::Language::ECMASCRIPT;
1603 
1604     if (isParsingFromPipe) {
1605         if (!ReadFromPipe(prog, options)) {
1606             std::cerr << "fail to parse Pipe!" << std::endl;
1607             return false;
1608         }
1609     } else {
1610         if (!ParseData(data, prog)) {
1611             std::cerr << "fail to parse Data!" << std::endl;
1612             return false;
1613         }
1614     }
1615 
1616     Logd("parsing done, calling pandasm\n");
1617 
1618     return EmitProgram(output, optLevel, optLogLevel, prog);
1619 }
1620 
CompileNpmEntries(const std::string & input,const std::string & output)1621 bool CompileNpmEntries(const std::string &input, const std::string &output)
1622 {
1623     auto inputAbs = panda::os::file::File::GetAbsolutePath(input);
1624     if (!inputAbs) {
1625         std::cerr << "Input file does not exist" << std::endl;
1626         return false;
1627     }
1628     auto fpath = inputAbs.Value();
1629     if (panda::os::file::File::IsRegularFile(fpath) == false) {
1630         std::cerr << "Input: " << fpath << " must be either a regular file or a directory" << std::endl;
1631         return false;
1632     }
1633 
1634     std::stringstream ss;
1635     std::ifstream inputStream(panda::os::file::File::GetExtendedFilePath(input));
1636     if (inputStream.fail()) {
1637         std::cerr << "Failed to read file to buffer: " << input << std::endl;
1638         return false;
1639     }
1640     ss << inputStream.rdbuf();
1641 
1642     panda::pandasm::Program prog = panda::pandasm::Program();
1643     prog.lang = LANG_EXT;
1644 
1645     std::string line;
1646     while (getline(ss, line)) {
1647         std::size_t pos = line.find(":");
1648         std::string recordName = line.substr(0, pos);
1649         std::string field = line.substr(pos + 1);
1650 
1651         auto langExt = LANG_EXT;
1652         auto entryNameField = panda::pandasm::Field(langExt);
1653         entryNameField.name = field;
1654         entryNameField.type = panda::pandasm::Type("u8", 0);
1655         entryNameField.metadata->SetValue(panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(
1656             static_cast<bool>(0)));
1657 
1658         panda::pandasm::Record entryRecord = panda::pandasm::Record(recordName, langExt);
1659         entryRecord.field_list.emplace_back(std::move(entryNameField));
1660         prog.record_table.emplace(recordName, std::move(entryRecord));
1661     }
1662 
1663     panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, output);
1664     return true;
1665 }
1666 
HandleJsonFile(const std::string & input,std::string & data)1667 bool HandleJsonFile(const std::string &input, std::string &data)
1668 {
1669     auto inputAbs = panda::os::file::File::GetAbsolutePath(input);
1670     if (!inputAbs) {
1671         std::cerr << "Input file does not exist" << std::endl;
1672         return false;
1673     }
1674     auto fpath = inputAbs.Value();
1675     if (panda::os::file::File::IsRegularFile(fpath) == false) {
1676         std::cerr << "Input must be either a regular file or a directory" << std::endl;
1677         return false;
1678     }
1679 
1680     std::ifstream file;
1681     file.open(panda::os::file::File::GetExtendedFilePath(fpath));
1682     if (file.fail()) {
1683         std::cerr << "failed to open:" << fpath << std::endl;
1684         return false;
1685     }
1686 
1687     file.seekg(0, std::ios::end);
1688     int64_t fileSize = file.tellg();
1689     if (fileSize == -1) {
1690         std::cerr << "failed to get position in input sequence: " << fpath << std::endl;
1691         return false;
1692     }
1693     file.seekg(0, std::ios::beg);
1694     auto buf = std::vector<char>(fileSize);
1695     file.read(reinterpret_cast<char *>(buf.data()), fileSize);
1696     data = buf.data();
1697     buf.clear();
1698     file.close();
1699 
1700     return true;
1701 }
1702 
1703 } // namespace panda::ts2abc
1704