• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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 "assembly-parser.h"
17#include "utils/number-utils.h"
18
19namespace panda::pandasm {
20
21bool Parser::ParseOperands()
22{
23    std::string_view p;
24    uint64_t number;
25    LOG(DEBUG, ASSEMBLER) << "operand search started (line " << line_stric_ << "): " << context_.tokens[0].whole_line;
26    switch(context_.WaitFor())
27    {
28% Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group|
29%  insn = group.first
30%  formats = group.map(&:format)
31%  operands = insn.operands
32%  properties = insn.properties
33%  verification = insn.verification
34            case Token::Type::ID_OP_<%= insn.asm_token%>: {
35%  if insn.return? && !insn.properties.include?('dynamic')
36%    if insn.return_obj?
37                if (!curr_func_->return_type.IsObject()) {
38%    elsif insn.return32?
39                if (!curr_func_->return_type.IsPrim32()) {
40%    elsif insn.return64?
41                if (!curr_func_->return_type.IsPrim64()) {
42%    elsif insn.return_void?
43                if (!curr_func_->return_type.IsVoid()) {
44%    end
45                    GetWarning("Unexpected return type. Correct the return type in the function definition: " +
46                               curr_func_->return_type.GetName(),
47                               Error::ErrorType::WAR_UNEXPECTED_RETURN_TYPE);
48                }
49%  end
50%  required_args = operands.size
51%  required_args = 1 if insn.call?
52%  required_args = 2 if insn.stripped_mnemonic == 'calli'
53%  operands.each_with_index  do |op, j|
54%
55%  if (j != 0)
56%    if j >= required_args
57                if (!context_.Mask()) {
58                    ParseOperandComma();
59                }
60%    else
61                if (!context_.Mask()) {
62                    ParseOperandComma();
63                } else {
64                    context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
65                }
66%    end
67%  end
68%
69                if (!context_.Mask()) {
70%    if op.reg?
71
72                if (RegValidName()) {
73                    p = context_.GiveToken();
74                    p.remove_prefix(1);
75                    number = ToNumber(p);
76                    size_t reg_width = curr_func_->ins.back().MaxRegEncodingWidth();
77                    if ((1ull << reg_width) <= number) {
78                        context_.err = GetError("Register width mismatch.", Error::ErrorType::ERR_BAD_OPERAND);
79                    }
80                } else if (context_.err.err == Error::ErrorType::ERR_NONE) {
81                    context_.err = GetError("Invalid name of register.", Error::ErrorType::ERR_BAD_NAME_REG);
82                }
83
84                ParseOperandVreg();
85%    elsif op.imm?
86%      if properties.include?("jump")
87                ParseOperandLabel();
88%      else
89%         if properties.include?("float")
90                ParseOperandFloat(<%= op.size == 64 ? "true" : "false" %>);
91%         else
92                ParseOperandInteger();
93%         end
94%      end
95%    elsif op.id?
96%      if properties.include?("type_id")
97%        if (verification.include?("type_id_array"))
98                ParseOperandType(Type::VerificationType::TYPE_ID_ARRAY);
99%        elsif (verification.include?("type_id_object"))
100                ParseOperandType(Type::VerificationType::TYPE_ID_OBJECT);
101%        elsif (verification.include?("type_id_any_object"))
102                ParseOperandType(Type::VerificationType::TYPE_ID_ANY_OBJECT);
103%        end
104%      elsif properties.include?("string_id")
105                ParseOperandString();
106%      elsif properties.include?("method_id")
107                ParseOperandCall();
108%      elsif properties.include?("field_id")
109                ParseOperandField();
110%      else
111                ParseOperandId();
112%      end
113%    end
114%
115%    if (j >= required_args) && (operands.size > 0)
116                }
117%    elsif operands.size > 0
118                } else {
119                    context_.err = GetError("Expected more arguments.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
120                }
121%    end
122%  end
123                ParseOperandNone();
124            } break;
125%end
126        default:
127            context_.err = GetError("No such operation.", Error::ErrorType::ERR_BAD_NONEXISTING_OPERATION);
128            return false;
129    }
130    return context_.Mask();
131}
132
133}  // namespace panda::pandasm
134