aboutsummaryrefslogtreecommitdiff
path: root/backend/utils/TableGen/MCPseudoLoweringEmitter.cpp
blob: 5afa911a1477ffcae0428c0ef8a99f8bd7f00224 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// SPDX-License-Identifier: GPL-3.0-or-later

#include "TableGenBackends.h"

#include <cstddef>
#include <ostream>
#include <sstream>
#include <string>
#include <string_view>

namespace rcc::targetgen {

std::string emitMCPseudoLowering(const NormalizedTargetModel &Model, std::string_view SourceName) {
  std::ostringstream Output;
  Output << "// SPDX-License-Identifier: GPL-3.0-or-later\n\n";
  Output << "// This file is generated by rcc-tblgen from ";
  appendQuoted(Output, SourceName);
  Output << ". Do not edit it manually.\n\n";
  Output << "#ifdef GET_MC_PSEUDO_LOWERING\n\n";
  Output << "[[nodiscard]] Expected<std::optional<mc::MCInst>>\n"
            "lowerGeneratedMCPseudo(const MachineInstr &Instruction,\n"
            "                       MachineMCContext &Context) {\n"
            "  switch (Instruction.opcode().value()) {\n"
            "  default:\n"
            "    return std::optional<mc::MCInst>{};\n";
  for (const NormalizedMCPseudoExpansion &Expansion : Model.MCPseudoExpansions) {
    Output << "  case " << Expansion.PseudoOpcode << ": {\n"
           << "    mc::MCInst Result(mc::MCOpcode::fromValue(" << Expansion.ResultOpcode
           << "));\n"
              "    Result.setFlags(Instruction.flags().rawValue());\n"
              "    Result.setSourceIdentity(Instruction.stableID().value());\n"
              "    Result.reserveOperands("
           << Expansion.Operands.size() << ");\n";
    for (std::size_t Index = 0; Index < Expansion.Operands.size(); ++Index) {
      const NormalizedMCPseudoOperand &Operand = Expansion.Operands[Index];
      switch (Operand.Kind) {
      case NormalizedMCPseudoOperandKind::SourceOperand:
        Output << "    const MachineOperand *Operand" << Index << " = Instruction.operandAt("
               << Operand.Value << ");\n"
               << "    if (Operand" << Index << " == nullptr)\n"
               << "      return makeUnexpected(ErrorCode::AssemblyLoweringFailed,\n"
                  "                            \"MC pseudo has too few operands\");\n"
               << "    auto Lowered" << Index << " =\n"
               << "        lowerOperand(*Operand" << Index
               << ", Instruction.function(), Context);\n"
               << "    if (!Lowered" << Index << ")\n"
               << "      return std::unexpected(Lowered" << Index << ".error());\n"
               << "    Result.addOperand(std::move(*Lowered" << Index << "));\n";
        break;
      case NormalizedMCPseudoOperandKind::Register:
        Output << "    Result.addOperand(mc::MCOperand::registerOperand(\n"
                  "        mc::MCRegister::fromValue("
               << Operand.Value << ")));\n";
        break;
      case NormalizedMCPseudoOperandKind::Immediate:
        Output << "    Result.addOperand(mc::MCOperand::immediate(" << Operand.Immediate << "));\n";
        break;
      }
    }
    Output << "    return std::optional<mc::MCInst>{std::move(Result)};\n"
              "  }\n";
  }
  Output << "  }\n"
            "}\n\n"
            "#endif // GET_MC_PSEUDO_LOWERING\n";
  return Output.str();
}

} // namespace rcc::targetgen