• 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 {
816     panda::panda_file::FunctionKind funcKind {};
817     if (function.isMember("kind") && function["kind"].isInt()) {
818         funcKind = static_cast<panda::panda_file::FunctionKind>(function["kind"].asUInt());
819         pandaFunc.SetFunctionKind(funcKind);
820     }
821 }
822 
ParseFunctionIcSize(const Json::Value & function,panda::pandasm::Function & pandaFunc)823 static void ParseFunctionIcSize(const Json::Value &function, panda::pandasm::Function &pandaFunc)
824 {
825     if (function.isMember("icSize") && function["icSize"].isInt()) {
826         size_t icSize = static_cast<size_t>(function["icSize"].asUInt());
827         pandaFunc.SetSlotsNum(icSize);
828     }
829 }
830 
ParseFunction(const Json::Value & function,panda::pandasm::Program & prog)831 static panda::pandasm::Function ParseFunction(const Json::Value &function, panda::pandasm::Program &prog)
832 {
833     auto pandaFunc = GetFunctionDefintion(function);
834     ParseFunctionInstructions(function, pandaFunc);
835     ParseVariablesDebugInfo(function, pandaFunc);
836     ParseSourceFileInfo(function, pandaFunc);
837     ParseFunctionLabels(function, pandaFunc);
838     ParseFunctionCatchTables(function, pandaFunc);
839     ParseFunctionTypeInfo(function, pandaFunc, prog);
840     ParseFunctionExportedType(function, pandaFunc, prog);
841     ParseFunctionDeclaredType(function, pandaFunc, prog);
842     ParseFunctionKind(function, pandaFunc);
843     ParseFunctionIcSize(function, pandaFunc);
844 
845     if (g_isDtsFile && !IsFuncMain0(pandaFunc.name)) {
846         pandaFunc.metadata->SetAttribute("external");
847     }
848 
849     return pandaFunc;
850 }
851 
GenerateESCallTypeAnnotationRecord(panda::pandasm::Program & prog)852 static void GenerateESCallTypeAnnotationRecord(panda::pandasm::Program &prog)
853 {
854     auto callTypeAnnotationRecord = panda::pandasm::Record("_ESCallTypeAnnotation", LANG_EXT);
855     callTypeAnnotationRecord.metadata->SetAttribute("external");
856     callTypeAnnotationRecord.metadata->SetAccessFlags(panda::ACC_ANNOTATION);
857     prog.record_table.emplace(callTypeAnnotationRecord.name, std::move(callTypeAnnotationRecord));
858 }
GenerateESTypeAnnotationRecord(panda::pandasm::Program & prog)859 static void GenerateESTypeAnnotationRecord(panda::pandasm::Program &prog)
860 {
861     auto tsTypeAnnotationRecord = panda::pandasm::Record(TSTYPE_ANNO_RECORD_NAME, LANG_EXT);
862     tsTypeAnnotationRecord.metadata->SetAttribute("external");
863     tsTypeAnnotationRecord.metadata->SetAccessFlags(panda::ACC_ANNOTATION);
864     prog.record_table.emplace(tsTypeAnnotationRecord.name, std::move(tsTypeAnnotationRecord));
865 }
866 
GenerateESModuleRecord(panda::pandasm::Program & prog)867 static void GenerateESModuleRecord(panda::pandasm::Program &prog)
868 {
869     auto ecmaModuleRecord = panda::pandasm::Record("_ESModuleRecord", LANG_EXT);
870     ecmaModuleRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC);
871     prog.record_table.emplace(ecmaModuleRecord.name, std::move(ecmaModuleRecord));
872 }
873 
GenerateCommonJsRecord(panda::pandasm::Program & prog,bool isCommonJs)874 static void GenerateCommonJsRecord(panda::pandasm::Program &prog, bool isCommonJs)
875 {
876     // when multi-abc file get merged, field should be inserted in abc's own record
877     auto commonjsRecord = panda::pandasm::Record("_CommonJsRecord", LANG_EXT);
878     commonjsRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC);
879     auto isCommonJsField = panda::pandasm::Field(LANG_EXT);
880     isCommonJsField.name = "isCommonJs";
881     isCommonJsField.type = panda::pandasm::Type("u8", 0);
882     isCommonJsField.metadata->SetValue(panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(
883         static_cast<uint8_t>(isCommonJs)));
884     commonjsRecord.field_list.emplace_back(std::move(isCommonJsField));
885 
886     prog.record_table.emplace(commonjsRecord.name, std::move(commonjsRecord));
887 }
888 
SetCommonjsField(panda::pandasm::Program & prog,bool isCommonjs)889 static void SetCommonjsField(panda::pandasm::Program &prog, bool isCommonjs)
890 {
891     auto iter = prog.record_table.find(g_recordName);
892     if (iter != prog.record_table.end()) {
893         auto &rec = iter->second;
894         auto isCommonJsField = panda::pandasm::Field(LANG_EXT);
895         isCommonJsField.name = "isCommonjs";
896         isCommonJsField.type = panda::pandasm::Type("u8", 0);
897         isCommonJsField.metadata->SetValue(
898             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(static_cast<uint8_t>(isCommonjs)));
899         rec.field_list.emplace_back(std::move(isCommonJsField));
900     }
901 }
902 
AddModuleRecord(panda::pandasm::Program & prog,const std::string & moduleName)903 static void AddModuleRecord(panda::pandasm::Program &prog, const std::string &moduleName)
904 {
905     std::string moduleRecordName = g_isMergeAbc ? g_recordName : "_ESModuleRecord";
906     std::string fieldName = g_isMergeAbc ? "moduleRecordIdx" : moduleName;
907     auto iter = prog.record_table.find(moduleRecordName);
908     if (iter != prog.record_table.end()) {
909         auto &rec = iter->second;
910         auto moduleIdxField = panda::pandasm::Field(LANG_EXT);
911         moduleIdxField.name = fieldName;
912         moduleIdxField.type = panda::pandasm::Type("u32", 0);
913         std::string moduleId = GetLiteralId(g_newLiteralArrayIndex);
914         moduleIdxField.metadata->SetValue(
915             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(moduleId));
916 
917         rec.field_list.emplace_back(std::move(moduleIdxField));
918     }
919 }
920 
ParseJson(const std::string & data,Json::Value & rootValue)921 int ParseJson(const std::string &data, Json::Value &rootValue)
922 {
923     JSONCPP_STRING errs;
924     Json::CharReaderBuilder readerBuilder;
925 
926     std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
927     bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &rootValue, &errs);
928     if (!res || !errs.empty()) {
929         std::cerr << "ParseJson err. " << errs.c_str() << std::endl;
930         return RETURN_FAILED;
931     }
932 
933     if (!rootValue.isObject()) {
934         std::cerr << "The parsed json data is not one object" << std::endl;
935         return RETURN_FAILED;
936     }
937 
938     return RETURN_SUCCESS;
939 }
940 
ParseMergeAbcMode(const Json::Value & rootValue)941 static void ParseMergeAbcMode(const Json::Value &rootValue)
942 {
943     Logd("---------------parse is_merge_abc----------------");
944     if (rootValue.isMember("merge_abc") && rootValue["merge_abc"].isBool()) {
945         g_isMergeAbc = rootValue["merge_abc"].asBool();
946     }
947 }
948 
ParseModuleMode(const Json::Value & rootValue,panda::pandasm::Program & prog)949 static void ParseModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog)
950 {
951     Logd("----------------parse module_mode-----------------");
952     if (rootValue.isMember("module_mode") && rootValue["module_mode"].isBool()) {
953         if (rootValue["module_mode"].asBool() && !g_isMergeAbc) {
954             GenerateESModuleRecord(prog);
955         }
956     }
957 }
958 
ParseCommonJsModuleMode(const Json::Value & rootValue,panda::pandasm::Program & prog)959 static void ParseCommonJsModuleMode(const Json::Value &rootValue, panda::pandasm::Program &prog)
960 {
961     Logd("------------parse commonjs_module_mode-------------");
962     if (rootValue.isMember("commonjs_module") && rootValue["commonjs_module"].isBool()) {
963         if (g_isMergeAbc) {
964             SetCommonjsField(prog, rootValue["commonjs_module"].asBool());
965         } else {
966             if (rootValue["commonjs_module"].asBool()) {
967                 GenerateCommonJsRecord(prog, true);
968             }
969         }
970     }
971 }
972 
ParseLogEnable(const Json::Value & rootValue)973 void ParseLogEnable(const Json::Value &rootValue)
974 {
975     if (rootValue.isMember("log_enabled") && rootValue["log_enabled"].isBool()) {
976         SetDebugLog(rootValue["log_enabled"].asBool());
977     }
978 }
979 
ParseDebugMode(const Json::Value & rootValue)980 void ParseDebugMode(const Json::Value &rootValue)
981 {
982     Logd("-----------------parse debug_mode-----------------");
983     if (rootValue.isMember("debug_mode") && rootValue["debug_mode"].isBool()) {
984         SetDebugModeEnabled(rootValue["debug_mode"].asBool());
985     }
986 }
987 
ParseOptLevel(const Json::Value & rootValue)988 static void ParseOptLevel(const Json::Value &rootValue)
989 {
990     Logd("-----------------parse opt level-----------------");
991     if (rootValue.isMember("opt_level") && rootValue["opt_level"].isInt()) {
992         g_optLevel = rootValue["opt_level"].asInt();
993     }
994     if (GetDebugModeEnabled()) {
995         g_optLevel = 0;
996     }
997 }
998 
ParseDisplayTypeinfo(const Json::Value & rootValue)999 static void ParseDisplayTypeinfo(const Json::Value &rootValue)
1000 {
1001     Logd("-----------------parse enable_typeinfo-----------------");
1002     if (rootValue.isMember("display_typeinfo") && rootValue["display_typeinfo"].isBool()) {
1003         g_displayTypeinfo = rootValue["display_typeinfo"].asBool();
1004     }
1005 }
1006 
ParseOptLogLevel(const Json::Value & rootValue)1007 static void ParseOptLogLevel(const Json::Value &rootValue)
1008 {
1009     Logd("-----------------parse opt log level-----------------");
1010     if (rootValue.isMember("opt_log_level") && rootValue["opt_log_level"].isString()) {
1011         g_optLogLevel = rootValue["opt_log_level"].asString();
1012     }
1013 }
1014 
ParseIsDtsFile(const Json::Value & rootValue)1015 static void ParseIsDtsFile(const Json::Value &rootValue)
1016 {
1017     Logd("-----------------parse is dts file-----------------");
1018     if (rootValue.isMember("is_dts_file") && rootValue["is_dts_file"].isBool()) {
1019         g_isDtsFile = rootValue["is_dts_file"].asBool();
1020     }
1021 }
1022 
ParseEnableTypeInfo(const Json::Value & rootValue)1023 static void ParseEnableTypeInfo(const Json::Value &rootValue)
1024 {
1025     Logd("-----------------parse enable type info-----------------");
1026     if (rootValue.isMember("record_type") && rootValue["record_type"].isBool()) {
1027         g_enableTypeinfo = rootValue["record_type"].asBool();
1028     }
1029 }
1030 
ParseCompilerOutputProto(const Json::Value & rootValue)1031 static void ParseCompilerOutputProto(const Json::Value &rootValue)
1032 {
1033     Logd("-----------------parse compiler output proto-----------------");
1034     if (rootValue.isMember("output-proto") && rootValue["output-proto"].isBool()) {
1035         g_isOutputProto = rootValue["output-proto"].asBool();
1036     }
1037 }
1038 
ReplaceAllDistinct(std::string & str,const std::string & oldValue,const std::string & newValue)1039 static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, const std::string &newValue)
1040 {
1041     for (std::string::size_type pos(0); pos != std::string::npos; pos += newValue.length()) {
1042         if ((pos = str.find(oldValue, pos)) != std::string::npos) {
1043             str.replace(pos, oldValue.length(), newValue);
1044         } else {
1045             break;
1046         }
1047     }
1048 }
1049 
ParseOptions(const Json::Value & rootValue,panda::pandasm::Program & prog)1050 static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program &prog)
1051 {
1052     GenerateESCallTypeAnnotationRecord(prog);
1053     GenerateESTypeAnnotationRecord(prog);
1054     ParseMergeAbcMode(rootValue);
1055     ParseModuleMode(rootValue, prog);
1056     ParseCommonJsModuleMode(rootValue, prog);
1057     ParseLogEnable(rootValue);
1058     ParseDebugMode(rootValue);
1059     ParseOptLevel(rootValue);
1060     ParseDisplayTypeinfo(rootValue);
1061     ParseOptLogLevel(rootValue);
1062     ParseIsDtsFile(rootValue);
1063     ParseEnableTypeInfo(rootValue);
1064     ParseCompilerOutputProto(rootValue);
1065 }
1066 
ParseSingleFunc(const Json::Value & rootValue,panda::pandasm::Program & prog)1067 static void ParseSingleFunc(const Json::Value &rootValue, panda::pandasm::Program &prog)
1068 {
1069     auto function = ParseFunction(rootValue["fb"], prog);
1070     prog.function_table.emplace(function.name.c_str(), std::move(function));
1071 }
1072 
ParseRec(const Json::Value & rootValue,panda::pandasm::Program & prog)1073 static void ParseRec(const Json::Value &rootValue, panda::pandasm::Program &prog)
1074 {
1075     auto record = ParseRecord(rootValue["rb"]);
1076     g_recordName = record.name;
1077     prog.record_table.emplace(record.name.c_str(), std::move(record));
1078 }
1079 
SetPackageName(const std::string & packageName,panda::pandasm::Program & prog)1080 static void SetPackageName(const std::string &packageName, panda::pandasm::Program &prog)
1081 {
1082     auto iter = prog.record_table.find(g_recordName);
1083     if (iter != prog.record_table.end()) {
1084         auto &rec = iter->second;
1085         auto pkgNameField = panda::pandasm::Field(LANG_EXT);
1086         pkgNameField.name = "pkgName@" + packageName;
1087         pkgNameField.type = panda::pandasm::Type("u8", 0);
1088         pkgNameField.metadata->SetValue(
1089             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(static_cast<uint8_t>(0)));
1090 
1091         rec.field_list.emplace_back(std::move(pkgNameField));
1092     }
1093 }
1094 
ParseInputJsonFileContent(const Json::Value & rootValue,panda::pandasm::Program & prog)1095 static void ParseInputJsonFileContent(const Json::Value &rootValue, panda::pandasm::Program &prog)
1096 {
1097     auto iter = prog.record_table.find(g_recordName);
1098     if (iter != prog.record_table.end()) {
1099         auto &rec = iter->second;
1100 
1101         auto inputJsonFileContentField = panda::pandasm::Field(LANG_EXT);
1102         inputJsonFileContentField.name = "jsonFileContent";
1103         inputJsonFileContentField.type = panda::pandasm::Type("u32", 0);
1104         inputJsonFileContentField.metadata->SetValue(
1105             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::STRING>(
1106             static_cast<std::string_view>(rootValue["ijfc"].asString())));
1107         rec.field_list.emplace_back(std::move(inputJsonFileContentField));
1108     }
1109 }
1110 
ParseSingleStr(const Json::Value & rootValue,panda::pandasm::Program & prog)1111 static void ParseSingleStr(const Json::Value &rootValue, panda::pandasm::Program &prog)
1112 {
1113     auto strArr = rootValue["s"];
1114     for (Json::ArrayIndex i = 0; i < strArr.size(); ++i) {
1115         prog.strings.insert(ParseString(strArr[i].asString()));
1116     }
1117 }
1118 
ParseSingleLiteralBuf(const Json::Value & rootValue,panda::pandasm::Program & prog)1119 static void ParseSingleLiteralBuf(const Json::Value &rootValue, panda::pandasm::Program &prog)
1120 {
1121     std::vector<panda::pandasm::LiteralArray::Literal> literalArray;
1122     auto literalBuffer = rootValue["lit_arr"];
1123     auto literals = literalBuffer["lb"];
1124     for (Json::ArrayIndex i = 0; i < literals.size(); ++i) {
1125         ParseLiteral(literals[i], literalArray);
1126     }
1127 
1128     auto literalarrayInstance = panda::pandasm::LiteralArray(literalArray);
1129     auto litId = literalBuffer["k"].asString();
1130     prog.literalarray_table.emplace(litId, std::move(literalarrayInstance));
1131 }
1132 
ParseModuleRequests(const Json::Value & moduleRequests,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1133 static void ParseModuleRequests(const Json::Value &moduleRequests,
1134                                 std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1135 {
1136     panda::pandasm::LiteralArray::Literal moduleSize = {
1137         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(moduleRequests.size())};
1138     moduleLiteralArray.emplace_back(moduleSize);
1139     for (Json::ArrayIndex i = 0; i < moduleRequests.size(); ++i) {
1140         panda::pandasm::LiteralArray::Literal moduleRequest = {
1141             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(moduleRequests[i].asString())};
1142         moduleLiteralArray.emplace_back(moduleRequest);
1143     }
1144 }
1145 
ParseRegularImportEntries(const Json::Value & regularImportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1146 static void ParseRegularImportEntries(const Json::Value &regularImportEntries,
1147                                       std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1148 {
1149     panda::pandasm::LiteralArray::Literal entrySize = {
1150         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(regularImportEntries.size())};
1151     moduleLiteralArray.emplace_back(entrySize);
1152     for (Json::ArrayIndex i = 0; i < regularImportEntries.size(); ++i) {
1153         auto entry = regularImportEntries[i];
1154         panda::pandasm::LiteralArray::Literal localName = {
1155             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["localName"].asString())};
1156         moduleLiteralArray.emplace_back(localName);
1157         panda::pandasm::LiteralArray::Literal importName = {
1158             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["importName"].asString())};
1159         moduleLiteralArray.emplace_back(importName);
1160         panda::pandasm::LiteralArray::Literal moduleRequest = {
1161             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
1162             .value_ = static_cast<uint16_t>(entry["moduleRequest"].asUInt())};
1163         moduleLiteralArray.emplace_back(moduleRequest);
1164     }
1165 }
1166 
ParseNamespaceImportEntries(const Json::Value & namespaceImportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1167 static void ParseNamespaceImportEntries(const Json::Value &namespaceImportEntries,
1168                                         std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1169 {
1170     panda::pandasm::LiteralArray::Literal entrySize = {
1171         .tag_ = panda::panda_file::LiteralTag::INTEGER,
1172         .value_ = static_cast<uint32_t>(namespaceImportEntries.size())};
1173     moduleLiteralArray.emplace_back(entrySize);
1174     for (Json::ArrayIndex i = 0; i < namespaceImportEntries.size(); ++i) {
1175         auto entry = namespaceImportEntries[i];
1176         panda::pandasm::LiteralArray::Literal localName = {
1177             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["localName"].asString())};
1178         moduleLiteralArray.emplace_back(localName);
1179         panda::pandasm::LiteralArray::Literal moduleRequest = {
1180             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
1181             .value_ = static_cast<uint16_t>(entry["moduleRequest"].asUInt())};
1182         moduleLiteralArray.emplace_back(moduleRequest);
1183     }
1184 }
1185 
ParseLocalExportEntries(const Json::Value & localExportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1186 static void ParseLocalExportEntries(const Json::Value &localExportEntries,
1187                                     std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1188 {
1189     panda::pandasm::LiteralArray::Literal entrySize = {
1190         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(localExportEntries.size())};
1191     moduleLiteralArray.emplace_back(entrySize);
1192     for (Json::ArrayIndex i = 0; i < localExportEntries.size(); ++i) {
1193         auto entry = localExportEntries[i];
1194         panda::pandasm::LiteralArray::Literal localName = {
1195             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["localName"].asString())};
1196         moduleLiteralArray.emplace_back(localName);
1197         panda::pandasm::LiteralArray::Literal exportName = {
1198             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["exportName"].asString())};
1199         moduleLiteralArray.emplace_back(exportName);
1200     }
1201 }
1202 
ParseIndirectExportEntries(const Json::Value & indirectExportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1203 static void ParseIndirectExportEntries(const Json::Value &indirectExportEntries,
1204                                        std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1205 {
1206     panda::pandasm::LiteralArray::Literal entrySize = {
1207         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(indirectExportEntries.size())};
1208     moduleLiteralArray.emplace_back(entrySize);
1209     for (Json::ArrayIndex i = 0; i < indirectExportEntries.size(); ++i) {
1210         auto entry = indirectExportEntries[i];
1211         panda::pandasm::LiteralArray::Literal exportName = {
1212             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["exportName"].asString())};
1213         moduleLiteralArray.emplace_back(exportName);
1214         panda::pandasm::LiteralArray::Literal importName = {
1215             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = ParseString(entry["importName"].asString())};
1216         moduleLiteralArray.emplace_back(importName);
1217         panda::pandasm::LiteralArray::Literal moduleRequest = {
1218             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
1219             .value_ = static_cast<uint16_t>(entry["moduleRequest"].asUInt())};
1220         moduleLiteralArray.emplace_back(moduleRequest);
1221     }
1222 }
1223 
ParseStarExportEntries(const Json::Value & starExportEntries,std::vector<panda::pandasm::LiteralArray::Literal> & moduleLiteralArray)1224 static void ParseStarExportEntries(const Json::Value &starExportEntries,
1225                                    std::vector<panda::pandasm::LiteralArray::Literal> &moduleLiteralArray)
1226 {
1227     panda::pandasm::LiteralArray::Literal entrySize = {
1228         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(starExportEntries.size())};
1229     moduleLiteralArray.emplace_back(entrySize);
1230     for (Json::ArrayIndex i = 0; i < starExportEntries.size(); ++i) {
1231         panda::pandasm::LiteralArray::Literal moduleRequest = {
1232             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
1233             .value_ = static_cast<uint16_t>(starExportEntries[i].asUInt())};
1234         moduleLiteralArray.emplace_back(moduleRequest);
1235     }
1236 }
1237 
ParseSingleModule(const Json::Value & rootValue,panda::pandasm::Program & prog)1238 static void ParseSingleModule(const Json::Value &rootValue, panda::pandasm::Program &prog)
1239 {
1240     std::vector<panda::pandasm::LiteralArray::Literal> moduleLiteralArray;
1241 
1242     auto moduleRecord = rootValue["mod"];
1243     ParseModuleRequests(moduleRecord["moduleRequests"], moduleLiteralArray);
1244     ParseRegularImportEntries(moduleRecord["regularImportEntries"], moduleLiteralArray);
1245     ParseNamespaceImportEntries(moduleRecord["namespaceImportEntries"], moduleLiteralArray);
1246     ParseLocalExportEntries(moduleRecord["localExportEntries"], moduleLiteralArray);
1247     ParseIndirectExportEntries(moduleRecord["indirectExportEntries"], moduleLiteralArray);
1248     ParseStarExportEntries(moduleRecord["starExportEntries"], moduleLiteralArray);
1249 
1250     std::string moduleName = ParseString(moduleRecord["moduleName"].asString());
1251     AddModuleRecord(prog, moduleName);
1252     std::string moduleId = GetLiteralId(g_newLiteralArrayIndex--);
1253 
1254     auto moduleLiteralarrayInstance = panda::pandasm::LiteralArray(moduleLiteralArray);
1255     prog.literalarray_table.emplace(moduleId, std::move(moduleLiteralarrayInstance));
1256 }
1257 
ParseSingleTypeInfo(const Json::Value & rootValue,panda::pandasm::Program & prog)1258 static void ParseSingleTypeInfo(const Json::Value &rootValue, panda::pandasm::Program &prog)
1259 {
1260     auto typeInfoRecord = rootValue["ti"];
1261     auto typeFlag = typeInfoRecord["tf"].asBool();
1262     auto typeSummaryIndex = typeInfoRecord["tsi"].asString();
1263 
1264     if (g_isMergeAbc) {
1265         auto iter = prog.record_table.find(g_recordName);
1266         if (iter != prog.record_table.end()) {
1267             auto &rec = iter->second;
1268 
1269             auto typeFlagField = panda::pandasm::Field(LANG_EXT);
1270             typeFlagField.name = "typeFlag";
1271             typeFlagField.type = panda::pandasm::Type("u8", 0);
1272             typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(
1273             static_cast<uint8_t>(typeFlag)));
1274             rec.field_list.emplace_back(std::move(typeFlagField));
1275 
1276             if (g_enableTypeinfo) {
1277                 auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT);
1278                 typeSummaryIndexField.name = "typeSummaryOffset";
1279                 typeSummaryIndexField.type = panda::pandasm::Type("u32", 0);
1280                 typeSummaryIndexField.metadata->SetValue(
1281                     panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(typeSummaryIndex));
1282                 rec.field_list.emplace_back(std::move(typeSummaryIndexField));
1283             }
1284         }
1285         return;
1286     }
1287     auto ecmaTypeInfoRecord = panda::pandasm::Record("_ESTypeInfoRecord", LANG_EXT);
1288     ecmaTypeInfoRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC);
1289 
1290     auto typeFlagField = panda::pandasm::Field(LANG_EXT);
1291     typeFlagField.name = "typeFlag";
1292     typeFlagField.type = panda::pandasm::Type("u8", 0);
1293     typeFlagField.metadata->SetValue(panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(
1294     static_cast<uint8_t>(typeFlag)));
1295     ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeFlagField));
1296 
1297     if (g_enableTypeinfo) {
1298         auto typeSummaryIndexField = panda::pandasm::Field(LANG_EXT);
1299         typeSummaryIndexField.name = "typeSummaryOffset";
1300         typeSummaryIndexField.type = panda::pandasm::Type("u32", 0);
1301         typeSummaryIndexField.metadata->SetValue(
1302             panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(typeSummaryIndex));
1303         ecmaTypeInfoRecord.field_list.emplace_back(std::move(typeSummaryIndexField));
1304     }
1305 
1306     prog.record_table.emplace(ecmaTypeInfoRecord.name, std::move(ecmaTypeInfoRecord));
1307 }
1308 
ParseSmallPieceJson(const std::string & subJson,panda::pandasm::Program & prog)1309 static int ParseSmallPieceJson(const std::string &subJson, panda::pandasm::Program &prog)
1310 {
1311     Json::Value rootValue;
1312     if (ParseJson(subJson, rootValue)) {
1313         std::cerr <<" Fail to parse json by JsonCPP" << std::endl;
1314         return RETURN_FAILED;
1315     }
1316     int type = -1;
1317     if (rootValue.isMember("t") && rootValue["t"].isInt()) {
1318         type = rootValue["t"].asInt();
1319     }
1320     switch (type) {
1321         case static_cast<int>(JsonType::FUNCTION): {
1322             if (rootValue.isMember("fb") && rootValue["fb"].isObject()) {
1323                 ParseSingleFunc(rootValue, prog);
1324             }
1325             break;
1326         }
1327         case static_cast<int>(JsonType::RECORD): {
1328             if (rootValue.isMember("rb") && rootValue["rb"].isObject()) {
1329                 ParseRec(rootValue, prog);
1330             }
1331             if (rootValue.isMember("pn") && rootValue["pn"].isString()) {
1332                 std::string packageName = rootValue["pn"].asString();
1333                 SetPackageName(packageName, prog);
1334             }
1335             break;
1336         }
1337         case static_cast<int>(JsonType::STRING): {
1338             if (rootValue.isMember("s") && rootValue["s"].isArray()) {
1339                 ParseSingleStr(rootValue, prog);
1340             }
1341             break;
1342         }
1343         case static_cast<int>(JsonType::LITERALBUFFER): {
1344             if (rootValue.isMember("lit_arr") && rootValue["lit_arr"].isObject()) {
1345                 ParseSingleLiteralBuf(rootValue, prog);
1346             }
1347             break;
1348         }
1349         case static_cast<int>(JsonType::MODULE): {
1350             if (rootValue.isMember("mod") && rootValue["mod"].isObject()) {
1351                 ParseSingleModule(rootValue, prog);
1352             }
1353             break;
1354         }
1355         case static_cast<int>(JsonType::OPTIONS): {
1356             ParseOptions(rootValue, prog);
1357             break;
1358         }
1359         case static_cast<int>(JsonType::TYPEINFO): {
1360             if (rootValue.isMember("ti") && rootValue["ti"].isObject()) {
1361                 ParseSingleTypeInfo(rootValue, prog);
1362             }
1363             break;
1364         }
1365         case static_cast<int>(JsonType::RECORDNAME): {
1366             if (rootValue.isMember("rn") && rootValue["rn"].isString()) {
1367                 g_recordName = rootValue["rn"].asString();
1368             }
1369             break;
1370         }
1371         case static_cast<int>(JsonType::OUTPUTFILENAME): {
1372             if (rootValue.isMember("ofn") && rootValue["ofn"].isString()) {
1373                 g_outputFileName = rootValue["ofn"].asString();
1374             }
1375             break;
1376         }
1377         case static_cast<int>(JsonType::INPUTJSONFILECONTENT): {
1378             if (rootValue.isMember("ijfc") && rootValue["ijfc"].isString()) {
1379                 ParseInputJsonFileContent(rootValue, prog);
1380             }
1381             break;
1382         }
1383         default: {
1384             std::cerr << "Unreachable json type: " << type << std::endl;
1385             return RETURN_FAILED;
1386         }
1387     }
1388     return RETURN_SUCCESS;
1389 }
1390 
ParseData(const std::string & data,panda::pandasm::Program & prog)1391 static bool ParseData(const std::string &data, panda::pandasm::Program &prog)
1392 {
1393     if (data.empty()) {
1394         std::cerr << "the stringify json is empty" << std::endl;
1395         return false;
1396     }
1397 
1398     size_t pos = 0;
1399 
1400     for (size_t idx = 0; idx < data.size(); idx++) {
1401         if (data[idx] == '$' && (idx == 0 || data[idx - 1] != '#')) {
1402             if (g_isStartDollar) {
1403                 pos = idx + 1;
1404                 g_isStartDollar = false;
1405                 continue;
1406             }
1407 
1408             std::string subJson = data.substr(pos, idx - pos);
1409             ReplaceAllDistinct(subJson, "#$", "$");
1410             ReplaceAllDistinct(subJson, "#*", "*");
1411             if (ParseSmallPieceJson(subJson, prog)) {
1412                 std::cerr << "fail to parse stringify json" << std::endl;
1413                 return false;
1414             }
1415             g_isStartDollar = true;
1416         }
1417     }
1418 
1419     return true;
1420 }
1421 
IsStartOrEndPosition(int idx,char * buff,const std::string & data)1422 static bool IsStartOrEndPosition(int idx, char *buff, const std::string &data)
1423 {
1424     if (buff[idx] != '$') {
1425         return false;
1426     }
1427 
1428     if (idx == 0 && (data.empty() || data.back() != '#')) {
1429         return true;
1430     }
1431 
1432     if (idx != 0 && buff[idx - 1] != '#') {
1433         return true;
1434     }
1435 
1436     return false;
1437 }
1438 
EmitProgram(const std::string & output,int optLevel,std::string optLogLevel,panda::pandasm::Program & prog)1439 static bool EmitProgram(const std::string &output, int optLevel, std::string optLogLevel, panda::pandasm::Program &prog)
1440 {
1441     if (g_isOutputProto) {
1442         g_compilerOutputProto = output.substr(0, output.find_last_of(".") + 1).append(PROTO_BIN_SUFFIX);
1443     }
1444     std::string convertedFilePath = panda::os::file::File::GetExtendedFilePath(output);
1445 
1446 #ifdef ENABLE_BYTECODE_OPT
1447     if (g_optLevel != static_cast<int>(OptLevel::O_LEVEL0) || optLevel != static_cast<int>(OptLevel::O_LEVEL0)) {
1448         optLogLevel = (optLogLevel != "error") ? optLogLevel : g_optLogLevel;
1449 
1450         if (g_optLogLevel != "error") {
1451             panda::Logger::ComponentMask mask;
1452             mask.set(panda::Logger::Component::ASSEMBLER);
1453             mask.set(panda::Logger::Component::BYTECODE_OPTIMIZER);
1454             mask.set(panda::Logger::Component::COMPILER);
1455             panda::Logger::InitializeStdLogging(panda::Logger::LevelFromString(optLogLevel), mask);
1456         }
1457 
1458         bool emitDebugInfo = true;
1459         std::map<std::string, size_t> stat;
1460         std::map<std::string, size_t> *statp = nullptr;
1461         panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
1462         panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps* mapsp = &maps;
1463 
1464         if (!panda::pandasm::AsmEmitter::Emit(convertedFilePath, prog, statp, mapsp, emitDebugInfo)) {
1465             std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl;
1466             return false;
1467         }
1468 
1469         panda::bytecodeopt::OptimizeBytecode(&prog, mapsp, convertedFilePath, true);
1470 
1471         if (g_compilerOutputProto.size() > 0) {
1472             panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, g_compilerOutputProto);
1473             return true;
1474         }
1475 
1476         if (!panda::pandasm::AsmEmitter::Emit(convertedFilePath, prog, statp, mapsp, emitDebugInfo)) {
1477             std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl;
1478             return false;
1479         }
1480         return true;
1481     }
1482 #endif
1483     if (g_compilerOutputProto.size() > 0) {
1484         panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, g_compilerOutputProto);
1485         return true;
1486     }
1487 
1488     if (!panda::pandasm::AsmEmitter::Emit(convertedFilePath, prog, nullptr)) {
1489         std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl;
1490         return false;
1491     }
1492 
1493     Logd("Successfully generated: %s\n", output.c_str());
1494     return true;
1495 }
1496 
EmitAndRestoreProgram(panda::pandasm::Program & prog,const panda::ts2abc::Options & options)1497 static bool EmitAndRestoreProgram(panda::pandasm::Program &prog, const panda::ts2abc::Options &options)
1498 {
1499     if (!EmitProgram(g_outputFileName, options.GetOptLevelArg(), options.GetOptLogLevelArg(), prog)) {
1500         std::cerr << "fail to emit porgram " << g_outputFileName << " in HandleBuffer" << std::endl;
1501         return false;
1502     }
1503     prog = panda::pandasm::Program();
1504     prog.lang = panda::pandasm::extensions::Language::ECMASCRIPT;
1505     g_newLiteralArrayIndex = -1;
1506     return true;
1507 }
1508 
HandleBuffer(const int & ret,char * buff,std::string & data,panda::pandasm::Program & prog,const panda::ts2abc::Options & options)1509 static bool HandleBuffer(const int &ret, char *buff, std::string &data, panda::pandasm::Program &prog,
1510                          const panda::ts2abc::Options &options)
1511 {
1512     uint32_t startPos = 0;
1513     if (options.IsMultiProgramsPipe() && ((buff[0] == '*' && data.back() != '#') ||
1514                                           (buff[0] == '\n' && buff[1] == '*'))) {
1515         if (!EmitAndRestoreProgram(prog, options)) {
1516             std::cerr << "fail to emit and restore program" << std::endl;
1517             return false;
1518         }
1519     }
1520 
1521     for (int idx = 0; idx < ret; idx++) {
1522         if (IsStartOrEndPosition(idx, buff, data)) {
1523             if (g_isStartDollar) {
1524                 startPos = idx + 1;
1525                 g_isStartDollar = false;
1526                 continue;
1527             }
1528 
1529             std::string substr(buff + startPos, buff + idx);
1530             data += substr;
1531             ReplaceAllDistinct(data, "#$", "$");
1532             ReplaceAllDistinct(data, "#*", "*");
1533             if (ParseSmallPieceJson(data, prog)) {
1534                 std::cerr << "fail to parse stringify json" << std::endl;
1535                 return false;
1536             }
1537             g_isStartDollar = true;
1538             // clear data after parsing
1539             data.clear();
1540             // idx: $, then idx + 1:'\n', so comparing buff[idx + 2] with '*'
1541             if (options.IsMultiProgramsPipe() && idx < ret - 2 && buff[idx + 2] == '*' &&
1542                 !EmitAndRestoreProgram(prog, options)) {
1543                 std::cerr << "fail to emit and restore program" << std::endl;
1544                 return false;
1545             }
1546         }
1547     }
1548 
1549     if (!g_isStartDollar) {
1550         std::string substr(buff + startPos, buff + ret);
1551         data += substr;
1552     }
1553 
1554     return true;
1555 }
1556 
ReadFromPipe(panda::pandasm::Program & prog,panda::ts2abc::Options options)1557 static bool ReadFromPipe(panda::pandasm::Program &prog, panda::ts2abc::Options options)
1558 {
1559     std::string data;
1560     const size_t bufSize = 4096;
1561     // the parent process open a pipe to this child process with fd of 3
1562     const size_t fd = 3;
1563 
1564     char buff[bufSize + 1];
1565     int ret = 0;
1566 
1567     while ((ret = read(fd, buff, bufSize)) != 0) {
1568         if (ret < 0) {
1569             std::cerr << "Read pipe error" << std::endl;
1570             return false;
1571         }
1572         buff[ret] = '\0';
1573 
1574         if (!HandleBuffer(ret, buff, data, prog, options)) {
1575             std::cerr << "fail to handle buffer" << std::endl;
1576             return false;
1577         }
1578     }
1579 
1580     Logd("finish parsing from pipe");
1581     return true;
1582 }
1583 
GenerateProgramsFromPipe(const panda::ts2abc::Options & options)1584 bool GenerateProgramsFromPipe(const panda::ts2abc::Options &options)
1585 {
1586     panda::pandasm::Program prog = panda::pandasm::Program();
1587     prog.lang = panda::pandasm::extensions::Language::ECMASCRIPT;
1588 
1589     if (!ReadFromPipe(prog, options)) {
1590         std::cerr << "fail to parse programs from Pipe!" << std::endl;
1591         return false;
1592     }
1593 
1594     return true;
1595 }
1596 
GenerateProgram(const std::string & data,const std::string & output,panda::ts2abc::Options options)1597 bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string &output,
1598                      panda::ts2abc::Options options)
1599 {
1600     bool isParsingFromPipe = options.GetCompileByPipeArg();
1601     int optLevel = options.GetOptLevelArg();
1602     std::string optLogLevel = options.GetOptLogLevelArg();
1603     panda::pandasm::Program prog = panda::pandasm::Program();
1604     prog.lang = panda::pandasm::extensions::Language::ECMASCRIPT;
1605 
1606     if (isParsingFromPipe) {
1607         if (!ReadFromPipe(prog, options)) {
1608             std::cerr << "fail to parse Pipe!" << std::endl;
1609             return false;
1610         }
1611     } else {
1612         if (!ParseData(data, prog)) {
1613             std::cerr << "fail to parse Data!" << std::endl;
1614             return false;
1615         }
1616     }
1617 
1618     Logd("parsing done, calling pandasm\n");
1619 
1620     return EmitProgram(output, optLevel, optLogLevel, prog);
1621 }
1622 
CompileNpmEntries(const std::string & input,const std::string & output)1623 bool CompileNpmEntries(const std::string &input, const std::string &output)
1624 {
1625     auto inputAbs = panda::os::file::File::GetAbsolutePath(input);
1626     if (!inputAbs) {
1627         std::cerr << "Input file does not exist" << std::endl;
1628         return false;
1629     }
1630     auto fpath = inputAbs.Value();
1631     if (panda::os::file::File::IsRegularFile(fpath) == false) {
1632         std::cerr << "Input: " << fpath << " must be either a regular file or a directory" << std::endl;
1633         return false;
1634     }
1635 
1636     std::stringstream ss;
1637     std::ifstream inputStream(panda::os::file::File::GetExtendedFilePath(input));
1638     if (inputStream.fail()) {
1639         std::cerr << "Failed to read file to buffer: " << input << std::endl;
1640         return false;
1641     }
1642     ss << inputStream.rdbuf();
1643 
1644     panda::pandasm::Program prog = panda::pandasm::Program();
1645     prog.lang = LANG_EXT;
1646 
1647     std::string line;
1648     while (getline(ss, line)) {
1649         std::size_t pos = line.find(":");
1650         std::string recordName = line.substr(0, pos);
1651         std::string field = line.substr(pos + 1);
1652 
1653         auto langExt = LANG_EXT;
1654         auto entryNameField = panda::pandasm::Field(langExt);
1655         entryNameField.name = field;
1656         entryNameField.type = panda::pandasm::Type("u8", 0);
1657         entryNameField.metadata->SetValue(panda::pandasm::ScalarValue::Create<panda::pandasm::Value::Type::U8>(
1658             static_cast<bool>(0)));
1659 
1660         panda::pandasm::Record entryRecord = panda::pandasm::Record(recordName, langExt);
1661         entryRecord.field_list.emplace_back(std::move(entryNameField));
1662         prog.record_table.emplace(recordName, std::move(entryRecord));
1663     }
1664 
1665     panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, output);
1666     return true;
1667 }
1668 
HandleJsonFile(const std::string & input,std::string & data)1669 bool HandleJsonFile(const std::string &input, std::string &data)
1670 {
1671     auto inputAbs = panda::os::file::File::GetAbsolutePath(input);
1672     if (!inputAbs) {
1673         std::cerr << "Input file does not exist" << std::endl;
1674         return false;
1675     }
1676     auto fpath = inputAbs.Value();
1677     if (panda::os::file::File::IsRegularFile(fpath) == false) {
1678         std::cerr << "Input must be either a regular file or a directory" << std::endl;
1679         return false;
1680     }
1681 
1682     std::ifstream file;
1683     file.open(panda::os::file::File::GetExtendedFilePath(fpath));
1684     if (file.fail()) {
1685         std::cerr << "failed to open:" << fpath << std::endl;
1686         return false;
1687     }
1688 
1689     file.seekg(0, std::ios::end);
1690     int64_t fileSize = file.tellg();
1691     if (fileSize == -1) {
1692         std::cerr << "failed to get position in input sequence: " << fpath << std::endl;
1693         return false;
1694     }
1695     file.seekg(0, std::ios::beg);
1696     auto buf = std::vector<char>(fileSize);
1697     file.read(reinterpret_cast<char *>(buf.data()), fileSize);
1698     data = buf.data();
1699     buf.clear();
1700     file.close();
1701 
1702     return true;
1703 }
1704 
1705 } // namespace panda::ts2abc
1706