1 /*
2 * Copyright (c) 2021-2024 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 <cctype>
17 #include <cerrno>
18
19 #include <iterator>
20
21 #include "assembly-type.h"
22 #include "libpandafile/type_helper.h"
23 #include "ins_emit.h"
24 #include "modifiers.h"
25 #include "opcode_parsing.h"
26 #include "operand_types_print.h"
27 #include "utils/number-utils.h"
28
29 namespace ark::pandasm {
30
ParseRecordFields()31 bool Parser::ParseRecordFields()
32 {
33 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
34 currRecord_->bodyLocation.begin = GetCurrentPosition(false);
35 open_ = true;
36
37 ++context_;
38 }
39
40 currRecord_->bodyPresence = true;
41
42 if (!open_) {
43 context_.err = GetError("Expected keyword.", Error::ErrorType::ERR_BAD_KEYWORD);
44 return false;
45 }
46
47 if (context_.Mask()) {
48 return true;
49 }
50
51 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
52 currRecord_->bodyLocation.end = GetCurrentPosition(true);
53 ++context_;
54
55 open_ = false;
56
57 return true;
58 }
59
60 currRecord_->fieldList.emplace_back(program_.lang);
61 currFld_ = &(currRecord_->fieldList[currRecord_->fieldList.size() - 1]);
62 currFld_->lineOfDef = lineStric_;
63 context_.insNumber = currRecord_->fieldList.size();
64
65 LOG(DEBUG, ASSEMBLER) << "parse line " << lineStric_ << " as field (.field name)";
66 if (!ParseRecordField()) {
67 if (context_.err.err != Error::ErrorType::ERR_NONE) {
68 return false;
69 }
70
71 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
72 currRecord_->bodyLocation.end = GetCurrentPosition(true);
73 ++context_;
74 open_ = false;
75 } else {
76 context_.err = GetError("Expected a new field on the next line.", Error::ErrorType::ERR_BAD_KEYWORD);
77 return false;
78 }
79 }
80
81 return true;
82 }
83
ParseFieldName()84 bool Parser::ParseFieldName()
85 {
86 if (PrefixedValidName()) {
87 std::string fieldName = std::string(context_.GiveToken().data(), context_.GiveToken().length());
88
89 auto matchNames = [&fieldName](const pandasm::Field &f) { return fieldName == f.name; };
90 const auto iter = std::find_if(currRecord_->fieldList.begin(), currRecord_->fieldList.end(), matchNames);
91 if (iter != currRecord_->fieldList.end()) {
92 if (iter->isDefined) {
93 context_.err =
94 GetError("Repeating field names in the same record.", Error::ErrorType::ERR_REPEATING_FIELD_NAME);
95
96 return false;
97 }
98
99 currRecord_->fieldList.erase(iter);
100 }
101
102 currFld_ = &(currRecord_->fieldList[currRecord_->fieldList.size() - 1]);
103
104 currFld_->name = fieldName;
105
106 ++context_;
107
108 return true;
109 }
110
111 context_.err = GetError("Invalid name of field.", Error::ErrorType::ERR_BAD_OPERATION_NAME);
112
113 return false;
114 }
115
ParseType(Type * type)116 bool Parser::ParseType(Type *type)
117 {
118 ASSERT(TypeValidName());
119
120 std::string componentName(context_.GiveToken());
121 size_t rank = 0;
122
123 ++context_;
124
125 while (*context_ == Token::Type::DEL_SQUARE_BRACKET_L) {
126 ++context_;
127 if (*context_ != Token::Type::DEL_SQUARE_BRACKET_R) {
128 context_.err = GetError("Expected ']'.", Error::ErrorType::ERR_BAD_ARRAY_TYPE_BOUND);
129 return false;
130 }
131 ++context_;
132 ++rank;
133 }
134
135 *type = Type(componentName, rank);
136
137 if (type->IsArray()) {
138 program_.arrayTypes.insert(*type);
139 }
140
141 return true;
142 }
143
ParseFieldType()144 bool Parser::ParseFieldType()
145 {
146 LOG(DEBUG, ASSEMBLER) << "started searching field type value (line " << lineStric_
147 << "): " << context_.tokens[context_.number - 1].wholeLine;
148
149 if (!TypeValidName()) {
150 context_.err = GetError("Not a correct type.", Error::ErrorType::ERR_BAD_FIELD_VALUE_TYPE);
151 return false;
152 }
153
154 if (!ParseType(&currFld_->type)) {
155 return false;
156 }
157
158 currFld_->metadata->SetFieldType(currFld_->type);
159
160 LOG(DEBUG, ASSEMBLER) << "field type found (line " << lineStric_ << "): " << context_.GiveToken();
161
162 return true;
163 }
164
ParseRecordField()165 bool Parser::ParseRecordField()
166 {
167 if (!ParseFieldType()) {
168 return false;
169 }
170
171 if (context_.Mask()) {
172 context_.err = GetError("Expected field name.", Error::ErrorType::ERR_BAD_FIELD_MISSING_NAME, +1);
173 return false;
174 }
175
176 if (!ParseFieldName()) {
177 return false;
178 }
179
180 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
181 currRecord_->bodyLocation.end = GetCurrentPosition(true);
182 ++context_;
183 open_ = false;
184 return true;
185 }
186
187 metadata_ = currFld_->metadata.get();
188 ParseMetaDef();
189
190 return context_.Mask();
191 }
192
IsConstArray()193 bool Parser::IsConstArray()
194 {
195 return isConstArray_;
196 }
197
ArrayElementsValidNumber()198 bool Parser::ArrayElementsValidNumber()
199 {
200 if (!IsConstArray()) {
201 return true;
202 }
203
204 ASSERT(currArray_->literals.size() > 1);
205
206 auto initSize = std::get<uint32_t>(currArray_->literals[1].value);
207 if (initSize < 1) {
208 return false;
209 }
210 if (currArray_->literals.size() != initSize + INTRO_CONST_ARRAY_LITERALS_NUMBER) {
211 return false;
212 }
213
214 return true;
215 }
216
ParseAsArray(const std::vector<Token> & tokens)217 void Parser::ParseAsArray(const std::vector<Token> &tokens)
218 {
219 LOG(DEBUG, ASSEMBLER) << "started parsing of array (line " << lineStric_ << "): " << tokens[0].wholeLine;
220 funcDef_ = false;
221 recordDef_ = false;
222 arrayDef_ = true;
223
224 if (!open_) {
225 ++context_;
226 } else {
227 context_.err =
228 GetError("No one array can be defined inside another array.", Error::ErrorType::ERR_BAD_DEFINITION);
229 return;
230 }
231
232 if (ParseArrayFullSign()) {
233 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
234 ++context_;
235
236 LOG(DEBUG, ASSEMBLER) << "array body is open, line " << lineStric_ << ": " << tokens[0].wholeLine;
237
238 open_ = true;
239 }
240
241 uint32_t iterNumber = 1;
242 if (IsConstArray()) {
243 iterNumber = std::get<uint32_t>(currArray_->literals[1].value);
244 }
245
246 if (iterNumber < 1) {
247 context_.err =
248 GetError("Сonstant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
249 return;
250 }
251
252 for (uint32_t i = 0; i < iterNumber; i++) {
253 if (open_ && !context_.Mask() && *context_ != Token::Type::DEL_BRACE_R) {
254 ParseArrayElements();
255 } else {
256 break;
257 }
258 }
259
260 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
261 if (!ArrayElementsValidNumber()) {
262 context_.err =
263 GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
264 return;
265 }
266 LOG(DEBUG, ASSEMBLER) << "array body is closed, line " << lineStric_ << ": " << tokens[0].wholeLine;
267
268 ++context_;
269
270 open_ = false;
271 }
272 }
273 }
274
ParseArrayElements()275 bool Parser::ParseArrayElements()
276 {
277 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
278 open_ = true;
279
280 ++context_;
281 }
282
283 if (!open_) {
284 context_.err = GetError("Expected keyword.", Error::ErrorType::ERR_BAD_KEYWORD);
285 return false;
286 }
287
288 if (context_.Mask()) {
289 return true;
290 }
291
292 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
293 if (!ArrayElementsValidNumber()) {
294 context_.err =
295 GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
296 return false;
297 }
298 ++context_;
299
300 open_ = false;
301
302 return true;
303 }
304
305 currArray_->literals.emplace_back();
306 currArrayElem_ = &(currArray_->literals[currArray_->literals.size() - 1]);
307
308 LOG(DEBUG, ASSEMBLER) << "parse line " << lineStric_ << " as array elem (.array_elem value)";
309 if (!ParseArrayElement()) {
310 if (context_.err.err != Error::ErrorType::ERR_NONE) {
311 return false;
312 }
313
314 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
315 ++context_;
316 open_ = false;
317
318 if (!ArrayElementsValidNumber()) {
319 context_.err =
320 GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
321 return false;
322 }
323 } else {
324 context_.err =
325 GetError("Expected a new array element on the next line.", Error::ErrorType::ERR_BAD_KEYWORD);
326 return false;
327 }
328 }
329
330 return true;
331 }
332
ParseArrayElement()333 bool Parser::ParseArrayElement()
334 {
335 if (IsConstArray()) {
336 currArrayElem_->tag = static_cast<panda_file::LiteralTag>(std::get<uint8_t>(currArray_->literals[0].value));
337 } else {
338 if (!ParseArrayElementType()) {
339 return false;
340 }
341
342 auto valTag = currArrayElem_->tag;
343
344 currArrayElem_->value = static_cast<uint8_t>(currArrayElem_->tag);
345 currArrayElem_->tag = panda_file::LiteralTag::TAGVALUE;
346
347 currArray_->literals.emplace_back();
348 currArrayElem_ = &(currArray_->literals[currArray_->literals.size() - 1]);
349 currArrayElem_->tag = valTag;
350 }
351
352 if (context_.Mask()) {
353 context_.err =
354 GetError("Expected array element value.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_MISSING_VALUE, +1);
355 return false;
356 }
357
358 if (!ParseArrayElementValue()) {
359 return false;
360 }
361
362 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
363 ++context_;
364 open_ = false;
365
366 if (!ArrayElementsValidNumber()) {
367 context_.err =
368 GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
369 return false;
370 }
371 return true;
372 }
373
374 return IsConstArray() ? true : context_.Mask();
375 }
376
ParseArrayElementType()377 bool Parser::ParseArrayElementType()
378 {
379 LOG(DEBUG, ASSEMBLER) << "started searching array element type value (line " << lineStric_
380 << "): " << context_.tokens[context_.number - 1].wholeLine;
381
382 if (!TypeValidName()) {
383 context_.err = GetError("Not a correct type.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_VALUE_TYPE);
384 return false;
385 }
386
387 Type type;
388 if (!ParseType(&type)) {
389 return false;
390 }
391
392 // workaround until #5776 is done
393 auto typeName = type.GetName();
394 std::replace(typeName.begin(), typeName.end(), '.', '/');
395 auto typeWithSlash = Type(typeName, 0);
396
397 if (ark::pandasm::Type::IsPandaPrimitiveType(type.GetName())) {
398 if (IsConstArray()) {
399 currArrayElem_->tag = ark::pandasm::LiteralArray::GetArrayTagFromComponentType(type.GetId());
400 } else {
401 currArrayElem_->tag = ark::pandasm::LiteralArray::GetLiteralTagFromComponentType(type.GetId());
402 }
403
404 if (program_.arrayTypes.find(type) == program_.arrayTypes.end()) {
405 program_.arrayTypes.emplace(type, 1);
406 }
407 } else if (ark::pandasm::Type::IsStringType(typeWithSlash.GetName(), program_.lang)) {
408 if (IsConstArray()) {
409 currArrayElem_->tag = panda_file::LiteralTag::ARRAY_STRING;
410 } else {
411 currArrayElem_->tag = panda_file::LiteralTag::STRING;
412 }
413
414 if (program_.arrayTypes.find(typeWithSlash) == program_.arrayTypes.end()) {
415 program_.arrayTypes.emplace(typeWithSlash, 1);
416 }
417 } else {
418 return false;
419 }
420
421 LOG(DEBUG, ASSEMBLER) << "array element type found (line " << lineStric_ << "): " << context_.GiveToken();
422
423 return true;
424 }
425
ParseArrayElementValueInteger()426 bool Parser::ParseArrayElementValueInteger()
427 {
428 int64_t n;
429 if (!ParseInteger(&n)) {
430 context_.err =
431 GetError("Invalid value of array integer element.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_VALUE_INTEGER);
432 return false;
433 }
434 if (currArrayElem_->IsBoolValue()) {
435 currArrayElem_->value = static_cast<bool>(n);
436 }
437 if (currArrayElem_->IsByteValue()) {
438 currArrayElem_->value = static_cast<uint8_t>(n);
439 }
440 if (currArrayElem_->IsShortValue()) {
441 currArrayElem_->value = static_cast<uint16_t>(n);
442 }
443 if (currArrayElem_->IsIntegerValue()) {
444 currArrayElem_->value = static_cast<uint32_t>(n);
445 }
446 if (currArrayElem_->IsLongValue()) {
447 currArrayElem_->value = static_cast<uint64_t>(n);
448 }
449 return true;
450 }
451
ParseArrayElementValueFloat()452 bool Parser::ParseArrayElementValueFloat()
453 {
454 double n;
455 if (!ParseFloat(&n, !currArrayElem_->IsFloatValue())) {
456 context_.err =
457 GetError("Invalid value of array float element.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_VALUE_FLOAT);
458 return false;
459 }
460 if (currArrayElem_->IsFloatValue()) {
461 currArrayElem_->value = static_cast<float>(n);
462 } else {
463 currArrayElem_->value = static_cast<double>(n);
464 }
465 return true;
466 }
467
ParseArrayElementValueString()468 bool Parser::ParseArrayElementValueString()
469 {
470 if (context_.err.err != Error::ErrorType::ERR_NONE) {
471 return false;
472 }
473
474 auto res = ParseStringLiteral();
475 if (!res) {
476 context_.err =
477 GetError("Invalid value of array string element.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_VALUE_STRING);
478 return false;
479 }
480 currArrayElem_->value = res.value();
481 return true;
482 }
483
ParseArrayElementValue()484 bool Parser::ParseArrayElementValue()
485 {
486 if (currArrayElem_->IsBoolValue() || currArrayElem_->IsByteValue() || currArrayElem_->IsShortValue() ||
487 currArrayElem_->IsIntegerValue() || currArrayElem_->IsLongValue()) {
488 if (!ParseArrayElementValueInteger()) {
489 return false;
490 }
491 }
492 if (currArrayElem_->IsFloatValue() || currArrayElem_->IsDoubleValue()) {
493 if (!ParseArrayElementValueFloat()) {
494 return false;
495 }
496 }
497 if (currArrayElem_->IsStringValue()) {
498 if (!ParseArrayElementValueString()) {
499 return false;
500 }
501 }
502
503 ++context_;
504
505 return true;
506 }
507
ParseFunctionCode()508 bool Parser::ParseFunctionCode()
509 {
510 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
511 open_ = true;
512 currFunc_->bodyLocation.begin = GetCurrentPosition(false);
513 ++context_;
514 }
515
516 currFunc_->bodyPresence = true;
517
518 if (!open_) {
519 context_.err = GetError("Expected keyword.", Error::ErrorType::ERR_BAD_KEYWORD);
520 return false;
521 }
522
523 if (context_.Mask()) {
524 return true;
525 }
526
527 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
528 currFunc_->bodyLocation.end = GetCurrentPosition(true);
529 ++context_;
530 open_ = false;
531 return true;
532 }
533
534 currIns_ = &currFunc_->ins.emplace_back();
535
536 LOG(DEBUG, ASSEMBLER) << "parse line " << lineStric_
537 << " as instruction ([label:] operation [operand,] [# comment])";
538
539 ParseFunctionInstruction();
540
541 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
542 currFunc_->bodyLocation.end = GetCurrentPosition(true);
543 ++context_;
544 open_ = false;
545 }
546
547 return true;
548 }
549
ParseAsRecord(const std::vector<Token> & tokens)550 void Parser::ParseAsRecord(const std::vector<Token> &tokens)
551 {
552 LOG(DEBUG, ASSEMBLER) << "started parsing of record (line " << lineStric_ << "): " << tokens[0].wholeLine;
553 funcDef_ = false;
554 recordDef_ = true;
555 arrayDef_ = false;
556
557 if (!open_) {
558 ++context_;
559 } else {
560 context_.err =
561 GetError("No one record can be defined inside another record.", Error::ErrorType::ERR_BAD_DEFINITION);
562 return;
563 }
564
565 if (ParseRecordFullSign()) {
566 metadata_ = currRecord_->metadata.get();
567 if (ParseMetaDef()) {
568 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
569 currRecord_->bodyLocation.begin = GetCurrentPosition(false);
570 ++context_;
571
572 LOG(DEBUG, ASSEMBLER) << "record body is open, line " << lineStric_ << ": " << tokens[0].wholeLine;
573
574 open_ = true;
575 }
576
577 if (open_ && !context_.Mask() && *context_ != Token::Type::DEL_BRACE_R) {
578 ParseRecordFields();
579 } else if (open_) {
580 currRecord_->bodyPresence = true;
581 }
582
583 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
584 LOG(DEBUG, ASSEMBLER) << "record body is closed, line " << lineStric_ << ": " << tokens[0].wholeLine;
585
586 currRecord_->bodyLocation.end = GetCurrentPosition(true);
587 ++context_;
588
589 open_ = false;
590 }
591 }
592 }
593 }
594
ParseAsFunction(const std::vector<Token> & tokens)595 void Parser::ParseAsFunction(const std::vector<Token> &tokens)
596 {
597 LOG(DEBUG, ASSEMBLER) << "started parsing of function (line " << lineStric_ << "): " << tokens[0].wholeLine;
598 recordDef_ = false;
599 funcDef_ = true;
600 arrayDef_ = false;
601
602 if (!open_) {
603 ++context_;
604 } else {
605 context_.err =
606 GetError("No one function can be defined inside another function.", Error::ErrorType::ERR_BAD_DEFINITION);
607 return;
608 }
609
610 if (ParseFunctionFullSign()) {
611 metadata_ = currFunc_->metadata.get();
612 if (ParseMetaDef()) {
613 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
614 currFunc_->bodyLocation.begin = GetCurrentPosition(false);
615 ++context_;
616
617 LOG(DEBUG, ASSEMBLER) << "function body is open, line " << lineStric_ << ": " << tokens[0].wholeLine;
618
619 open_ = true;
620 }
621
622 if (open_ && !context_.Mask() && *context_ != Token::Type::DEL_BRACE_R) {
623 ParseFunctionCode();
624 } else if (open_) {
625 currFunc_->bodyPresence = true;
626 }
627
628 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
629 LOG(DEBUG, ASSEMBLER) << "function body is closed, line " << lineStric_ << ": " << tokens[0].wholeLine;
630
631 currFunc_->bodyLocation.end = GetCurrentPosition(true);
632 ++context_;
633 open_ = false;
634 }
635 }
636 }
637 }
638
ParseAsUnionField(const std::vector<Token> & tokens)639 void Parser::ParseAsUnionField(const std::vector<Token> &tokens)
640 {
641 LOG(DEBUG, ASSEMBLER) << "started parsing of union field (line " << lineStric_ << "): " << tokens[0].wholeLine;
642
643 if (!open_) {
644 ++context_;
645 } else {
646 context_.err =
647 GetError("No union field can be defined inside record or function.", Error::ErrorType::ERR_BAD_DEFINITION);
648 return;
649 }
650
651 auto dummyRecord = program_.recordTable.find(panda_file::GetDummyClassName());
652 if (dummyRecord == program_.recordTable.end()) {
653 SetRecordInformation(panda_file::GetDummyClassName());
654 }
655 currRecord_->fieldList.emplace_back(program_.lang);
656 currFld_ = &(currRecord_->fieldList[currRecord_->fieldList.size() - 1]);
657 currFld_->lineOfDef = lineStric_;
658 ParseRecordField();
659 }
660
ParseAsBraceRight(const std::vector<Token> & tokens)661 void Parser::ParseAsBraceRight(const std::vector<Token> &tokens)
662 {
663 if (!open_) {
664 context_.err =
665 GetError("Delimiter '}' for the code area is outside a function.", Error::ErrorType::ERR_BAD_BOUND);
666 return;
667 }
668
669 LOG(DEBUG, ASSEMBLER) << "body is closed (line " << lineStric_ << "): " << tokens[0].wholeLine;
670
671 open_ = false;
672 if (funcDef_) {
673 currFunc_->bodyLocation.end = GetCurrentPosition(true);
674 } else if (recordDef_) {
675 currRecord_->bodyLocation.end = GetCurrentPosition(true);
676 } else if (arrayDef_) {
677 if (!ArrayElementsValidNumber()) {
678 context_.err =
679 GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
680 return;
681 }
682 } else {
683 LOG(FATAL, ASSEMBLER) << "Internal error: either function or record must be parsed here";
684 }
685 ++context_;
686 }
687
ParseResetFunctionLabelsAndParams()688 void Parser::ParseResetFunctionLabelsAndParams()
689 {
690 if (open_ || err_.err != Error::ErrorType::ERR_NONE) {
691 return;
692 }
693
694 for (const auto &f : program_.functionTable) {
695 for (const auto &k : f.second.labelTable) {
696 if (!k.second.fileLocation->isDefined) {
697 context_.err = Error("This label does not exist.", lineStric_, Error::ErrorType::ERR_BAD_LABEL_EXT, "",
698 k.second.fileLocation->boundLeft, k.second.fileLocation->boundRight,
699 k.second.fileLocation->wholeLine);
700 SetError();
701 }
702 }
703 }
704
705 for (const auto &t : context_.functionArgumentsLists) {
706 currFunc_ = &(program_.functionTable.at(t.first));
707 currFunc_->regsNum = static_cast<size_t>(currFunc_->valueOfFirstParam + 1);
708
709 for (const auto &v : t.second) {
710 if (currFunc_->ins.empty() && currFunc_->ins.size() < v.first && currFunc_->ins[v.first - 1].regs.empty()) {
711 continue;
712 }
713 currFunc_->ins[v.first - 1].regs[v.second] += static_cast<uint16_t>(currFunc_->valueOfFirstParam + 1);
714 // NOLINTNEXTLINE(hicpp-signed-bitwise)
715 size_t maxRegNumber = (1 << currFunc_->ins[v.first - 1].MaxRegEncodingWidth());
716 if (currFunc_->ins[v.first - 1].regs[v.second] >= maxRegNumber) {
717 const auto &debug = currFunc_->ins[v.first - 1].insDebug;
718 context_.err = Error("Register width mismatch.", debug.lineNumber, Error::ErrorType::ERR_BAD_NAME_REG,
719 "", debug.boundLeft, debug.boundRight, debug.wholeLine);
720 SetError();
721 break;
722 }
723 }
724 }
725 }
726
ParseInsFromFuncTable(ark::pandasm::Function & func)727 void Parser::ParseInsFromFuncTable(ark::pandasm::Function &func)
728 {
729 for (auto &insn : func.ins) {
730 if (!insn.HasFlag(InstFlags::METHOD_ID)) {
731 // we need to correct all method_id's
732 continue;
733 }
734
735 bool isInitobj = insn.opcode == Opcode::INITOBJ || insn.opcode == Opcode::INITOBJ_SHORT ||
736 insn.opcode == Opcode::INITOBJ_RANGE;
737 size_t diff = isInitobj ? 0 : 1;
738 auto funcName = insn.ids[0];
739
740 if (!IsSignatureOrMangled(funcName)) {
741 const auto itSynonym = program_.functionSynonyms.find(funcName);
742 if (itSynonym == program_.functionSynonyms.end()) {
743 continue;
744 }
745
746 if (itSynonym->second.size() > 1) {
747 const auto &debug = insn.insDebug;
748 context_.err = Error("Unable to resolve ambiguous function call", debug.lineNumber,
749 Error::ErrorType::ERR_FUNCTION_MULTIPLE_ALTERNATIVES, "", debug.boundLeft,
750 debug.boundRight, debug.wholeLine);
751 SetError();
752 break;
753 }
754
755 insn.ids[0] = program_.functionSynonyms.at(funcName)[0];
756 }
757
758 if (insn.OperandListLength() - diff < program_.functionTable.at(insn.ids[0]).GetParamsNum()) {
759 if (insn.IsCallRange() && (static_cast<int>(insn.regs.size()) - static_cast<int>(diff) >= 0)) {
760 continue;
761 }
762
763 const auto &debug = insn.insDebug;
764 context_.err =
765 Error("Function argument mismatch.", debug.lineNumber, Error::ErrorType::ERR_FUNCTION_ARGUMENT_MISMATCH,
766 "", debug.boundLeft, debug.boundRight, debug.wholeLine);
767 SetError();
768 }
769 }
770 }
771
ParseResetFunctionTable()772 void Parser::ParseResetFunctionTable()
773 {
774 for (auto &[unusedKey, func] : program_.functionTable) {
775 (void)unusedKey;
776 if (!func.fileLocation->isDefined) {
777 context_.err = Error("This function does not exist.", func.fileLocation->lineNumber,
778 Error::ErrorType::ERR_BAD_ID_FUNCTION, "", func.fileLocation->boundLeft,
779 func.fileLocation->boundRight, func.fileLocation->wholeLine);
780 SetError();
781 } else if (func.HasImplementation() != func.bodyPresence) {
782 context_.err =
783 Error("Inconsistency of the definition of the function and its metadata.",
784 func.fileLocation->lineNumber, Error::ErrorType::ERR_BAD_DEFINITION_FUNCTION, "",
785 func.fileLocation->boundLeft, func.fileLocation->boundRight, func.fileLocation->wholeLine);
786 SetError();
787 } else {
788 ParseInsFromFuncTable(func);
789 }
790 }
791 }
792
ParseResetRecords(const ark::pandasm::Record & record)793 void Parser::ParseResetRecords(const ark::pandasm::Record &record)
794 {
795 for (const auto &fld : record.fieldList) {
796 if (!record.HasImplementation() && !fld.metadata->IsForeign()) {
797 context_.err =
798 Error("External record may have only external fields", fld.lineOfDef,
799 Error::ErrorType::ERR_BAD_FIELD_METADATA, "", fld.boundLeft, fld.boundRight, fld.wholeLine);
800 SetError();
801 }
802 if (!fld.isDefined) {
803 context_.err = Error("This field does not exist.", fld.lineOfDef, Error::ErrorType::ERR_BAD_ID_FIELD, "",
804 fld.boundLeft, fld.boundRight, fld.wholeLine);
805 SetError();
806 }
807 }
808 }
809
ParseResetRecordTable()810 void Parser::ParseResetRecordTable()
811 {
812 for (const auto &[unusedKey, record] : program_.recordTable) {
813 (void)unusedKey;
814 if (!record.fileLocation->isDefined) {
815 context_.err = Error("This record does not exist.", record.fileLocation->lineNumber,
816 Error::ErrorType::ERR_BAD_ID_RECORD, "", record.fileLocation->boundLeft,
817 record.fileLocation->boundRight, record.fileLocation->wholeLine);
818 SetError();
819 } else {
820 ParseResetRecords(record);
821 }
822 }
823 }
824
ParseResetTables()825 void Parser::ParseResetTables()
826 {
827 if (err_.err != Error::ErrorType::ERR_NONE) {
828 return;
829 }
830
831 ParseResetFunctionTable();
832
833 if (err_.err != Error::ErrorType::ERR_NONE) {
834 return;
835 }
836
837 ParseResetRecordTable();
838 }
839
ParseAsLanguageDirective()840 void Parser::ParseAsLanguageDirective()
841 {
842 ++context_;
843
844 if (context_.Mask()) {
845 context_.err = GetError("Incorrect .language directive: Expected language",
846 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
847 return;
848 }
849
850 auto lang = context_.GiveToken();
851 auto res = ark::panda_file::LanguageFromString(lang);
852 if (!res) {
853 context_.err =
854 GetError("Incorrect .language directive: Unknown language", Error::ErrorType::ERR_UNKNOWN_LANGUAGE);
855 return;
856 }
857
858 ++context_;
859
860 if (!context_.Mask()) {
861 context_.err = GetError("Incorrect .language directive: Unexpected token",
862 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
863 }
864
865 program_.lang = res.value();
866 }
867
PrepareCatchBlock(bool isCatchall,size_t size,size_t catchallTokensNum,size_t catchTokensNum)868 Function::CatchBlock Parser::PrepareCatchBlock(bool isCatchall, size_t size, size_t catchallTokensNum,
869 size_t catchTokensNum)
870 {
871 constexpr size_t TRY_BEGIN = 0;
872 constexpr size_t TRY_END = 1;
873 constexpr size_t CATCH_BEGIN = 2;
874 constexpr size_t CATCH_END = 3;
875
876 Function::CatchBlock catchBlock;
877 catchBlock.wholeLine = context_.tokens[0].wholeLine;
878 std::vector<std::string> labelNames {"try block begin", "try block end", "catch block begin"};
879 std::vector<std::string> labels;
880 bool fullCatchBlock = (isCatchall && size == catchallTokensNum) || (!isCatchall && size == catchTokensNum);
881 if (fullCatchBlock) {
882 labelNames.emplace_back("catch block end");
883 }
884 if (!isCatchall) {
885 catchBlock.exceptionRecord = context_.GiveToken();
886 ++context_;
887 }
888
889 bool skipComma = isCatchall;
890 for (const auto &labelName : labelNames) {
891 if (!skipComma) {
892 if (*context_ != Token::Type::DEL_COMMA) {
893 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
894 return catchBlock;
895 }
896 ++context_;
897 }
898 skipComma = false;
899 if (!LabelValidName()) {
900 context_.err =
901 GetError(std::string("Invalid name of the ") + labelName + " label.", Error::ErrorType::ERR_BAD_LABEL);
902 return catchBlock;
903 }
904 labels.emplace_back(context_.GiveToken());
905 AddObjectInTable(false, *labelTable_);
906 ++context_;
907 }
908
909 ASSERT(context_.Mask());
910 catchBlock.tryBeginLabel = labels[TRY_BEGIN];
911 catchBlock.tryEndLabel = labels[TRY_END];
912 catchBlock.catchBeginLabel = labels[CATCH_BEGIN];
913 if (fullCatchBlock) {
914 catchBlock.catchEndLabel = labels[CATCH_END];
915 } else {
916 catchBlock.catchEndLabel = labels[CATCH_BEGIN];
917 }
918 return catchBlock;
919 }
920
ParseAsCatchDirective()921 void Parser::ParseAsCatchDirective()
922 {
923 ASSERT(*context_ == Token::Type::ID_CATCH || *context_ == Token::Type::ID_CATCHALL);
924
925 constexpr size_t CATCH_DIRECTIVE_TOKENS_NUM = 8;
926 constexpr size_t CATCHALL_DIRECTIVE_TOKENS_NUM = 6;
927 constexpr size_t CATCH_FULL_DIRECTIVE_TOKENS_NUM = 10;
928 constexpr size_t CATCHALL_FULL_DIRECTIVE_TOKENS_NUM = 8;
929
930 bool isCatchall = *context_ == Token::Type::ID_CATCHALL;
931 size_t size = context_.tokens.size();
932 if (isCatchall && size != CATCHALL_DIRECTIVE_TOKENS_NUM && size != CATCHALL_FULL_DIRECTIVE_TOKENS_NUM) {
933 context_.err = GetError(
934 "Incorrect catch block declaration. Must be in the format: .catchall <try_begin_label>, <try_end_label>, "
935 "<catch_begin_label>[, <catch_end_label>]",
936 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
937 return;
938 }
939
940 if (!isCatchall && size != CATCH_DIRECTIVE_TOKENS_NUM && size != CATCH_FULL_DIRECTIVE_TOKENS_NUM) {
941 context_.err = GetError(
942 "Incorrect catch block declaration. Must be in the format: .catch <exception_record>, <try_begin_label>, "
943 "<try_end_label>, <catch_begin_label>[, <catch_end_label>]",
944 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
945 return;
946 }
947
948 ++context_;
949
950 if (!isCatchall && !RecordValidName()) {
951 context_.err = GetError("Invalid name of the exception record.", Error::ErrorType::ERR_BAD_RECORD_NAME);
952 return;
953 }
954
955 Function::CatchBlock catchBlock =
956 PrepareCatchBlock(isCatchall, size, CATCHALL_FULL_DIRECTIVE_TOKENS_NUM, CATCH_FULL_DIRECTIVE_TOKENS_NUM);
957
958 currFunc_->catchBlocks.push_back(catchBlock);
959 }
960
ParseAsCatchall(const std::vector<Token> & tokens)961 void Parser::ParseAsCatchall(const std::vector<Token> &tokens)
962 {
963 std::string directiveName = *context_ == Token::Type::ID_CATCH ? ".catch" : ".catchall";
964 if (!funcDef_) {
965 context_.err = GetError(directiveName + " directive is located outside of a function body.",
966 Error::ErrorType::ERR_INCORRECT_DIRECTIVE_LOCATION);
967 return;
968 }
969
970 LOG(DEBUG, ASSEMBLER) << "started parsing of " << directiveName << " directive (line " << lineStric_
971 << "): " << tokens[0].wholeLine;
972
973 ParseAsCatchDirective();
974 }
975
ParseAsLanguage(const std::vector<Token> & tokens,bool & isLangParsed,bool & isFirstStatement)976 void Parser::ParseAsLanguage(const std::vector<Token> &tokens, bool &isLangParsed, bool &isFirstStatement)
977 {
978 if (isLangParsed) {
979 context_.err = GetError("Multiple .language directives", Error::ErrorType::ERR_MULTIPLE_DIRECTIVES);
980 return;
981 }
982
983 if (!isFirstStatement) {
984 context_.err = GetError(".language directive must be specified before any other declarations",
985 Error::ErrorType::ERR_INCORRECT_DIRECTIVE_LOCATION);
986 return;
987 }
988
989 LOG(DEBUG, ASSEMBLER) << "started parsing of .language directive (line " << lineStric_
990 << "): " << tokens[0].wholeLine;
991
992 ParseAsLanguageDirective();
993
994 isLangParsed = true;
995 }
996
ParseAfterLine(bool & isFirstStatement)997 bool Parser::ParseAfterLine(bool &isFirstStatement)
998 {
999 SetError();
1000
1001 if (!context_.Mask() && err_.err == Error::ErrorType::ERR_NONE) {
1002 context_.err = GetError("There can be nothing after.", Error::ErrorType::ERR_BAD_END);
1003 }
1004
1005 if (err_.err != Error::ErrorType::ERR_NONE) {
1006 LOG(DEBUG, ASSEMBLER) << "processing aborted (error detected)";
1007 return false;
1008 }
1009
1010 LOG(DEBUG, ASSEMBLER) << "parsing of line " << lineStric_ << " is successful";
1011
1012 SetError();
1013
1014 isFirstStatement = false;
1015
1016 return true;
1017 }
1018
ParseAfterMainLoop(const std::string & fileName)1019 Expected<Program, Error> Parser::ParseAfterMainLoop(const std::string &fileName)
1020 {
1021 ParseResetFunctionLabelsAndParams();
1022
1023 if (open_ && err_.err == Error::ErrorType::ERR_NONE) {
1024 context_.err = Error("Code area is not closed.", currFunc_->fileLocation->lineNumber,
1025 Error::ErrorType::ERR_BAD_CLOSE, "", 0, currFunc_->name.size(), currFunc_->name);
1026 SetError();
1027 }
1028
1029 ParseResetTables();
1030
1031 if (err_.err != Error::ErrorType::ERR_NONE) {
1032 return Unexpected(err_);
1033 }
1034
1035 for (auto &func : program_.functionTable) {
1036 if (func.second.metadata->HasImplementation()) {
1037 func.second.sourceFile = fileName;
1038 }
1039 }
1040
1041 for (auto &rec : program_.recordTable) {
1042 if (rec.second.HasImplementation()) {
1043 rec.second.sourceFile = fileName;
1044 }
1045 }
1046
1047 return std::move(program_);
1048 }
1049
ParseContextByType(const std::vector<Token> & tokens,bool & isLangParsed,bool & isFirstStatement)1050 void Parser::ParseContextByType(const std::vector<Token> &tokens, bool &isLangParsed, bool &isFirstStatement)
1051 {
1052 switch (*context_) {
1053 case Token::Type::ID_CATCH:
1054 case Token::Type::ID_CATCHALL: {
1055 ParseAsCatchall(tokens);
1056 break;
1057 }
1058 case Token::Type::ID_LANG: {
1059 ParseAsLanguage(tokens, isLangParsed, isFirstStatement);
1060 break;
1061 }
1062 case Token::Type::ID_REC: {
1063 ParseAsRecord(tokens);
1064 break;
1065 }
1066 case Token::Type::ID_FUN: {
1067 ParseAsFunction(tokens);
1068 break;
1069 }
1070 case Token::Type::ID_UNION: {
1071 ParseAsUnionField(tokens);
1072 break;
1073 }
1074 case Token::Type::ID_ARR: {
1075 ParseAsArray(tokens);
1076 break;
1077 }
1078 case Token::Type::DEL_BRACE_R: {
1079 ParseAsBraceRight(tokens);
1080 break;
1081 }
1082 default: {
1083 if (funcDef_) {
1084 ParseFunctionCode();
1085 } else if (recordDef_) {
1086 ParseRecordFields();
1087 } else if (arrayDef_) {
1088 ParseArrayElements();
1089 }
1090 }
1091 }
1092 }
1093
Parse(TokenSet & vectorsTokens,const std::string & fileName)1094 Expected<Program, Error> Parser::Parse(TokenSet &vectorsTokens, const std::string &fileName)
1095 {
1096 bool isLangParsed = false;
1097 bool isFirstStatement = true;
1098 for (const auto &tokens : vectorsTokens) {
1099 ++lineStric_;
1100 if (tokens.empty()) {
1101 continue;
1102 }
1103 LOG(DEBUG, ASSEMBLER) << "started parsing of line " << lineStric_ << ": " << tokens[0].wholeLine;
1104 context_.Make(tokens);
1105
1106 ParseContextByType(tokens, isLangParsed, isFirstStatement);
1107
1108 if (!ParseAfterLine(isFirstStatement)) {
1109 break;
1110 }
1111 }
1112
1113 return ParseAfterMainLoop(fileName);
1114 }
1115
Parse(const std::string & source,const std::string & fileName)1116 Expected<Program, Error> Parser::Parse(const std::string &source, const std::string &fileName)
1117 {
1118 auto ss = std::stringstream(source);
1119 std::string line;
1120
1121 Lexer l;
1122 std::vector<std::vector<Token>> v;
1123
1124 while (std::getline(ss, line)) {
1125 auto [tokens, error] = l.TokenizeString(line);
1126 if (error.err != Error::ErrorType::ERR_NONE) {
1127 return Unexpected(error);
1128 }
1129
1130 v.push_back(tokens);
1131 }
1132
1133 return Parse(v, fileName);
1134 }
1135
SetError()1136 void Parser::SetError()
1137 {
1138 err_ = context_.err;
1139 }
1140
RegValidName()1141 bool Parser::RegValidName()
1142 {
1143 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1144 return false;
1145 }
1146
1147 if (currFunc_->GetParamsNum() > 0) {
1148 return context_.ValidateRegisterName('v') || context_.ValidateRegisterName('a', currFunc_->GetParamsNum() - 1);
1149 }
1150
1151 return context_.ValidateRegisterName('v');
1152 }
1153
ParamValidName()1154 bool Parser::ParamValidName()
1155 {
1156 return context_.ValidateParameterName(currFunc_->GetParamsNum());
1157 }
1158
IsAlphaNumeric(char c)1159 bool IsAlphaNumeric(char c)
1160 {
1161 return std::isalnum(c) != 0 || c == '_' || c == '$';
1162 }
1163
IsNonDigit(char c)1164 bool IsNonDigit(char c)
1165 {
1166 return std::isalpha(c) != 0 || c == '_' || c == '$';
1167 }
1168
PrefixedValidName(bool allowBrackets)1169 bool Parser::PrefixedValidName(bool allowBrackets)
1170 {
1171 auto s = context_.GiveToken();
1172 if (!IsNonDigit(s[0])) {
1173 return false;
1174 }
1175
1176 size_t i = 1;
1177
1178 while (i < s.size()) {
1179 if (s[i] == '.') {
1180 ++i;
1181 if (i >= s.size() || !IsNonDigit(s[i])) {
1182 return false;
1183 }
1184 } else {
1185 if (!allowBrackets && !IsAlphaNumeric(s[i]) && s[i] != '-') {
1186 return false;
1187 }
1188 if (allowBrackets && !(IsAlphaNumeric(s[i]) || s[i] == ']' || s[i] == '[') && s[i] != '-') {
1189 return false;
1190 }
1191 }
1192
1193 ++i;
1194 }
1195
1196 return true;
1197 }
1198
RecordValidName()1199 bool Parser::RecordValidName()
1200 {
1201 return PrefixedValidName(true);
1202 }
1203
FunctionValidName()1204 bool Parser::FunctionValidName()
1205 {
1206 return PrefixedValidName(true);
1207 }
1208
ArrayValidName()1209 bool Parser::ArrayValidName()
1210 {
1211 return PrefixedValidName();
1212 }
1213
LabelValidName()1214 bool Parser::LabelValidName()
1215 {
1216 auto token = context_.GiveToken();
1217 if (!IsNonDigit(token[0])) {
1218 return false;
1219 }
1220
1221 token.remove_prefix(1);
1222
1223 for (auto i : token) {
1224 if (!IsAlphaNumeric(i)) {
1225 return false;
1226 }
1227 }
1228
1229 return true;
1230 }
1231
ParseLabel()1232 bool Parser::ParseLabel()
1233 {
1234 LOG(DEBUG, ASSEMBLER) << "label search started (line " << lineStric_ << "): " << context_.tokens[0].wholeLine;
1235
1236 context_++;
1237
1238 if (*context_ == Token::Type::DEL_COLON) {
1239 context_--;
1240 if (LabelValidName()) {
1241 if (AddObjectInTable(true, *labelTable_)) {
1242 currIns_->setLabel = true;
1243 currIns_->label = context_.GiveToken();
1244
1245 LOG(DEBUG, ASSEMBLER) << "label detected (line " << lineStric_ << "): " << context_.GiveToken();
1246
1247 context_++;
1248 context_++;
1249 return !context_.Mask();
1250 }
1251
1252 LOG(DEBUG, ASSEMBLER) << "label is detected (line " << lineStric_ << "): " << context_.GiveToken()
1253 << ", but this label already exists";
1254
1255 context_.err = GetError("This label already exists.", Error::ErrorType::ERR_BAD_LABEL_EXT);
1256 } else {
1257 LOG(DEBUG, ASSEMBLER) << "label with non-standard character is detected, attempt to create a label is "
1258 "supposed, but this cannot be any label name (line "
1259 << lineStric_ << "): " << context_.GiveToken();
1260
1261 context_.err = GetError(
1262 "Invalid name of label. Label contains only characters: '_', '0' - '9', 'a' - 'z', 'A' - 'Z'; and "
1263 "starts with any letter or with '_'.",
1264 Error::ErrorType::ERR_BAD_LABEL);
1265 }
1266
1267 return false;
1268 }
1269
1270 context_--;
1271
1272 LOG(DEBUG, ASSEMBLER) << "label is not detected (line " << lineStric_ << ")";
1273
1274 return true;
1275 }
1276
TokenToOpcode(Token::Type id)1277 static Opcode TokenToOpcode(Token::Type id)
1278 {
1279 ASSERT(id > Token::Type::OPERATION && id < Token::Type::KEYWORD);
1280 using Utype = std::underlying_type_t<Token::Type>;
1281 return static_cast<Opcode>(static_cast<Utype>(id) - static_cast<Utype>(Token::Type::OPERATION) - 1);
1282 }
1283
ParseOperation()1284 bool Parser::ParseOperation()
1285 {
1286 if (context_.Mask()) {
1287 LOG(DEBUG, ASSEMBLER) << "no more tokens (line " << lineStric_ << "): " << context_.tokens[0].wholeLine;
1288
1289 return false;
1290 }
1291
1292 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
1293 return false;
1294 }
1295
1296 LOG(DEBUG, ASSEMBLER) << "operaion search started (line " << lineStric_ << "): " << context_.tokens[0].wholeLine;
1297
1298 if (*context_ > Token::Type::OPERATION && *context_ < Token::Type::KEYWORD) {
1299 SetOperationInformation();
1300
1301 context_.UpSignOperation();
1302 currIns_->opcode = TokenToOpcode(context_.id);
1303
1304 LOG(DEBUG, ASSEMBLER) << "operatiuon is detected (line " << lineStric_ << "): " << context_.GiveToken()
1305 << " (operand type: " << OperandTypePrint(currIns_->opcode) << ")";
1306
1307 context_++;
1308 return true;
1309 }
1310
1311 LOG(DEBUG, ASSEMBLER) << "founded " << context_.GiveToken() << ", it is not an operation (line " << lineStric_
1312 << ")";
1313
1314 context_.err = GetError("Invalid operation.", Error::ErrorType::ERR_BAD_OPERATION_NAME);
1315
1316 return false;
1317 }
1318
ParseOperandVreg()1319 bool Parser::ParseOperandVreg()
1320 {
1321 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1322 return false;
1323 }
1324
1325 if (*context_ != Token::Type::ID) {
1326 context_.err = GetError("Expected register.", Error::ErrorType::ERR_BAD_OPERAND, +1);
1327 return false;
1328 }
1329
1330 std::string_view p = context_.GiveToken();
1331 if (p[0] == 'v') {
1332 p.remove_prefix(1);
1333 auto number = static_cast<int64_t>(ToNumber(p));
1334 if (number > *(context_.maxValueOfReg)) {
1335 *(context_.maxValueOfReg) = number;
1336 }
1337
1338 currIns_->regs.push_back(static_cast<uint16_t>(number));
1339 } else if (p[0] == 'a') {
1340 p.remove_prefix(1);
1341 currIns_->regs.push_back(static_cast<uint16_t>(ToNumber(p)));
1342 context_.functionArgumentsList->emplace_back(context_.insNumber, currIns_->regs.size() - 1);
1343 }
1344
1345 ++context_;
1346 return true;
1347 }
1348
ParseOperandCall()1349 bool Parser::ParseOperandCall()
1350 {
1351 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1352 return false;
1353 }
1354
1355 if (!FunctionValidName()) {
1356 context_.err = GetError("Invalid name of function.", Error::ErrorType::ERR_BAD_NAME_REG);
1357 return false;
1358 }
1359
1360 const auto p = std::string(context_.GiveToken().data(), context_.GiveToken().length());
1361 currIns_->ids.emplace_back(p);
1362
1363 AddObjectInTable(false, program_.functionTable);
1364
1365 ++context_;
1366
1367 std::string funcSignature {};
1368
1369 if (!ParseOperandSignature(&funcSignature)) {
1370 return false;
1371 }
1372
1373 if (funcSignature.empty()) {
1374 const auto itSynonym = program_.functionSynonyms.find(currIns_->ids.back());
1375 if (itSynonym == program_.functionSynonyms.end()) {
1376 return true;
1377 }
1378
1379 if (itSynonym->second.size() > 1) {
1380 context_.err = GetError("Unable to resolve ambiguous function call",
1381 Error::ErrorType::ERR_FUNCTION_MULTIPLE_ALTERNATIVES);
1382 return false;
1383 }
1384
1385 program_.functionTable.erase(p);
1386 } else {
1387 currIns_->ids.back() += funcSignature;
1388
1389 if (program_.functionTable.find(currIns_->ids.back()) == program_.functionTable.end()) {
1390 auto nodeHandle = program_.functionTable.extract(p);
1391 nodeHandle.key() = currIns_->ids.back();
1392 program_.functionTable.insert(std::move(nodeHandle));
1393 } else {
1394 program_.functionTable.erase(p);
1395 }
1396 }
1397
1398 return true;
1399 }
1400
ParseOperandSignature(std::string * sign)1401 bool Parser::ParseOperandSignature(std::string *sign)
1402 {
1403 if (*context_ != Token::Type::DEL_COLON) {
1404 // no signature provided
1405 return true;
1406 }
1407
1408 ++context_;
1409
1410 if (*context_ != Token::Type::DEL_BRACKET_L) {
1411 context_.err = GetError("Expected \'(\' before signature", Error::ErrorType::ERR_BAD_SIGNATURE);
1412 return false;
1413 }
1414
1415 ++context_;
1416
1417 *sign += ":(";
1418
1419 if (!ParseOperandSignatureTypesList(sign)) {
1420 return false;
1421 }
1422
1423 if (*context_ != Token::Type::DEL_BRACKET_R) {
1424 context_.err = GetError("Expected \')\' at the end of the signature", Error::ErrorType::ERR_BAD_SIGNATURE);
1425 return false;
1426 }
1427
1428 *sign += ")";
1429
1430 ++context_;
1431
1432 return true;
1433 }
1434
ParseOperandSignatureTypesList(std::string * sign)1435 bool Parser::ParseOperandSignatureTypesList(std::string *sign)
1436 {
1437 bool comma = false;
1438
1439 while (true) {
1440 if (context_.Mask()) {
1441 return true;
1442 }
1443
1444 if (*context_ != Token::Type::DEL_COMMA && *context_ != Token::Type::ID) {
1445 break;
1446 }
1447
1448 if (comma) {
1449 *sign += ",";
1450 }
1451
1452 if (!ParseFunctionArgComma(comma)) {
1453 return false;
1454 }
1455
1456 if (*context_ != Token::Type::ID) {
1457 context_.err = GetError("Expected signature arguments", Error::ErrorType::ERR_BAD_SIGNATURE_PARAMETERS);
1458 return false;
1459 }
1460
1461 if (!TypeValidName()) {
1462 context_.err = GetError("Expected valid type", Error::ErrorType::ERR_BAD_TYPE);
1463 return false;
1464 }
1465
1466 Type type;
1467 if (!ParseType(&type)) {
1468 return false;
1469 }
1470
1471 *sign += type.GetName();
1472 }
1473
1474 return true;
1475 }
1476
IsOctal(char c)1477 static bool IsOctal(char c)
1478 {
1479 return c >= '0' && c <= '7';
1480 }
1481
IsHex(char c)1482 static bool IsHex(char c)
1483 {
1484 return std::isxdigit(c) != 0;
1485 }
1486
FromHex(char c)1487 static uint8_t FromHex(char c)
1488 {
1489 constexpr size_t DIGIT_NUM = 10;
1490
1491 if (c >= '0' && c <= '9') {
1492 return c - '0';
1493 }
1494
1495 if (c >= 'A' && c <= 'F') {
1496 return c - 'A' + DIGIT_NUM;
1497 }
1498
1499 return c - 'a' + DIGIT_NUM;
1500 }
1501
FromOctal(char c)1502 static uint8_t FromOctal(char c)
1503 {
1504 return c - '0';
1505 }
1506
ParseOctalEscapeSequence(std::string_view s,size_t * i)1507 Expected<char, Error> Parser::ParseOctalEscapeSequence(std::string_view s, size_t *i)
1508 {
1509 constexpr size_t OCT_SHIFT = 3;
1510
1511 size_t idx = *i;
1512 size_t n = 0;
1513 uint32_t r = 0;
1514
1515 while (idx < s.length() && IsOctal(s[idx]) && n < OCT_SHIFT) {
1516 r |= FromOctal(s[idx++]);
1517 r <<= 3U;
1518 ++n;
1519 }
1520
1521 r >>= 3U;
1522 *i += n;
1523
1524 return r;
1525 }
1526
ParseHexEscapeSequence(std::string_view s,size_t * i)1527 Expected<char, Error> Parser::ParseHexEscapeSequence(std::string_view s, size_t *i)
1528 {
1529 constexpr size_t HEX_SHIFT = 2;
1530
1531 uint32_t r = 0;
1532 size_t idx = *i;
1533
1534 for (size_t j = 0; j < HEX_SHIFT; j++) {
1535 char v = s[(*i)++];
1536
1537 if (!IsHex(v)) {
1538 return Unexpected(GetError("Invalid \\x escape sequence",
1539 Error::ErrorType::ERR_BAD_STRING_INVALID_HEX_ESCAPE_SEQUENCE, idx - HEX_SHIFT));
1540 }
1541
1542 r |= FromHex(v);
1543 r <<= 4U;
1544 }
1545
1546 r >>= 4U;
1547
1548 return r;
1549 }
1550
ParseEscapeSequence(std::string_view s,size_t * i)1551 Expected<char, Error> Parser::ParseEscapeSequence(std::string_view s, size_t *i)
1552 {
1553 size_t idx = *i;
1554
1555 char c = s[idx];
1556
1557 if (IsOctal(c)) {
1558 return ParseOctalEscapeSequence(s, i);
1559 }
1560
1561 ++(*i);
1562
1563 switch (c) {
1564 case '\'':
1565 case '"':
1566 case '\\':
1567 return c;
1568 case 'a':
1569 return '\a';
1570 case 'b':
1571 return '\b';
1572 case 'f':
1573 return '\f';
1574 case 'n':
1575 return '\n';
1576 case 'r':
1577 return '\r';
1578 case 't':
1579 return '\t';
1580 case 'v':
1581 return '\v';
1582 default:
1583 break;
1584 }
1585
1586 if (c == 'x') {
1587 return ParseHexEscapeSequence(s, i);
1588 }
1589
1590 return Unexpected(
1591 GetError("Unknown escape sequence", Error::ErrorType::ERR_BAD_STRING_UNKNOWN_ESCAPE_SEQUENCE, idx - 1));
1592 }
1593
ParseStringLiteral()1594 std::optional<std::string> Parser::ParseStringLiteral()
1595 {
1596 auto token = context_.GiveToken();
1597 if (*context_ != Token::Type::ID_STRING) {
1598 context_.err = GetError("Expected string literal", Error::ErrorType::ERR_BAD_OPERAND);
1599 return {};
1600 }
1601
1602 size_t i = 1; /* skip leading quote */
1603 size_t len = token.length();
1604
1605 std::string s;
1606
1607 while (i < len - 1) {
1608 char c = token[i++];
1609
1610 if (c != '\\') {
1611 s.append(1, c);
1612 continue;
1613 }
1614
1615 auto res = ParseEscapeSequence(token, &i);
1616 if (!res) {
1617 context_.err = res.Error();
1618 return {};
1619 }
1620
1621 s.append(1, res.Value());
1622 }
1623
1624 program_.strings.insert(s);
1625
1626 return s;
1627 }
1628
ParseOperandString()1629 bool Parser::ParseOperandString()
1630 {
1631 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1632 return false;
1633 }
1634
1635 auto res = ParseStringLiteral();
1636 if (!res) {
1637 return false;
1638 }
1639
1640 currIns_->ids.push_back(res.value());
1641
1642 ++context_;
1643
1644 return true;
1645 }
1646
ParseOperandComma()1647 bool Parser::ParseOperandComma()
1648 {
1649 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1650 return false;
1651 }
1652
1653 if (context_++ != Token::Type::DEL_COMMA) {
1654 if (!context_.Mask() && *context_ != Token::Type::DEL_BRACKET_R) {
1655 --context_;
1656 }
1657
1658 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
1659 return false;
1660 }
1661
1662 return true;
1663 }
1664
ParseInteger(int64_t * value)1665 bool Parser::ParseInteger(int64_t *value)
1666 {
1667 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1668 return false;
1669 }
1670
1671 if (*context_ != Token::Type::ID) {
1672 if (*context_ == Token::Type::DEL_BRACE_R) {
1673 --context_;
1674 }
1675 context_.err = GetError("Expected immediate.", Error::ErrorType::ERR_BAD_OPERAND, +1);
1676 return false;
1677 }
1678
1679 std::string_view p = context_.GiveToken();
1680 if (!ValidateInteger(p)) {
1681 context_.err = GetError("Expected integer.", Error::ErrorType::ERR_BAD_INTEGER_NAME);
1682 return false;
1683 }
1684
1685 *value = IntegerNumber(p);
1686 if (errno == ERANGE) {
1687 context_.err =
1688 GetError("Too large immediate (length is more than 64 bit).", Error::ErrorType::ERR_BAD_INTEGER_WIDTH);
1689 return false;
1690 }
1691
1692 return true;
1693 }
1694
ParseFloat(double * value,bool is64bit)1695 bool Parser::ParseFloat(double *value, bool is64bit)
1696 {
1697 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1698 return false;
1699 }
1700
1701 if (*context_ != Token::Type::ID) {
1702 if (*context_ == Token::Type::DEL_BRACE_R) {
1703 --context_;
1704 }
1705 context_.err = GetError("Expected immediate.", Error::ErrorType::ERR_BAD_OPERAND, +1);
1706 return false;
1707 }
1708
1709 std::string_view p = context_.GiveToken();
1710 if (!ValidateFloat(p)) {
1711 context_.err = GetError("Expected float.", Error::ErrorType::ERR_BAD_FLOAT_NAME);
1712 return false;
1713 }
1714
1715 *value = FloatNumber(p, is64bit);
1716 if (errno == ERANGE) {
1717 context_.err =
1718 GetError("Too large immediate (length is more than 64 bit).", Error::ErrorType::ERR_BAD_FLOAT_WIDTH);
1719 return false;
1720 }
1721
1722 return true;
1723 }
1724
ParseOperandInteger()1725 bool Parser::ParseOperandInteger()
1726 {
1727 int64_t n;
1728 if (!ParseInteger(&n)) {
1729 return false;
1730 }
1731
1732 currIns_->imms.emplace_back(n);
1733 ++context_;
1734 return true;
1735 }
1736
ParseOperandFloat(bool is64bit)1737 bool Parser::ParseOperandFloat(bool is64bit)
1738 {
1739 double n;
1740 if (!ParseFloat(&n, is64bit)) {
1741 return false;
1742 }
1743
1744 currIns_->imms.emplace_back(n);
1745 ++context_;
1746 return true;
1747 }
1748
ParseOperandLabel()1749 bool Parser::ParseOperandLabel()
1750 {
1751 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1752 return false;
1753 }
1754
1755 if (!LabelValidName()) {
1756 context_.err = GetError("Invalid name of Label.", Error::ErrorType::ERR_BAD_NAME_ID);
1757 return false;
1758 }
1759
1760 std::string_view p = context_.GiveToken();
1761 currIns_->ids.emplace_back(p.data(), p.length());
1762 AddObjectInTable(false, *labelTable_);
1763
1764 ++context_;
1765
1766 return true;
1767 }
1768
ParseOperandId()1769 bool Parser::ParseOperandId()
1770 {
1771 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1772 return false;
1773 }
1774
1775 if (*context_ != Token::Type::ID) {
1776 context_.err = GetError("Expected Label.", Error::ErrorType::ERR_BAD_OPERAND);
1777 return false;
1778 }
1779 if (!LabelValidName()) {
1780 context_.err = GetError("Invalid name of Label.", Error::ErrorType::ERR_BAD_NAME_ID);
1781 return false;
1782 }
1783
1784 std::string_view p = context_.GiveToken();
1785 currIns_->ids.emplace_back(p.data(), p.length());
1786 AddObjectInTable(false, *labelTable_);
1787
1788 ++context_;
1789
1790 return true;
1791 }
1792
ParseOperandType(Type::VerificationType verType)1793 bool Parser::ParseOperandType(Type::VerificationType verType)
1794 {
1795 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1796 return false;
1797 }
1798
1799 if (*context_ != Token::Type::ID) {
1800 context_.err = GetError("Expected type.", Error::ErrorType::ERR_BAD_OPERAND);
1801 return false;
1802 }
1803 if (!TypeValidName()) {
1804 context_.err = GetError("Invalid name of type.", Error::ErrorType::ERR_BAD_NAME_ID);
1805 return false;
1806 }
1807
1808 Type type;
1809 if (!ParseType(&type)) {
1810 return false;
1811 }
1812
1813 bool isObject = context_.GiveToken() != "]";
1814 if (isObject) {
1815 AddObjectInTable(false, program_.recordTable);
1816
1817 if (verType == Type::VerificationType::TYPE_ID_ARRAY) {
1818 GetWarning("Unexpected type_id recieved! Expected array, but object given",
1819 Error::ErrorType::WAR_UNEXPECTED_TYPE_ID);
1820 }
1821 } else {
1822 if (!type.IsArrayContainsPrimTypes() &&
1823 program_.recordTable.find(type.GetComponentName()) == program_.recordTable.end()) {
1824 std::string componentName = type.GetComponentName();
1825 context_.token = componentName;
1826 AddObjectInTable(false, program_.recordTable);
1827 }
1828
1829 if (verType == Type::VerificationType::TYPE_ID_OBJECT) {
1830 GetWarning("Unexpected type_id recieved! Expected object, but array given",
1831 Error::ErrorType::WAR_UNEXPECTED_TYPE_ID);
1832 }
1833 }
1834
1835 currIns_->ids.push_back(type.GetName());
1836
1837 return true;
1838 }
1839
ParseOperandLiteralArray()1840 bool Parser::ParseOperandLiteralArray()
1841 {
1842 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1843 return false;
1844 }
1845 if (*context_ != Token::Type::ID) {
1846 context_.err = GetError("Expected array id.", Error::ErrorType::ERR_BAD_OPERAND);
1847 return false;
1848 }
1849 if (!ArrayValidName()) {
1850 context_.err = GetError("Invalid name of array.", Error::ErrorType::ERR_BAD_NAME_ID);
1851 return false;
1852 }
1853
1854 std::string_view p = context_.GiveToken();
1855 auto arrayId = std::string(p.data(), p.length());
1856 if (program_.literalarrayTable.find(arrayId) == program_.literalarrayTable.end()) {
1857 context_.err = GetError("No array was found for this array id", Error::ErrorType::ERR_BAD_ID_ARRAY);
1858 return false;
1859 }
1860
1861 currIns_->ids.emplace_back(p.data(), p.length());
1862
1863 ++context_;
1864
1865 return true;
1866 }
1867
ParseOperandField()1868 bool Parser::ParseOperandField()
1869 {
1870 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1871 return false;
1872 }
1873
1874 if (*context_ != Token::Type::ID) {
1875 context_.err = GetError("Expected field.", Error::ErrorType::ERR_BAD_OPERAND);
1876 return false;
1877 }
1878 if (!PrefixedValidName()) {
1879 context_.err = GetError("Invalid name of field.", Error::ErrorType::ERR_BAD_NAME_ID);
1880 return false;
1881 }
1882
1883 std::string_view p = context_.GiveToken();
1884 std::string recordFullName = std::string(p);
1885 // Some names of records in pandastdlib starts with 'panda.', therefore,
1886 // the record name is before the second dot, and the field name is after the second dot
1887 auto posPoint = recordFullName.find_last_of('.');
1888 std::string recordName;
1889 std::string fieldName;
1890 if (posPoint == std::string::npos) {
1891 recordName = panda_file::GetDummyClassName();
1892 fieldName = recordFullName;
1893 } else {
1894 recordName = recordFullName.substr(0, posPoint);
1895 fieldName = recordFullName.substr(posPoint + 1);
1896 }
1897
1898 auto itRecord = program_.recordTable.find(recordName);
1899 if (itRecord == program_.recordTable.end()) {
1900 context_.token = recordName;
1901 AddObjectInTable(false, program_.recordTable);
1902 itRecord = program_.recordTable.find(recordName);
1903 }
1904 auto itField = std::find_if(itRecord->second.fieldList.begin(), itRecord->second.fieldList.end(),
1905 [&fieldName](pandasm::Field &field) { return fieldName == field.name; });
1906 if (!fieldName.empty() && itField == itRecord->second.fieldList.end()) {
1907 itRecord->second.fieldList.emplace_back(program_.lang);
1908 auto &field = itRecord->second.fieldList.back();
1909 field.name = fieldName;
1910 field.lineOfDef = lineStric_;
1911 field.wholeLine = context_.tokens[context_.number - 1].wholeLine;
1912 field.boundLeft = context_.tokens[context_.number - 1].boundLeft + recordName.length() + 1;
1913 field.boundRight = context_.tokens[context_.number - 1].boundRight;
1914 field.isDefined = false;
1915 }
1916
1917 currIns_->ids.emplace_back(p.data(), p.length());
1918
1919 ++context_;
1920
1921 return true;
1922 }
1923
ParseOperandNone()1924 bool Parser::ParseOperandNone()
1925 {
1926 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1927 return false;
1928 }
1929
1930 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
1931 return false;
1932 }
1933
1934 if (!context_.Mask()) {
1935 context_.err = GetError("Invalid number of operands.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
1936 --context_;
1937 return false;
1938 }
1939 return true;
1940 }
1941
ParseRecordFullSign()1942 bool Parser::ParseRecordFullSign()
1943 {
1944 return ParseRecordName();
1945 }
1946
ParseFunctionFullSign()1947 bool Parser::ParseFunctionFullSign()
1948 {
1949 if (!ParseFunctionReturn()) {
1950 return false;
1951 }
1952
1953 if (!ParseFunctionName()) {
1954 return false;
1955 }
1956
1957 if (*context_ == Token::Type::DEL_BRACKET_L) {
1958 ++context_;
1959
1960 if (ParseFunctionArgs()) {
1961 if (*context_ == Token::Type::DEL_BRACKET_R) {
1962 ++context_;
1963 return UpdateFunctionName();
1964 }
1965 context_.err = GetError("Expected ')'.", Error::ErrorType::ERR_BAD_ARGS_BOUND);
1966 }
1967 } else {
1968 context_.err = GetError("Expected '('.", Error::ErrorType::ERR_BAD_ARGS_BOUND);
1969 }
1970
1971 return false;
1972 }
1973
UpdateFunctionName()1974 bool Parser::UpdateFunctionName()
1975 {
1976 auto signature = GetFunctionSignatureFromName(currFunc_->name, currFunc_->params);
1977 auto iter = program_.functionTable.find(signature);
1978 if (iter == program_.functionTable.end() || !iter->second.fileLocation->isDefined) {
1979 program_.functionSynonyms[currFunc_->name].push_back(signature);
1980 program_.functionTable.erase(signature);
1981 auto nodeHandle = program_.functionTable.extract(currFunc_->name);
1982 nodeHandle.key() = signature;
1983 program_.functionTable.insert(std::move(nodeHandle));
1984 currFunc_->name = signature;
1985 context_.maxValueOfReg = &(currFunc_->valueOfFirstParam);
1986 context_.functionArgumentsList = &(context_.functionArgumentsLists[currFunc_->name]);
1987
1988 return true;
1989 }
1990
1991 context_.err = GetError("This function already exists.", Error::ErrorType::ERR_BAD_ID_FUNCTION);
1992
1993 return false;
1994 }
1995
ParseArrayFullSign()1996 bool Parser::ParseArrayFullSign()
1997 {
1998 if (!ParseArrayName()) {
1999 return false;
2000 }
2001
2002 if (*context_ == Token::Type::DEL_BRACE_L) {
2003 isConstArray_ = false;
2004 return true;
2005 }
2006
2007 isConstArray_ = true;
2008
2009 currArray_->literals.emplace_back();
2010 currArrayElem_ = &(currArray_->literals[currArray_->literals.size() - 1]);
2011
2012 if (!ParseArrayElementType()) {
2013 context_.err = GetError("Invalid array type for static array.", Error::ErrorType::ERR_BAD_ARRAY_TYPE);
2014 return false;
2015 }
2016
2017 currArrayElem_->value = static_cast<uint8_t>(currArrayElem_->tag);
2018 currArrayElem_->tag = panda_file::LiteralTag::TAGVALUE;
2019
2020 if (*context_ == Token::Type::DEL_BRACE_L) {
2021 context_.err = GetError("No array size for static array.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
2022 return false;
2023 }
2024
2025 currArray_->literals.emplace_back();
2026 currArrayElem_ = &(currArray_->literals[currArray_->literals.size() - 1]);
2027 currArrayElem_->tag = panda_file::LiteralTag::INTEGER;
2028
2029 if (!ParseArrayElementValueInteger()) {
2030 context_.err =
2031 GetError("Invalid value for static array size value.", Error::ErrorType::ERR_BAD_ARRAY_SIZE_VALUE);
2032 return false;
2033 }
2034
2035 ++context_;
2036
2037 return true;
2038 }
2039
ParseRecordName()2040 bool Parser::ParseRecordName()
2041 {
2042 LOG(DEBUG, ASSEMBLER) << "started searching for record name (line " << lineStric_
2043 << "): " << context_.tokens[context_.number - 1].wholeLine;
2044
2045 if (!RecordValidName()) {
2046 if (*context_ == Token::Type::DEL_BRACKET_L) {
2047 context_.err = GetError("No record name.", Error::ErrorType::ERR_BAD_RECORD_NAME);
2048 return false;
2049 }
2050 context_.err = GetError("Invalid name of the record.", Error::ErrorType::ERR_BAD_RECORD_NAME);
2051 return false;
2052 }
2053
2054 auto recordName = std::string(context_.GiveToken());
2055 context_++;
2056 if (*context_ == Token::Type::DEL_SQUARE_BRACKET_L) {
2057 auto dim = ParseMultiArrayHallmark();
2058 if (context_.err.err != Error::ErrorType::ERR_NONE) {
2059 return false;
2060 }
2061 for (uint8_t i = 0; i < dim; i++) {
2062 recordName += "[]";
2063 }
2064 }
2065 if (!context_.Mask()) {
2066 context_--;
2067 }
2068
2069 auto iter = program_.recordTable.find(recordName);
2070 if (iter == program_.recordTable.end() || !iter->second.fileLocation->isDefined) {
2071 SetRecordInformation(recordName);
2072 } else {
2073 context_.err = GetError("This record already exists.", Error::ErrorType::ERR_BAD_ID_RECORD);
2074 return false;
2075 }
2076
2077 LOG(DEBUG, ASSEMBLER) << "record name found (line " << lineStric_ << "): " << context_.GiveToken();
2078
2079 ++context_;
2080
2081 return true;
2082 }
2083
SetRecordInformation(const std::string & recordName)2084 void Parser::SetRecordInformation(const std::string &recordName)
2085 {
2086 AddObjectInTable(true, program_.recordTable, recordName);
2087 currRecord_ = &(program_.recordTable.at(recordName));
2088 }
2089
ParseFunctionName()2090 bool Parser::ParseFunctionName()
2091 {
2092 LOG(DEBUG, ASSEMBLER) << "started searching for function name (line " << lineStric_
2093 << "): " << context_.tokens[context_.number - 1].wholeLine;
2094
2095 if (!FunctionValidName()) {
2096 if (*context_ == Token::Type::DEL_BRACKET_L) {
2097 context_.err = GetError("No function name.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2098 return false;
2099 }
2100 context_.err = GetError("Invalid name of the function.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2101 return false;
2102 }
2103
2104 // names are mangled, so no need to check for same names here
2105 SetFunctionInformation();
2106 if (context_.err.err != Error::ErrorType::ERR_NONE) {
2107 return false;
2108 }
2109
2110 LOG(DEBUG, ASSEMBLER) << "function name found (line " << lineStric_ << "): " << context_.GiveToken();
2111
2112 ++context_;
2113
2114 return true;
2115 }
2116
SetFunctionInformation()2117 void Parser::SetFunctionInformation()
2118 {
2119 auto p = std::string(context_.GiveToken());
2120
2121 context_++;
2122 if (*context_ == Token::Type::DEL_SQUARE_BRACKET_L || context_.Mask()) {
2123 auto dim = ParseMultiArrayHallmark();
2124 for (uint8_t i = 0; i < dim; i++) {
2125 p += "[]";
2126 }
2127 if (context_.GiveToken() == ".ctor") {
2128 p += ".ctor";
2129 AddObjectInTable(true, program_.functionTable, p);
2130 }
2131 } else {
2132 context_--;
2133 AddObjectInTable(true, program_.functionTable);
2134 }
2135 currFunc_ = &(program_.functionTable.at(p));
2136 labelTable_ = &(currFunc_->labelTable);
2137 currFunc_->returnType = context_.currFuncReturnType;
2138 }
2139
ParseArrayName()2140 bool Parser::ParseArrayName()
2141 {
2142 LOG(DEBUG, ASSEMBLER) << "started searching for array name (line " << lineStric_
2143 << "): " << context_.tokens[context_.number - 1].wholeLine;
2144
2145 if (!ArrayValidName()) {
2146 if (*context_ == Token::Type::DEL_BRACKET_L) {
2147 context_.err = GetError("No array name.", Error::ErrorType::ERR_BAD_ARRAY_NAME);
2148 return false;
2149 }
2150 context_.err = GetError("Invalid name of the array.", Error::ErrorType::ERR_BAD_ARRAY_NAME);
2151 return false;
2152 }
2153
2154 auto iter =
2155 program_.literalarrayTable.find(std::string(context_.GiveToken().data(), context_.GiveToken().length()));
2156 if (iter == program_.literalarrayTable.end()) {
2157 SetArrayInformation();
2158 } else {
2159 context_.err = GetError("This array already exists.", Error::ErrorType::ERR_BAD_ID_ARRAY);
2160 return false;
2161 }
2162
2163 LOG(DEBUG, ASSEMBLER) << "array id found (line " << lineStric_ << "): " << context_.GiveToken();
2164
2165 ++context_;
2166
2167 return true;
2168 }
2169
SetArrayInformation()2170 void Parser::SetArrayInformation()
2171 {
2172 program_.literalarrayTable.try_emplace(std::string(context_.GiveToken().data(), context_.GiveToken().length()),
2173 ark::pandasm::LiteralArray());
2174
2175 currArray_ =
2176 &(program_.literalarrayTable.at(std::string(context_.GiveToken().data(), context_.GiveToken().length())));
2177 }
2178
SetOperationInformation()2179 void Parser::SetOperationInformation()
2180 {
2181 context_.insNumber = currFunc_->ins.size();
2182 auto &currDebug = currFunc_->ins.back().insDebug;
2183 currDebug.lineNumber = lineStric_;
2184 currDebug.wholeLine = context_.tokens[context_.number - 1].wholeLine;
2185 currDebug.boundLeft = context_.tokens[context_.number - 1].boundLeft;
2186 currDebug.boundRight = context_.tokens[context_.number - 1].boundRight;
2187 }
2188
ParseFunctionReturn()2189 bool Parser::ParseFunctionReturn()
2190 {
2191 LOG(DEBUG, ASSEMBLER) << "started searching for return function value (line " << lineStric_
2192 << "): " << context_.tokens[context_.number - 1].wholeLine;
2193
2194 if (!TypeValidName()) {
2195 if (*context_ == Token::Type::DEL_BRACKET_L) {
2196 context_.err = GetError("No return type.", Error::ErrorType::ERR_BAD_FUNCTION_RETURN_VALUE);
2197 return false;
2198 }
2199 context_.err = GetError("Not a return type.", Error::ErrorType::ERR_BAD_FUNCTION_RETURN_VALUE);
2200 return false;
2201 }
2202
2203 if (!ParseType(&context_.currFuncReturnType)) {
2204 return false;
2205 }
2206
2207 LOG(DEBUG, ASSEMBLER) << "return type found (line " << lineStric_ << "): " << context_.GiveToken();
2208
2209 return true;
2210 }
2211
TypeValidName()2212 bool Parser::TypeValidName()
2213 {
2214 if (Type::GetId(context_.GiveToken()) != panda_file::Type::TypeId::REFERENCE) {
2215 return true;
2216 }
2217
2218 return PrefixedValidName(true);
2219 }
2220
ParseFunctionArg()2221 bool Parser::ParseFunctionArg()
2222 {
2223 if (*context_ != Token::Type::ID) {
2224 context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_FUNCTION_PARAMETERS);
2225 return false;
2226 }
2227
2228 if (!TypeValidName()) {
2229 context_.err = GetError("Expected parameter type.", Error::ErrorType::ERR_BAD_TYPE);
2230 return false;
2231 }
2232
2233 Type type;
2234 if (!ParseType(&type)) {
2235 return false;
2236 }
2237
2238 if (context_.Mask()) {
2239 return false;
2240 }
2241
2242 if (*context_ != Token::Type::ID) {
2243 context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_FUNCTION_PARAMETERS);
2244 return false;
2245 }
2246
2247 if (!ParamValidName()) {
2248 context_.err = GetError("Incorrect name of parameter.", Error::ErrorType::ERR_BAD_PARAM_NAME);
2249 return false;
2250 }
2251
2252 ++context_;
2253
2254 Function::Parameter parameter(type, program_.lang);
2255 metadata_ = parameter.metadata.get();
2256
2257 if (*context_ == Token::Type::DEL_LT && !ParseMetaDef()) {
2258 return false;
2259 }
2260
2261 currFunc_->params.push_back(std::move(parameter));
2262
2263 return true;
2264 }
2265
ParseFunctionArgComma(bool & comma)2266 bool Parser::ParseFunctionArgComma(bool &comma)
2267 {
2268 if (comma && *context_ != Token::Type::DEL_COMMA) {
2269 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
2270 return false;
2271 }
2272
2273 if (comma) {
2274 ++context_;
2275 }
2276
2277 comma = true;
2278
2279 return true;
2280 }
2281
ParseFunctionArgs()2282 bool Parser::ParseFunctionArgs()
2283 {
2284 LOG(DEBUG, ASSEMBLER) << "started searching for function parameters (line " << lineStric_
2285 << "): " << context_.tokens[context_.number - 1].wholeLine;
2286
2287 bool comma = false;
2288
2289 while (true) {
2290 if (context_.Mask()) {
2291 return false;
2292 }
2293
2294 if (context_.id != Token::Type::DEL_COMMA && context_.id != Token::Type::ID) {
2295 break;
2296 }
2297
2298 if (!ParseFunctionArgComma(comma)) {
2299 return false;
2300 }
2301
2302 if (!ParseFunctionArg()) {
2303 return false;
2304 }
2305 }
2306
2307 LOG(DEBUG, ASSEMBLER) << "parameters found (line " << lineStric_ << "): ";
2308
2309 return true;
2310 }
2311
ParseMetaDef()2312 bool Parser::ParseMetaDef()
2313 {
2314 LOG(DEBUG, ASSEMBLER) << "started searching for meta information (line " << lineStric_
2315 << "): " << context_.tokens[context_.number - 1].wholeLine;
2316
2317 bool flag = false;
2318
2319 if (context_.Mask()) {
2320 return false;
2321 }
2322
2323 if (*context_ == Token::Type::DEL_LT) {
2324 flag = true;
2325 ++context_;
2326 }
2327
2328 if (!ParseMetaList(flag)) {
2329 return false;
2330 }
2331
2332 if (!flag && *context_ == Token::Type::DEL_GT) {
2333 context_.err = GetError("Expected '<'.", Error::ErrorType::ERR_BAD_METADATA_BOUND);
2334 ++context_;
2335 return false;
2336 }
2337
2338 LOG(DEBUG, ASSEMBLER) << "searching for meta information (line " << lineStric_ << ") is successful";
2339
2340 if (flag && context_.err.err == Error::ErrorType::ERR_NONE) {
2341 ++context_;
2342 }
2343
2344 return true;
2345 }
2346
SetMetadataContextError(const Metadata::Error & err,bool hasValue)2347 void Parser::SetMetadataContextError(const Metadata::Error &err, bool hasValue)
2348 {
2349 constexpr int64_t NO_VALUE_OFF = -1;
2350 constexpr int64_t SPECIAL_OFF = -2;
2351 constexpr int64_t STANDARD_OFF = -3;
2352
2353 switch (err.GetType()) {
2354 case Metadata::Error::Type::UNKNOWN_ATTRIBUTE: {
2355 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNKNOWN_ATTRIBUTE, 0,
2356 hasValue ? STANDARD_OFF : NO_VALUE_OFF);
2357 break;
2358 }
2359 case Metadata::Error::Type::MISSING_ATTRIBUTE: {
2360 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MISSING_ATTRIBUTE);
2361 break;
2362 }
2363 case Metadata::Error::Type::MISSING_VALUE: {
2364 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MISSING_VALUE);
2365 break;
2366 }
2367 case Metadata::Error::Type::UNEXPECTED_ATTRIBUTE: {
2368 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNEXPECTED_ATTRIBUTE, 0,
2369 hasValue ? STANDARD_OFF : NO_VALUE_OFF);
2370 break;
2371 }
2372 case Metadata::Error::Type::UNEXPECTED_VALUE: {
2373 context_.err =
2374 GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNEXPECTED_VALUE, 0, SPECIAL_OFF);
2375 break;
2376 }
2377 case Metadata::Error::Type::INVALID_VALUE: {
2378 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_INVALID_VALUE, 0, -1);
2379 break;
2380 }
2381 case Metadata::Error::Type::MULTIPLE_ATTRIBUTE: {
2382 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MULTIPLE_ATTRIBUTE, 0,
2383 hasValue ? STANDARD_OFF : NO_VALUE_OFF);
2384 break;
2385 }
2386 default: {
2387 UNREACHABLE();
2388 }
2389 }
2390 }
2391
ParseMetaListComma(bool & comma,bool eq)2392 bool Parser::ParseMetaListComma(bool &comma, bool eq)
2393 {
2394 if (!eq && comma && *context_ != Token::Type::DEL_COMMA) {
2395 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
2396 return false;
2397 }
2398
2399 if (!eq && comma) {
2400 ++context_;
2401 }
2402
2403 comma = true;
2404
2405 return true;
2406 }
2407
MeetExpMetaList(bool eq)2408 bool Parser::MeetExpMetaList(bool eq)
2409 {
2410 if (!eq && *context_ != Token::Type::ID) {
2411 context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA, +1);
2412 return false;
2413 }
2414
2415 if (eq && *context_ != Token::Type::ID && *context_ != Token::Type::ID_STRING) {
2416 context_.err =
2417 GetError("Expected identifier or string literal.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA, +1);
2418 return false;
2419 }
2420
2421 if (!eq && !PrefixedValidName()) {
2422 context_.err = GetError("Invalid attribute name.", Error::ErrorType::ERR_BAD_NAME_ID);
2423 return false;
2424 }
2425
2426 return true;
2427 }
2428
BuildMetaListAttr(bool & eq,std::string & attributeName,std::string & attributeValue)2429 bool Parser::BuildMetaListAttr(bool &eq, std::string &attributeName, std::string &attributeValue)
2430 {
2431 if (eq && *context_ == Token::Type::ID_STRING) {
2432 auto res = ParseStringLiteral();
2433 if (!res) {
2434 return false;
2435 }
2436
2437 attributeValue = res.value();
2438 } else if (eq) {
2439 std::string sign {};
2440 attributeValue = context_.GiveToken();
2441 ++context_;
2442
2443 if (!ParseOperandSignature(&sign)) {
2444 return false;
2445 }
2446
2447 --context_;
2448 attributeValue += sign;
2449 } else {
2450 attributeName = context_.GiveToken();
2451 }
2452
2453 ++context_;
2454
2455 if (context_.Mask()) {
2456 return false;
2457 }
2458
2459 if (*context_ == Token::Type::DEL_EQ) {
2460 if (eq) {
2461 context_.err = GetError("'=' was not expected.", Error::ErrorType::ERR_BAD_NOEXP_DELIM);
2462 return false;
2463 }
2464
2465 ++context_;
2466 eq = true;
2467 } else {
2468 std::optional<Metadata::Error> res;
2469 bool hasValue = eq;
2470 if (hasValue) {
2471 res = metadata_->SetAttributeValue(attributeName, attributeValue);
2472 } else {
2473 res = metadata_->SetAttribute(attributeName);
2474 }
2475
2476 eq = false;
2477
2478 if (res) {
2479 auto err = res.value();
2480 SetMetadataContextError(err, hasValue);
2481 return false;
2482 }
2483 }
2484
2485 return true;
2486 }
2487
ParseMetaList(bool flag)2488 bool Parser::ParseMetaList(bool flag)
2489 {
2490 if (!flag && !context_.Mask() && *context_ != Token::Type::DEL_GT && *context_ != Token::Type::DEL_BRACE_L) {
2491 context_.err = GetError("No meta data expected.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA);
2492 return false;
2493 }
2494
2495 bool comma = false;
2496 bool eq = false;
2497
2498 std::string attributeName;
2499 std::string attributeValue;
2500
2501 while (true) {
2502 if (context_.Mask()) {
2503 context_.err = GetError("Expected '>'.", Error::ErrorType::ERR_BAD_METADATA_BOUND, +1);
2504 return false;
2505 }
2506
2507 if (context_.id != Token::Type::DEL_COMMA && context_.id != Token::Type::ID &&
2508 context_.id != Token::Type::ID_STRING && context_.id != Token::Type::DEL_EQ) {
2509 break;
2510 }
2511
2512 if (!ParseMetaListComma(comma, eq)) {
2513 return false;
2514 }
2515
2516 if (!MeetExpMetaList(eq)) {
2517 return false;
2518 }
2519
2520 if (!BuildMetaListAttr(eq, attributeName, attributeValue)) {
2521 return false;
2522 }
2523 }
2524
2525 if (flag && *context_ != Token::Type::DEL_GT) {
2526 context_.err = GetError("Expected '>'.", Error::ErrorType::ERR_BAD_METADATA_BOUND);
2527 ++context_;
2528
2529 return false;
2530 }
2531
2532 auto res = metadata_->ValidateData();
2533 if (res) {
2534 auto err = res.value();
2535 SetMetadataContextError(err, false);
2536 return false;
2537 }
2538
2539 return true;
2540 }
2541
ParseFunctionInstruction()2542 bool Parser::ParseFunctionInstruction()
2543 {
2544 if (ParseLabel()) {
2545 if (ParseOperation()) {
2546 if (ParseOperands()) {
2547 return true;
2548 }
2549 }
2550 }
2551
2552 return context_.Mask();
2553 }
2554
GetFuncNameWithoutArgs(const std::string & fullName)2555 static std::string GetFuncNameWithoutArgs(const std::string &fullName)
2556 {
2557 auto pos = fullName.find(':');
2558 return fullName.substr(0, pos);
2559 }
2560
ParseOperandInitobj()2561 bool Parser::ParseOperandInitobj()
2562 {
2563 if (context_.err.err != Error::ErrorType::ERR_NONE) {
2564 return false;
2565 }
2566
2567 if (!FunctionValidName()) {
2568 context_.err = GetError("Invalid name of function.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2569 return false;
2570 }
2571
2572 auto cid = std::string(context_.GiveToken().data(), context_.GiveToken().length());
2573
2574 context_++;
2575 if (*context_ == Token::Type::DEL_COMMA || *context_ == Token::Type::DEL_COLON || context_.Mask()) {
2576 if (!context_.Mask()) {
2577 context_--;
2578 }
2579 return ParseOperandCall();
2580 }
2581 auto dim = ParseMultiArrayHallmark();
2582 if (context_.err.err != Error::ErrorType::ERR_NONE) {
2583 return false;
2584 }
2585 if (dim < 2U) {
2586 context_.err = GetError("Invalid name of function.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2587 return false;
2588 }
2589
2590 for (uint8_t i = 0; i < dim; i++) {
2591 cid += "[]";
2592 }
2593
2594 if (context_.GiveToken() == ".ctor") {
2595 cid += ".ctor";
2596 currIns_->ids.emplace_back(cid);
2597 bool findFuncInTable = false;
2598 for (const auto &func : program_.functionTable) {
2599 if (GetFuncNameWithoutArgs(func.first) == cid) {
2600 findFuncInTable = true;
2601 break;
2602 }
2603 }
2604 if (!findFuncInTable) {
2605 AddObjectInTable(false, program_.functionTable, cid);
2606 }
2607 context_++;
2608 return true;
2609 }
2610 return false;
2611 }
2612
ParseMultiArrayHallmark()2613 uint8_t Parser::ParseMultiArrayHallmark()
2614 {
2615 uint8_t counter = 0;
2616 do {
2617 if (*context_ == Token::Type::DEL_SQUARE_BRACKET_L) {
2618 context_++;
2619 if (*context_ == Token::Type::DEL_SQUARE_BRACKET_R) {
2620 context_++;
2621 counter++;
2622 } else {
2623 context_.err = GetError("] expected.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2624 return counter;
2625 }
2626 } else {
2627 context_.err = GetError("[ expected.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2628 return counter;
2629 }
2630 } while (!context_.Mask() &&
2631 (*context_ == Token::Type::DEL_SQUARE_BRACKET_L || *context_ == Token::Type::DEL_SQUARE_BRACKET_R));
2632 return counter;
2633 }
2634
2635 } // namespace ark::pandasm
2636