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 ®ularImportEntries,
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