#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "llvm/ADT/STLExtras.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/SymbolTable.h" #include "revng/Clift/CliftOpTraits.h" #include "revng/Clift/CliftTypes.h" namespace clift { class LabelAssignmentOpInterface; class StatementRegionOpInterface; class ExpressionRegionOpInterface; namespace impl { /// Returns the break or continue label value (if any), depending on the /// specified index. (Index=0 for break, Index=1 for continue). template mlir::Value getLoopLabel(LoopOpT Op, unsigned Index) { unsigned Mask = Op.getLabelMask(); unsigned Flag = 1 << Index; if ((Mask & Flag) == 0) return nullptr; // The operand index is given by the value of the lower flag (if any): unsigned OperandIndex = Mask & Flag >> 1; return Op->getOperand(OperandIndex); } template void setLoopLabel(LoopOpT Op, unsigned Index, mlir::Value Label) { unsigned Mask = Op.getLabelMask(); unsigned Flag = 1 << Index; // The operand index is given by the value of the lower flag (if any): unsigned OperandIndex = Mask & Flag >> 1; bool HasLabelOperand = Mask & Flag; if (HasLabelOperand != static_cast(Label)) Op.setLabelMask(Mask ^ Flag); if (Label) { if (HasLabelOperand) Op->setOperand(OperandIndex, Label); else Op->insertOperands(OperandIndex, { Label }); } else if (HasLabelOperand) { Op->eraseOperand(OperandIndex); } } LabelAssignmentOpInterface getLabelAssignmentOp(mlir::Value Label); } // namespace impl /// Provides a range over the statement regions of an operation by utilizing the /// index-based interface of StatementRegionOpInterface. struct StatementRegionRange : llvm::indexed_accessor_range { StatementRegionRange() : indexed_accessor_range(static_cast(nullptr), 0, 0) {} using indexed_accessor_range::indexed_accessor_range; static mlir::Region &dereference(mlir::Operation *Op, ptrdiff_t Index); }; /// Provides a range over the expression regions of an operation by utilizing /// the index-based interface of ExpressionRegionOpInterface. struct ExpressionRegionRange : llvm::indexed_accessor_range { ExpressionRegionRange() : indexed_accessor_range(static_cast(nullptr), 0, 0) {} using indexed_accessor_range::indexed_accessor_range; static mlir::Region &dereference(mlir::Operation *Op, ptrdiff_t Index); }; } // namespace clift // Prevent reordering: #include "revng/Clift/CliftOpInterfacesBasic.h.inc" // Prevent reordering: #include "revng/Clift/CliftOpInterfacesLabel.h.inc" // Prevent reordering: #include "revng/Clift/CliftOpInterfacesJump.h.inc" // Prevent reordering: #include "revng/Clift/CliftOpInterfacesControlFlow.h.inc" // Prevent reordering: #include "revng/Clift/CliftOpInterfacesExpr.h.inc" namespace clift { inline mlir::Region &StatementRegionRange::dereference(mlir::Operation *Op, ptrdiff_t Index) { auto Regions = mlir::cast(Op); revng_assert(Index >= 0); revng_assert(Index <= Regions.getStatementRegionCount()); return Regions.getStatementRegion(static_cast(Index)); } inline mlir::Region &ExpressionRegionRange::dereference(mlir::Operation *Op, ptrdiff_t Index) { auto Regions = mlir::cast(Op); revng_assert(Index >= 0); revng_assert(Index <= Regions.getExpressionRegionCount()); return Regions.getExpressionRegion(static_cast(Index)); } bool isLvalueExpression(mlir::Value Value); } // namespace clift