aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/TableGen/Parser.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-16 17:28:49 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-16 17:28:49 +0800
commit864a29abbdce86353ec91c3587757711d3a42f10 (patch)
tree772390cad70fe8e47044f5c921174b254bd8297a /backend/lib/TableGen/Parser.cpp
parentca25d25d4c5131491a50b1a94e63e9b2d3c34ed4 (diff)
downloadrcc-project-864a29abbdce86353ec91c3587757711d3a42f10.tar.gz
rcc-project-864a29abbdce86353ec91c3587757711d3a42f10.tar.xz
[RISCV][GlobalISel] Generate integer comparisons
Diffstat (limited to 'backend/lib/TableGen/Parser.cpp')
-rw-r--r--backend/lib/TableGen/Parser.cpp173
1 files changed, 145 insertions, 28 deletions
diff --git a/backend/lib/TableGen/Parser.cpp b/backend/lib/TableGen/Parser.cpp
index 9807534..c194448 100644
--- a/backend/lib/TableGen/Parser.cpp
+++ b/backend/lib/TableGen/Parser.cpp
@@ -1180,25 +1180,53 @@ private:
for (const yaml::NodeID ElementID : Node.sequence()) {
const yaml::Node *Element = Input.node(ElementID);
if (!requireMapping(Element, "selection operand definition constant") ||
- !checkKeys(*Element, {"index", "value"}, "selection operand definition constant")) {
+ !checkKeys(*Element, {"index", "ranges"}, "selection operand definition constant")) {
return false;
}
const yaml::Node *IndexNode =
requiredNode(*Element, "index", "selection operand definition constant");
- const yaml::Node *ValueNode =
- requiredNode(*Element, "value", "selection operand definition constant");
- if (IndexNode == nullptr || ValueNode == nullptr)
+ const yaml::Node *RangesNode =
+ requiredNode(*Element, "ranges", "selection operand definition constant");
+ if (IndexNode == nullptr || RangesNode == nullptr)
return false;
const auto Index =
unsignedInteger32(*IndexNode, "selection operand definition constant index");
- const auto Value = signedInteger(*ValueNode, "selection operand definition constant value");
- if (!Index || !Value)
+ if (!Index || !requireSequence(RangesNode, "selection operand definition constant ranges") ||
+ RangesNode->sequence().empty()) {
return false;
- Result.push_back({
+ }
+
+ SourceSelectionOperandDefConstantPredicate Predicate{
.OperandIndex = *Index,
- .Value = *Value,
+ .Ranges = {},
.Range = Element->range(),
- });
+ };
+ for (const yaml::NodeID RangeID : RangesNode->sequence()) {
+ const yaml::Node *Range = Input.node(RangeID);
+ if (!requireMapping(Range, "selection operand definition constant range") ||
+ !checkKeys(*Range, {"min", "max"}, "selection operand definition constant range")) {
+ return false;
+ }
+ const yaml::Node *MinimumNode =
+ requiredNode(*Range, "min", "selection operand definition constant range");
+ const yaml::Node *MaximumNode =
+ requiredNode(*Range, "max", "selection operand definition constant range");
+ if (MinimumNode == nullptr || MaximumNode == nullptr)
+ return false;
+ const auto Minimum = signedInteger(*MinimumNode, "selection constant range minimum");
+ const auto Maximum = signedInteger(*MaximumNode, "selection constant range maximum");
+ if (!Minimum || !Maximum || *Minimum > *Maximum) {
+ if (Minimum && Maximum)
+ fail(Range->range(), "selection operand definition constant range is invalid");
+ return false;
+ }
+ Predicate.Ranges.push_back({
+ .Minimum = *Minimum,
+ .Maximum = *Maximum,
+ .SourceRange = Range->range(),
+ });
+ }
+ Result.push_back(std::move(Predicate));
}
return true;
}
@@ -1211,20 +1239,33 @@ private:
for (const yaml::NodeID ElementID : Node.sequence()) {
const yaml::Node *Element = Input.node(ElementID);
if (!requireMapping(Element, "selection operand renderer") ||
- !checkKeys(*Element, {"operand", "physical_register", "flags"},
+ !checkKeys(*Element,
+ {"operand", "physical_register", "temporary", "captured_immediate",
+ "immediate", "transform", "flags"},
"selection operand renderer")) {
return false;
}
const yaml::Node *OperandNode = optionalNode(*Element, "operand");
const yaml::Node *PhysicalRegisterNode = optionalNode(*Element, "physical_register");
- if ((OperandNode == nullptr) == (PhysicalRegisterNode == nullptr)) {
- fail(Element->range(), "selection operand renderer requires exactly one of 'operand' or "
- "'physical_register'");
+ const yaml::Node *TemporaryNode = optionalNode(*Element, "temporary");
+ const yaml::Node *CapturedImmediateNode = optionalNode(*Element, "captured_immediate");
+ const yaml::Node *ImmediateNode = optionalNode(*Element, "immediate");
+ const std::uint32_t SourceCount = static_cast<std::uint32_t>(OperandNode != nullptr) +
+ static_cast<std::uint32_t>(PhysicalRegisterNode != nullptr) +
+ static_cast<std::uint32_t>(TemporaryNode != nullptr) +
+ static_cast<std::uint32_t>(CapturedImmediateNode != nullptr) +
+ static_cast<std::uint32_t>(ImmediateNode != nullptr);
+ if (SourceCount != 1) {
+ fail(Element->range(), "selection operand renderer requires exactly one source");
return false;
}
SourceSelectionOperandRenderer Renderer{
.OperandIndex = std::nullopt,
.PhysicalRegisterSymbol = {},
+ .TemporarySymbol = {},
+ .CapturedImmediateOperand = std::nullopt,
+ .Immediate = std::nullopt,
+ .ImmediateTransform = "identity",
.Flags = {},
.Range = Element->range(),
};
@@ -1233,12 +1274,38 @@ private:
if (!Index)
return false;
Renderer.OperandIndex = Index;
- } else {
+ } else if (PhysicalRegisterNode != nullptr) {
const auto Symbol =
scalar(*PhysicalRegisterNode, "selection operand renderer physical register");
if (!Symbol)
return false;
Renderer.PhysicalRegisterSymbol = *Symbol;
+ } else if (TemporaryNode != nullptr) {
+ const auto Symbol = scalar(*TemporaryNode, "selection operand renderer temporary");
+ if (!Symbol)
+ return false;
+ Renderer.TemporarySymbol = *Symbol;
+ } else if (CapturedImmediateNode != nullptr) {
+ const auto Index =
+ unsignedInteger32(*CapturedImmediateNode, "selection operand renderer captured immediate");
+ if (!Index)
+ return false;
+ Renderer.CapturedImmediateOperand = *Index;
+ } else {
+ const auto Value = signedInteger(*ImmediateNode, "selection operand renderer immediate");
+ if (!Value)
+ return false;
+ Renderer.Immediate = *Value;
+ }
+ if (const yaml::Node *TransformNode = optionalNode(*Element, "transform")) {
+ const auto Transform = scalar(*TransformNode, "selection operand renderer transform");
+ if (!Transform)
+ return false;
+ Renderer.ImmediateTransform = *Transform;
+ }
+ if (!Renderer.CapturedImmediateOperand && Renderer.ImmediateTransform != "identity") {
+ fail(Element->range(), "selection operand renderer transform requires a captured immediate");
+ return false;
}
if (const yaml::Node *FlagsNode = optionalNode(*Element, "flags")) {
const auto Flags = scalarSequence(*FlagsNode, "selection operand renderer flags");
@@ -1251,6 +1318,63 @@ private:
return true;
}
+ [[nodiscard]] bool parseSelectionTemporaries(const yaml::Node &Node,
+ std::vector<SourceSelectionTemporary> &Result) {
+ if (!requireSequence(&Node, "selection temporaries"))
+ return false;
+ for (const yaml::NodeID ElementID : Node.sequence()) {
+ const yaml::Node *Element = Input.node(ElementID);
+ if (!requireMapping(Element, "selection temporary") ||
+ !checkKeys(*Element, {"id", "type_from_operand"}, "selection temporary")) {
+ return false;
+ }
+ const auto Symbol = requiredScalar(*Element, "id", "selection temporary");
+ const yaml::Node *TypeNode = requiredNode(*Element, "type_from_operand", "selection temporary");
+ if (!Symbol || TypeNode == nullptr)
+ return false;
+ const auto TypeFromOperand = unsignedInteger32(*TypeNode, "selection temporary type operand");
+ if (!TypeFromOperand)
+ return false;
+ Result.push_back({
+ .Symbol = *Symbol,
+ .TypeFromOperand = *TypeFromOperand,
+ .Range = Element->range(),
+ });
+ }
+ return true;
+ }
+
+ [[nodiscard]] bool parseSelectionActions(const yaml::Node &Node,
+ std::vector<SourceSelectionAction> &Result) {
+ if (!requireSequence(&Node, "selection instructions"))
+ return false;
+ for (const yaml::NodeID ElementID : Node.sequence()) {
+ const yaml::Node *Element = Input.node(ElementID);
+ if (!requireMapping(Element, "selection instruction") ||
+ !checkKeys(*Element, {"opcode", "root", "operands"}, "selection instruction")) {
+ return false;
+ }
+ const auto Opcode = requiredScalar(*Element, "opcode", "selection instruction");
+ const yaml::Node *RootNode = requiredNode(*Element, "root", "selection instruction");
+ const yaml::Node *OperandsNode = requiredNode(*Element, "operands", "selection instruction");
+ if (!Opcode || RootNode == nullptr || OperandsNode == nullptr)
+ return false;
+ const auto ReplacesRoot = boolean(*RootNode, "selection instruction root");
+ if (!ReplacesRoot)
+ return false;
+ std::vector<SourceSelectionOperandRenderer> Renderers;
+ if (!parseSelectionOperandRenderers(*OperandsNode, Renderers))
+ return false;
+ Result.push_back({
+ .ResultOpcodeSymbol = *Opcode,
+ .ReplacesRoot = *ReplacesRoot,
+ .OperandRenderers = std::move(Renderers),
+ .Range = Element->range(),
+ });
+ }
+ return true;
+ }
+
[[nodiscard]] bool parseSelectionRuleMatch(const yaml::Node &Node, SourceSelectionRule &Result) {
if (!requireMapping(&Node, "selection rule match") ||
!checkKeys(Node,
@@ -1294,26 +1418,19 @@ private:
[[nodiscard]] bool parseSelectionRuleApply(const yaml::Node &Node, SourceSelectionRule &Result) {
if (!requireMapping(&Node, "selection rule apply") ||
- !checkKeys(Node, {"opcode", "append_immediates", "operands", "erase_operand_definitions"},
+ !checkKeys(Node, {"temporaries", "instructions", "erase_operand_definitions"},
"selection rule apply")) {
return false;
}
- const auto Opcode = requiredScalar(Node, "opcode", "selection rule apply");
- if (!Opcode)
+ const yaml::Node *Instructions = requiredNode(Node, "instructions", "selection rule apply");
+ if (Instructions == nullptr)
return false;
- Result.ResultOpcodeSymbol = *Opcode;
- if (const yaml::Node *Immediates = optionalNode(Node, "append_immediates")) {
- auto Values = signedIntegerSequence(*Immediates, "selection rule appended immediates");
- if (!Values)
+ if (const yaml::Node *Temporaries = optionalNode(Node, "temporaries")) {
+ if (!parseSelectionTemporaries(*Temporaries, Result.Temporaries))
return false;
- Result.AppendedImmediates = std::move(*Values);
- }
- if (const yaml::Node *Operands = optionalNode(Node, "operands")) {
- std::vector<SourceSelectionOperandRenderer> Renderers;
- if (!parseSelectionOperandRenderers(*Operands, Renderers))
- return false;
- Result.OperandRenderers = std::move(Renderers);
}
+ if (!parseSelectionActions(*Instructions, Result.Actions))
+ return false;
if (const yaml::Node *Erase = optionalNode(Node, "erase_operand_definitions")) {
auto Indices = unsignedInteger32Sequence(*Erase, "selection operand definitions");
if (!Indices)