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