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