[clang] a7fbca4 - [NFC] Extract `CodeGenInstAlias` into its own *.h/*.cpp
Sergei Barannikov via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 31 18:23:59 PST 2023
Author: Sergei Barannikov
Date: 2023-02-01T05:23:43+03:00
New Revision: a7fbca40805ca414a9dc37b91075e89e6a3b75d5
URL: https://github.com/llvm/llvm-project/commit/a7fbca40805ca414a9dc37b91075e89e6a3b75d5
DIFF: https://github.com/llvm/llvm-project/commit/a7fbca40805ca414a9dc37b91075e89e6a3b75d5.diff
LOG: [NFC] Extract `CodeGenInstAlias` into its own *.h/*.cpp
Differential Revision: https://reviews.llvm.org/D142968
Added:
llvm/utils/TableGen/CodeGenInstAlias.cpp
llvm/utils/TableGen/CodeGenInstAlias.h
Modified:
clang/docs/tools/clang-formatted-files.txt
llvm/utils/TableGen/AsmMatcherEmitter.cpp
llvm/utils/TableGen/AsmWriterEmitter.cpp
llvm/utils/TableGen/CMakeLists.txt
llvm/utils/TableGen/CodeGenInstruction.cpp
llvm/utils/TableGen/CodeGenInstruction.h
llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn
Removed:
################################################################################
diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt
index cbac961982e6a..aa9b871ea58cb 100644
--- a/clang/docs/tools/clang-formatted-files.txt
+++ b/clang/docs/tools/clang-formatted-files.txt
@@ -7418,6 +7418,8 @@ llvm/unittests/XRay/FDRRecordsTest.cpp
llvm/unittests/XRay/FDRTraceWriterTest.cpp
llvm/unittests/XRay/ProfileTest.cpp
llvm/utils/not/not.cpp
+llvm/Utils/TableGen/CodeGenInstAlias.cpp
+llvm/Utils/TableGen/CodeGenInstAlias.h
llvm/utils/TableGen/CodeBeadsGen.cpp
llvm/utils/TableGen/CompressInstEmitter.cpp
llvm/utils/TableGen/DFAEmitter.h
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index c13e5b5deff6f..4b37347bbae62 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -95,6 +95,7 @@
//
//===----------------------------------------------------------------------===//
+#include "CodeGenInstAlias.h"
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
#include "SubtargetFeatureInfo.h"
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index f2e4d15a2c755..e7c0604b8ec75 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "AsmWriterInst.h"
+#include "CodeGenInstAlias.h"
#include "CodeGenInstruction.h"
#include "CodeGenRegisters.h"
#include "CodeGenTarget.h"
diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt
index aa16e7e894aca..44ed5549c8ea3 100644
--- a/llvm/utils/TableGen/CMakeLists.txt
+++ b/llvm/utils/TableGen/CMakeLists.txt
@@ -13,6 +13,7 @@ add_tablegen(llvm-tblgen LLVM
CodeEmitterGen.cpp
CodeGenDAGPatterns.cpp
CodeGenHwModes.cpp
+ CodeGenInstAlias.cpp
CodeGenInstruction.cpp
CodeGenMapTable.cpp
CodeGenRegisters.cpp
diff --git a/llvm/utils/TableGen/CodeGenInstAlias.cpp b/llvm/utils/TableGen/CodeGenInstAlias.cpp
new file mode 100644
index 0000000000000..f3e722d17866a
--- /dev/null
+++ b/llvm/utils/TableGen/CodeGenInstAlias.cpp
@@ -0,0 +1,282 @@
+//===- CodeGenInstAlias.cpp - CodeGen InstAlias Class Wrapper -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the CodeGenInstAlias class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenInstAlias.h"
+#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+
+using namespace llvm;
+
+/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
+/// constructor. It checks if an argument in an InstAlias pattern matches
+/// the corresponding operand of the instruction. It returns true on a
+/// successful match, with ResOp set to the result operand to be used.
+bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
+ Record *InstOpRec, bool hasSubOps,
+ ArrayRef<SMLoc> Loc, CodeGenTarget &T,
+ ResultOperand &ResOp) {
+ Init *Arg = Result->getArg(AliasOpNo);
+ DefInit *ADI = dyn_cast<DefInit>(Arg);
+ Record *ResultRecord = ADI ? ADI->getDef() : nullptr;
+
+ if (ADI && ADI->getDef() == InstOpRec) {
+ // If the operand is a record, it must have a name, and the record type
+ // must match up with the instruction's argument type.
+ if (!Result->getArgName(AliasOpNo))
+ PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
+ " must have a name!");
+ ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
+ ResultRecord);
+ return true;
+ }
+
+ // For register operands, the source register class can be a subclass
+ // of the instruction register class, not just an exact match.
+ if (InstOpRec->isSubClassOf("RegisterOperand"))
+ InstOpRec = InstOpRec->getValueAsDef("RegClass");
+
+ if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand"))
+ ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit();
+
+ if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) {
+ if (!InstOpRec->isSubClassOf("RegisterClass"))
+ return false;
+ if (!T.getRegisterClass(InstOpRec).hasSubClass(
+ &T.getRegisterClass(ADI->getDef())))
+ return false;
+ ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
+ ResultRecord);
+ return true;
+ }
+
+ // Handle explicit registers.
+ if (ADI && ADI->getDef()->isSubClassOf("Register")) {
+ if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
+ DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
+ // The operand info should only have a single (register) entry. We
+ // want the register class of it.
+ InstOpRec = cast<DefInit>(DI->getArg(0))->getDef();
+ }
+
+ if (!InstOpRec->isSubClassOf("RegisterClass"))
+ return false;
+
+ if (!T.getRegisterClass(InstOpRec).contains(
+ T.getRegBank().getReg(ADI->getDef())))
+ PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() +
+ " is not a member of the " +
+ InstOpRec->getName() + " register class!");
+
+ if (Result->getArgName(AliasOpNo))
+ PrintFatalError(Loc, "result fixed register argument must "
+ "not have a name!");
+
+ ResOp = ResultOperand(ResultRecord);
+ return true;
+ }
+
+ // Handle "zero_reg" for optional def operands.
+ if (ADI && ADI->getDef()->getName() == "zero_reg") {
+
+ // Check if this is an optional def.
+ // Tied operands where the source is a sub-operand of a complex operand
+ // need to represent both operands in the alias destination instruction.
+ // Allow zero_reg for the tied portion. This can and should go away once
+ // the MC representation of things doesn't use tied operands at all.
+ // if (!InstOpRec->isSubClassOf("OptionalDefOperand"))
+ // throw TGError(Loc, "reg0 used for result that is not an "
+ // "OptionalDefOperand!");
+
+ ResOp = ResultOperand(static_cast<Record *>(nullptr));
+ return true;
+ }
+
+ // Literal integers.
+ if (IntInit *II = dyn_cast<IntInit>(Arg)) {
+ if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
+ return false;
+ // Integer arguments can't have names.
+ if (Result->getArgName(AliasOpNo))
+ PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
+ " must not have a name!");
+ ResOp = ResultOperand(II->getValue());
+ return true;
+ }
+
+ // Bits<n> (also used for 0bxx literals)
+ if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) {
+ if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
+ return false;
+ if (!BI->isComplete())
+ return false;
+ // Convert the bits init to an integer and use that for the result.
+ IntInit *II = dyn_cast_or_null<IntInit>(
+ BI->convertInitializerTo(IntRecTy::get(BI->getRecordKeeper())));
+ if (!II)
+ return false;
+ ResOp = ResultOperand(II->getValue());
+ return true;
+ }
+
+ // If both are Operands with the same MVT, allow the conversion. It's
+ // up to the user to make sure the values are appropriate, just like
+ // for isel Pat's.
+ if (InstOpRec->isSubClassOf("Operand") && ADI &&
+ ADI->getDef()->isSubClassOf("Operand")) {
+ // FIXME: What other attributes should we check here? Identical
+ // MIOperandInfo perhaps?
+ if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type"))
+ return false;
+ ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
+ ADI->getDef());
+ return true;
+ }
+
+ return false;
+}
+
+unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
+ if (!isRecord())
+ return 1;
+
+ Record *Rec = getRecord();
+ if (!Rec->isSubClassOf("Operand"))
+ return 1;
+
+ DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
+ if (MIOpInfo->getNumArgs() == 0) {
+ // Unspecified, so it defaults to 1
+ return 1;
+ }
+
+ return MIOpInfo->getNumArgs();
+}
+
+CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
+ Result = R->getValueAsDag("ResultInst");
+ AsmString = std::string(R->getValueAsString("AsmString"));
+
+ // Verify that the root of the result is an instruction.
+ DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
+ if (!DI || !DI->getDef()->isSubClassOf("Instruction"))
+ PrintFatalError(R->getLoc(),
+ "result of inst alias should be an instruction");
+
+ ResultInst = &T.getInstruction(DI->getDef());
+
+ // NameClass - If argument names are repeated, we need to verify they have
+ // the same class.
+ StringMap<Record *> NameClass;
+ for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
+ DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i));
+ if (!ADI || !Result->getArgName(i))
+ continue;
+ // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
+ // $foo can exist multiple times in the result list, but it must have the
+ // same type.
+ Record *&Entry = NameClass[Result->getArgNameStr(i)];
+ if (Entry && Entry != ADI->getDef())
+ PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) +
+ " is both " + Entry->getName() +
+ " and " + ADI->getDef()->getName() +
+ "!");
+ Entry = ADI->getDef();
+ }
+
+ // Decode and validate the arguments of the result.
+ unsigned AliasOpNo = 0;
+ for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
+
+ // Tied registers don't have an entry in the result dag unless they're part
+ // of a complex operand, in which case we include them anyways, as we
+ // don't have any other way to specify the whole operand.
+ if (ResultInst->Operands[i].MINumOperands == 1 &&
+ ResultInst->Operands[i].getTiedRegister() != -1) {
+ // Tied operands of
diff erent RegisterClass should be explicit within an
+ // instruction's syntax and so cannot be skipped.
+ int TiedOpNum = ResultInst->Operands[i].getTiedRegister();
+ if (ResultInst->Operands[i].Rec->getName() ==
+ ResultInst->Operands[TiedOpNum].Rec->getName())
+ continue;
+ }
+
+ if (AliasOpNo >= Result->getNumArgs())
+ PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
+
+ Record *InstOpRec = ResultInst->Operands[i].Rec;
+ unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
+ ResultOperand ResOp(static_cast<int64_t>(0));
+ if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
+ R->getLoc(), T, ResOp)) {
+ // If this is a simple operand, or a complex operand with a custom match
+ // class, then we can match is verbatim.
+ if (NumSubOps == 1 || (InstOpRec->getValue("ParserMatchClass") &&
+ InstOpRec->getValueAsDef("ParserMatchClass")
+ ->getValueAsString("Name") != "Imm")) {
+ ResultOperands.push_back(ResOp);
+ ResultInstOperandIndex.push_back(std::make_pair(i, -1));
+ ++AliasOpNo;
+
+ // Otherwise, we need to match each of the suboperands individually.
+ } else {
+ DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
+ for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
+ Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
+
+ // Take care to instantiate each of the suboperands with the correct
+ // nomenclature: $foo.bar
+ ResultOperands.emplace_back(
+ Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." +
+ MIOI->getArgName(SubOp)->getAsUnquotedString(),
+ SubRec);
+ ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
+ }
+ ++AliasOpNo;
+ }
+ continue;
+ }
+
+ // If the argument did not match the instruction operand, and the operand
+ // is composed of multiple suboperands, try matching the suboperands.
+ if (NumSubOps > 1) {
+ DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
+ for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
+ if (AliasOpNo >= Result->getNumArgs())
+ PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
+ Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
+ if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, R->getLoc(), T,
+ ResOp)) {
+ ResultOperands.push_back(ResOp);
+ ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
+ ++AliasOpNo;
+ } else {
+ PrintFatalError(
+ R->getLoc(),
+ "result argument #" + Twine(AliasOpNo) +
+ " does not match instruction operand class " +
+ (SubOp == 0 ? InstOpRec->getName() : SubRec->getName()));
+ }
+ }
+ continue;
+ }
+ PrintFatalError(R->getLoc(),
+ "result argument #" + Twine(AliasOpNo) +
+ " does not match instruction operand class " +
+ InstOpRec->getName());
+ }
+
+ if (AliasOpNo != Result->getNumArgs())
+ PrintFatalError(R->getLoc(), "too many operands for instruction!");
+}
diff --git a/llvm/utils/TableGen/CodeGenInstAlias.h b/llvm/utils/TableGen/CodeGenInstAlias.h
new file mode 100644
index 0000000000000..2a05273e72701
--- /dev/null
+++ b/llvm/utils/TableGen/CodeGenInstAlias.h
@@ -0,0 +1,105 @@
+//===- CodeGenInstAlias.h - InstAlias Class Wrapper -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a wrapper class for the 'InstAlias' TableGen class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTALIAS_H
+#define LLVM_UTILS_TABLEGEN_CODEGENINSTALIAS_H
+
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+template <typename T> class ArrayRef;
+class CodeGenInstruction;
+class CodeGenTarget;
+class DagInit;
+class SMLoc;
+class Record;
+
+/// CodeGenInstAlias - This represents an InstAlias definition.
+class CodeGenInstAlias {
+public:
+ Record *TheDef; // The actual record defining this InstAlias.
+
+ /// AsmString - The format string used to emit a .s file for the
+ /// instruction.
+ std::string AsmString;
+
+ /// Result - The result instruction.
+ DagInit *Result;
+
+ /// ResultInst - The instruction generated by the alias (decoded from
+ /// Result).
+ CodeGenInstruction *ResultInst;
+
+ struct ResultOperand {
+ private:
+ std::string Name;
+ Record *R = nullptr;
+ int64_t Imm = 0;
+
+ public:
+ enum { K_Record, K_Imm, K_Reg } Kind;
+
+ ResultOperand(std::string N, Record *r)
+ : Name(std::move(N)), R(r), Kind(K_Record) {}
+ ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
+ ResultOperand(Record *r) : R(r), Kind(K_Reg) {}
+
+ bool isRecord() const { return Kind == K_Record; }
+ bool isImm() const { return Kind == K_Imm; }
+ bool isReg() const { return Kind == K_Reg; }
+
+ StringRef getName() const {
+ assert(isRecord());
+ return Name;
+ }
+ Record *getRecord() const {
+ assert(isRecord());
+ return R;
+ }
+ int64_t getImm() const {
+ assert(isImm());
+ return Imm;
+ }
+ Record *getRegister() const {
+ assert(isReg());
+ return R;
+ }
+
+ unsigned getMINumOperands() const;
+ };
+
+ /// ResultOperands - The decoded operands for the result instruction.
+ std::vector<ResultOperand> ResultOperands;
+
+ /// ResultInstOperandIndex - For each operand, this vector holds a pair of
+ /// indices to identify the corresponding operand in the result
+ /// instruction. The first index specifies the operand and the second
+ /// index specifies the suboperand. If there are no suboperands or if all
+ /// of them are matched by the operand, the second value should be -1.
+ std::vector<std::pair<unsigned, int>> ResultInstOperandIndex;
+
+ CodeGenInstAlias(Record *R, CodeGenTarget &T);
+
+ bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, Record *InstOpRec,
+ bool hasSubOps, ArrayRef<SMLoc> Loc, CodeGenTarget &T,
+ ResultOperand &ResOp);
+};
+
+} // namespace llvm
+
+#endif // LLVM_UTILS_TABLEGEN_CODEGENINSTALIAS_H
diff --git a/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp
index 238c6a1b6ba8c..11133918a8ff2 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -13,7 +13,6 @@
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <set>
@@ -592,266 +591,3 @@ bool CodeGenInstruction::isOperandImpl(StringRef OpListName, unsigned i,
return Constraint->getDef()->isSubClassOf("TypedOperand") &&
Constraint->getDef()->getValueAsBit(PropertyName);
}
-
-//===----------------------------------------------------------------------===//
-/// CodeGenInstAlias Implementation
-//===----------------------------------------------------------------------===//
-
-/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
-/// constructor. It checks if an argument in an InstAlias pattern matches
-/// the corresponding operand of the instruction. It returns true on a
-/// successful match, with ResOp set to the result operand to be used.
-bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
- Record *InstOpRec, bool hasSubOps,
- ArrayRef<SMLoc> Loc, CodeGenTarget &T,
- ResultOperand &ResOp) {
- Init *Arg = Result->getArg(AliasOpNo);
- DefInit *ADI = dyn_cast<DefInit>(Arg);
- Record *ResultRecord = ADI ? ADI->getDef() : nullptr;
-
- if (ADI && ADI->getDef() == InstOpRec) {
- // If the operand is a record, it must have a name, and the record type
- // must match up with the instruction's argument type.
- if (!Result->getArgName(AliasOpNo))
- PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
- " must have a name!");
- ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
- ResultRecord);
- return true;
- }
-
- // For register operands, the source register class can be a subclass
- // of the instruction register class, not just an exact match.
- if (InstOpRec->isSubClassOf("RegisterOperand"))
- InstOpRec = InstOpRec->getValueAsDef("RegClass");
-
- if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand"))
- ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit();
-
- if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) {
- if (!InstOpRec->isSubClassOf("RegisterClass"))
- return false;
- if (!T.getRegisterClass(InstOpRec)
- .hasSubClass(&T.getRegisterClass(ADI->getDef())))
- return false;
- ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
- ResultRecord);
- return true;
- }
-
- // Handle explicit registers.
- if (ADI && ADI->getDef()->isSubClassOf("Register")) {
- if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
- DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
- // The operand info should only have a single (register) entry. We
- // want the register class of it.
- InstOpRec = cast<DefInit>(DI->getArg(0))->getDef();
- }
-
- if (!InstOpRec->isSubClassOf("RegisterClass"))
- return false;
-
- if (!T.getRegisterClass(InstOpRec)
- .contains(T.getRegBank().getReg(ADI->getDef())))
- PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() +
- " is not a member of the " + InstOpRec->getName() +
- " register class!");
-
- if (Result->getArgName(AliasOpNo))
- PrintFatalError(Loc, "result fixed register argument must "
- "not have a name!");
-
- ResOp = ResultOperand(ResultRecord);
- return true;
- }
-
- // Handle "zero_reg" for optional def operands.
- if (ADI && ADI->getDef()->getName() == "zero_reg") {
-
- // Check if this is an optional def.
- // Tied operands where the source is a sub-operand of a complex operand
- // need to represent both operands in the alias destination instruction.
- // Allow zero_reg for the tied portion. This can and should go away once
- // the MC representation of things doesn't use tied operands at all.
- //if (!InstOpRec->isSubClassOf("OptionalDefOperand"))
- // throw TGError(Loc, "reg0 used for result that is not an "
- // "OptionalDefOperand!");
-
- ResOp = ResultOperand(static_cast<Record*>(nullptr));
- return true;
- }
-
- // Literal integers.
- if (IntInit *II = dyn_cast<IntInit>(Arg)) {
- if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
- return false;
- // Integer arguments can't have names.
- if (Result->getArgName(AliasOpNo))
- PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
- " must not have a name!");
- ResOp = ResultOperand(II->getValue());
- return true;
- }
-
- // Bits<n> (also used for 0bxx literals)
- if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) {
- if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
- return false;
- if (!BI->isComplete())
- return false;
- // Convert the bits init to an integer and use that for the result.
- IntInit *II = dyn_cast_or_null<IntInit>(
- BI->convertInitializerTo(IntRecTy::get(BI->getRecordKeeper())));
- if (!II)
- return false;
- ResOp = ResultOperand(II->getValue());
- return true;
- }
-
- // If both are Operands with the same MVT, allow the conversion. It's
- // up to the user to make sure the values are appropriate, just like
- // for isel Pat's.
- if (InstOpRec->isSubClassOf("Operand") && ADI &&
- ADI->getDef()->isSubClassOf("Operand")) {
- // FIXME: What other attributes should we check here? Identical
- // MIOperandInfo perhaps?
- if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type"))
- return false;
- ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
- ADI->getDef());
- return true;
- }
-
- return false;
-}
-
-unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
- if (!isRecord())
- return 1;
-
- Record *Rec = getRecord();
- if (!Rec->isSubClassOf("Operand"))
- return 1;
-
- DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
- if (MIOpInfo->getNumArgs() == 0) {
- // Unspecified, so it defaults to 1
- return 1;
- }
-
- return MIOpInfo->getNumArgs();
-}
-
-CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T)
- : TheDef(R) {
- Result = R->getValueAsDag("ResultInst");
- AsmString = std::string(R->getValueAsString("AsmString"));
-
- // Verify that the root of the result is an instruction.
- DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
- if (!DI || !DI->getDef()->isSubClassOf("Instruction"))
- PrintFatalError(R->getLoc(),
- "result of inst alias should be an instruction");
-
- ResultInst = &T.getInstruction(DI->getDef());
-
- // NameClass - If argument names are repeated, we need to verify they have
- // the same class.
- StringMap<Record*> NameClass;
- for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
- DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i));
- if (!ADI || !Result->getArgName(i))
- continue;
- // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
- // $foo can exist multiple times in the result list, but it must have the
- // same type.
- Record *&Entry = NameClass[Result->getArgNameStr(i)];
- if (Entry && Entry != ADI->getDef())
- PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) +
- " is both " + Entry->getName() + " and " +
- ADI->getDef()->getName() + "!");
- Entry = ADI->getDef();
- }
-
- // Decode and validate the arguments of the result.
- unsigned AliasOpNo = 0;
- for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
-
- // Tied registers don't have an entry in the result dag unless they're part
- // of a complex operand, in which case we include them anyways, as we
- // don't have any other way to specify the whole operand.
- if (ResultInst->Operands[i].MINumOperands == 1 &&
- ResultInst->Operands[i].getTiedRegister() != -1) {
- // Tied operands of
diff erent RegisterClass should be explicit within an
- // instruction's syntax and so cannot be skipped.
- int TiedOpNum = ResultInst->Operands[i].getTiedRegister();
- if (ResultInst->Operands[i].Rec->getName() ==
- ResultInst->Operands[TiedOpNum].Rec->getName())
- continue;
- }
-
- if (AliasOpNo >= Result->getNumArgs())
- PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
-
- Record *InstOpRec = ResultInst->Operands[i].Rec;
- unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
- ResultOperand ResOp(static_cast<int64_t>(0));
- if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
- R->getLoc(), T, ResOp)) {
- // If this is a simple operand, or a complex operand with a custom match
- // class, then we can match is verbatim.
- if (NumSubOps == 1 ||
- (InstOpRec->getValue("ParserMatchClass") &&
- InstOpRec->getValueAsDef("ParserMatchClass")
- ->getValueAsString("Name") != "Imm")) {
- ResultOperands.push_back(ResOp);
- ResultInstOperandIndex.push_back(std::make_pair(i, -1));
- ++AliasOpNo;
-
- // Otherwise, we need to match each of the suboperands individually.
- } else {
- DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
- for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
- Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
-
- // Take care to instantiate each of the suboperands with the correct
- // nomenclature: $foo.bar
- ResultOperands.emplace_back(
- Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." +
- MIOI->getArgName(SubOp)->getAsUnquotedString(), SubRec);
- ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
- }
- ++AliasOpNo;
- }
- continue;
- }
-
- // If the argument did not match the instruction operand, and the operand
- // is composed of multiple suboperands, try matching the suboperands.
- if (NumSubOps > 1) {
- DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
- for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
- if (AliasOpNo >= Result->getNumArgs())
- PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
- Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
- if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false,
- R->getLoc(), T, ResOp)) {
- ResultOperands.push_back(ResOp);
- ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
- ++AliasOpNo;
- } else {
- PrintFatalError(R->getLoc(), "result argument #" + Twine(AliasOpNo) +
- " does not match instruction operand class " +
- (SubOp == 0 ? InstOpRec->getName() :SubRec->getName()));
- }
- }
- continue;
- }
- PrintFatalError(R->getLoc(), "result argument #" + Twine(AliasOpNo) +
- " does not match instruction operand class " +
- InstOpRec->getName());
- }
-
- if (AliasOpNo != Result->getNumArgs())
- PrintFatalError(R->getLoc(), "too many operands for instruction!");
-}
diff --git a/llvm/utils/TableGen/CodeGenInstruction.h b/llvm/utils/TableGen/CodeGenInstruction.h
index 72626caada566..2a1f17c37834a 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.h
+++ b/llvm/utils/TableGen/CodeGenInstruction.h
@@ -23,8 +23,6 @@
#include <vector>
namespace llvm {
-class SMLoc;
-template <typename T> class ArrayRef;
class Record;
class DagInit;
class CodeGenTarget;
@@ -340,71 +338,6 @@ template <typename T> class ArrayRef;
bool isOperandImpl(StringRef OpListName, unsigned i,
StringRef PropertyName) const;
};
-
-
- /// CodeGenInstAlias - This represents an InstAlias definition.
- class CodeGenInstAlias {
- public:
- Record *TheDef; // The actual record defining this InstAlias.
-
- /// AsmString - The format string used to emit a .s file for the
- /// instruction.
- std::string AsmString;
-
- /// Result - The result instruction.
- DagInit *Result;
-
- /// ResultInst - The instruction generated by the alias (decoded from
- /// Result).
- CodeGenInstruction *ResultInst;
-
-
- struct ResultOperand {
- private:
- std::string Name;
- Record *R = nullptr;
- int64_t Imm = 0;
-
- public:
- enum {
- K_Record,
- K_Imm,
- K_Reg
- } Kind;
-
- ResultOperand(std::string N, Record *r)
- : Name(std::move(N)), R(r), Kind(K_Record) {}
- ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
- ResultOperand(Record *r) : R(r), Kind(K_Reg) {}
-
- bool isRecord() const { return Kind == K_Record; }
- bool isImm() const { return Kind == K_Imm; }
- bool isReg() const { return Kind == K_Reg; }
-
- StringRef getName() const { assert(isRecord()); return Name; }
- Record *getRecord() const { assert(isRecord()); return R; }
- int64_t getImm() const { assert(isImm()); return Imm; }
- Record *getRegister() const { assert(isReg()); return R; }
-
- unsigned getMINumOperands() const;
- };
-
- /// ResultOperands - The decoded operands for the result instruction.
- std::vector<ResultOperand> ResultOperands;
-
- /// ResultInstOperandIndex - For each operand, this vector holds a pair of
- /// indices to identify the corresponding operand in the result
- /// instruction. The first index specifies the operand and the second
- /// index specifies the suboperand. If there are no suboperands or if all
- /// of them are matched by the operand, the second value should be -1.
- std::vector<std::pair<unsigned, int> > ResultInstOperandIndex;
-
- CodeGenInstAlias(Record *R, CodeGenTarget &T);
-
- bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
- Record *InstOpRec, bool hasSubOps, ArrayRef<SMLoc> Loc,
- CodeGenTarget &T, ResultOperand &ResOp);
- };
-}
+} // namespace llvm
#endif
diff --git a/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn
index b5c774f363109..b0abe638c528a 100644
--- a/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn
@@ -15,6 +15,7 @@ executable("llvm-tblgen") {
"CodeEmitterGen.cpp",
"CodeGenDAGPatterns.cpp",
"CodeGenHwModes.cpp",
+ "CodeGenInstAlias.cpp",
"CodeGenInstruction.cpp",
"CodeGenMapTable.cpp",
"CodeGenRegisters.cpp",
More information about the cfe-commits
mailing list