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
15using namespace llvm;
16
17bool 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