14#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
15#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
16#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
17#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
18#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
19#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
20#include "mlir/Dialect/ControlFlow/IR/ControlFlow.h"
21#include "mlir/Dialect/Func/IR/FuncOps.h"
22#include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
23#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
24#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
25#include "mlir/Dialect/SCF/IR/SCF.h"
26#include "mlir/Dialect/SMT/IR/SMTOps.h"
27#include "mlir/IR/BuiltinDialect.h"
28#include "mlir/Interfaces/FunctionInterfaces.h"
29#include "mlir/Pass/Pass.h"
30#include "mlir/Transforms/DialectConversion.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/SmallPtrSet.h"
33#include "llvm/ADT/StringMap.h"
34#include "llvm/ADT/TypeSwitch.h"
35#include "llvm/Support/Debug.h"
37#define DEBUG_TYPE "lower-smt-to-z3-llvm"
40#define GEN_PASS_DEF_LOWERSMTTOZ3LLVM
41#include "circt/Conversion/Passes.h.inc"
54 OpBuilder::InsertionGuard guard(builder);
55 builder.setInsertionPointToStart(module.getBody());
62 Location loc =
module.getLoc();
63 auto ptrTy = LLVM::LLVMPointerType::get(builder.getContext());
65 auto createGlobal = [&](StringRef namePrefix) {
66 auto global = LLVM::GlobalOp::create(
67 builder, loc, ptrTy,
false, LLVM::Linkage::Internal,
69 OpBuilder::InsertionGuard g(builder);
70 builder.createBlock(&global.getInitializer());
71 Value res = LLVM::ZeroOp::create(builder, loc, ptrTy);
72 LLVM::ReturnOp::create(builder, loc, res);
76 auto ctxGlobal = createGlobal(
"ctx");
77 auto solverGlobal = createGlobal(
"solver");
83 mlir::LLVM::GlobalOp solver,
84 mlir::LLVM::GlobalOp ctx)
85 : solver(solver), ctx(ctx), names(names) {}
88 mlir::LLVM::GlobalOp solver,
89 mlir::LLVM::GlobalOp ctx)
90 : solver(solver), ctx(ctx) {
102template <
typename OpTy>
105 SMTLoweringPattern(
const TypeConverter &typeConverter, MLIRContext *
context,
107 const LowerSMTToZ3LLVMOptions &options)
112 Value buildGlobalPtrToGlobal(OpBuilder &builder, Location loc,
113 LLVM::GlobalOp global,
114 DenseMap<Block *, Value> &cache)
const {
115 Block *block = builder.getBlock();
116 if (
auto iter = cache.find(block); iter != cache.end())
117 return iter->getSecond();
119 OpBuilder::InsertionGuard g(builder);
120 builder.setInsertionPointToStart(block);
121 Value globalAddr = LLVM::AddressOfOp::create(builder, loc, global);
122 return cache[block] = LLVM::LoadOp::create(
123 builder, loc, LLVM::LLVMPointerType::get(builder.getContext()),
133 Value buildContextPtr(OpBuilder &builder, Location loc)
const {
134 return buildGlobalPtrToGlobal(builder, loc, globals.ctx, globals.ctxCache);
142 Value buildSolverPtr(OpBuilder &builder, Location loc)
const {
143 return buildGlobalPtrToGlobal(builder, loc, globals.solver,
144 globals.solverCache);
150 LLVM::CallOp buildCall(OpBuilder &builder, Location loc, StringRef name,
151 LLVM::LLVMFunctionType funcType,
152 ValueRange args)
const {
153 auto &funcOp = globals.funcMap[builder.getStringAttr(name)];
155 OpBuilder::InsertionGuard guard(builder);
157 builder.getBlock()->getParent()->getParentOfType<ModuleOp>();
158 builder.setInsertionPointToEnd(module.getBody());
159 auto funcOpResult = LLVM::lookupOrCreateFn(
160 builder, module, name, funcType.getParams(), funcType.getReturnType(),
161 funcType.getVarArg());
162 assert(succeeded(funcOpResult) &&
"expected to lookup or create printf");
163 funcOp = funcOpResult.value();
165 return LLVM::CallOp::create(builder, loc, funcOp, args);
172 Value buildString(OpBuilder &builder, Location loc, StringRef str)
const {
173 auto &global = globals.stringCache[builder.getStringAttr(str)];
175 OpBuilder::InsertionGuard guard(builder);
177 builder.getBlock()->getParent()->getParentOfType<ModuleOp>();
178 builder.setInsertionPointToEnd(module.getBody());
180 LLVM::LLVMArrayType::get(builder.getI8Type(), str.size() + 1);
181 auto strAttr = builder.getStringAttr(str.str() +
'\00');
182 global = LLVM::GlobalOp::create(
183 builder, loc, arrayTy,
true, LLVM::Linkage::Internal,
184 globals.names.newName(
"str"), strAttr);
186 return LLVM::AddressOfOp::create(builder, loc, global);
191 LLVM::CallOp buildAPICallWithContext(OpBuilder &builder, Location loc,
192 StringRef name, Type returnType,
193 ValueRange args = {})
const {
194 auto ctx = buildContextPtr(builder, loc);
195 SmallVector<Value> arguments;
196 arguments.emplace_back(ctx);
197 arguments.append(SmallVector<Value>(args));
200 LLVM::LLVMFunctionType::get(
201 returnType, SmallVector<Type>(ValueRange(arguments).getTypes())),
208 Value buildPtrAPICall(OpBuilder &builder, Location loc, StringRef name,
209 ValueRange args = {})
const {
210 return buildAPICallWithContext(
212 LLVM::LLVMPointerType::get(builder.getContext()), args)
217 Value buildSort(OpBuilder &builder, Location loc, Type type)
const {
220 return TypeSwitch<Type, Value>(type)
221 .Case([&](smt::IntType ty) {
222 return buildPtrAPICall(builder, loc,
"Z3_mk_int_sort");
224 .Case([&](smt::BitVectorType ty) {
225 Value bitwidth = LLVM::ConstantOp::create(
226 builder, loc, builder.getI32Type(), ty.getWidth());
227 return buildPtrAPICall(builder, loc,
"Z3_mk_bv_sort", {bitwidth});
229 .Case([&](smt::BoolType ty) {
230 return buildPtrAPICall(builder, loc,
"Z3_mk_bool_sort");
232 .Case([&](smt::SortType ty) {
233 Value str = buildString(builder, loc, ty.getIdentifier());
235 buildPtrAPICall(builder, loc,
"Z3_mk_string_symbol", {str});
236 return buildPtrAPICall(builder, loc,
"Z3_mk_uninterpreted_sort",
239 .Case([&](smt::ArrayType ty) {
240 return buildPtrAPICall(builder, loc,
"Z3_mk_array_sort",
241 {buildSort(builder, loc, ty.getDomainType()),
242 buildSort(builder, loc, ty.getRangeType())});
247 const LowerSMTToZ3LLVMOptions &options;
264struct DeclareFunOpLowering :
public SMTLoweringPattern<DeclareFunOp> {
265 using SMTLoweringPattern::SMTLoweringPattern;
268 matchAndRewrite(DeclareFunOp op, OpAdaptor adaptor,
269 ConversionPatternRewriter &rewriter)
const final {
270 Location loc = op.getLoc();
274 if (adaptor.getNamePrefix())
275 prefix = buildString(rewriter, loc, *adaptor.getNamePrefix());
277 prefix = LLVM::ZeroOp::create(rewriter, loc,
278 LLVM::LLVMPointerType::get(getContext()));
281 if (!isa<SMTFuncType>(op.getType())) {
282 Value sort = buildSort(rewriter, loc, op.getType());
284 buildPtrAPICall(rewriter, loc,
"Z3_mk_fresh_const", {prefix, sort});
285 rewriter.replaceOp(op, constDecl);
290 Type llvmPtrTy = LLVM::LLVMPointerType::get(getContext());
291 auto funcType = cast<SMTFuncType>(op.getResult().getType());
292 Value rangeSort = buildSort(rewriter, loc, funcType.getRangeType());
295 LLVM::LLVMArrayType::get(llvmPtrTy, funcType.getDomainTypes().size());
297 Value domain = LLVM::UndefOp::create(rewriter, loc, arrTy);
298 for (
auto [i, ty] :
llvm::enumerate(funcType.getDomainTypes())) {
299 Value sort = buildSort(rewriter, loc, ty);
300 domain = LLVM::InsertValueOp::create(rewriter, loc, domain, sort, i);
304 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
305 Value domainStorage =
306 LLVM::AllocaOp::create(rewriter, loc, llvmPtrTy, arrTy, one);
307 LLVM::StoreOp::create(rewriter, loc, domain, domainStorage);
309 Value domainSize = LLVM::ConstantOp::create(
310 rewriter, loc, rewriter.getI32Type(), funcType.getDomainTypes().size());
312 buildPtrAPICall(rewriter, loc,
"Z3_mk_fresh_func_decl",
313 {prefix, domainSize, domainStorage, rangeSort});
315 rewriter.replaceOp(op, decl);
325struct ApplyFuncOpLowering :
public SMTLoweringPattern<ApplyFuncOp> {
326 using SMTLoweringPattern::SMTLoweringPattern;
329 matchAndRewrite(ApplyFuncOp op, OpAdaptor adaptor,
330 ConversionPatternRewriter &rewriter)
const final {
331 Location loc = op.getLoc();
332 Type llvmPtrTy = LLVM::LLVMPointerType::get(getContext());
333 Type arrTy = LLVM::LLVMArrayType::get(llvmPtrTy, adaptor.getArgs().size());
336 Value domain = LLVM::UndefOp::create(rewriter, loc, arrTy);
337 for (
auto [i, arg] :
llvm::enumerate(adaptor.getArgs()))
338 domain = LLVM::InsertValueOp::create(rewriter, loc, domain, arg, i);
342 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
343 Value domainStorage =
344 LLVM::AllocaOp::create(rewriter, loc, llvmPtrTy, arrTy, one);
345 LLVM::StoreOp::create(rewriter, loc, domain, domainStorage);
349 Value domainSize = LLVM::ConstantOp::create(
350 rewriter, loc, rewriter.getI32Type(), adaptor.getArgs().size());
352 buildPtrAPICall(rewriter, loc,
"Z3_mk_app",
353 {adaptor.getFunc(), domainSize, domainStorage});
354 rewriter.replaceOp(op, returnVal);
372struct BVConstantOpLowering :
public SMTLoweringPattern<smt::BVConstantOp> {
373 using SMTLoweringPattern::SMTLoweringPattern;
376 matchAndRewrite(smt::BVConstantOp op, OpAdaptor adaptor,
377 ConversionPatternRewriter &rewriter)
const final {
378 Location loc = op.getLoc();
379 unsigned width = op.getType().getWidth();
380 auto bvSort = buildSort(rewriter, loc, op.getResult().getType());
381 APInt val = adaptor.getValue().getValue();
384 Value bvConst = LLVM::ConstantOp::create(
385 rewriter, loc, rewriter.getI64Type(), val.getZExtValue());
386 Value res = buildPtrAPICall(rewriter, loc,
"Z3_mk_unsigned_int64",
388 rewriter.replaceOp(op, res);
393 llvm::raw_string_ostream stream(str);
395 Value bvString = buildString(rewriter, loc, str);
397 buildPtrAPICall(rewriter, loc,
"Z3_mk_numeral", {bvString, bvSort});
399 rewriter.replaceOp(op, bvNumeral);
409template <
typename SourceTy>
410struct VariadicSMTPattern :
public SMTLoweringPattern<SourceTy> {
411 using OpAdaptor =
typename SMTLoweringPattern<SourceTy>::OpAdaptor;
413 VariadicSMTPattern(
const TypeConverter &typeConverter, MLIRContext *
context,
415 const LowerSMTToZ3LLVMOptions &options,
416 StringRef apiFuncName,
unsigned minNumArgs)
417 : SMTLoweringPattern<SourceTy>(typeConverter,
context, globals, options),
418 apiFuncName(apiFuncName), minNumArgs(minNumArgs) {}
421 matchAndRewrite(SourceTy op, OpAdaptor adaptor,
422 ConversionPatternRewriter &rewriter)
const final {
423 if (adaptor.getOperands().size() < minNumArgs)
426 Location loc = op.getLoc();
427 Value numOperands = LLVM::ConstantOp::create(
428 rewriter, loc, rewriter.getI32Type(), op->getNumOperands());
430 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
431 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
432 Type arrTy = LLVM::LLVMArrayType::get(ptrTy, op->getNumOperands());
434 LLVM::AllocaOp::create(rewriter, loc, ptrTy, arrTy, constOne);
435 Value array = LLVM::UndefOp::create(rewriter, loc, arrTy);
437 for (
auto [i, operand] :
llvm::enumerate(adaptor.getOperands()))
438 array = LLVM::InsertValueOp::create(rewriter, loc, array, operand,
439 ArrayRef<int64_t>{(int64_t)i});
441 LLVM::StoreOp::create(rewriter, loc, array, storage);
443 rewriter.replaceOp(op,
444 SMTLoweringPattern<SourceTy>::buildPtrAPICall(
445 rewriter, loc, apiFuncName, {numOperands, storage}));
450 StringRef apiFuncName;
456template <
typename SourceTy>
457struct OneToOneSMTPattern :
public SMTLoweringPattern<SourceTy> {
458 using OpAdaptor =
typename SMTLoweringPattern<SourceTy>::OpAdaptor;
460 OneToOneSMTPattern(
const TypeConverter &typeConverter, MLIRContext *
context,
462 const LowerSMTToZ3LLVMOptions &options,
463 StringRef apiFuncName,
unsigned numOperands)
464 : SMTLoweringPattern<SourceTy>(typeConverter,
context, globals, options),
465 apiFuncName(apiFuncName), numOperands(numOperands) {}
468 matchAndRewrite(SourceTy op, OpAdaptor adaptor,
469 ConversionPatternRewriter &rewriter)
const final {
470 if (adaptor.getOperands().size() != numOperands)
474 op, SMTLoweringPattern<SourceTy>::buildPtrAPICall(
475 rewriter, op.getLoc(), apiFuncName, adaptor.getOperands()));
480 StringRef apiFuncName;
481 unsigned numOperands;
486template <
typename SourceTy>
487class LowerChainableSMTPattern :
public SMTLoweringPattern<SourceTy> {
488 using SMTLoweringPattern<SourceTy>::SMTLoweringPattern;
489 using OpAdaptor =
typename SMTLoweringPattern<SourceTy>::OpAdaptor;
492 matchAndRewrite(SourceTy op, OpAdaptor adaptor,
493 ConversionPatternRewriter &rewriter)
const final {
494 if (adaptor.getOperands().size() <= 2)
497 Location loc = op.getLoc();
498 SmallVector<Value> elements;
499 for (
int i = 1, e = adaptor.getOperands().size(); i < e; ++i) {
500 Value val = SourceTy::create(
501 rewriter, loc, op->getResultTypes(),
502 ValueRange{adaptor.getOperands()[i - 1], adaptor.getOperands()[i]});
503 elements.push_back(val);
505 rewriter.replaceOpWithNewOp<smt::AndOp>(op, elements);
512template <
typename SourceTy>
513class LowerLeftAssocSMTPattern :
public SMTLoweringPattern<SourceTy> {
514 using SMTLoweringPattern<SourceTy>::SMTLoweringPattern;
515 using OpAdaptor =
typename SMTLoweringPattern<SourceTy>::OpAdaptor;
518 matchAndRewrite(SourceTy op, OpAdaptor adaptor,
519 ConversionPatternRewriter &rewriter)
const final {
520 if (adaptor.getOperands().size() <= 2)
521 return rewriter.notifyMatchFailure(op,
"must have at least two operands");
523 Value runner = adaptor.getOperands()[0];
524 for (Value val : adaptor.getOperands().drop_front())
525 runner = SourceTy::create(rewriter, op.
getLoc(), op->getResultTypes(),
526 ValueRange{runner, val});
528 rewriter.replaceOp(op, runner);
563struct SolverOpLowering :
public SMTLoweringPattern<SolverOp> {
564 using SMTLoweringPattern::SMTLoweringPattern;
567 matchAndRewrite(SolverOp op, OpAdaptor adaptor,
568 ConversionPatternRewriter &rewriter)
const final {
569 Location loc = op.getLoc();
570 auto ptrTy = LLVM::LLVMPointerType::get(getContext());
571 auto voidTy = LLVM::LLVMVoidType::get(getContext());
572 auto ptrToPtrFunc = LLVM::LLVMFunctionType::get(ptrTy, ptrTy);
573 auto ptrPtrToPtrFunc = LLVM::LLVMFunctionType::get(ptrTy, {ptrTy, ptrTy});
574 auto ptrToVoidFunc = LLVM::LLVMFunctionType::get(voidTy, ptrTy);
575 auto ptrPtrToVoidFunc = LLVM::LLVMFunctionType::get(voidTy, {ptrTy, ptrTy});
578 Value config = buildCall(rewriter, loc,
"Z3_mk_config",
579 LLVM::LLVMFunctionType::get(ptrTy, {}), {})
585 Value paramKey = buildString(rewriter, loc,
"proof");
586 Value paramValue = buildString(rewriter, loc,
"true");
587 buildCall(rewriter, loc,
"Z3_set_param_value",
588 LLVM::LLVMFunctionType::get(voidTy, {ptrTy, ptrTy, ptrTy}),
589 {config, paramKey, paramValue});
593 std::optional<StringRef> logic = std::nullopt;
594 auto setLogicOps = op.getBodyRegion().getOps<smt::SetLogicOp>();
595 if (!setLogicOps.empty()) {
598 auto setLogicOp = *setLogicOps.begin();
599 logic = setLogicOp.getLogic();
600 rewriter.eraseOp(setLogicOp);
604 Value ctx = buildCall(rewriter, loc,
"Z3_mk_context", ptrToPtrFunc, config)
607 LLVM::AddressOfOp::create(rewriter, loc, globals.ctx).getResult();
608 LLVM::StoreOp::create(rewriter, loc, ctx, ctxAddr);
611 buildCall(rewriter, loc,
"Z3_del_config", ptrToVoidFunc, {config});
617 auto logicStr = buildString(rewriter, loc, logic.value());
618 solver = buildCall(rewriter, loc,
"Z3_mk_solver_for_logic",
619 ptrPtrToPtrFunc, {ctx, logicStr})
622 solver = buildCall(rewriter, loc,
"Z3_mk_solver", ptrToPtrFunc, ctx)
625 buildCall(rewriter, loc,
"Z3_solver_inc_ref", ptrPtrToVoidFunc,
628 LLVM::AddressOfOp::create(rewriter, loc, globals.solver).getResult();
629 LLVM::StoreOp::create(rewriter, loc, solver, solverAddr);
637 SmallVector<Type> convertedTypes;
639 typeConverter->convertTypes(op->getResultTypes(), convertedTypes)))
645 bool containsBMCTrace =
false;
646 op.getBodyRegion().walk(
647 [&](verif::BMCTraceOp) { containsBMCTrace =
true; });
649 SmallVector<Type> inputTypes(adaptor.getInputs().getTypes());
650 SmallVector<Value> callOperands(adaptor.getInputs());
651 if (containsBMCTrace) {
652 auto parentFunction = op->getParentOfType<FunctionOpInterface>();
653 if (!parentFunction || parentFunction.getNumArguments() == 0)
654 return rewriter.notifyMatchFailure(op,
"missing BMC trace context");
656 parentFunction.getArgument(parentFunction.getNumArguments() - 1);
657 if (!isa<LLVM::LLVMPointerType>(traceContext.getType()))
658 return rewriter.notifyMatchFailure(op,
659 "invalid BMC trace context type");
660 inputTypes.push_back(traceContext.getType());
661 callOperands.push_back(traceContext);
662 op.getBodyRegion().addArgument(traceContext.getType(), loc);
667 OpBuilder::InsertionGuard guard(rewriter);
668 auto module = op->getParentOfType<ModuleOp>();
669 rewriter.setInsertionPointToEnd(module.getBody());
671 funcOp = func::FuncOp::create(
672 rewriter, loc, globals.names.newName(
"solver"),
673 rewriter.getFunctionType(inputTypes, convertedTypes));
674 rewriter.inlineRegionBefore(op.getBodyRegion(), funcOp.getBody(),
679 func::CallOp::create(rewriter, loc, funcOp, callOperands)->getResults();
689 buildCall(rewriter, loc,
"Z3_solver_dec_ref", ptrPtrToVoidFunc,
691 buildCall(rewriter, loc,
"Z3_del_context", ptrToVoidFunc, ctx);
693 rewriter.replaceOp(op, results);
702struct AssertOpLowering :
public SMTLoweringPattern<AssertOp> {
703 using SMTLoweringPattern::SMTLoweringPattern;
706 matchAndRewrite(AssertOp op, OpAdaptor adaptor,
707 ConversionPatternRewriter &rewriter)
const final {
708 Location loc = op.getLoc();
709 buildAPICallWithContext(
710 rewriter, loc,
"Z3_solver_assert",
711 LLVM::LLVMVoidType::get(getContext()),
712 {buildSolverPtr(rewriter, loc), adaptor.getInput()});
714 rewriter.eraseOp(op);
723struct ResetOpLowering :
public SMTLoweringPattern<ResetOp> {
724 using SMTLoweringPattern::SMTLoweringPattern;
727 matchAndRewrite(ResetOp op, OpAdaptor adaptor,
728 ConversionPatternRewriter &rewriter)
const final {
729 Location loc = op.getLoc();
730 buildAPICallWithContext(rewriter, loc,
"Z3_solver_reset",
731 LLVM::LLVMVoidType::get(getContext()),
732 {buildSolverPtr(rewriter, loc)});
734 rewriter.eraseOp(op);
743struct PushOpLowering :
public SMTLoweringPattern<PushOp> {
744 using SMTLoweringPattern::SMTLoweringPattern;
746 matchAndRewrite(PushOp op, OpAdaptor adaptor,
747 ConversionPatternRewriter &rewriter)
const final {
748 Location loc = op.getLoc();
752 for (uint32_t i = 0; i < op.getCount(); i++)
753 buildAPICallWithContext(rewriter, loc,
"Z3_solver_push",
754 LLVM::LLVMVoidType::get(getContext()),
755 {buildSolverPtr(rewriter, loc)});
756 rewriter.eraseOp(op);
765struct PopOpLowering :
public SMTLoweringPattern<PopOp> {
766 using SMTLoweringPattern::SMTLoweringPattern;
768 matchAndRewrite(PopOp op, OpAdaptor adaptor,
769 ConversionPatternRewriter &rewriter)
const final {
770 Location loc = op.getLoc();
771 Value constVal = LLVM::ConstantOp::create(
772 rewriter, loc, rewriter.getI32Type(), op.getCount());
773 buildAPICallWithContext(rewriter, loc,
"Z3_solver_pop",
774 LLVM::LLVMVoidType::get(getContext()),
775 {buildSolverPtr(rewriter, loc), constVal});
776 rewriter.eraseOp(op);
786struct YieldOpLowering :
public SMTLoweringPattern<YieldOp> {
787 using SMTLoweringPattern::SMTLoweringPattern;
790 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
791 ConversionPatternRewriter &rewriter)
const final {
792 if (op->getParentOfType<func::FuncOp>()) {
793 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getValues());
796 if (op->getParentOfType<LLVM::LLVMFuncOp>()) {
797 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(op, adaptor.getValues());
800 if (isa_and_nonnull<scf::SCFDialect>(op->getParentOp()->getDialect())) {
801 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getValues());
819struct CheckOpLowering :
public SMTLoweringPattern<CheckOp> {
820 using SMTLoweringPattern::SMTLoweringPattern;
823 matchAndRewrite(CheckOp op, OpAdaptor adaptor,
824 ConversionPatternRewriter &rewriter)
const final {
825 Location loc = op.getLoc();
826 auto ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
827 auto printfType = LLVM::LLVMFunctionType::get(
828 LLVM::LLVMVoidType::get(rewriter.getContext()), {ptrTy},
true);
830 auto getHeaderString = [](
const std::string &title) {
831 unsigned titleSize = title.size() + 2;
832 return std::string((80 - titleSize) / 2,
'-') +
" " + title +
" " +
833 std::string((80 - titleSize + 1) / 2,
'-') +
"\n%s\n" +
834 std::string(80,
'-') +
"\n";
838 Value solver = buildSolverPtr(rewriter, loc);
843 auto solverStringPtr =
844 buildPtrAPICall(rewriter, loc,
"Z3_solver_to_string", {solver});
845 auto solverFormatString =
846 buildString(rewriter, loc, getHeaderString(
"Solver"));
847 buildCall(rewriter, op.getLoc(),
"printf", printfType,
848 {solverFormatString, solverStringPtr});
852 SmallVector<Type> resultTypes;
853 if (failed(typeConverter->convertTypes(op->getResultTypes(), resultTypes)))
858 buildAPICallWithContext(rewriter, loc,
"Z3_solver_check",
859 rewriter.getI32Type(), {solver})
862 LLVM::ConstantOp::create(rewriter, loc, checkResult.getType(), 1);
863 Value isSat = LLVM::ICmpOp::create(rewriter, loc, LLVM::ICmpPredicate::eq,
864 checkResult, constOne);
867 auto satIfOp = scf::IfOp::create(rewriter, loc, resultTypes, isSat);
868 rewriter.inlineRegionBefore(op.getSatRegion(), satIfOp.getThenRegion(),
869 satIfOp.getThenRegion().end());
874 rewriter.createBlock(&satIfOp.getElseRegion());
876 LLVM::ConstantOp::create(rewriter, loc, checkResult.getType(), -1);
877 Value isUnsat = LLVM::ICmpOp::create(rewriter, loc, LLVM::ICmpPredicate::eq,
878 checkResult, constNegOne);
879 auto unsatIfOp = scf::IfOp::create(rewriter, loc, resultTypes, isUnsat);
880 scf::YieldOp::create(rewriter, loc, unsatIfOp->getResults());
882 rewriter.inlineRegionBefore(op.getUnsatRegion(), unsatIfOp.getThenRegion(),
883 unsatIfOp.getThenRegion().end());
884 rewriter.inlineRegionBefore(op.getUnknownRegion(),
885 unsatIfOp.getElseRegion(),
886 unsatIfOp.getElseRegion().end());
888 rewriter.replaceOp(op, satIfOp->getResults());
893 rewriter.setInsertionPointToStart(unsatIfOp.thenBlock());
894 auto proof = buildPtrAPICall(rewriter, op.getLoc(),
"Z3_solver_get_proof",
897 buildPtrAPICall(rewriter, op.getLoc(),
"Z3_ast_to_string", {proof});
899 buildString(rewriter, op.getLoc(), getHeaderString(
"Proof"));
900 buildCall(rewriter, op.getLoc(),
"printf", printfType,
901 {formatString, stringPtr});
905 rewriter.setInsertionPointToStart(satIfOp.thenBlock());
906 auto model = buildPtrAPICall(rewriter, op.getLoc(),
"Z3_solver_get_model",
908 auto modelStringPtr =
909 buildPtrAPICall(rewriter, op.getLoc(),
"Z3_model_to_string", {model});
910 auto modelFormatString =
911 buildString(rewriter, op.getLoc(), getHeaderString(
"Model"));
912 buildCall(rewriter, op.getLoc(),
"printf", printfType,
913 {modelFormatString, modelStringPtr});
941template <
typename QuantifierOp>
942struct QuantifierLowering :
public SMTLoweringPattern<QuantifierOp> {
943 using SMTLoweringPattern<QuantifierOp>::SMTLoweringPattern;
944 using SMTLoweringPattern<QuantifierOp>::typeConverter;
945 using SMTLoweringPattern<QuantifierOp>::buildPtrAPICall;
946 using OpAdaptor =
typename QuantifierOp::Adaptor;
948 Value createStorageForValueList(ValueRange values, Location loc,
949 ConversionPatternRewriter &rewriter)
const {
950 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
951 Type arrTy = LLVM::LLVMArrayType::get(ptrTy, values.size());
953 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
955 LLVM::AllocaOp::create(rewriter, loc, ptrTy, arrTy, constOne);
956 Value array = LLVM::UndefOp::create(rewriter, loc, arrTy);
958 for (
auto [i, val] :
llvm::enumerate(values))
959 array = LLVM::InsertValueOp::create(rewriter, loc, array, val,
960 ArrayRef<int64_t>(i));
962 LLVM::StoreOp::create(rewriter, loc, array, storage);
968 matchAndRewrite(QuantifierOp op, OpAdaptor adaptor,
969 ConversionPatternRewriter &rewriter)
const final {
970 Location loc = op.getLoc();
971 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
977 if (adaptor.getNoPattern())
978 return rewriter.notifyMatchFailure(
979 op,
"no-pattern attribute not yet supported!");
981 rewriter.setInsertionPoint(op);
984 Value weight = LLVM::ConstantOp::create(
985 rewriter, loc, rewriter.getI32Type(), adaptor.getWeight());
988 unsigned numDecls = op.getBody().getNumArguments();
989 Value numDeclsVal = LLVM::ConstantOp::create(
990 rewriter, loc, rewriter.getI32Type(), numDecls);
997 SmallVector<Value> repl;
998 for (
auto [i, arg] :
llvm::enumerate(op.getBody().getArguments())) {
1000 if (adaptor.getBoundVarNames().has_value())
1001 newArg = smt::DeclareFunOp::create(
1002 rewriter, loc, arg.getType(),
1003 cast<StringAttr>((*adaptor.getBoundVarNames())[i]));
1005 newArg = smt::DeclareFunOp::create(rewriter, loc, arg.getType());
1006 repl.push_back(typeConverter->materializeTargetConversion(
1007 rewriter, loc, typeConverter->convertType(arg.getType()), newArg));
1010 Value boundStorage = createStorageForValueList(repl, loc, rewriter);
1013 auto yieldOp = cast<smt::YieldOp>(op.getBody().front().getTerminator());
1014 Value bodyExp = yieldOp.getValues()[0];
1015 rewriter.setInsertionPointAfterValue(bodyExp);
1016 bodyExp = typeConverter->materializeTargetConversion(
1017 rewriter, loc, typeConverter->convertType(bodyExp.getType()), bodyExp);
1018 rewriter.eraseOp(yieldOp);
1020 rewriter.inlineBlockBefore(&op.getBody().front(), op, repl);
1021 rewriter.setInsertionPoint(op);
1024 unsigned numPatterns = adaptor.getPatterns().size();
1025 Value numPatternsVal = LLVM::ConstantOp::create(
1026 rewriter, loc, rewriter.getI32Type(), numPatterns);
1028 Value patternStorage;
1029 if (numPatterns > 0) {
1031 for (Region *patternRegion : adaptor.getPatterns()) {
1033 cast<smt::YieldOp>(patternRegion->front().getTerminator());
1034 auto patternTerms = yieldOp.getOperands();
1036 rewriter.setInsertionPoint(yieldOp);
1037 SmallVector<Value> patternList;
1038 for (
auto val : patternTerms)
1039 patternList.push_back(typeConverter->materializeTargetConversion(
1040 rewriter, loc, typeConverter->
convertType(val.getType()), val));
1042 rewriter.eraseOp(yieldOp);
1043 rewriter.inlineBlockBefore(&patternRegion->front(), op, repl);
1045 rewriter.setInsertionPoint(op);
1046 Value numTerms = LLVM::ConstantOp::create(
1047 rewriter, loc, rewriter.getI32Type(), patternTerms.size());
1048 Value patternTermStorage =
1049 createStorageForValueList(patternList, loc, rewriter);
1050 Value
pattern = buildPtrAPICall(rewriter, loc,
"Z3_mk_pattern",
1051 {numTerms, patternTermStorage});
1055 patternStorage = createStorageForValueList(
patterns, loc, rewriter);
1059 patternStorage = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
1062 StringRef apiCallName =
"Z3_mk_forall_const";
1063 if (std::is_same_v<QuantifierOp, ExistsOp>)
1064 apiCallName =
"Z3_mk_exists_const";
1065 Value quantifierExp =
1066 buildPtrAPICall(rewriter, loc, apiCallName,
1067 {weight, numDeclsVal, boundStorage, numPatternsVal,
1068 patternStorage, bodyExp});
1070 rewriter.replaceOp(op, quantifierExp);
1079struct RepeatOpLowering :
public SMTLoweringPattern<RepeatOp> {
1080 using SMTLoweringPattern::SMTLoweringPattern;
1083 matchAndRewrite(RepeatOp op, OpAdaptor adaptor,
1084 ConversionPatternRewriter &rewriter)
const final {
1085 Value count = LLVM::ConstantOp::create(
1086 rewriter, op.getLoc(), rewriter.getI32Type(), op.getCount());
1087 rewriter.replaceOp(op,
1088 buildPtrAPICall(rewriter, op.getLoc(),
"Z3_mk_repeat",
1089 {count, adaptor.getInput()}));
1101struct ExtractOpLowering :
public SMTLoweringPattern<ExtractOp> {
1102 using SMTLoweringPattern::SMTLoweringPattern;
1105 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
1106 ConversionPatternRewriter &rewriter)
const final {
1107 Location loc = op.getLoc();
1108 Value low = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1109 adaptor.getLowBit());
1110 Value high = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1111 adaptor.getLowBit() +
1112 op.getType().getWidth() - 1);
1113 rewriter.replaceOp(op, buildPtrAPICall(rewriter, loc,
"Z3_mk_extract",
1114 {high, low, adaptor.getInput()}));
1123struct ArrayBroadcastOpLowering
1124 :
public SMTLoweringPattern<smt::ArrayBroadcastOp> {
1125 using SMTLoweringPattern::SMTLoweringPattern;
1128 matchAndRewrite(smt::ArrayBroadcastOp op, OpAdaptor adaptor,
1129 ConversionPatternRewriter &rewriter)
const final {
1130 auto domainSort = buildSort(
1131 rewriter, op.getLoc(),
1132 cast<smt::ArrayType>(op.getResult().getType()).getDomainType());
1134 rewriter.replaceOp(op, buildPtrAPICall(rewriter, op.getLoc(),
1135 "Z3_mk_const_array",
1136 {domainSort, adaptor.getValue()}));
1147struct BoolConstantOpLowering :
public SMTLoweringPattern<smt::BoolConstantOp> {
1148 using SMTLoweringPattern::SMTLoweringPattern;
1151 matchAndRewrite(smt::BoolConstantOp op, OpAdaptor adaptor,
1152 ConversionPatternRewriter &rewriter)
const final {
1154 op, buildPtrAPICall(rewriter, op.getLoc(),
1155 adaptor.getValue() ?
"Z3_mk_true" :
"Z3_mk_false"));
1171struct IntConstantOpLowering :
public SMTLoweringPattern<smt::IntConstantOp> {
1172 using SMTLoweringPattern::SMTLoweringPattern;
1175 matchAndRewrite(smt::IntConstantOp op, OpAdaptor adaptor,
1176 ConversionPatternRewriter &rewriter)
const final {
1177 Location loc = op.getLoc();
1178 Value type = buildPtrAPICall(rewriter, loc,
"Z3_mk_int_sort");
1179 if (adaptor.getValue().getBitWidth() <= 64) {
1180 Value val = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(),
1181 adaptor.getValue().getSExtValue());
1183 op, buildPtrAPICall(rewriter, loc,
"Z3_mk_int64", {val, type}));
1187 std::string numeralStr;
1188 llvm::raw_string_ostream stream(numeralStr);
1189 stream << adaptor.getValue().abs();
1191 Value numeral = buildString(rewriter, loc, numeralStr);
1193 buildPtrAPICall(rewriter, loc,
"Z3_mk_numeral", {numeral, type});
1195 if (adaptor.getValue().isNegative())
1197 buildPtrAPICall(rewriter, loc,
"Z3_mk_unary_minus", intNumeral);
1199 rewriter.replaceOp(op, intNumeral);
1209struct IntCmpOpLowering :
public SMTLoweringPattern<IntCmpOp> {
1210 using SMTLoweringPattern::SMTLoweringPattern;
1213 matchAndRewrite(IntCmpOp op, OpAdaptor adaptor,
1214 ConversionPatternRewriter &rewriter)
const final {
1217 buildPtrAPICall(rewriter, op.getLoc(),
1218 "Z3_mk_" + stringifyIntPredicate(op.getPred()).str(),
1219 {adaptor.getLhs(), adaptor.getRhs()}));
1228struct Int2BVOpLowering :
public SMTLoweringPattern<Int2BVOp> {
1229 using SMTLoweringPattern::SMTLoweringPattern;
1232 matchAndRewrite(Int2BVOp op, OpAdaptor adaptor,
1233 ConversionPatternRewriter &rewriter)
const final {
1235 LLVM::ConstantOp::create(rewriter, op->getLoc(), rewriter.getI32Type(),
1236 op.getResult().getType().getWidth());
1237 rewriter.replaceOp(op,
1238 buildPtrAPICall(rewriter, op.getLoc(),
"Z3_mk_int2bv",
1239 {widthConst, adaptor.getInput()}));
1248struct BV2IntOpLowering :
public SMTLoweringPattern<BV2IntOp> {
1249 using SMTLoweringPattern::SMTLoweringPattern;
1252 matchAndRewrite(BV2IntOp op, OpAdaptor adaptor,
1253 ConversionPatternRewriter &rewriter)
const final {
1256 Value isSignedConst = LLVM::ConstantOp::create(
1257 rewriter, op->getLoc(), rewriter.getI1Type(), op.getIsSigned());
1258 rewriter.replaceOp(op,
1259 buildPtrAPICall(rewriter, op.getLoc(),
"Z3_mk_bv2int",
1260 {adaptor.getInput(), isSignedConst}));
1271struct BVCmpOpLowering :
public SMTLoweringPattern<BVCmpOp> {
1272 using SMTLoweringPattern::SMTLoweringPattern;
1275 matchAndRewrite(BVCmpOp op, OpAdaptor adaptor,
1276 ConversionPatternRewriter &rewriter)
const final {
1278 op, buildPtrAPICall(rewriter, op.getLoc(),
1280 stringifyBVCmpPredicate(op.getPred()).str(),
1281 {adaptor.getLhs(), adaptor.getRhs()}));
1287struct IntAbsOpLowering :
public SMTLoweringPattern<IntAbsOp> {
1288 using SMTLoweringPattern::SMTLoweringPattern;
1291 matchAndRewrite(IntAbsOp op, OpAdaptor adaptor,
1292 ConversionPatternRewriter &rewriter)
const final {
1293 Location loc = op.getLoc();
1294 Value zero = IntConstantOp::create(
1295 rewriter, loc, rewriter.getIntegerAttr(rewriter.getI1Type(), 0));
1296 Value cmp = IntCmpOp::create(rewriter, loc, IntPredicate::lt,
1297 adaptor.getInput(), zero);
1298 Value neg = IntSubOp::create(rewriter, loc, zero, adaptor.getInput());
1299 rewriter.replaceOpWithNewOp<IteOp>(op, cmp, neg, adaptor.getInput());
1313struct BMCTraceLowering :
public SMTLoweringPattern<verif::BMCTraceOp> {
1314 using SMTLoweringPattern::SMTLoweringPattern;
1317 matchAndRewrite(verif::BMCTraceOp op, OpAdaptor adaptor,
1318 ConversionPatternRewriter &rewriter)
const final {
1319 auto bitVectorType = dyn_cast<smt::BitVectorType>(op.getValue().getType());
1320 if (!bitVectorType) {
1321 rewriter.eraseOp(op);
1325 Location loc = op.getLoc();
1326 Value name = buildString(rewriter, loc, op.getName());
1327 Value width = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1328 bitVectorType.getWidth());
1329 auto function = op->getParentOfType<FunctionOpInterface>();
1330 if (!function || function.getNumArguments() == 0)
1331 return rewriter.notifyMatchFailure(op,
"missing BMC trace context");
1332 Value traceContext = function.getArgument(function.getNumArguments() - 1);
1333 if (!isa<LLVM::LLVMPointerType>(traceContext.getType()))
1334 return rewriter.notifyMatchFailure(op,
"invalid BMC trace context type");
1335 auto voidType = LLVM::LLVMVoidType::get(rewriter.getContext());
1337 rewriter, loc,
"circt_bmc_record_trace",
1338 LLVM::LLVMFunctionType::get(voidType, {traceContext.getType(),
1339 adaptor.getStep().getType(),
1340 name.getType(), width.getType(),
1341 adaptor.getValue().getType()}),
1342 {traceContext, adaptor.getStep(), name, width, adaptor.getValue()});
1343 rewriter.eraseOp(op);
1350 using OpConversionPattern::OpConversionPattern;
1353 matchAndRewrite(debug::VariableOp op, OpAdaptor adaptor,
1354 ConversionPatternRewriter &rewriter)
const final {
1355 rewriter.eraseOp(op);
1362 using OpConversionPattern::OpConversionPattern;
1365 matchAndRewrite(debug::ScopeOp op, OpAdaptor adaptor,
1366 ConversionPatternRewriter &rewriter)
const final {
1368 if (llvm::any_of(op->getUsers(), [](Operation *user) {
1369 return !isa<debug::VariableOp>(user);
1372 rewriter.eraseOp(op);
1384struct LowerSMTToZ3LLVMPass
1385 :
public circt::impl::LowerSMTToZ3LLVMBase<LowerSMTToZ3LLVMPass> {
1387 void runOnOperation()
override;
1392 converter.addConversion([](smt::BoolType type) {
1393 return LLVM::LLVMPointerType::get(type.getContext());
1395 converter.addConversion([](smt::BitVectorType type) {
1396 return LLVM::LLVMPointerType::get(type.getContext());
1398 converter.addConversion([](smt::ArrayType type) {
1399 return LLVM::LLVMPointerType::get(type.getContext());
1401 converter.addConversion([](smt::IntType type) {
1402 return LLVM::LLVMPointerType::get(type.getContext());
1404 converter.addConversion([](smt::SMTFuncType type) {
1405 return LLVM::LLVMPointerType::get(type.getContext());
1407 converter.addConversion([](smt::SortType type) {
1408 return LLVM::LLVMPointerType::get(type.getContext());
1413 RewritePatternSet &
patterns, TypeConverter &converter,
1415#define ADD_VARIADIC_PATTERN(OP, APINAME, MIN_NUM_ARGS) \
1416 patterns.add<VariadicSMTPattern<OP>>( \
1417 converter, patterns.getContext(), \
1418 globals, options, APINAME, \
1421#define ADD_ONE_TO_ONE_PATTERN(OP, APINAME, NUM_ARGS) \
1422 patterns.add<OneToOneSMTPattern<OP>>( \
1423 converter, patterns.getContext(), \
1424 globals, options, APINAME, NUM_ARGS);
1477 patterns.add<LowerLeftAssocSMTPattern<XOrOp>>(
1478 converter,
patterns.getContext(), globals, options);
1578#undef ADD_VARIADIC_PATTERN
1579#undef ADD_ONE_TO_ONE_PATTERN
1596 patterns.add<LowerChainableSMTPattern<EqOp>>(converter,
patterns.getContext(),
1599 globals, options,
"Z3_mk_eq", 2);
1603 patterns.add<BVConstantOpLowering, DeclareFunOpLowering, AssertOpLowering,
1604 ResetOpLowering, PushOpLowering, PopOpLowering, CheckOpLowering,
1605 SolverOpLowering, ApplyFuncOpLowering, YieldOpLowering,
1606 RepeatOpLowering, ExtractOpLowering, BoolConstantOpLowering,
1607 IntConstantOpLowering, ArrayBroadcastOpLowering, BVCmpOpLowering,
1608 IntCmpOpLowering, IntAbsOpLowering, Int2BVOpLowering,
1609 BV2IntOpLowering, QuantifierLowering<ForallOp>,
1610 QuantifierLowering<ExistsOp>>(converter,
patterns.getContext(),
1614 patterns.add<DbgVariableLowering, DbgScopeLowering>(
patterns.getContext());
1617void LowerSMTToZ3LLVMPass::runOnOperation() {
1618 LowerSMTToZ3LLVMOptions options;
1619 options.debug =
debug;
1623 auto setLogicCheck = getOperation().walk([&](SolverOp solverOp)
1627 auto setLogicOps = solverOp.getBodyRegion().getOps<smt::SetLogicOp>();
1628 auto numSetLogicOps = std::distance(setLogicOps.begin(), setLogicOps.end());
1629 if (numSetLogicOps > 1) {
1630 return solverOp.emitError(
1631 "multiple set-logic operations found in one solver operation - Z3 "
1632 "only supports setting the logic once");
1634 if (numSetLogicOps == 1)
1636 for (
auto &blockOp : solverOp.getBodyRegion().getOps()) {
1637 if (isa<smt::SetLogicOp>(blockOp))
1639 if (!blockOp.hasTrait<OpTrait::ConstantLike>()) {
1640 return solverOp.emitError(
"set-logic operation must be the first "
1641 "non-constant operation in a solver "
1645 return WalkResult::advance();
1647 if (setLogicCheck.wasInterrupted())
1648 return signalPassFailure();
1650 llvm::StringMap<Operation *> traceNames;
1651 auto traceNameCheck =
1652 getOperation().walk([&](verif::BMCTraceOp traceOp) -> WalkResult {
1653 auto [it, inserted] =
1654 traceNames.try_emplace(traceOp.getName(), traceOp.getOperation());
1656 return WalkResult::advance();
1657 auto error = traceOp.emitError() <<
"duplicate BMC trace name '"
1658 << traceOp.getName() <<
"'";
1659 error.attachNote(it->second->getLoc())
1660 <<
"first BMC trace with this name is here";
1661 return WalkResult::interrupt();
1663 if (traceNameCheck.wasInterrupted())
1664 return signalPassFailure();
1669 llvm::SmallPtrSet<Operation *, 4> traceFunctions;
1670 getOperation().walk([&](verif::BMCTraceOp traceOp) {
1671 auto function = traceOp->getParentOfType<FunctionOpInterface>();
1673 traceFunctions.insert(function.getOperation());
1675 auto traceContextType = LLVM::LLVMPointerType::get(&getContext());
1676 for (Operation *operation : traceFunctions) {
1677 auto function = cast<FunctionOpInterface>(operation);
1678 if (failed(function.insertArgument(function.getNumArguments(),
1679 traceContextType, {},
1680 function.getLoc()))) {
1681 function.emitError(
"failed to add BMC trace context argument");
1682 return signalPassFailure();
1687 LLVMTypeConverter converter(&getContext());
1690 RewritePatternSet
patterns(&getContext());
1706 populateFuncToLLVMConversionPatterns(converter,
patterns);
1707 arith::populateArithToLLVMConversionPatterns(converter,
patterns);
1712 populateSCFToControlFlowConversionPatterns(
patterns);
1713 mlir::cf::populateControlFlowToLLVMConversionPatterns(converter,
patterns);
1717 OpBuilder builder(&getContext());
1723 LLVMConversionTarget target(getContext());
1724 target.addLegalOp<mlir::ModuleOp>();
1725 target.addLegalOp<scf::YieldOp>();
1726 target.addIllegalDialect<debug::DebugDialect>();
1727 target.addIllegalOp<verif::BMCTraceOp>();
1729 if (failed(applyFullConversion(getOperation(), target, std::move(
patterns))))
1730 return signalPassFailure();
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static FIRRTLBaseType convertType(FIRRTLBaseType type)
Returns null type if no conversion is needed.
#define ADD_VARIADIC_PATTERN(OP, APINAME, MIN_NUM_ARGS)
#define ADD_ONE_TO_ONE_PATTERN(OP, APINAME, NUM_ARGS)
static Location getLoc(DefSlot slot)
RewritePatternSet pattern
A namespace that is used to store existing names and generate new names in some scope within the IR.
void add(mlir::ModuleOp module)
StringRef newName(const Twine &name)
Return a unique name, derived from the input name, and add the new name to the internal namespace.
void addDefinitions(mlir::Operation *top)
Populate the symbol cache with all symbol-defining operations within the 'top' operation.
Default symbol cache implementation; stores associations between names (StringAttr's) to mlir::Operat...
void error(Twine message)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
void populateSMTToZ3LLVMTypeConverter(TypeConverter &converter)
Populate the given type converter with the SMT to LLVM type conversions.
void populateSMTToZ3LLVMConversionPatterns(RewritePatternSet &patterns, TypeConverter &converter, SMTGlobalsHandler &globals, const LowerSMTToZ3LLVMOptions &options)
Add the SMT to LLVM IR conversion patterns to 'patterns'.
A symbol cache for LLVM globals and functions relevant to SMT lowering patterns.
static SMTGlobalsHandler create(OpBuilder &builder, ModuleOp module)
Creates the LLVM global operations to store the pointers to the solver and the context and returns a ...
SMTGlobalsHandler(ModuleOp module, mlir::LLVM::GlobalOp solver, mlir::LLVM::GlobalOp ctx)
Initializes the caches and keeps track of the given globals to store the pointers to the SMT solver a...