| 1 | //===- PredicateExpanderDag.cpp - Composable predicate dag lowering -------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "PredicateExpanderDag.h" |
| 10 | #include "llvm/ADT/STLExtras.h" |
| 11 | #include "llvm/Support/raw_ostream.h" |
| 12 | #include "llvm/TableGen/Error.h" |
| 13 | #include "llvm/TableGen/Record.h" |
| 14 | |
| 15 | using namespace llvm; |
| 16 | |
| 17 | bool llvm::emitPredicateDag( |
| 18 | const Record *Owner, const Init &Val, bool ParenIfBinOp, raw_ostream &OS, |
| 19 | function_ref<bool(const Init &, raw_ostream &)> EmitLeaf) { |
| 20 | if (const auto *D = dyn_cast<DagInit>(Val: &Val)) { |
| 21 | const auto *Op = dyn_cast<DefInit>(Val: D->getOperator()); |
| 22 | if (!Op) |
| 23 | PrintFatalError(Rec: Owner, Msg: "invalid predicate dag operator" ); |
| 24 | StringRef OpName = Op->getDef()->getName(); |
| 25 | if (OpName == "not" ) { |
| 26 | if (D->getNumArgs() != 1) |
| 27 | PrintFatalError(Rec: Owner, Msg: "'not' takes exactly one operand" ); |
| 28 | OS << "!(" ; |
| 29 | bool Err = emitPredicateDag(Owner, Val: *D->getArg(Num: 0), /*ParenIfBinOp=*/false, |
| 30 | OS, EmitLeaf); |
| 31 | OS << ')'; |
| 32 | return Err; |
| 33 | } |
| 34 | if (OpName == "any_of" || OpName == "all_of" ) { |
| 35 | if (D->getNumArgs() == 0) |
| 36 | PrintFatalError(Rec: Owner, |
| 37 | Msg: "'" + OpName + "' requires at least one operand" ); |
| 38 | bool Paren = D->getNumArgs() > 1 && std::exchange(obj&: ParenIfBinOp, new_val: true); |
| 39 | if (Paren) |
| 40 | OS << '('; |
| 41 | ListSeparator LS(OpName == "any_of" ? " || " : " && " ); |
| 42 | for (const Init *Arg : D->getArgs()) { |
| 43 | OS << LS; |
| 44 | if (emitPredicateDag(Owner, Val: *Arg, ParenIfBinOp, OS, EmitLeaf)) |
| 45 | return true; |
| 46 | } |
| 47 | if (Paren) |
| 48 | OS << ')'; |
| 49 | return false; |
| 50 | } |
| 51 | PrintFatalError(Rec: Owner, Msg: "unknown predicate dag operator '" + OpName + |
| 52 | "'; expected all_of/any_of/not" ); |
| 53 | } |
| 54 | |
| 55 | // Any non-dag operand (or the base leaf) is emitted by the caller, which |
| 56 | // diagnoses leaf-level errors specific to its consumer. |
| 57 | return EmitLeaf(Val, OS); |
| 58 | } |
| 59 | |