blob: 15510abce6fefd437fdef69f998541ed0557f3e0 [file] [edit]
//===- PredicateExpanderDag.cpp - Composable predicate dag lowering -------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "PredicateExpanderDag.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
using namespace llvm;
bool llvm::emitPredicateDag(
const Record *Owner, const Init &Val, bool ParenIfBinOp, raw_ostream &OS,
function_ref<bool(const Init &, raw_ostream &)> EmitLeaf) {
if (const auto *D = dyn_cast<DagInit>(&Val)) {
const auto *Op = dyn_cast<DefInit>(D->getOperator());
if (!Op)
PrintFatalError(Owner, "invalid predicate dag operator");
StringRef OpName = Op->getDef()->getName();
if (OpName == "not") {
if (D->getNumArgs() != 1)
PrintFatalError(Owner, "'not' takes exactly one operand");
OS << "!(";
bool Err = emitPredicateDag(Owner, *D->getArg(0), /*ParenIfBinOp=*/false,
OS, EmitLeaf);
OS << ')';
return Err;
}
if (OpName == "any_of" || OpName == "all_of") {
if (D->getNumArgs() == 0)
PrintFatalError(Owner,
"'" + OpName + "' requires at least one operand");
bool Paren = D->getNumArgs() > 1 && std::exchange(ParenIfBinOp, true);
if (Paren)
OS << '(';
ListSeparator LS(OpName == "any_of" ? " || " : " && ");
for (const Init *Arg : D->getArgs()) {
OS << LS;
if (emitPredicateDag(Owner, *Arg, ParenIfBinOp, OS, EmitLeaf))
return true;
}
if (Paren)
OS << ')';
return false;
}
PrintFatalError(Owner, "unknown predicate dag operator '" + OpName +
"'; expected all_of/any_of/not");
}
// Any non-dag operand (or the base leaf) is emitted by the caller, which
// diagnoses leaf-level errors specific to its consumer.
return EmitLeaf(Val, OS);
}