// // This file is distributed under the MIT License. See LICENSE.md for details. // #include "revng/Clift/ModuleVisitor.h" #include "revng/CliftEmitC/CSemantics.h" using namespace clift; namespace { static clift::PointerType getPointerOperationType(mlir::Operation *Op) { if (mlir::isa(Op)) return clift::unwrapped_cast(Op->getResult(0).getType()); if (mlir::isa(Op)) return clift::unwrapped_cast(Op->getOperand(0).getType()); if (auto A = mlir::dyn_cast(Op); A and A.isIndirect()) return clift::unwrapped_cast(A.getValue().getType()); if (auto C = mlir::dyn_cast(Op)) return clift::unwrapped_cast(C.getResult().getType()); if (auto C = mlir::dyn_cast(Op)) { if (auto T = clift::unwrapped_dyn_cast(C.getFunction() .getType())) return T; } return {}; } class CVerifier : public ModuleVisitor { std::optional DataModel; public: mlir::LogicalResult visitNestedOp(mlir::Operation *Op) { if (auto T = getPointerOperationType(Op)) { if (T.getPointerSize() != DataModel->PointerSize) return getCurrentOp()->emitOpError() << "Pointer operation is not " "representable in the target " "implementation."; } if (mlir::isa(Op)) { if (isPotentiallyPromotingType(Op->getResult(0).getType())) return Op->emitOpError() << " is not representable in the target" << " implementation."; } if (isPromotingOp(Op)) { if (isPotentiallyPromotingType(Op->getResult(0).getType())) return Op->emitOpError() << " causes integer promotion in the target" " implementation."; } if (isBooleanOp(Op)) { if (not isCanonicalBooleanType(Op->getResult(0).getType())) return Op->emitOpError() << " - not yielding the canonical boolean type" << " - is not representable in the target" << " implementation."; } return mlir::success(); } mlir::LogicalResult visitModuleOp(mlir::ModuleOp Op) { DataModel = getDataModel(Op); return mlir::success(); } private: static bool isPromotingOp(mlir::Operation *Op) { return mlir::isa(Op); } static bool isBooleanOp(mlir::Operation *Op) { return mlir::isa(Op); } bool isPotentiallyPromotingType(mlir::Type Type) { if (auto IntType = clift::unwrapped_dyn_cast(Type)) return IntType.getSize() < DataModel->getIntSize(); return false; } bool isCanonicalBooleanType(mlir::Type Type) { if (auto IntType = clift::unwrapped_dyn_cast(Type)) return IntType.getSize() == DataModel->getIntSize(); return false; } }; } // namespace mlir::LogicalResult verifyCSemantics(mlir::ModuleOp Module) { return CVerifier::visit(Module); }