From 7af41161f0004c38e61d5b0c3c3c5d350e3d51e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:31:17 +0200 Subject: [PATCH 01/70] Add bitvectors to theta type converter --- tools/gazer-theta/CMakeLists.txt | 1 + tools/gazer-theta/lib/ThetaCfaGenerator.cpp | 24 ++------ tools/gazer-theta/lib/ThetaType.cpp | 66 +++++++++++++++++++++ tools/gazer-theta/lib/ThetaType.h | 39 ++++++++++++ 4 files changed, 110 insertions(+), 20 deletions(-) create mode 100644 tools/gazer-theta/lib/ThetaType.cpp create mode 100644 tools/gazer-theta/lib/ThetaType.h diff --git a/tools/gazer-theta/CMakeLists.txt b/tools/gazer-theta/CMakeLists.txt index eca621b6..b5f64758 100644 --- a/tools/gazer-theta/CMakeLists.txt +++ b/tools/gazer-theta/CMakeLists.txt @@ -1,4 +1,5 @@ set(LIB_SOURCE_FILES + lib/ThetaType.cpp lib/ThetaCfaGenerator.cpp lib/ThetaExpr.cpp lib/ThetaVerifier.cpp diff --git a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp index 13a7ff07..ade8748f 100644 --- a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp +++ b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp @@ -16,6 +16,8 @@ // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" +#include "ThetaType.h" + #include "gazer/Core/LiteralExpr.h" #include "gazer/Automaton/CfaTransforms.h" @@ -191,24 +193,6 @@ void ThetaEdgeDecl::print(llvm::raw_ostream& os) const os << "}\n"; } -static std::string typeName(Type& type) -{ - switch (type.getTypeID()) { - case Type::IntTypeID: - return "int"; - case Type::RealTypeID: - return "rat"; - case Type::BoolTypeID: - return "bool"; - case Type::ArrayTypeID: { - auto& arrTy = llvm::cast(type); - return "[" + typeName(arrTy.getIndexType()) + "] -> " + typeName(arrTy.getElementType()); - } - default: - llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); - } -} - void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace) { Cfa* main = mSystem.getMainAutomaton(); @@ -234,7 +218,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace // Add variables for (auto& variable : main->locals()) { auto name = validName(variable.getName(), isValidVarName); - auto type = typeName(variable.getType()); + auto type = ThetaType::getThetaTypeName(variable.getType()); nameTrace.variables[name] = &variable; vars.try_emplace(&variable, std::make_unique(name, type)); @@ -242,7 +226,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace for (auto& variable : main->inputs()) { auto name = validName(variable.getName(), isValidVarName); - auto type = typeName(variable.getType()); + auto type = ThetaType::getThetaTypeName(variable.getType()); nameTrace.variables[name] = &variable; vars.try_emplace(&variable, std::make_unique(name, type)); diff --git a/tools/gazer-theta/lib/ThetaType.cpp b/tools/gazer-theta/lib/ThetaType.cpp new file mode 100644 index 00000000..71886e3d --- /dev/null +++ b/tools/gazer-theta/lib/ThetaType.cpp @@ -0,0 +1,66 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2019 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// + +#include "ThetaType.h" + +using namespace gazer; +using namespace gazer::theta; + +std::string ThetaType::getThetaTypeName(Type &type) +{ + switch (type.getTypeID()) { + case Type::IntTypeID: + return "int"; + case Type::RealTypeID: + return "rat"; + case Type::BoolTypeID: + return "bool"; + case Type::ArrayTypeID: { + auto& arrTy = llvm::cast(type); + return "[" + getThetaTypeName(arrTy.getIndexType()) + "] -> " + getThetaTypeName(arrTy.getElementType()); + } + case Type::BvTypeID: { + auto& bvTy = llvm::cast(type); + return "bv[" + std::to_string(bvTy.getWidth()) + "]"; + } + default: + llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); + } +} + +std::string ThetaType::getThetaTypeDefaultValue(Type &type) +{ + switch (type.getTypeID()) { + case Type::IntTypeID: + return "0"; + case Type::RealTypeID: + return "0%1"; + case Type::BoolTypeID: + return "false"; + case Type::ArrayTypeID: { + auto& arrTy = llvm::cast(type); + return "[<" + getThetaTypeName(arrTy.getIndexType()) + ">default <- " + getThetaTypeDefaultValue(arrTy.getElementType()) + "]"; + } + case Type::BvTypeID: { + auto& bvTy = llvm::cast(type); + return std::to_string(bvTy.getWidth()) + "'d0"; + } + default: + llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); + } +} diff --git a/tools/gazer-theta/lib/ThetaType.h b/tools/gazer-theta/lib/ThetaType.h new file mode 100644 index 00000000..8eb6f528 --- /dev/null +++ b/tools/gazer-theta/lib/ThetaType.h @@ -0,0 +1,39 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2019 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +#ifndef GAZER_TOOLS_GAZERTHETA_LIB_THETATYPE_H +#define GAZER_TOOLS_GAZERTHETA_LIB_THETATYPE_H + +#include "gazer/Core/Type.h" + +#include + +namespace gazer::theta +{ + +class ThetaType final +{ +public: + ThetaType() = delete; + + static std::string getThetaTypeName(Type& type); + static std::string getThetaTypeDefaultValue(Type& type); +}; + +} // end namespace gazer::theta + +#endif // GAZER_TOOLS_GAZERTHETA_LIB_THETATYPE_H From 63c649040e06fd682091fd7c6b28266117d2c916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:35:45 +0200 Subject: [PATCH 02/70] Add bitvector expression conversion to theta converter --- tools/gazer-theta/lib/ThetaExpr.cpp | 120 +++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index d12b4bcf..aea64bcf 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -16,6 +16,7 @@ // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" +#include "ThetaType.h" #include "gazer/Core/Expr/ExprWalker.h" #include "gazer/ADT/StringUtils.h" @@ -23,9 +24,11 @@ #include +#include #include using namespace gazer; +using namespace gazer::theta; class ThetaExprPrinter : public ExprWalker { @@ -63,6 +66,11 @@ class ThetaExprPrinter : public ExprWalker return std::to_string(val.numerator()) + "%" + std::to_string(val.denominator()); } + if(auto bvLit = llvm::dyn_cast(expr)) { + auto exactValue = bvLit->getValue().getZExtValue(); + auto exactString = std::bitset(exactValue).to_string(); + return std::to_string(bvLit->getType().getWidth()) + "'b" + exactString.substr(exactString.length() - bvLit->getType().getWidth()); + } return visitExpr(expr); } @@ -81,24 +89,60 @@ class ThetaExprPrinter : public ExprWalker // Binary std::string visitAdd(const ExprRef& expr) { + if(expr->getType().isBvType()) { + return "(" + getOperand(0) + " bvadd " + getOperand(1) + ")"; + } + else { return "(" + getOperand(0) + " + " + getOperand(1) + ")"; } + } std::string visitSub(const ExprRef& expr) { + if(expr->getType().isBvType()) { + return "(" + getOperand(0) + " bvsub " + getOperand(1) + ")"; + } + else { return "(" + getOperand(0) + " - " + getOperand(1) + ")"; } + } std::string visitMul(const ExprRef& expr) { + if(expr->getType().isBvType()) { + return "(" + getOperand(0) + " bvmul " + getOperand(1) + ")"; + } + else { return "(" + getOperand(0) + " * " + getOperand(1) + ")"; } + } std::string visitDiv(const ExprRef& expr) { return "(" + getOperand(0) + " / " + getOperand(1) + ")"; } + std::string visitBvUDiv([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvudiv " + getOperand(1) + ")"; + } + + std::string visitBvSDiv([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsdiv " + getOperand(1) + ")"; + } + std::string visitMod(const ExprRef& expr) { + if(expr->getType().isBvType()) { + return "(" + getOperand(0) + " bvsmod " + getOperand(1) + ")"; + } + else { return "(" + getOperand(0) + " mod " + getOperand(1) + ")"; } + } + + std::string visitBvURem([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvurem " + getOperand(1) + ")"; + } + + std::string visitBvSRem([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsrem " + getOperand(1) + ")"; + } std::string visitAnd(const ExprRef& expr) { @@ -137,7 +181,49 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " imply " + getOperand(1) + ")"; } - std::string visitEq(const ExprRef& expr) { + std::string visitBvAnd([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvand " + getOperand(1) + ")"; + } + + std::string visitBvOr([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvor " + getOperand(1) + ")"; + } + + std::string visitBvXor([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvxor " + getOperand(1) + ")"; + } + + std::string visitShl([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvshl " + getOperand(1) + ")"; + } + + std::string visitAShr([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvashr " + getOperand(1) + ")"; + } + + std::string visitBvConcat([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " ++ " + getOperand(1) + ")"; + } + + std::string visitExtract(const ExprRef& expr) { + auto from = expr->getOffset(); + auto until = expr->getOffset() + expr->getWidth(); + return "(" + getOperand(0) + ")[" + std::to_string(until) + ":" + std::to_string(from) + "]"; + } + + std::string visitZExt(const ExprRef& expr) { + auto width = expr->getExtendedWidth(); + return "(" + getOperand(0) + " bv_zero_extend bv[" + std::to_string(width) + "])"; + } + + std::string visitSExt(const ExprRef& expr) { + auto width = expr->getExtendedWidth(); + return "(" + getOperand(0) + " bv_sign_extend bv[" + std::to_string(width) + "])"; + } + + std::string visitLShr([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvlshr " + getOperand(1) + ")"; + } return "(" + getOperand(0) + " = " + getOperand(1) + ")"; } @@ -161,7 +247,37 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " >= " + getOperand(1) + ")"; } - std::string visitSelect(const ExprRef& expr) { + std::string visitBvULt([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvult " + getOperand(1) + ")"; + } + + std::string visitBvULtEq([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvule " + getOperand(1) + ")"; + } + + std::string visitBvUGt([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvugt " + getOperand(1) + ")"; + } + + std::string visitBvUGtEq([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvuge " + getOperand(1) + ")"; + } + + std::string visitBvSLt([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvslt " + getOperand(1) + ")"; + } + + std::string visitBvSLtEq([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsle " + getOperand(1) + ")"; + } + + std::string visitBvSGt([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsgt " + getOperand(1) + ")"; + } + + std::string visitBvSGtEq([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsge " + getOperand(1) + ")"; + } return "(if " + getOperand(0) + " then " + getOperand(1) + " else " + getOperand(2) + ")"; } From 2d07f8242c0a554464bb8103c8662fb573b7b8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:37:25 +0200 Subject: [PATCH 03/70] Add array literal conversion to theta converter --- tools/gazer-theta/lib/ThetaExpr.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index aea64bcf..4a924d01 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -71,6 +71,32 @@ class ThetaExprPrinter : public ExprWalker auto exactString = std::bitset(exactValue).to_string(); return std::to_string(bvLit->getType().getWidth()) + "'b" + exactString.substr(exactString.length() - bvLit->getType().getWidth()); } + + if(auto arrLit = llvm::dyn_cast(expr)) { + std::string arrLitStr = "["; + + const auto& kvPairs = arrLit->getMap(); + if(kvPairs.size() > 0) { + for(const auto& [index, elem] : kvPairs) { + arrLitStr += this->walk(index) + " <- " + this->walk(elem) + ", "; + } + arrLitStr += "default <- "; + } + else { + arrLitStr += "<" + ThetaType::getThetaTypeName(arrLit->getType().getIndexType()) + ">default <- "; + } + + if(arrLit->hasDefault()) { + arrLitStr += this->walk(arrLit->getDefault()); + } + else { + arrLitStr += ThetaType::getThetaTypeDefaultValue(arrLit->getType().getElementType()); + } + + arrLitStr += "]"; + return arrLitStr; + } + return visitExpr(expr); } From 4e90f1020ac2f072689bb25ab181e76a2b2be51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:37:57 +0200 Subject: [PATCH 04/70] Add [[maybe_unused]] to visitor parameters --- tools/gazer-theta/lib/ThetaExpr.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 4a924d01..729eab0b 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -109,7 +109,7 @@ class ThetaExprPrinter : public ExprWalker return expr->getVariable().getName(); } - std::string visitNot(const ExprRef& expr) { + std::string visitNot([[maybe_unused]] const ExprRef& expr) { return "(not " + getOperand(0) + ")"; } @@ -141,7 +141,7 @@ class ThetaExprPrinter : public ExprWalker } } - std::string visitDiv(const ExprRef& expr) { + std::string visitDiv([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " / " + getOperand(1) + ")"; } @@ -203,7 +203,7 @@ class ThetaExprPrinter : public ExprWalker return rso.str(); } - std::string visitImply(const ExprRef& expr) { + std::string visitImply([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " imply " + getOperand(1) + ")"; } @@ -250,26 +250,28 @@ class ThetaExprPrinter : public ExprWalker std::string visitLShr([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " bvlshr " + getOperand(1) + ")"; } + + std::string visitEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " = " + getOperand(1) + ")"; } - std::string visitNotEq(const ExprRef& expr) { + std::string visitNotEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " /= " + getOperand(1) + ")"; } - std::string visitLt(const ExprRef& expr) { + std::string visitLt([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " < " + getOperand(1) + ")"; } - std::string visitLtEq(const ExprRef& expr) { + std::string visitLtEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " <= " + getOperand(1) + ")"; } - std::string visitGt(const ExprRef& expr) { + std::string visitGt([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " > " + getOperand(1) + ")"; } - std::string visitGtEq(const ExprRef& expr) { + std::string visitGtEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " >= " + getOperand(1) + ")"; } @@ -304,14 +306,16 @@ class ThetaExprPrinter : public ExprWalker std::string visitBvSGtEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " bvsge " + getOperand(1) + ")"; } + + std::string visitSelect([[maybe_unused]] const ExprRef& expr) { return "(if " + getOperand(0) + " then " + getOperand(1) + " else " + getOperand(2) + ")"; } - std::string visitArrayRead(const ExprRef& expr) { + std::string visitArrayRead([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + ")[" + getOperand(1) + "]"; } - std::string visitArrayWrite(const ExprRef& expr) { + std::string visitArrayWrite([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + ")[" + getOperand(1) + " <- " + getOperand(2) + "]"; } From ca4d6007f86ca25db8c000fecfcb285fe9efa1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:41:20 +0200 Subject: [PATCH 05/70] Add bitvector specific theta keywords --- tools/gazer-theta/lib/ThetaCfaGenerator.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp index ade8748f..17da3256 100644 --- a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp +++ b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp @@ -45,7 +45,14 @@ constexpr std::array ThetaKeywords = { "return", "havoc", "bool", "int", "rat", "if", "then", "else", "iff", "imply", "forall", "exists", "or", "and", "not", - "mod", "rem", "true", "false" + "mod", "rem", "true", "false", + "bvadd", "bvsub", "bvpos", "bvneg", + "bvmul", "bvudiv", "bvsdiv", + "bvsmod", "bvurem", "bvsrem", + "bvshl", "bvashr", "bvlshr", "bvrol", "bvror", + "bvult", "bvule", "bvugt", "bvuge", + "bvslt", "bvsle", "bvsgt", "bvsge", + "bv_zero_extend", "bv_sign_extend" }; struct ThetaAst From b4b7eb5ee519a725f547babfe410fcc5296f0e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:46:29 +0200 Subject: [PATCH 06/70] Refactor RecursiveToCyclicTransformer to support other types for the error field variable --- src/Automaton/RecursiveToCyclicCfa.cpp | 77 ++++++++++++++------------ 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/src/Automaton/RecursiveToCyclicCfa.cpp b/src/Automaton/RecursiveToCyclicCfa.cpp index 8d7db1fc..3831a931 100644 --- a/src/Automaton/RecursiveToCyclicCfa.cpp +++ b/src/Automaton/RecursiveToCyclicCfa.cpp @@ -42,15 +42,16 @@ class RecursiveToCyclicTransformer RecursiveToCyclicResult transform(); private: - void addUniqueErrorLocation(); void inlineCallIntoRoot(CallTransition* call, llvm::Twine suffix); + void createErrorTransition(Location* from, ExprPtr errorFieldExpr); + void createDummyErrorTransition(); private: Cfa* mRoot; CallGraph mCallGraph; llvm::SmallVector mTailRecursiveCalls; - Location* mError; - Variable* mErrorFieldVariable;; + Location* mError = nullptr; + Variable* mErrorFieldVariable = nullptr; llvm::DenseMap mInlinedLocations; llvm::DenseMap mInlinedVariables; std::unique_ptr mExprBuilder; @@ -61,8 +62,16 @@ class RecursiveToCyclicTransformer RecursiveToCyclicResult RecursiveToCyclicTransformer::transform() { - this->addUniqueErrorLocation(); + mError = mRoot->createErrorLocation(); + + // Connect error location + for (Location* loc : mRoot->nodes()) { + if (loc->isError() && loc != mError) { + this->createErrorTransition(loc, mRoot->getErrorFieldExpr(loc)); + } + } + // Collect tail-recursive calls for (Transition* edge : mRoot->edges()) { if (auto call = llvm::dyn_cast(edge)) { if (mCallGraph.isTailRecursive(call->getCalledAutomaton())) { @@ -78,6 +87,12 @@ RecursiveToCyclicResult RecursiveToCyclicTransformer::transform() this->inlineCallIntoRoot(call, "_inlined" + llvm::Twine(mInlineCnt++)); } + + if(mErrorFieldVariable == nullptr) { + // If there are no error locations, create one to use as goal + this->createDummyErrorTransition(); + } + mRoot->clearDisconnectedElements(); // Calculate the new call graph and remove unneeded automata. @@ -141,9 +156,7 @@ void RecursiveToCyclicTransformer::inlineCallIntoRoot(CallTransition* call, llvm locToLocMap[&*origLoc] = newLoc; mInlinedLocations[newLoc] = origLoc; if (origLoc->isError()) { - mRoot->createAssignTransition(newLoc, mError, mExprBuilder->True(), { - { mErrorFieldVariable, callee->getErrorFieldExpr(origLoc) } - }); + this->createErrorTransition(newLoc, callee->getErrorFieldExpr(origLoc)); } } @@ -259,39 +272,33 @@ void RecursiveToCyclicTransformer::inlineCallIntoRoot(CallTransition* call, llvm mRoot->disconnectEdge(call); } -void RecursiveToCyclicTransformer::addUniqueErrorLocation() +void RecursiveToCyclicTransformer::createErrorTransition(Location *from, ExprPtr errorFieldExpr) { + assert(mError != nullptr); + assert(mErrorFieldVariable == nullptr || mErrorFieldVariable->getType() == errorFieldExpr->getType()); + + if(mErrorFieldVariable == nullptr) { + mErrorFieldVariable = mRoot->createLocal("__gazer_error_field", errorFieldExpr->getType()); + } + + mRoot->createAssignTransition(from, mError, BoolLiteralExpr::True(mRoot->getParent().getContext()), { + VariableAssignment { mErrorFieldVariable, errorFieldExpr } + }); +} + +void RecursiveToCyclicTransformer::createDummyErrorTransition() +{ + assert(mError != nullptr); + assert(mErrorFieldVariable == nullptr); + auto& intTy = IntType::Get(mRoot->getParent().getContext()); auto& ctx = mRoot->getParent().getContext(); - llvm::SmallVector errors; - for (Location* loc : mRoot->nodes()) { - if (loc->isError()) { - errors.push_back(loc); - } - } - - mError = mRoot->createErrorLocation(); + // A dummy error location will be used as a goal as there are no error locations in the automaton mErrorFieldVariable = mRoot->createLocal("__gazer_error_field", intTy); - - if (errors.empty()) { - // If there are no error locations in the main automaton, they might still exist in a called CFA. - // A dummy error location will be used as a goal. - mRoot->createAssignTransition(mRoot->getEntry(), mError, BoolLiteralExpr::False(ctx), { - VariableAssignment{ mErrorFieldVariable, IntLiteralExpr::Get(intTy, 0) } - }); - } else { - // The error location will be directly reachable from already existing error locations. - for (Location* err : errors) { - auto errorExpr = mRoot->getErrorFieldExpr(err); - - assert(errorExpr->getType().isIntType() && "Error expression must be arithmetic integers in the theta backend!"); - - mRoot->createAssignTransition(err, mError, BoolLiteralExpr::True(ctx), { - VariableAssignment { mErrorFieldVariable, errorExpr } - }); - } - } + mRoot->createAssignTransition(mRoot->getEntry(), mError, BoolLiteralExpr::False(ctx), { + VariableAssignment{ mErrorFieldVariable, IntLiteralExpr::Get(intTy, 0) } + }); } RecursiveToCyclicResult gazer::TransformRecursiveToCyclic(Cfa* cfa) From c2d35f52da96702965a91fc31e44cca2101e1092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:48:12 +0200 Subject: [PATCH 07/70] Parse bitvectors from cex --- tools/gazer-theta/lib/ThetaVerifier.cpp | 129 ++++++++++++++++++------ 1 file changed, 97 insertions(+), 32 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 4f646cc1..e619d889 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -30,6 +30,8 @@ #include #include +#include + using namespace gazer; using namespace gazer::theta; @@ -237,6 +239,100 @@ static void reportInvalidCex(llvm::StringRef message, llvm::StringRef cex, sexpr llvm::errs() << "Raw counterexample is: " << cex << "\n"; } +static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr; + +static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> boost::intrusive_ptr +{ + llvm::StringRef value = sexpr->asAtom(); + if (value.equals_lower("true")) { + return BoolLiteralExpr::True(varTy.getContext()); + } + else if (value.equals_lower("false")) { + return BoolLiteralExpr::False(varTy.getContext()); + } + else { + return nullptr; + } +} + +static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> boost::intrusive_ptr +{ + llvm::StringRef value = sexpr->asAtom(); + long long int intVal; + if (!value.getAsInteger(10, intVal)) { + return IntLiteralExpr::Get(varTy, intVal); + } + else { + return nullptr; + } +} + +static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusive_ptr +{ + llvm::StringRef value = sexpr->asAtom(); + llvm::APInt intVal; + + if (!value.getAsInteger(10, intVal)) { + return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); + } + else if (const auto lit = value.split("'"); std::get<1>(lit) != "") { + auto bvSizeStr = std::get<0>(lit); + auto bvLitForm = std::get<1>(lit)[0]; + auto bvLitValueStr = std::get<1>(lit).substr(1); + + unsigned bvSize; + auto [p, ec] = std::from_chars(bvSizeStr.data(), bvSizeStr.data() + bvSizeStr.size(), bvSize); + + if (ec == std::errc() && bvSize == varTy.getWidth()) { + switch (std::tolower(bvLitForm)) { + case 'b': + if (!bvLitValueStr.getAsInteger(2, intVal)) { + return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); + } + break; + case 'x': + if (!bvLitValueStr.getAsInteger(16, intVal)) { + return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); + } + break; + case 'd': + if (!bvLitValueStr.getAsInteger(10, intVal)) { + return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); + } + break; + } + + // Error while parsing + return nullptr; + } + else { + // Error while parsing the size + return nullptr; + } + } + else { + // Not supported format + return nullptr; + } +} +static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr +{ + switch (varTy.getTypeID()) { + case Type::BoolTypeID: { + return parseBoolLiteral(sexpr, cast(varTy)); + } + case Type::IntTypeID: { + return parseIntLiteral(sexpr, cast(varTy)); + } + case Type::BvTypeID: { + return parseBvLiteral(sexpr, cast(varTy)); + } + default: { + return nullptr; + } + } +} + std::unique_ptr ThetaVerifierImpl::parseCex(llvm::StringRef cex, unsigned* errorCode) { // TODO: The whole parsing process is very fragile. We should introduce some proper error cheks. @@ -273,7 +369,6 @@ std::unique_ptr ThetaVerifierImpl::parseCex(llvm::StringRef cex, unsigned std::vector assigns; for (size_t j = 1; j < actionList.size(); ++j) { llvm::StringRef varName = actionList[j]->asList()[0]->asAtom(); - llvm::StringRef value = actionList[j]->asList()[1]->asAtom(); Variable* variable = mNameMapping.variables.lookup(varName); assert(variable != nullptr && "Each variable must be present in the theta name mapping!"); @@ -283,37 +378,7 @@ std::unique_ptr ThetaVerifierImpl::parseCex(llvm::StringRef cex, unsigned origVariable = variable; } - ExprPtr rhs; - Type& varTy = origVariable->getType(); - - switch (varTy.getTypeID()) { - case Type::IntTypeID: { - long long int intVal; - if (!value.getAsInteger(10, intVal)) { - rhs = IntLiteralExpr::Get(cast(varTy), intVal); - } - break; - } - case Type::BvTypeID: { - llvm::APInt intVal; - if (!value.getAsInteger(10, intVal)) { - auto& bvTy = cast(varTy); - rhs = BvLiteralExpr::Get(bvTy, intVal.zextOrTrunc(bvTy.getWidth())); - } - break; - } - case Type::BoolTypeID: { - if (value.equals_lower("true")) { - rhs = BoolLiteralExpr::True(varTy.getContext()); - } else if (value.equals_lower("false")) { - rhs = BoolLiteralExpr::False(varTy.getContext()); - } - break; - } - default: - break; - } - + auto rhs = parseLiteral(actionList[j]->asList()[1], origVariable->getType()); if (rhs == nullptr) { reportInvalidCex("expected a valid integer or boolean value", cex, &*(actionList[j]->asList()[1])); return nullptr; From 3641d971f6894d3cd74e77cc1e5a8d4d484a8f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:48:23 +0200 Subject: [PATCH 08/70] Parse array literals from cex --- tools/gazer-theta/lib/ThetaVerifier.cpp | 30 ++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index e619d889..0ddb6b52 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -315,6 +315,31 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusi return nullptr; } } + +static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> boost::intrusive_ptr +{ + auto arrLitImpl = sexpr->asList(); + // The string "array" at the beginning + arrLitImpl.erase(arrLitImpl.begin()); + + ArrayLiteralExpr::MappingT entries; + ExprRef def = nullptr; + + for(auto arrEntryImpl : arrLitImpl) { + auto keyImpl = arrEntryImpl->asList()[0]; + auto valueImpl = arrEntryImpl->asList()[1]; + + if(keyImpl->isAtom() && keyImpl->asAtom() == "default") { + def = parseLiteral(valueImpl, varTy.getElementType()); + } + else { + entries[parseLiteral(keyImpl, varTy.getIndexType())] = parseLiteral(valueImpl, varTy.getElementType()); + } + } + + return ArrayLiteralExpr::Get(varTy, entries, def); +} + static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr { switch (varTy.getTypeID()) { @@ -327,6 +352,9 @@ static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_p case Type::BvTypeID: { return parseBvLiteral(sexpr, cast(varTy)); } + case Type::ArrayTypeID: { + return parseArrayLiteral(sexpr, cast(varTy)); + } default: { return nullptr; } @@ -380,7 +408,7 @@ std::unique_ptr ThetaVerifierImpl::parseCex(llvm::StringRef cex, unsigned auto rhs = parseLiteral(actionList[j]->asList()[1], origVariable->getType()); if (rhs == nullptr) { - reportInvalidCex("expected a valid integer or boolean value", cex, &*(actionList[j]->asList()[1])); + reportInvalidCex("expected a valid integer, bitvector, boolean or their array as value", cex, &*(actionList[j]->asList()[1])); return nullptr; } From 02150816df528f822ea6befde889c3809b692aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:48:47 +0200 Subject: [PATCH 09/70] Remove forced int representation from gazer-theta --- tools/gazer-theta/gazer-theta.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gazer-theta/gazer-theta.cpp b/tools/gazer-theta/gazer-theta.cpp index 00cfab8e..62c29133 100644 --- a/tools/gazer-theta/gazer-theta.cpp +++ b/tools/gazer-theta/gazer-theta.cpp @@ -128,7 +128,8 @@ int main(int argc, char* argv[]) } // Force -math-int - config.getSettings().ints = IntRepresentation::Integers; + // TODO: Find a way to make this behavior default + // config.getSettings().ints = IntRepresentation::Integers; // Create the frontend object auto frontend = config.buildFrontend(InputFilenames); From 50ded991c58d84a5ce71f7f2b823f986878c9665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 13:28:29 +0200 Subject: [PATCH 10/70] Remove dependency --- tools/gazer-theta/lib/ThetaVerifier.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 0ddb6b52..b25b495d 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -30,8 +30,6 @@ #include #include -#include - using namespace gazer; using namespace gazer::theta; @@ -281,9 +279,8 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusi auto bvLitValueStr = std::get<1>(lit).substr(1); unsigned bvSize; - auto [p, ec] = std::from_chars(bvSizeStr.data(), bvSizeStr.data() + bvSizeStr.size(), bvSize); - if (ec == std::errc() && bvSize == varTy.getWidth()) { + if (!bvSizeStr.getAsInteger(10, bvSize) && bvSize == varTy.getWidth()) { switch (std::tolower(bvLitForm)) { case 'b': if (!bvLitValueStr.getAsInteger(2, intVal)) { From 7c93243e33c9d470df2fabfc9eb09b5d13616720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 14:25:53 +0200 Subject: [PATCH 11/70] Correct whitespace discrepancies --- tools/gazer-theta/lib/ThetaExpr.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 729eab0b..ee6991ee 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -119,8 +119,8 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " bvadd " + getOperand(1) + ")"; } else { - return "(" + getOperand(0) + " + " + getOperand(1) + ")"; - } + return "(" + getOperand(0) + " + " + getOperand(1) + ")"; + } } std::string visitSub(const ExprRef& expr) { @@ -128,8 +128,8 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " bvsub " + getOperand(1) + ")"; } else { - return "(" + getOperand(0) + " - " + getOperand(1) + ")"; - } + return "(" + getOperand(0) + " - " + getOperand(1) + ")"; + } } std::string visitMul(const ExprRef& expr) { @@ -137,8 +137,8 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " bvmul " + getOperand(1) + ")"; } else { - return "(" + getOperand(0) + " * " + getOperand(1) + ")"; - } + return "(" + getOperand(0) + " * " + getOperand(1) + ")"; + } } std::string visitDiv([[maybe_unused]] const ExprRef& expr) { @@ -158,8 +158,8 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " bvsmod " + getOperand(1) + ")"; } else { - return "(" + getOperand(0) + " mod " + getOperand(1) + ")"; - } + return "(" + getOperand(0) + " mod " + getOperand(1) + ")"; + } } std::string visitBvURem([[maybe_unused]] const ExprRef& expr) { From b26b0de8c36ac3ba72454b68870fe03fc63f02f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 14:48:13 +0200 Subject: [PATCH 12/70] Add -math-int to theta functional tests --- test/theta/cfa/counter.c | 2 +- test/theta/verif/base/loops1.c | 2 +- test/theta/verif/base/loops2_fail.c | 2 +- test/theta/verif/base/loops3_fail.c | 2 +- test/theta/verif/base/main_no_assert.c | 2 +- test/theta/verif/base/separate_assert.c | 2 +- test/theta/verif/base/simple_fail.c | 2 +- test/theta/verif/base/uninitialized_var_false.c | 4 ++-- test/theta/verif/memory/arrays1.c | 2 +- test/theta/verif/memory/arrays2_fail.c | 2 +- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 2 +- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- test/theta/verif/svcomp/locks/test_locks_13_true.c | 2 +- test/theta/verif/svcomp/locks/test_locks_14_false.c | 2 +- test/theta/verif/svcomp/locks/test_locks_14_true.c | 2 +- test/theta/verif/svcomp/locks/test_locks_15_false.c | 2 +- test/theta/verif/svcomp/locks/test_locks_15_true.c | 2 +- 29 files changed, 30 insertions(+), 30 deletions(-) diff --git a/test/theta/cfa/counter.c b/test/theta/cfa/counter.c index 60e77f6e..2f26da35 100644 --- a/test/theta/cfa/counter.c +++ b/test/theta/cfa/counter.c @@ -1,4 +1,4 @@ -// RUN: %theta -model-only "%s" -o "%t" +// RUN: %theta -model-only -math-int "%s" -o "%t" // RUN: cat "%t" | /usr/bin/diff -B -Z "%p/Expected/counter.theta" - #include diff --git a/test/theta/verif/base/loops1.c b/test/theta/verif/base/loops1.c index f71e3fb3..aefc12bf 100644 --- a/test/theta/verif/base/loops1.c +++ b/test/theta/verif/base/loops1.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/base/loops2_fail.c b/test/theta/verif/base/loops2_fail.c index a5b671ea..3637712a 100644 --- a/test/theta/verif/base/loops2_fail.c +++ b/test/theta/verif/base/loops2_fail.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/loops3_fail.c b/test/theta/verif/base/loops3_fail.c index b704f1a5..999d4365 100644 --- a/test/theta/verif/base/loops3_fail.c +++ b/test/theta/verif/base/loops3_fail.c @@ -1,4 +1,4 @@ -// RUN: %theta -no-optimize -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -no-optimize -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/main_no_assert.c b/test/theta/verif/base/main_no_assert.c index 30201f2d..242f4305 100644 --- a/test/theta/verif/base/main_no_assert.c +++ b/test/theta/verif/base/main_no_assert.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/base/separate_assert.c b/test/theta/verif/base/separate_assert.c index dce49a26..5c60c34d 100644 --- a/test/theta/verif/base/separate_assert.c +++ b/test/theta/verif/base/separate_assert.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/base/simple_fail.c b/test/theta/verif/base/simple_fail.c index dba370e5..c9f6d830 100644 --- a/test/theta/verif/base/simple_fail.c +++ b/test/theta/verif/base/simple_fail.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/uninitialized_var_false.c b/test/theta/verif/base/uninitialized_var_false.c index c7731dd1..0c2b7e3c 100644 --- a/test/theta/verif/base/uninitialized_var_false.c +++ b/test/theta/verif/base/uninitialized_var_false.c @@ -1,5 +1,5 @@ -// RUN: %theta -no-optimize -memory=havoc "%s" | FileCheck "%s" -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -no-optimize -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/arrays1.c b/test/theta/verif/memory/arrays1.c index dae726e5..7daa50d7 100644 --- a/test/theta/verif/memory/arrays1.c +++ b/test/theta/verif/memory/arrays1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index 0cbb2c0f..c62fada8 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index 6579935e..92f2dbd1 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index 8eb281f2..5726e50c 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 10e3242e..847ba069 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index 5975a3c8..6c6e8adb 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index c7b8808d..82cc0f15 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 50213622..62a5f181 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index a4a054e0..2770d0dd 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index 0c44ad05..db466580 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index 1465eaf5..47ebe1bf 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index 8ac40ced..7bc4ad03 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index ef4d7024..39159c6c 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index f46abffe..807101dc 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index f562d97d..5bab01fd 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index 9debb018..e6a47b8c 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/svcomp/locks/test_locks_13_true.c b/test/theta/verif/svcomp/locks/test_locks_13_true.c index 429ecf2a..5ebb658b 100644 --- a/test/theta/verif/svcomp/locks/test_locks_13_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_13_true.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_14_false.c b/test/theta/verif/svcomp/locks/test_locks_14_false.c index 85b90907..143f2a98 100644 --- a/test/theta/verif/svcomp/locks/test_locks_14_false.c +++ b/test/theta/verif/svcomp/locks/test_locks_14_false.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_14_true.c b/test/theta/verif/svcomp/locks/test_locks_14_true.c index daebc4c0..b53ff8a7 100644 --- a/test/theta/verif/svcomp/locks/test_locks_14_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_14_true.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_15_false.c b/test/theta/verif/svcomp/locks/test_locks_15_false.c index b7b83108..e3f77578 100644 --- a/test/theta/verif/svcomp/locks/test_locks_15_false.c +++ b/test/theta/verif/svcomp/locks/test_locks_15_false.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_15_true.c b/test/theta/verif/svcomp/locks/test_locks_15_true.c index 4e2fc85b..3daa1e35 100644 --- a/test/theta/verif/svcomp/locks/test_locks_15_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_15_true.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); From e8ebf1ba1eedd681ae489c084509c82e5f8543a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 16:03:14 +0200 Subject: [PATCH 13/70] Fix Ninja build error at ExternalProject_Add --- src/SolverZ3/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SolverZ3/CMakeLists.txt b/src/SolverZ3/CMakeLists.txt index 3406b682..aac20f66 100644 --- a/src/SolverZ3/CMakeLists.txt +++ b/src/SolverZ3/CMakeLists.txt @@ -4,20 +4,22 @@ set(SOURCE_FILES ) # Z3 + +set(Z3_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/vendor/src/z3_download/include") +set(Z3_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/vendor/src/z3_download/bin") + ExternalProject_Add(z3_download PREFIX vendor # Download URL https://github.com/Z3Prover/z3/releases/download/z3-4.8.6/z3-4.8.6-x64-ubuntu-16.04.zip URL_HASH SHA1=1663a7825c45f24642045dfcc5e100d65c1b6b1e + BUILD_BYPRODUCTS "${Z3_LIBRARY_DIR}/libz3.so" CONFIGURE_COMMAND "" BUILD_COMMAND "" UPDATE_COMMAND "" INSTALL_COMMAND "" ) -set(Z3_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/vendor/src/z3_download/include") -set(Z3_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/vendor/src/z3_download/bin") - message("Z3 includes are ${Z3_INCLUDE_DIR}") # Z3 From 2cc819e2be168801a169c11c7be601cd27cc3c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 20:17:51 +0200 Subject: [PATCH 14/70] Add bitvector related functional tests --- test/theta/verif/base/loops1.c | 2 ++ test/theta/verif/base/loops2_fail.c | 1 + test/theta/verif/base/loops3_fail.c | 1 + test/theta/verif/base/main_no_assert.c | 1 + test/theta/verif/base/separate_assert.c | 1 + test/theta/verif/base/simple_fail.c | 1 + test/theta/verif/base/uninitialized_var_false.c | 1 + test/theta/verif/memory/arrays1.c | 2 +- test/theta/verif/memory/arrays2_fail.c | 2 +- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 2 +- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- test/theta/verif/svcomp/locks/test_locks_13_true.c | 1 + test/theta/verif/svcomp/locks/test_locks_14_false.c | 1 + test/theta/verif/svcomp/locks/test_locks_14_true.c | 1 + test/theta/verif/svcomp/locks/test_locks_15_false.c | 1 + test/theta/verif/svcomp/locks/test_locks_15_true.c | 1 + 28 files changed, 29 insertions(+), 16 deletions(-) diff --git a/test/theta/verif/base/loops1.c b/test/theta/verif/base/loops1.c index aefc12bf..07ff225f 100644 --- a/test/theta/verif/base/loops1.c +++ b/test/theta/verif/base/loops1.c @@ -1,4 +1,6 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" + // CHECK: Verification SUCCESSFUL extern int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/base/loops2_fail.c b/test/theta/verif/base/loops2_fail.c index 3637712a..36e0804e 100644 --- a/test/theta/verif/base/loops2_fail.c +++ b/test/theta/verif/base/loops2_fail.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/loops3_fail.c b/test/theta/verif/base/loops3_fail.c index 999d4365..0951f34f 100644 --- a/test/theta/verif/base/loops3_fail.c +++ b/test/theta/verif/base/loops3_fail.c @@ -1,4 +1,5 @@ // RUN: %theta -no-optimize -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/main_no_assert.c b/test/theta/verif/base/main_no_assert.c index 242f4305..88ebd64a 100644 --- a/test/theta/verif/base/main_no_assert.c +++ b/test/theta/verif/base/main_no_assert.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/base/separate_assert.c b/test/theta/verif/base/separate_assert.c index 5c60c34d..cc0eaa79 100644 --- a/test/theta/verif/base/separate_assert.c +++ b/test/theta/verif/base/separate_assert.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/base/simple_fail.c b/test/theta/verif/base/simple_fail.c index c9f6d830..36338c76 100644 --- a/test/theta/verif/base/simple_fail.c +++ b/test/theta/verif/base/simple_fail.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/uninitialized_var_false.c b/test/theta/verif/base/uninitialized_var_false.c index 0c2b7e3c..cbdc7748 100644 --- a/test/theta/verif/base/uninitialized_var_false.c +++ b/test/theta/verif/base/uninitialized_var_false.c @@ -1,5 +1,6 @@ // RUN: %theta -no-optimize -memory=havoc "%s" -math-int | FileCheck "%s" // RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/arrays1.c b/test/theta/verif/memory/arrays1.c index 7daa50d7..c2769805 100644 --- a/test/theta/verif/memory/arrays1.c +++ b/test/theta/verif/memory/arrays1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index c62fada8..0cbb2c0f 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index 92f2dbd1..6579935e 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index 5726e50c..8eb281f2 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 847ba069..10e3242e 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index 6c6e8adb..5975a3c8 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index 82cc0f15..c7b8808d 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 62a5f181..50213622 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index 2770d0dd..a4a054e0 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index db466580..0c44ad05 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index 47ebe1bf..1465eaf5 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index 7bc4ad03..8ac40ced 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index 39159c6c..ef4d7024 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index 807101dc..f46abffe 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index 5bab01fd..f562d97d 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index e6a47b8c..9debb018 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/svcomp/locks/test_locks_13_true.c b/test/theta/verif/svcomp/locks/test_locks_13_true.c index 5ebb658b..92fae859 100644 --- a/test/theta/verif/svcomp/locks/test_locks_13_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_13_true.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_14_false.c b/test/theta/verif/svcomp/locks/test_locks_14_false.c index 143f2a98..9517a036 100644 --- a/test/theta/verif/svcomp/locks/test_locks_14_false.c +++ b/test/theta/verif/svcomp/locks/test_locks_14_false.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_14_true.c b/test/theta/verif/svcomp/locks/test_locks_14_true.c index b53ff8a7..5884fde9 100644 --- a/test/theta/verif/svcomp/locks/test_locks_14_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_14_true.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_15_false.c b/test/theta/verif/svcomp/locks/test_locks_15_false.c index e3f77578..e8d61a9c 100644 --- a/test/theta/verif/svcomp/locks/test_locks_15_false.c +++ b/test/theta/verif/svcomp/locks/test_locks_15_false.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_15_true.c b/test/theta/verif/svcomp/locks/test_locks_15_true.c index 3daa1e35..aec8ffe1 100644 --- a/test/theta/verif/svcomp/locks/test_locks_15_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_15_true.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); From 6c15fc5b9c2e5ba42a49b60f89f6c1f879368aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 09:54:14 +0200 Subject: [PATCH 15/70] Refactor ThetaType to use free functions --- tools/gazer-theta/lib/ThetaCfaGenerator.cpp | 4 ++-- tools/gazer-theta/lib/ThetaExpr.cpp | 4 ++-- tools/gazer-theta/lib/ThetaType.cpp | 8 ++++---- tools/gazer-theta/lib/ThetaType.h | 10 ++-------- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp index 17da3256..65916319 100644 --- a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp +++ b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp @@ -225,7 +225,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace // Add variables for (auto& variable : main->locals()) { auto name = validName(variable.getName(), isValidVarName); - auto type = ThetaType::getThetaTypeName(variable.getType()); + auto type = thetaType(variable.getType()); nameTrace.variables[name] = &variable; vars.try_emplace(&variable, std::make_unique(name, type)); @@ -233,7 +233,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace for (auto& variable : main->inputs()) { auto name = validName(variable.getName(), isValidVarName); - auto type = ThetaType::getThetaTypeName(variable.getType()); + auto type = thetaType(variable.getType()); nameTrace.variables[name] = &variable; vars.try_emplace(&variable, std::make_unique(name, type)); diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index ee6991ee..ab67a404 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -83,14 +83,14 @@ class ThetaExprPrinter : public ExprWalker arrLitStr += "default <- "; } else { - arrLitStr += "<" + ThetaType::getThetaTypeName(arrLit->getType().getIndexType()) + ">default <- "; + arrLitStr += "<" + thetaType(arrLit->getType().getIndexType()) + ">default <- "; } if(arrLit->hasDefault()) { arrLitStr += this->walk(arrLit->getDefault()); } else { - arrLitStr += ThetaType::getThetaTypeDefaultValue(arrLit->getType().getElementType()); + arrLitStr += defaultValueForType(arrLit->getType().getElementType()); } arrLitStr += "]"; diff --git a/tools/gazer-theta/lib/ThetaType.cpp b/tools/gazer-theta/lib/ThetaType.cpp index 71886e3d..75f8276c 100644 --- a/tools/gazer-theta/lib/ThetaType.cpp +++ b/tools/gazer-theta/lib/ThetaType.cpp @@ -21,7 +21,7 @@ using namespace gazer; using namespace gazer::theta; -std::string ThetaType::getThetaTypeName(Type &type) +std::string gazer::theta::thetaType(Type &type) { switch (type.getTypeID()) { case Type::IntTypeID: @@ -32,7 +32,7 @@ std::string ThetaType::getThetaTypeName(Type &type) return "bool"; case Type::ArrayTypeID: { auto& arrTy = llvm::cast(type); - return "[" + getThetaTypeName(arrTy.getIndexType()) + "] -> " + getThetaTypeName(arrTy.getElementType()); + return "[" + thetaType(arrTy.getIndexType()) + "] -> " + thetaType(arrTy.getElementType()); } case Type::BvTypeID: { auto& bvTy = llvm::cast(type); @@ -43,7 +43,7 @@ std::string ThetaType::getThetaTypeName(Type &type) } } -std::string ThetaType::getThetaTypeDefaultValue(Type &type) +std::string gazer::theta::defaultValueForType(Type &type) { switch (type.getTypeID()) { case Type::IntTypeID: @@ -54,7 +54,7 @@ std::string ThetaType::getThetaTypeDefaultValue(Type &type) return "false"; case Type::ArrayTypeID: { auto& arrTy = llvm::cast(type); - return "[<" + getThetaTypeName(arrTy.getIndexType()) + ">default <- " + getThetaTypeDefaultValue(arrTy.getElementType()) + "]"; + return "[<" + thetaType(arrTy.getIndexType()) + ">default <- " + defaultValueForType(arrTy.getElementType()) + "]"; } case Type::BvTypeID: { auto& bvTy = llvm::cast(type); diff --git a/tools/gazer-theta/lib/ThetaType.h b/tools/gazer-theta/lib/ThetaType.h index 8eb6f528..582776db 100644 --- a/tools/gazer-theta/lib/ThetaType.h +++ b/tools/gazer-theta/lib/ThetaType.h @@ -25,14 +25,8 @@ namespace gazer::theta { -class ThetaType final -{ -public: - ThetaType() = delete; - - static std::string getThetaTypeName(Type& type); - static std::string getThetaTypeDefaultValue(Type& type); -}; +std::string thetaType(Type& type); +std::string defaultValueForType(Type& type); } // end namespace gazer::theta From fe29400cf0d44db31afc47de82619a62edec4678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 09:57:26 +0200 Subject: [PATCH 16/70] Replace boost::intrusive_ptr with Gazer defined ExprRef --- tools/gazer-theta/lib/ThetaVerifier.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 4edb3f87..31b1dc60 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -240,9 +240,9 @@ static void reportInvalidCex(llvm::StringRef message, llvm::StringRef cex, sexpr llvm::errs() << "Raw counterexample is: " << cex << "\n"; } -static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr; +static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> ExprRef; -static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> boost::intrusive_ptr +static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> ExprRef { llvm::StringRef value = sexpr->asAtom(); if (value.equals_lower("true")) { @@ -256,7 +256,7 @@ static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> boost::int } } -static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> boost::intrusive_ptr +static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> ExprRef { llvm::StringRef value = sexpr->asAtom(); long long int intVal; @@ -268,7 +268,7 @@ static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> boost::intru } } -static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusive_ptr +static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> ExprRef { llvm::StringRef value = sexpr->asAtom(); llvm::APInt intVal; @@ -316,7 +316,7 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusi } } -static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> boost::intrusive_ptr +static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> ExprRef { auto arrLitImpl = sexpr->asList(); // The string "array" at the beginning @@ -340,7 +340,7 @@ static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> boost::i return ArrayLiteralExpr::Get(varTy, entries, def); } -static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr +static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> ExprRef { switch (varTy.getTypeID()) { case Type::BoolTypeID: { From 6041ca965c6311ee7be6e46c16d6b19d1c347279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 10:02:56 +0200 Subject: [PATCH 17/70] Adhere to code formatting guidelines --- tools/gazer-theta/lib/ThetaExpr.cpp | 36 +++++++++++-------------- tools/gazer-theta/lib/ThetaVerifier.cpp | 25 +++++++---------- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index ab67a404..807a24aa 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -66,30 +66,28 @@ class ThetaExprPrinter : public ExprWalker return std::to_string(val.numerator()) + "%" + std::to_string(val.denominator()); } - if(auto bvLit = llvm::dyn_cast(expr)) { + if (auto bvLit = llvm::dyn_cast(expr)) { auto exactValue = bvLit->getValue().getZExtValue(); auto exactString = std::bitset(exactValue).to_string(); return std::to_string(bvLit->getType().getWidth()) + "'b" + exactString.substr(exactString.length() - bvLit->getType().getWidth()); } - if(auto arrLit = llvm::dyn_cast(expr)) { + if (auto arrLit = llvm::dyn_cast(expr)) { std::string arrLitStr = "["; const auto& kvPairs = arrLit->getMap(); - if(kvPairs.size() > 0) { - for(const auto& [index, elem] : kvPairs) { + if (kvPairs.size() > 0) { + for (const auto& [index, elem] : kvPairs) { arrLitStr += this->walk(index) + " <- " + this->walk(elem) + ", "; } arrLitStr += "default <- "; - } - else { + } else { arrLitStr += "<" + thetaType(arrLit->getType().getIndexType()) + ">default <- "; } - if(arrLit->hasDefault()) { + if (arrLit->hasDefault()) { arrLitStr += this->walk(arrLit->getDefault()); - } - else { + } else { arrLitStr += defaultValueForType(arrLit->getType().getElementType()); } @@ -115,28 +113,25 @@ class ThetaExprPrinter : public ExprWalker // Binary std::string visitAdd(const ExprRef& expr) { - if(expr->getType().isBvType()) { + if (expr->getType().isBvType()) { return "(" + getOperand(0) + " bvadd " + getOperand(1) + ")"; - } - else { + } else { return "(" + getOperand(0) + " + " + getOperand(1) + ")"; } } std::string visitSub(const ExprRef& expr) { - if(expr->getType().isBvType()) { + if (expr->getType().isBvType()) { return "(" + getOperand(0) + " bvsub " + getOperand(1) + ")"; - } - else { + } else { return "(" + getOperand(0) + " - " + getOperand(1) + ")"; } } std::string visitMul(const ExprRef& expr) { - if(expr->getType().isBvType()) { + if (expr->getType().isBvType()) { return "(" + getOperand(0) + " bvmul " + getOperand(1) + ")"; - } - else { + } else { return "(" + getOperand(0) + " * " + getOperand(1) + ")"; } } @@ -154,10 +149,9 @@ class ThetaExprPrinter : public ExprWalker } std::string visitMod(const ExprRef& expr) { - if(expr->getType().isBvType()) { + if (expr->getType().isBvType()) { return "(" + getOperand(0) + " bvsmod " + getOperand(1) + ")"; - } - else { + } else { return "(" + getOperand(0) + " mod " + getOperand(1) + ")"; } } diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 31b1dc60..f3705193 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -247,11 +247,9 @@ static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> ExprRef
  • asAtom(); if (value.equals_lower("true")) { return BoolLiteralExpr::True(varTy.getContext()); - } - else if (value.equals_lower("false")) { + } else if (value.equals_lower("false")) { return BoolLiteralExpr::False(varTy.getContext()); - } - else { + } else { return nullptr; } } @@ -262,8 +260,7 @@ static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> ExprRef ExprRef(lit) != "") { + } else if (const auto lit = value.split("'"); std::get<1>(lit) != "") { auto bvSizeStr = std::get<0>(lit); auto bvLitForm = std::get<1>(lit)[0]; auto bvLitValueStr = std::get<1>(lit).substr(1); @@ -304,13 +300,11 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> ExprRef ExprRef< ArrayLiteralExpr::MappingT entries; ExprRef def = nullptr; - for(auto arrEntryImpl : arrLitImpl) { + for (auto arrEntryImpl : arrLitImpl) { auto keyImpl = arrEntryImpl->asList()[0]; auto valueImpl = arrEntryImpl->asList()[1]; - if(keyImpl->isAtom() && keyImpl->asAtom() == "default") { + if (keyImpl->isAtom() && keyImpl->asAtom() == "default") { def = parseLiteral(valueImpl, varTy.getElementType()); - } - else { + } else { entries[parseLiteral(keyImpl, varTy.getIndexType())] = parseLiteral(valueImpl, varTy.getElementType()); } } From c9c7cc246bb53bbdda6207599be685e6e6362946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 15:49:35 +0200 Subject: [PATCH 18/70] Remove dependency from std::bitset --- tools/gazer-theta/lib/ThetaExpr.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 807a24aa..21356ce2 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -12,7 +12,7 @@ // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and -// limitations under the License. +// limitations under the Lic without '0b' prefixense. // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" @@ -20,11 +20,11 @@ #include "gazer/Core/Expr/ExprWalker.h" #include "gazer/ADT/StringUtils.h" +#include #include #include -#include #include using namespace gazer; @@ -67,9 +67,16 @@ class ThetaExprPrinter : public ExprWalker } if (auto bvLit = llvm::dyn_cast(expr)) { - auto exactValue = bvLit->getValue().getZExtValue(); - auto exactString = std::bitset(exactValue).to_string(); - return std::to_string(bvLit->getType().getWidth()) + "'b" + exactString.substr(exactString.length() - bvLit->getType().getWidth()); + llvm::SmallString<64> exactString; + llvm::SmallString<64> paddedString; + + bvLit->getValue().toStringUnsigned(exactString, 2); // The bitvector may be signed, but only the bits are relevant + + auto paddingLength = std::max((bvLit->getType().getWidth() - exactString.size()), 0ul); + paddedString.append(paddingLength, '0'); // Leading zeros + paddedString.append(exactString); // Append literal + + return std::to_string(bvLit->getType().getWidth()) + "'b" + std::string(paddedString.data(), paddedString.data() + paddedString.size()); } if (auto arrLit = llvm::dyn_cast(expr)) { From ab25fe1682022cc4ab7d10cc1e883d9fbdb95a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:09:08 +0200 Subject: [PATCH 19/70] Add tests in ThetaExprPrinter for bitvector transformation --- .../gazer-theta/ThetaExprPrinterTest.cpp | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp index f98234a5..9a5dc8af 100644 --- a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp +++ b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp @@ -18,6 +18,7 @@ #include "../../../tools/gazer-theta/lib/ThetaCfaGenerator.h" #include "gazer/Core/Expr/ExprBuilder.h" +#include "gazer/Core/Type.h" #include @@ -59,7 +60,33 @@ ThetaExprPrinterTest::ThetaExprPrinterTest() b->Lt(b->IntLit(1), b->IntLit(2)), b->Gt(b->IntLit(2), b->IntLit(1)) }), "((1 = 1) and (1 < 2) and (2 > 1))" }, - { b->Select(b->Eq(b->IntLit(1), b->IntLit(2)), b->IntLit(3), b->IntLit(4)), "(if (1 = 2) then 3 else 4)" } + { b->Select(b->Eq(b->IntLit(1), b->IntLit(2)), b->IntLit(3), b->IntLit(4)), "(if (1 = 2) then 3 else 4)" }, + { b->Add(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvadd 8'b00000011)" }, + { b->Sub(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsub 8'b00000011)" }, + { b->Mul(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvmul 8'b00000011)" }, + { b->BvUDiv(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvudiv 8'b00000011)" }, + { b->BvSDiv(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsdiv 8'b00000011)" }, + { b->Mod(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsmod 8'b00000011)" }, + { b->BvURem(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvurem 8'b00000011)" }, + { b->BvSRem(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsrem 8'b00000011)" }, + { b->BvAnd(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvand 8'b00000011)" }, + { b->BvOr(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvor 8'b00000011)" }, + { b->BvXor(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvxor 8'b00000011)" }, + { b->Shl(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvshl 8'b00000011)" }, + { b->AShr(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvashr 8'b00000011)" }, + { b->LShr(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvlshr 8'b00000011)" }, + { b->BvConcat(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 ++ 8'b00000011)" }, + { b->Extract(b->BvLit(2, 8), 3, 3), "(8'b00000010)[6:3]" }, + { b->ZExt(b->BvLit(2, 8), BvType::Get(ctx, 16)), "(8'b00000010 bv_zero_extend bv[16])" }, + { b->SExt(b->BvLit(2, 8), BvType::Get(ctx, 16)), "(8'b00000010 bv_sign_extend bv[16])" }, + { b->BvULt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvult 8'b00000011)" }, + { b->BvULtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvule 8'b00000011)" }, + { b->BvUGt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvugt 8'b00000011)" }, + { b->BvUGtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvuge 8'b00000011)" }, + { b->BvSLt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvslt 8'b00000011)" }, + { b->BvSLtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsle 8'b00000011)" }, + { b->BvSGt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsgt 8'b00000011)" }, + { b->BvSGtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsge 8'b00000011)" } }) {} From 6c3785486ba8140bd3777213867c4d1a4ec4b9f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:32:14 +0200 Subject: [PATCH 20/70] Add methods that create array literals to ExprBuilder --- include/gazer/Core/Expr/ExprBuilder.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/gazer/Core/Expr/ExprBuilder.h b/include/gazer/Core/Expr/ExprBuilder.h index b46ab283..0d8d8824 100644 --- a/include/gazer/Core/Expr/ExprBuilder.h +++ b/include/gazer/Core/Expr/ExprBuilder.h @@ -59,6 +59,22 @@ class ExprBuilder return IntLiteralExpr::Get(IntType::Get(mContext), value); } + ExprRef ArrayLit(ArrayType& arrTy, const ArrayLiteralExpr::MappingT& entries, const ExprRef& elze = nullptr) { + return ArrayLiteralExpr::Get(arrTy, entries, elze); + } + + ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries) { + assert(entries.size() > 0); + const auto& [index, elem] = *entries.begin(); + return ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, nullptr); + } + + ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries, const ExprRef& elze) { + assert(entries.size() > 0); + const auto& [index, elem] = *entries.begin(); + return ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, elze); + } + ExprRef BoolLit(bool value) { return value ? True() : False(); } ExprRef True() { return BoolLiteralExpr::True(BoolType::Get(mContext)); } ExprRef False() { return BoolLiteralExpr::False(BoolType::Get(mContext)); } From 589daf70ae2f8171e3e73182fc45526ad4526cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:32:40 +0200 Subject: [PATCH 21/70] Add tests targeting array literal transformation in ThetaExprPrinter --- unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp index 9a5dc8af..ef1cc857 100644 --- a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp +++ b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp @@ -86,7 +86,13 @@ ThetaExprPrinterTest::ThetaExprPrinterTest() { b->BvSLt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvslt 8'b00000011)" }, { b->BvSLtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsle 8'b00000011)" }, { b->BvSGt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsgt 8'b00000011)" }, - { b->BvSGtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsge 8'b00000011)" } + { b->BvSGtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsge 8'b00000011)" }, + { b->ArrayLit({ + { b->BvLit(2, 4), b->BvLit(3, 4) }, + { b->BvLit(1, 4), b->BvLit(0, 4) } + }, b->BvLit(0, 4)), "[4'b0010 <- 4'b0011, 4'b0001 <- 4'b0000, default <- 4'b0000]" + }, + { b->ArrayLit(ArrayType::Get(BvType::Get(ctx, 8), BvType::Get(ctx, 4)), {}, b->BvLit(0, 4)), "[default <- 4'b0000]" } }) {} From 1afa12a0cf4c1f071d41257785be6e563c74adec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:33:05 +0200 Subject: [PATCH 22/70] Fix error regarding recursive usage of ThetaExprPrinter --- tools/gazer-theta/lib/ThetaExpr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 21356ce2..1dca127b 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -85,7 +85,7 @@ class ThetaExprPrinter : public ExprWalker const auto& kvPairs = arrLit->getMap(); if (kvPairs.size() > 0) { for (const auto& [index, elem] : kvPairs) { - arrLitStr += this->walk(index) + " <- " + this->walk(elem) + ", "; + arrLitStr += printThetaExpr(index, mReplacedNames) + " <- " + printThetaExpr(elem, mReplacedNames) + ", "; } arrLitStr += "default <- "; } else { @@ -93,7 +93,7 @@ class ThetaExprPrinter : public ExprWalker } if (arrLit->hasDefault()) { - arrLitStr += this->walk(arrLit->getDefault()); + arrLitStr += printThetaExpr(arrLit->getDefault(), mReplacedNames); } else { arrLitStr += defaultValueForType(arrLit->getType().getElementType()); } From fd97cf6b084a2ea8e2e59db7bdaa54ea912a4db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:44:21 +0200 Subject: [PATCH 23/70] Run functional tests requiring flat memory model with bitvector compatible algorithm --- test/theta/verif/memory/arrays2_fail.c | 2 +- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 2 +- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index 0cbb2c0f..c57993a0 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index 6579935e..f46a8b96 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index 8eb281f2..7240570a 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 10e3242e..20a93440 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index 5975a3c8..0b9ae027 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index c7b8808d..ad74958c 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 50213622..14cd59d5 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index a4a054e0..a234d8ce 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index 0c44ad05..6bf4320a 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index 1465eaf5..e69889aa 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index 8ac40ced..ebc6ace7 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index ef4d7024..96b10a3e 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index f46abffe..0b57f447 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index f562d97d..51a44080 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index 9debb018..1ee94812 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED From d30244e1a1f32dac2104c99f3d7112805bfdd0ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 17:47:40 +0200 Subject: [PATCH 24/70] Enable theta tests that require bitvector support --- test/theta/verif/memory/arrays1.c | 2 +- test/theta/verif/memory/arrays2_fail.c | 4 ++-- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/lit.local.cfg | 2 +- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 4 ++-- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/theta/verif/memory/arrays1.c b/test/theta/verif/memory/arrays1.c index c2769805..ae9ae021 100644 --- a/test/theta/verif/memory/arrays1.c +++ b/test/theta/verif/memory/arrays1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index c57993a0..127bc186 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); @@ -13,7 +13,7 @@ int main(void) x[i] = i; } - if (x[0] != 0) { + if (x[0] == 0) { __VERIFIER_error(); } diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index f46a8b96..de0a6dac 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index 7240570a..fdb10387 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 20a93440..75798691 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index 0b9ae027..aefbd9bf 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/lit.local.cfg b/test/theta/verif/memory/lit.local.cfg index 61864550..390d8959 100644 --- a/test/theta/verif/memory/lit.local.cfg +++ b/test/theta/verif/memory/lit.local.cfg @@ -4,4 +4,4 @@ import lit import pathlib # Disable these tests until we will have a theta-compatible memory model -config.unsupported = True +# config.unsupported = True diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index ad74958c..d5fa05ac 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 14cd59d5..90292589 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index a234d8ce..065fa831 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index 6bf4320a..9c48ee3c 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index e69889aa..bd9770e2 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index ebc6ace7..48ce0446 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index 96b10a3e..dd12fd88 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index 0b57f447..469ef2b2 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED @@ -20,7 +20,7 @@ int main(void) int prod; sumprod(a, b, &prod, &prod); - if (prod != 25) { + if (prod == 25) { __VERIFIER_error(); } diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index 51a44080..edf69d2f 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index 1ee94812..09f75915 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED From 1237309f4e9a3c1b0ecf55fc19317d35ca71ec68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 11:55:05 +0200 Subject: [PATCH 25/70] Use more efficient refinement strategy for theta/memory functional tests --- test/theta/verif/memory/arrays2_fail.c | 2 +- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/lit.local.cfg | 7 ------- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 2 +- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- 16 files changed, 15 insertions(+), 22 deletions(-) delete mode 100644 test/theta/verif/memory/lit.local.cfg diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index 127bc186..dad980af 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index de0a6dac..1dbdcb8f 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index fdb10387..58dc1a71 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 75798691..484271d8 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index aefbd9bf..1585a86c 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/lit.local.cfg b/test/theta/verif/memory/lit.local.cfg deleted file mode 100644 index 390d8959..00000000 --- a/test/theta/verif/memory/lit.local.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# -*- Python -*- - -import lit -import pathlib - -# Disable these tests until we will have a theta-compatible memory model -# config.unsupported = True diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index d5fa05ac..f41b4d40 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 90292589..ec18cab9 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index 065fa831..950a73ae 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index 9c48ee3c..a10af409 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index bd9770e2..36d4b3c4 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index 48ce0446..18b57519 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index dd12fd88..0ba7813a 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index 469ef2b2..ef0a6b0a 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index edf69d2f..85acf8ca 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index 09f75915..c1d119a2 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED From 60ecbfcd2bb62c009789c826c00788eadf53bed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 15:53:44 +0200 Subject: [PATCH 26/70] Remove tests that timeout --- test/theta/verif/memory/globals4.c | 28 ------------------------- test/theta/verif/memory/passbyref6.c | 31 ---------------------------- 2 files changed, 59 deletions(-) delete mode 100644 test/theta/verif/memory/globals4.c delete mode 100644 test/theta/verif/memory/passbyref6.c diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c deleted file mode 100644 index 1585a86c..00000000 --- a/test/theta/verif/memory/globals4.c +++ /dev/null @@ -1,28 +0,0 @@ -// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" - -// CHECK: Verification SUCCESSFUL - -int __VERIFIER_nondet_int(void); -void __VERIFIER_error(void) __attribute__((__noreturn__)); - -int a = 1; -int b = 1; -int c = 3; - -int main(void) -{ - int input = 1; - while (input != 0) { - input = __VERIFIER_nondet_int(); - if (input == 1) { - a = a + 1; - } - } - - if (a < b) { - __VERIFIER_error(); - } - - return 0; -} - diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c deleted file mode 100644 index 0ba7813a..00000000 --- a/test/theta/verif/memory/passbyref6.c +++ /dev/null @@ -1,31 +0,0 @@ -// REQUIRES: memory.burstall -// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" - -// CHECK: Verification SUCCESSFUL - -int __VERIFIER_nondet_int(void); -void __VERIFIER_error(void) __attribute__((__noreturn__)); - -void sumprod(int* a, int* b, int *sum, int *prod) -{ - *sum = *a + *b; - *prod = *a * *b; -} - -int main(void) -{ - int a = __VERIFIER_nondet_int(); - int b = a + 1; - int c = __VERIFIER_nondet_int(); - - int* p = a == 0 ? &c : &a; - - int sum, prod; - sumprod(p, &b, &sum, &prod); - - if (a != 0 && b != 0 && prod == 0) { - __VERIFIER_error(); - } - - return 0; -} From eb61fb2b67f1a67da61829565f23fb57f2c267c7 Mon Sep 17 00:00:00 2001 From: as3810t Date: Tue, 15 Sep 2020 17:20:18 +0200 Subject: [PATCH 27/70] Correct typo in licence Co-authored-by: Gyula Sallai --- tools/gazer-theta/lib/ThetaExpr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 1dca127b..098e66a6 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -12,7 +12,7 @@ // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and -// limitations under the Lic without '0b' prefixense. +// limitations under the License. // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" @@ -336,4 +336,4 @@ std::string gazer::theta::printThetaExpr(const ExprPtr& expr, std::function Date: Tue, 15 Sep 2020 17:25:02 +0200 Subject: [PATCH 28/70] Fix coding style issues Co-authored-by: Gyula Sallai --- include/gazer/Core/Expr/ExprBuilder.h | 2 +- tools/gazer-theta/lib/ThetaVerifier.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/gazer/Core/Expr/ExprBuilder.h b/include/gazer/Core/Expr/ExprBuilder.h index c6eb7bf5..b826ffcd 100644 --- a/include/gazer/Core/Expr/ExprBuilder.h +++ b/include/gazer/Core/Expr/ExprBuilder.h @@ -72,7 +72,7 @@ class ExprBuilder ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries, const ExprRef& elze) { assert(entries.size() > 0); const auto& [index, elem] = *entries.begin(); - return ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, elze); + return this->ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, elze); } ExprRef BoolLit(bool value) { return value ? True() : False(); } diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index f3705193..0d649336 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -260,9 +260,9 @@ static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> ExprRef ExprRef From 295a6373efc95530b8165edc64d938d40af0a393 Mon Sep 17 00:00:00 2001 From: radl97 Date: Sun, 20 Sep 2020 20:18:26 +0200 Subject: [PATCH 29/70] Update issue templates Add issue template for bug report --- .github/ISSUE_TEMPLATE/bug_report.md | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..2130a397 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,43 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +Exact command issued, with the input files attached. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Version (please complete the following information):** + - Version (branch, etc.) + - Theta version (if applicable) + +**Additional context** +Add any other context about the problem here. + +**Additional tips to pinpoint when the error was introduced:** + +- Run with ... and check if the error persists: + - `--no-optimize` + - `--memory=havoc --math=int` + - note that these might break soundness. Check if the CFA is correct! +Intermediate state dumps: check these files to pinpoint the problem. + - `clang -S -emit-llvm input.c` + - `gazer-cfa -pipeline ` + - This (and the next) creates one file (.function.dot) per loop and per function. + - `gazer-cfa ...` + - When running gazer-theta, check the output file From 243c37481b7050241bc7b351525ff85a4fdf7ae8 Mon Sep 17 00:00:00 2001 From: radl97 Date: Mon, 21 Sep 2020 12:02:13 +0200 Subject: [PATCH 30/70] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 2130a397..d5e5e31c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -12,12 +12,8 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error -Exact command issued, with the input files attached. +Exact command issued, with the input files attached, possibly minimized. **Expected behavior** A clear and concise description of what you expected to happen. @@ -31,13 +27,17 @@ Add any other context about the problem here. **Additional tips to pinpoint when the error was introduced:** -- Run with ... and check if the error persists: +Run with ... and check if the error persists: + - `--no-optimize` - `--memory=havoc --math=int` - note that these might break soundness. Check if the CFA is correct! + - `--debug` flag to dump more data + Intermediate state dumps: check these files to pinpoint the problem. + - `clang -S -emit-llvm input.c` - - `gazer-cfa -pipeline ` + - `gazer-cfa --run-pipeline ` - This (and the next) creates one file (.function.dot) per loop and per function. - - `gazer-cfa ...` + - `gazer-cfa ...` (this is for checking the backend only. Probably passing an optimized LLVM IR file is the best) - When running gazer-theta, check the output file From 2a61bb92144e8ab4fec4ac79a8f8838760033392 Mon Sep 17 00:00:00 2001 From: radl97 Date: Mon, 21 Sep 2020 13:25:10 +0200 Subject: [PATCH 31/70] Fix input assignments relying on ordering --- src/Automaton/RecursiveToCyclicCfa.cpp | 34 ++++++++++++++++++++------ 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/Automaton/RecursiveToCyclicCfa.cpp b/src/Automaton/RecursiveToCyclicCfa.cpp index 8d7db1fc..c713d11a 100644 --- a/src/Automaton/RecursiveToCyclicCfa.cpp +++ b/src/Automaton/RecursiveToCyclicCfa.cpp @@ -111,9 +111,10 @@ void RecursiveToCyclicTransformer::inlineCallIntoRoot(CallTransition* call, llvm rewrite[&local] = newLocal->getRefExpr(); } } - + // Clone input variables as well; we will insert an assign transition // with the initial values later. + std::vector inputTemporaries; for (Variable& input : callee->inputs()) { if (!callee->isOutput(&input)) { auto varname = (input.getName() + suffix).str(); @@ -122,6 +123,9 @@ void RecursiveToCyclicTransformer::inlineCallIntoRoot(CallTransition* call, llvm mInlinedVariables[newInput] = &input; //rewrite[input] = call->getInputArgument(i); rewrite[&input] = newInput->getRefExpr(); + + auto val = mRoot->createLocal(varname+"_", input.getType()); + inputTemporaries.emplace_back(val); } } @@ -174,20 +178,36 @@ void RecursiveToCyclicTransformer::inlineCallIntoRoot(CallTransition* call, llvm // to the entry. std::vector recursiveInputArgs; for (size_t i = 0; i < callee->getNumInputs(); ++i) { - Variable* input = callee->getInput(i); + // result variable is different then original inputs #46 + // to simulate parallel assignments + Variable* input = inputTemporaries[i]; + Variable* realInput = callee->getInput(i); - auto variable = oldVarToNew[input]; - auto value = rewrite.walk(nestedCall->getInputArgument(*input)->getValue()); + auto variable = input; + auto value = rewrite.walk(nestedCall->getInputArgument(*realInput)->getValue()); if (variable->getRefExpr() != value) { // Do not add unneeded assignments (X := X). recursiveInputArgs.push_back({ - oldVarToNew[input], - value - }); + variable, + value + }); } } + for (size_t i = 0; i < callee->getNumInputs(); ++i) { + Variable* inputTemp = inputTemporaries[i]; + Variable* realInput = callee->getInput(i); + + auto variable = oldVarToNew[realInput]; + auto value = inputTemp->getRefExpr(); + + recursiveInputArgs.push_back({ + variable, + value + }); + } + // Create the assignment back-edge. mRoot->createAssignTransition( source, locToLocMap[callee->getEntry()], From 05b4ea35d2da272dded3dd2b5db8a5435a4a9e2f Mon Sep 17 00:00:00 2001 From: Akos Hajdu Date: Tue, 22 Sep 2020 11:52:45 +0200 Subject: [PATCH 32/70] Upgrade Theta to 2.5.0 --- .travis.yml | 2 +- Dockerfile | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 285dc7fb..987119fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ addons: - python3-setuptools - python3-psutil env: -- THETA_VERSION="v2.4.0" +- THETA_VERSION="v2.5.0" script: # fetch LLVM and other dependencies - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - diff --git a/Dockerfile b/Dockerfile index 8aafa2df..2e0f92a3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:18.04 -ENV THETA_VERSION v2.4.0 +ENV THETA_VERSION v2.5.0 RUN apt-get update && \ apt-get install -y build-essential git cmake \ diff --git a/README.md b/README.md index a10e5901..9412cb84 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ It provides a user-friendly end-to-end verification workflow, with support for m Currently we support two verification backends: * `gazer-theta` leverages the power of the [theta](https://github.com/ftsrg/theta) model checking framework. - * Currently, [v2.4.0](https://github.com/ftsrg/theta/releases/tag/v2.4.0) is tested, but newer releases might also work. + * Currently, [v2.5.0](https://github.com/ftsrg/theta/releases/tag/v2.5.0) is tested, but newer releases might also work. * `gazer-bmc` is gazer's built-in bounded model checking engine. # Usage From 1fd3e57da8c1206b1558d3a190f459ef97f85524 Mon Sep 17 00:00:00 2001 From: Gyula Sallai Date: Thu, 24 Sep 2020 15:40:05 +0200 Subject: [PATCH 33/70] Bump version number to 1.0.0 --- CMakeLists.txt | 30 +++++++++++++++++++++- include/gazer/Config/gazer-config.h.cmake | 31 +++++++++++++++++++++++ src/LLVM/FrontendConfig.cpp | 5 ++-- 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 include/gazer/Config/gazer-config.h.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 73232bc5..ef46d6fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,26 @@ cmake_minimum_required(VERSION 3.8) project(gazer) +# Set version information + +if(NOT DEFINED GAZER_VERSION_MAJOR) + set(GAZER_VERSION_MAJOR 1) +endif() +if(NOT DEFINED GAZER_VERSION_MINOR) + set(GAZER_VERSION_MINOR 0) +endif() +if(NOT DEFINED GAZER_VERSION_PATCH) + set(GAZER_VERSION_PATCH 0) +endif() +if(NOT DEFINED GAZER_VERSION_SUFFIX) + set(GAZER_VERSION_SUFFIX "") +endif() + +if (NOT PACKAGE_VERSION) + set(PACKAGE_VERSION + "${GAZER_VERSION_MAJOR}.${GAZER_VERSION_MINOR}.${GAZER_VERSION_PATCH}${GAZER_VERSION_SUFFIX}") +endif() + include(ExternalProject) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") @@ -53,7 +73,10 @@ include_directories(${Boost_INCLUDE_DIR}) add_definitions(-DBOOST_NO_RTTI -DBOOST_EXCEPTION_DISABLE -DBOOST_NO_EXCEPTIONS) # Project directories -include_directories(include) +set(GAZER_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include") +set(GAZER_MAIN_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/include") + +include_directories(${GAZER_INCLUDE_DIR} ${GAZER_MAIN_INCLUDE_DIR}) # Find out which solvers are enabled set(GAZER_ENABLE_SOLVERS "z3" CACHE STRING "Semicolon-separated list of solvers to build") @@ -61,6 +84,11 @@ set(GAZER_ENABLE_SOLVERS "z3" CACHE STRING "Semicolon-separated list of solvers add_subdirectory(src) add_subdirectory(tools) +# Generate the configuration file +configure_file( + ${GAZER_INCLUDE_DIR}/gazer/Config/gazer-config.h.cmake + ${GAZER_MAIN_INCLUDE_DIR}/gazer/Config/gazer-config.h) + option(GAZER_ENABLE_UNIT_TESTS "Enable unit tests" ON) if (GAZER_ENABLE_UNIT_TESTS) diff --git a/include/gazer/Config/gazer-config.h.cmake b/include/gazer/Config/gazer-config.h.cmake new file mode 100644 index 00000000..6d864434 --- /dev/null +++ b/include/gazer/Config/gazer-config.h.cmake @@ -0,0 +1,31 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2019 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +#ifndef GAZER_CONFIG_GAZER_CONFIG_H +#define GAZER_CONFIG_GAZER_CONFIG_H + +#define GAZER_VERSION_MAJOR ${GAZER_VERSION_MAJOR} + +#define GAZER_VERSION_MINOR ${GAZER_VERSION_MINOR} + +#define GAZER_VERSION_PATCH ${GAZER_VERSION_PATCH} + +#define GAZER_VERSION_SUFFIX ${GAZER_VERSION_SUFFIX} + +#define GAZER_VERSION_STRING "${PACKAGE_VERSION}" + +#endif \ No newline at end of file diff --git a/src/LLVM/FrontendConfig.cpp b/src/LLVM/FrontendConfig.cpp index de0ea3b2..bb5b228b 100644 --- a/src/LLVM/FrontendConfig.cpp +++ b/src/LLVM/FrontendConfig.cpp @@ -18,6 +18,7 @@ #include "gazer/LLVM/LLVMFrontend.h" #include "gazer/LLVM/Instrumentation/DefaultChecks.h" #include "gazer/Support/Warnings.h" +#include "gazer/Config/gazer-config.h" #include #include @@ -108,6 +109,6 @@ void FrontendConfig::createChecks(std::vector>& checks) void FrontendConfigWrapper::PrintVersion(llvm::raw_ostream& os) { os << "gazer - a formal verification frontend\n"; - os << " version 0.1\n"; - os << " LLVM version 9.0\n"; + os.indent(2) << "version " << GAZER_VERSION_STRING << "\n"; + os.indent(2) << "LLVM version " << LLVM_VERSION_STRING << "\n"; } From 0576ab93c4034915c766407435e798d633b3438b Mon Sep 17 00:00:00 2001 From: Akos Hajdu Date: Thu, 24 Sep 2020 17:43:16 +0200 Subject: [PATCH 34/70] Add info on versioning/PRs in docs --- doc/Contribution.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/Contribution.md b/doc/Contribution.md index 302b7b95..0061edd5 100644 --- a/doc/Contribution.md +++ b/doc/Contribution.md @@ -1,5 +1,16 @@ # Contribution Guidelines +## General + +As the main repository is read-only, we suggest you to create your own [fork](https://help.github.com/articles/fork-a-repo/). +Within your fork, we also recommend to create new _branches_ for your development. +This enables us later on to easily integrate your work into the main repository by using [pull requests](https://help.github.com/articles/about-pull-requests/). + +As the framework is under development, we suggest you to [sync your fork](https://help.github.com/articles/syncing-a-fork/) often and merge the master branch into your development branch(es). + +Gazer uses [semantic versioning](https://semver.org/) in a `MAJOR.MINOR.PATCH` format, e.g., `1.2.3`. +The preferred development workflow is to bump the version number (see `CMakeLists.txt `) each time a PR gets merged. + ## Coding style and naming convention You can use `clang-format` with our provided style configuration file to reformat source code files to the appropriate coding style before commiting a patch. From 2b1ecb2b3cd3cb07f47e58e8983c7c6fc3fe27a4 Mon Sep 17 00:00:00 2001 From: Gyula Sallai Date: Wed, 5 Aug 2020 21:00:24 +0200 Subject: [PATCH 35/70] Rework checks and fix signed overflow check --- include/gazer/LLVM/Instrumentation/Check.h | 11 +- .../gazer/LLVM/Instrumentation/Intrinsics.h | 4 +- include/gazer/LLVM/Transform/Passes.h | 2 + src/LLVM/Automaton/InstToExpr.cpp | 3 - src/LLVM/Automaton/ModuleToAutomata.cpp | 5 +- src/LLVM/CMakeLists.txt | 5 +- src/LLVM/ClangFrontend.cpp | 5 +- src/LLVM/FrontendConfig.cpp | 1 - src/LLVM/Instrumentation/Check.cpp | 41 +++ .../Checks/AssertionFailCheck.cpp | 77 +++++ .../Checks/DivisionByZeroCheck.cpp | 104 ++++++ .../Checks/SignedIntegerOverflowCheck.cpp | 202 +++++++++++ src/LLVM/Instrumentation/DefaultChecks.cpp | 323 ------------------ src/LLVM/Instrumentation/Intrinsics.cpp | 1 - src/LLVM/LLVMFrontend.cpp | 1 + src/LLVM/LLVMTraceBuilder.cpp | 3 + .../Transform/LoopExitCanonizationPass.cpp | 115 +++++++ test/lit.cfg | 2 +- test/theta/verif/overflow/overflow_loops.c | 23 ++ test/theta/verif/overflow/overflow_simple.c | 14 + test/verif/overflow/overflow_loops.c | 23 ++ test/verif/overflow/overflow_simple.c | 15 + test/verif/svcomp/locks/test_locks_14_false.c | 2 + 23 files changed, 645 insertions(+), 337 deletions(-) create mode 100644 src/LLVM/Instrumentation/Checks/AssertionFailCheck.cpp create mode 100644 src/LLVM/Instrumentation/Checks/DivisionByZeroCheck.cpp create mode 100644 src/LLVM/Instrumentation/Checks/SignedIntegerOverflowCheck.cpp delete mode 100644 src/LLVM/Instrumentation/DefaultChecks.cpp create mode 100644 src/LLVM/Transform/LoopExitCanonizationPass.cpp create mode 100644 test/theta/verif/overflow/overflow_loops.c create mode 100644 test/theta/verif/overflow/overflow_simple.c create mode 100644 test/verif/overflow/overflow_loops.c create mode 100644 test/verif/overflow/overflow_simple.c diff --git a/include/gazer/LLVM/Instrumentation/Check.h b/include/gazer/LLVM/Instrumentation/Check.h index ec0123fa..cf3e7028 100644 --- a/include/gazer/LLVM/Instrumentation/Check.h +++ b/include/gazer/LLVM/Instrumentation/Check.h @@ -52,12 +52,21 @@ class Check : public llvm::ModulePass virtual bool mark(llvm::Function& function) = 0; protected: - /// Creates an error block with a gazer.error_code(i16 code) call and a terminating unreachable instruction. llvm::BasicBlock* createErrorBlock( llvm::Function& function, const llvm::Twine& name = "", llvm::Instruction* location = nullptr ); + /// Replaces all instructions matching the given predicate with an error call. + /// This function assumes that all instructions that follow a matching instruction within the + /// block are unreachable. + /// \return True if there were any matches; false otherwise. + bool replaceMatchingUnreachableWithError( + llvm::Function& function, + const llvm::Twine& errorBlockName, + std::function predicate + ); + CheckRegistry& getRegistry() const; private: diff --git a/include/gazer/LLVM/Instrumentation/Intrinsics.h b/include/gazer/LLVM/Instrumentation/Intrinsics.h index 084a6ee8..4ad3cfe0 100644 --- a/include/gazer/LLVM/Instrumentation/Intrinsics.h +++ b/include/gazer/LLVM/Instrumentation/Intrinsics.h @@ -50,7 +50,7 @@ class GazerIntrinsic enum class Overflow { - SAdd, UAdd, SSub, USub, SMul, UMul, SDiv, Shl + SAdd, UAdd, SSub, USub, SMul, UMul }; public: @@ -76,8 +76,6 @@ class GazerIntrinsic /// Returns a 'gazer.KIND.no_overflow.T(T left, T right)' intrinsic. static llvm::FunctionCallee GetOrInsertOverflowCheck(llvm::Module& module, Overflow kind, llvm::Type* type); - - static bool isPredicate(llvm::Function& function); }; } diff --git a/include/gazer/LLVM/Transform/Passes.h b/include/gazer/LLVM/Transform/Passes.h index 5d9800d8..bce13d39 100644 --- a/include/gazer/LLVM/Transform/Passes.h +++ b/include/gazer/LLVM/Transform/Passes.h @@ -39,6 +39,8 @@ llvm::Pass* createNormalizeVerifierCallsPass(); /// A simpler (and more restricted) inlining pass. llvm::Pass* createSimpleInlinerPass(llvm::Function& entry, InlineLevel level); +llvm::Pass* createCanonizeLoopExitsPass(); + } #endif diff --git a/src/LLVM/Automaton/InstToExpr.cpp b/src/LLVM/Automaton/InstToExpr.cpp index c623ba0d..c426f113 100644 --- a/src/LLVM/Automaton/InstToExpr.cpp +++ b/src/LLVM/Automaton/InstToExpr.cpp @@ -636,7 +636,6 @@ static GazerIntrinsic::Overflow getOverflowKind(llvm::StringRef name) HANDLE_PREFIX(GazerIntrinsic::SAddNoOverflowPrefix, SAdd) HANDLE_PREFIX(GazerIntrinsic::SSubNoOverflowPrefix, SSub) HANDLE_PREFIX(GazerIntrinsic::SMulNoOverflowPrefix, SMul) - HANDLE_PREFIX(GazerIntrinsic::SDivNoOverflowPrefix, SDiv) #undef HANDLE_PREFIX @@ -724,7 +723,6 @@ ExprPtr InstToExpr::handleOverflowPredicate(const llvm::CallInst& call) case GazerIntrinsic::Overflow::SAdd: result = mExprBuilder.Add(left, right); break; case GazerIntrinsic::Overflow::SSub: result = mExprBuilder.Sub(left, right); break; case GazerIntrinsic::Overflow::SMul: result = mExprBuilder.Mul(left, right); break; - case GazerIntrinsic::Overflow::SDiv: result = mExprBuilder.Div(left, right); break; default: llvm_unreachable("Unknown overflow kind!"); } @@ -754,7 +752,6 @@ ExprPtr InstToExpr::handleOverflowPredicate(const llvm::CallInst& call) case GazerIntrinsic::Overflow::SAdd: return handleSAddOverflow(left, right, mExprBuilder); case GazerIntrinsic::Overflow::SSub: return handleSSubOverflow(left, right, mExprBuilder); case GazerIntrinsic::Overflow::SMul: return handleSMulOverflow(left, right, mExprBuilder); - case GazerIntrinsic::Overflow::SDiv: return handleSDivOverflow(left, right, mExprBuilder); default: llvm_unreachable("Unknown overflow kind!"); } diff --git a/src/LLVM/Automaton/ModuleToAutomata.cpp b/src/LLVM/Automaton/ModuleToAutomata.cpp index 7aa65e92..18ad9062 100644 --- a/src/LLVM/Automaton/ModuleToAutomata.cpp +++ b/src/LLVM/Automaton/ModuleToAutomata.cpp @@ -326,6 +326,7 @@ void ModuleToCfa::createAutomata() // Create locations for the blocks for (BasicBlock* bb : loopOnlyBlocks) { + LLVM_DEBUG(llvm::dbgs() << "[LoopOnly] " << bb->getName() << "\n"); Location* entry = nested->createLocation(); Location* exit = isErrorBlock(bb) ? nested->createErrorLocation() : nested->createLocation(); @@ -382,12 +383,14 @@ void ModuleToCfa::createAutomata() // For the local variables, we only need to add the values not present in any of the loops. for (BasicBlock& bb : function) { + LLVM_DEBUG(llvm::dbgs() << "Translating function-level block " << bb.getName() << "\n"); for (Instruction& inst : bb) { + LLVM_DEBUG(llvm::dbgs().indent(2) << "Instruction " << inst.getName() << "\n"); if (auto loop = loopInfo->getLoopFor(&bb)) { // If the variable is an output of a loop, add it here as a local variable Variable* output = mGenCtx.getLoopCfa(loop).findOutput(&inst); if (output == nullptr && !hasUsesInBlockRange(&inst, functionBlocks)) { - LLVM_DEBUG(llvm::dbgs() << "Not adding " << inst << "\n"); + LLVM_DEBUG(llvm::dbgs().indent(4) << "Not adding (no uses in function) " << inst << "\n"); continue; } } diff --git a/src/LLVM/CMakeLists.txt b/src/LLVM/CMakeLists.txt index 8f6ccff2..a9911068 100644 --- a/src/LLVM/CMakeLists.txt +++ b/src/LLVM/CMakeLists.txt @@ -8,7 +8,6 @@ set(SOURCE_FILES Transform/TransformUtils.cpp Instrumentation/MarkFunctionEntries.cpp Instrumentation/Check.cpp - Instrumentation/DefaultChecks.cpp Instrumentation/Intrinsics.cpp Trace/TestHarnessGenerator.cpp Automaton/ModuleToAutomata.cpp @@ -32,7 +31,9 @@ set(SOURCE_FILES Automaton/ExtensionPoints.cpp Automaton/ValueOrMemoryObject.cpp Analysis/PDG.cpp -) + Instrumentation/Checks/AssertionFailCheck.cpp + Instrumentation/Checks/DivisionByZeroCheck.cpp + Instrumentation/Checks/SignedIntegerOverflowCheck.cpp Transform/LoopExitCanonizationPass.cpp) llvm_map_components_to_libnames(GAZER_LLVM_LIBS core irreader transformutils scalaropts ipo) message(STATUS "Using LLVM libraries: ${GAZER_LLVM_LIBS}") diff --git a/src/LLVM/ClangFrontend.cpp b/src/LLVM/ClangFrontend.cpp index 53f45fec..0405babe 100644 --- a/src/LLVM/ClangFrontend.cpp +++ b/src/LLVM/ClangFrontend.cpp @@ -240,6 +240,9 @@ void ClangOptions::addSanitizerFlag(llvm::StringRef flag) void ClangOptions::createArgumentList(std::vector& args) { if (!mSanitizerFlags.empty()) { - args.emplace_back("-fsanitize-trap=" + llvm::join(mSanitizerFlags, ",")); + auto sanitizerNames = llvm::join(mSanitizerFlags, ","); + + args.emplace_back("-fsanitize=" + sanitizerNames); + args.emplace_back("-fno-sanitize-recover=" + sanitizerNames); } } diff --git a/src/LLVM/FrontendConfig.cpp b/src/LLVM/FrontendConfig.cpp index bb5b228b..1b2d17f4 100644 --- a/src/LLVM/FrontendConfig.cpp +++ b/src/LLVM/FrontendConfig.cpp @@ -83,7 +83,6 @@ void FrontendConfig::createChecks(std::vector>& checks) // Do the defaults fragments.push_back("assertion-fail"); fragments.push_back("div-by-zero"); - fragments.push_back("signed-overflow"); } else if (filter == AllChecksSetting) { // Add all registered checks for (auto& [name, factory] : mFactories) { diff --git a/src/LLVM/Instrumentation/Check.cpp b/src/LLVM/Instrumentation/Check.cpp index 1555c825..3f09c06a 100644 --- a/src/LLVM/Instrumentation/Check.cpp +++ b/src/LLVM/Instrumentation/Check.cpp @@ -76,6 +76,47 @@ llvm::BasicBlock* Check::createErrorBlock( return errorBB; } +bool Check::replaceMatchingUnreachableWithError( + llvm::Function& function, + const llvm::Twine& errorBlockName, + std::function predicate) +{ + llvm::SmallVector errorCalls; + for (Instruction& inst : llvm::instructions(function)) { + if (predicate(inst)) { + errorCalls.emplace_back(&inst); + } + } + + if (errorCalls.empty()) { + return false; + } + + for (llvm::Instruction* inst : errorCalls) { + // Replace error calls with an unconditional jump to an error block + BasicBlock* errorBB = this->createErrorBlock( + function, + errorBlockName, + inst + ); + + // Remove all instructions from the error call to the terminator + auto it = inst->getIterator(); + auto terminator = inst->getParent()->getTerminator()->getIterator(); + while (it != terminator) { + auto instToDelete = it++; + instToDelete->eraseFromParent(); + } + + llvm::ReplaceInstWithInst( + &*terminator, + llvm::BranchInst::Create(errorBB) + ); + } + + return true; +} + CheckRegistry& Check::getRegistry() const { return *mRegistry; } void Check::setCheckRegistry(CheckRegistry& registry) diff --git a/src/LLVM/Instrumentation/Checks/AssertionFailCheck.cpp b/src/LLVM/Instrumentation/Checks/AssertionFailCheck.cpp new file mode 100644 index 00000000..cb2ed852 --- /dev/null +++ b/src/LLVM/Instrumentation/Checks/AssertionFailCheck.cpp @@ -0,0 +1,77 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2020 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +#include "gazer/LLVM/Instrumentation/DefaultChecks.h" + +#include +#include + +using namespace gazer; +using namespace llvm; + +namespace +{ + +/// This check ensures that no assertion failure instructions are reachable. +class AssertionFailCheck final : public Check +{ +public: + static char ID; + + AssertionFailCheck() + : Check(ID) + {} + + bool mark(llvm::Function& function) override; + + llvm::StringRef getErrorDescription() const override { return "Assertion failure"; } +}; + +} // namespace + +char AssertionFailCheck::ID; + +static bool isCallToErrorFunction(llvm::Instruction& inst) +{ + auto call = llvm::dyn_cast(&inst); + if (call == nullptr) { + return false; + } + + if (call->getCalledFunction() == nullptr) { + return false; + } + + auto name = call->getCalledFunction()->getName(); + + return name == "__VERIFIER_error" + || name == "__assert_fail" + || name == "__gazer_error" + || name == "reach_error"; +} + +bool AssertionFailCheck::mark(llvm::Function &function) +{ + return this->replaceMatchingUnreachableWithError( + function, "error.assert_fail", isCallToErrorFunction + ); +} + +std::unique_ptr gazer::checks::createAssertionFailCheck(ClangOptions& options) +{ + return std::make_unique(); +} diff --git a/src/LLVM/Instrumentation/Checks/DivisionByZeroCheck.cpp b/src/LLVM/Instrumentation/Checks/DivisionByZeroCheck.cpp new file mode 100644 index 00000000..e09d19f6 --- /dev/null +++ b/src/LLVM/Instrumentation/Checks/DivisionByZeroCheck.cpp @@ -0,0 +1,104 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2020 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +#include "gazer/LLVM/Instrumentation/DefaultChecks.h" + +#include +#include +#include + +using namespace gazer; +using namespace llvm; + +namespace +{ + +/// Checks for division by zero errors. +class DivisionByZeroCheck final : public Check +{ +public: + static char ID; + + DivisionByZeroCheck() + : Check(ID) + {} + + bool mark(llvm::Function& function) override; + + llvm::StringRef getErrorDescription() const override + { + return "Divison by zero"; + } +}; + +} // namespace + +char DivisionByZeroCheck::ID; + +static bool isDivisionInst(unsigned opcode) +{ + return opcode == Instruction::SDiv || opcode == Instruction::UDiv; +} + +bool DivisionByZeroCheck::mark(llvm::Function& function) +{ + auto& context = function.getContext(); + + std::vector divs; + for (llvm::Instruction& inst : instructions(function)) { + if (isDivisionInst(inst.getOpcode())) { + divs.push_back(&inst); + } + } + + if (divs.empty()) { + return false; + } + + IRBuilder<> builder(context); + for (llvm::Instruction* inst : divs) { + BasicBlock* errorBB = this->createErrorBlock( + function, + "error.divzero", + inst + ); + + BasicBlock* bb = inst->getParent(); + llvm::Value* rhs = inst->getOperand(1); + + builder.SetInsertPoint(inst); + auto icmp = builder.CreateICmpNE( + rhs, builder.getInt(llvm::APInt( + rhs->getType()->getIntegerBitWidth(), 0 + )) + ); + + BasicBlock* newBB = bb->splitBasicBlock(inst); + builder.ClearInsertionPoint(); + llvm::ReplaceInstWithInst( + bb->getTerminator(), + builder.CreateCondBr(icmp, newBB, errorBB) + ); + } + + return true; +} + +std::unique_ptr gazer::checks::createDivisionByZeroCheck(ClangOptions& options) +{ + return std::make_unique(); +} diff --git a/src/LLVM/Instrumentation/Checks/SignedIntegerOverflowCheck.cpp b/src/LLVM/Instrumentation/Checks/SignedIntegerOverflowCheck.cpp new file mode 100644 index 00000000..079988cb --- /dev/null +++ b/src/LLVM/Instrumentation/Checks/SignedIntegerOverflowCheck.cpp @@ -0,0 +1,202 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2020 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +#include "gazer/LLVM/Instrumentation/DefaultChecks.h" +#include "gazer/LLVM/Instrumentation/Intrinsics.h" +#include "gazer/Support/Warnings.h" + +#include +#include +#include +#include +#include + +using namespace gazer; +using namespace llvm; + +namespace +{ + +class SignedIntegerOverflowCheck final : public Check +{ + static constexpr char IntrinsicPattern[] = "^llvm\\.(u|s)(add|sub|mul)\\.with\\.overflow\\.i([0-9]+)$"; +public: + static char ID; + + SignedIntegerOverflowCheck() + : Check(ID), mIntrinsicRegex(IntrinsicPattern) + {} + + bool mark(llvm::Function& function) override; + + StringRef getErrorDescription() const override + { + return "Signed integer overflow"; + } +private: + bool isOverflowIntrinsic(llvm::Function* callee, GazerIntrinsic::Overflow* overflowKind); + +private: + llvm::Regex mIntrinsicRegex; +}; + +} // namespace + +char SignedIntegerOverflowCheck::ID; + +bool SignedIntegerOverflowCheck::isOverflowIntrinsic( + llvm::Function* callee, + GazerIntrinsic::Overflow* overflowKind) +{ + if (callee == nullptr) { + return false; + } + + // [ input, signedness, op, width ] + llvm::SmallVector groups; + if (!mIntrinsicRegex.match(callee->getName(), &groups)) { + return false; + } + + // Determine signedness + bool isSigned; + if (groups[1] == "s") { + isSigned = true; + } else if (groups[1] == "u") { + isSigned = false; + } else { + llvm_unreachable("Unknown overflow intrinsic signedness!"); + } + + llvm::StringRef op = groups[2]; + if (isSigned) { + *overflowKind = llvm::StringSwitch(op) + .Case("add", GazerIntrinsic::Overflow::SAdd) + .Case("sub", GazerIntrinsic::Overflow::SSub) + .Case("mul", GazerIntrinsic::Overflow::SMul); + } else { + *overflowKind = llvm::StringSwitch(op) + .Case("add", GazerIntrinsic::Overflow::UAdd) + .Case("sub", GazerIntrinsic::Overflow::USub) + .Case("mul", GazerIntrinsic::Overflow::UMul); + } + + return true; +} + +static bool isOverflowTrapCall(llvm::Instruction& inst) +{ + auto call = llvm::dyn_cast(&inst); + if (call == nullptr) { + return false; + } + + auto callee = call->getCalledFunction(); + if (callee == nullptr) { + return false; + } + + auto name = callee->getName(); + + return name == "__ubsan_handle_add_overflow_abort" + || name == "__ubsan_handle_sub_overflow_abort" + || name == "__ubsan_handle_mul_overflow_abort"; +} + +bool SignedIntegerOverflowCheck::mark(llvm::Function &function) +{ + bool modified = false; + + llvm::Module& module = *function.getParent(); + llvm::IRBuilder<> builder(module.getContext()); + + llvm::SmallVector, 16> targets; + llvm::SmallVector sanitizerCalls; + + for (Instruction& inst : instructions(function)) { + if (auto call = dyn_cast(&inst)) { + GazerIntrinsic::Overflow ovrKind; + if (this->isOverflowIntrinsic(call->getCalledFunction(), &ovrKind)) { + targets.emplace_back(call, ovrKind); + } + } + } + + // A call to `llvm.*.with.overflow.iN` returns a {iN, i1} pair where the + // second element is the flag which tells us whether an overflow has occured. + // As such, we will replace all uses of the second element with our own overflow + // check, and all uses of the first element with the actual operation. + for (auto& [call, ovrKind] : targets) { + llvm::Type* valTy = call->getType()->getStructElementType(0); + + auto lhs = call->getArgOperand(0); + auto rhs = call->getArgOperand(1); + + auto overflowCheckFn = GazerIntrinsic::GetOrInsertOverflowCheck(module, ovrKind, valTy); + + builder.SetInsertPoint(call); + auto check = builder.CreateCall(overflowCheckFn, { lhs, rhs }, "ovr_check"); + auto checkFail = builder.CreateNot(check); + + llvm::Value* binOp = nullptr; + switch (ovrKind) { + case GazerIntrinsic::Overflow::SAdd: binOp = builder.CreateAdd(lhs, rhs, "", /*HasNUW=*/false, /*HasNSW=*/true); break; + case GazerIntrinsic::Overflow::SSub: binOp = builder.CreateSub(lhs, rhs, "", /*HasNUW=*/false, /*HasNSW=*/true); break; + case GazerIntrinsic::Overflow::SMul: binOp = builder.CreateMul(lhs, rhs, "", /*HasNUW=*/false, /*HasNSW=*/true); break; + case GazerIntrinsic::Overflow::UAdd: binOp = builder.CreateAdd(lhs, rhs, "", /*HasNUW=*/true, /*HasNSW=*/false); break; + case GazerIntrinsic::Overflow::USub: binOp = builder.CreateSub(lhs, rhs, "", /*HasNUW=*/true, /*HasNSW=*/false); break; + case GazerIntrinsic::Overflow::UMul: binOp = builder.CreateMul(lhs, rhs, "", /*HasNUW=*/true, /*HasNSW=*/false); break; + } + + assert(binOp != nullptr && "Unknown overflow kind!"); + + // Check the uses of 'call' + for (auto ui = call->user_begin(), ue = call->user_end(); ui != ue;) { + auto current = ui++; + if (auto extract = llvm::dyn_cast(*current)) { + unsigned firstIdx = extract->getIndices()[0]; + if (firstIdx == 0) { + extract->replaceAllUsesWith(binOp); + } else if (firstIdx == 1) { + extract->replaceAllUsesWith(checkFail); + } else { + llvm_unreachable("Unknown overflow struct index!"); + } + + extract->dropAllReferences(); + extract->eraseFromParent(); + } + } + + call->dropAllReferences(); + call->eraseFromParent(); + + modified = true; + } + + // Find trap calls and replace them with our own error block + modified |= this->replaceMatchingUnreachableWithError(function, "error.signed_overflow", isOverflowTrapCall); + + return modified; +} + +std::unique_ptr gazer::checks::createSignedIntegerOverflowCheck(ClangOptions& options) +{ + options.addSanitizerFlag("signed-integer-overflow"); + return std::make_unique(); +} + diff --git a/src/LLVM/Instrumentation/DefaultChecks.cpp b/src/LLVM/Instrumentation/DefaultChecks.cpp deleted file mode 100644 index 14e73bc5..00000000 --- a/src/LLVM/Instrumentation/DefaultChecks.cpp +++ /dev/null @@ -1,323 +0,0 @@ -//==-------------------------------------------------------------*- C++ -*--==// -// -// Copyright 2019 Contributors to the Gazer project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -#include "gazer/LLVM/Instrumentation/DefaultChecks.h" -#include "gazer/LLVM/Instrumentation/Intrinsics.h" - -#include -#include -#include -#include -#include - -using namespace gazer; -using namespace llvm; - -namespace -{ - -bool isCallToErrorFunction(llvm::Instruction& inst) { - auto call = llvm::dyn_cast(&inst); - if (call == nullptr) { - return false; - } - - if (call->getCalledFunction() == nullptr) { - return false; - } - - auto name = call->getCalledFunction()->getName(); - - return name == "__VERIFIER_error" - || name == "__assert_fail" - || name == "__gazer_error" - || name == "reach_error"; -} - -/// This check ensures that no assertion failure instructions are reachable. -class AssertionFailCheck final : public Check -{ -public: - static char ID; - - AssertionFailCheck() - : Check(ID) - {} - - bool mark(llvm::Function& function) override - { - llvm::SmallVector errorCalls; - for (Instruction& inst : llvm::instructions(function)) { - if (isCallToErrorFunction(inst)) { - errorCalls.emplace_back(&inst); - } - } - - for (llvm::Instruction* inst : errorCalls) { - // Replace error calls with an unconditional jump to an error block - BasicBlock* errorBB = this->createErrorBlock( - function, - "error.assert_fail", - inst - ); - - // Remove all instructions from the error call to the terminator - auto it = inst->getIterator(); - auto terminator = inst->getParent()->getTerminator()->getIterator(); - while (it != terminator) { - auto instToDelete = it++; - instToDelete->eraseFromParent(); - } - - llvm::ReplaceInstWithInst( - &*terminator, - llvm::BranchInst::Create(errorBB) - ); - } - - return true; - } - - llvm::StringRef getErrorDescription() const override { return "Assertion failure"; } -}; - -bool isDiv(unsigned opcode) { - return opcode == Instruction::SDiv || opcode == Instruction::UDiv; -} - -/// Checks for division by zero errors. -class DivisionByZeroCheck final : public Check -{ -public: - static char ID; - - DivisionByZeroCheck() - : Check(ID) - {} - - bool mark(llvm::Function& function) override - { - auto& context = function.getContext(); - - std::vector divs; - for (llvm::Instruction& inst : instructions(function)) { - if (isDiv(inst.getOpcode())) { - divs.push_back(&inst); - } - } - - if (divs.empty()) { - return false; - } - - unsigned divCnt = 0; - IRBuilder<> builder(context); - for (llvm::Instruction* inst : divs) { - BasicBlock* errorBB = this->createErrorBlock( - function, - "error.divzero" + llvm::Twine(divCnt++), - inst - ); - - BasicBlock* bb = inst->getParent(); - llvm::Value* rhs = inst->getOperand(1); - - builder.SetInsertPoint(inst); - auto icmp = builder.CreateICmpNE( - rhs, builder.getInt(llvm::APInt( - rhs->getType()->getIntegerBitWidth(), 0 - )) - ); - - BasicBlock* newBB = bb->splitBasicBlock(inst); - builder.ClearInsertionPoint(); - llvm::ReplaceInstWithInst( - bb->getTerminator(), - builder.CreateCondBr(icmp, newBB, errorBB) - ); - } - - return true; - } - - llvm::StringRef getErrorDescription() const override { return "Divison by zero"; } -}; - -/// Checks for over- and underflow in signed integer operations. -class SignedIntegerOverflowCheck : public Check -{ - static constexpr char IntrinsicPattern[] = "^llvm\\.(u|s)(add|sub|mul)\\.with\\.overflow\\.i([0-9]+)$"; -public: - static char ID; - - SignedIntegerOverflowCheck() - : Check(ID), mIntrinsicRegex(IntrinsicPattern) - {} - - bool mark(llvm::Function& function) override; - - llvm::StringRef getErrorDescription() const override { return "Signed integer overflow"; } -private: - bool isOverflowIntrinsic(llvm::Function* callee, GazerIntrinsic::Overflow* ovrKind); - bool isSanitizerCall(llvm::Function* callee); - -private: - llvm::Regex mIntrinsicRegex; -}; - -char DivisionByZeroCheck::ID; -char AssertionFailCheck::ID; -char SignedIntegerOverflowCheck::ID; - -} // end anonymous namespace - -bool SignedIntegerOverflowCheck::isOverflowIntrinsic(llvm::Function* callee, GazerIntrinsic::Overflow* ovrKind) -{ - if (callee == nullptr) { - return false; - } - - // [ input, signedness, op, width ] - llvm::SmallVector groups; - if (!mIntrinsicRegex.match(callee->getName(), &groups)) { - return false; - } - - // Determine signedness - bool isSigned; - if (groups[1] == "s") { - isSigned = true; - } else if (groups[1] == "u") { - isSigned = false; - } else { - llvm_unreachable("Unknown overflow intrinsic signedness!"); - } - - llvm::StringRef op = groups[2]; - if (op == "add") { - *ovrKind = isSigned ? GazerIntrinsic::Overflow::SAdd : GazerIntrinsic::Overflow::UAdd; - } else if (op == "sub") { - *ovrKind = isSigned ? GazerIntrinsic::Overflow::SSub : GazerIntrinsic::Overflow::USub; - } else if (op == "mul") { - *ovrKind = isSigned ? GazerIntrinsic::Overflow::SMul : GazerIntrinsic::Overflow::UMul; - } else { - llvm_unreachable("Unknown overflow intrinsic operation!"); - } - - return true; -} - -bool SignedIntegerOverflowCheck::mark(llvm::Function& function) -{ - llvm::Module& module = *function.getParent(); - llvm::IRBuilder<> builder(module.getContext()); - - llvm::SmallVector, 16> targets; - llvm::SmallVector sanitizerCalls; - - for (Instruction& inst : instructions(function)) { - if (auto call = dyn_cast(&inst)) { - GazerIntrinsic::Overflow ovrKind; - if (this->isOverflowIntrinsic(call->getCalledFunction(), &ovrKind)) { - targets.emplace_back(call, ovrKind); - } - } - } - - // A call to `llvm.*.with.overflow.iN` returns a {iN, i1} pair where the - // second element is the flag which tells us whether an overflow has occured. - // As such, we will replace all uses of the second element with our own overflow - // check, and all uses of the first element with the actual operation. - for (auto& [call, ovrKind] : targets) { - llvm::Type* valTy = call->getType()->getStructElementType(0); - - auto lhs = call->getArgOperand(0); - auto rhs = call->getArgOperand(1); - - auto fn = GazerIntrinsic::GetOrInsertOverflowCheck(module, ovrKind, valTy); - - builder.SetInsertPoint(call); - auto check = builder.CreateCall(fn, { lhs, rhs }, "ovr_check"); - auto ovrFail = builder.CreateNot(check); - - auto prev = builder.GetInsertPoint(); - - llvm::Value* binOp; - switch (ovrKind) { - case GazerIntrinsic::Overflow::SAdd: binOp = builder.CreateAdd(lhs, rhs, "", /*HasNUW=*/false, /*HasNSW=*/true); break; - case GazerIntrinsic::Overflow::SSub: binOp = builder.CreateSub(lhs, rhs, "", /*HasNUW=*/false, /*HasNSW=*/true); break; - case GazerIntrinsic::Overflow::SMul: binOp = builder.CreateMul(lhs, rhs, "", /*HasNUW=*/false, /*HasNSW=*/true); break; - case GazerIntrinsic::Overflow::UAdd: binOp = builder.CreateAdd(lhs, rhs, "", /*HasNUW=*/true, /*HasNSW=*/false); break; - case GazerIntrinsic::Overflow::USub: binOp = builder.CreateSub(lhs, rhs, "", /*HasNUW=*/true, /*HasNSW=*/false); break; - case GazerIntrinsic::Overflow::UMul: binOp = builder.CreateMul(lhs, rhs, "", /*HasNUW=*/true, /*HasNSW=*/false); break; - } - - assert(binOp != nullptr && "Unknown overflow kind!"); - - BasicBlock* bb = call->getParent(); - BasicBlock* errorBB = this->createErrorBlock(function, "error.ovr", call); - - BasicBlock* newBB = bb->splitBasicBlock(std::next(prev)); - builder.ClearInsertionPoint(); - llvm::ReplaceInstWithInst( - bb->getTerminator(), - builder.CreateCondBr(check, newBB, errorBB) - ); - - // Clean up the original sanitizer instrumentation - - auto ui = call->user_begin(); - auto ue = call->user_end(); - - while (ui != ue) { - auto curr = ui++; - if (auto extract = dyn_cast(*curr)) { - unsigned index = extract->getIndices()[0]; - if (index == 0) { - extract->replaceAllUsesWith(binOp); - } else if (index == 1) { - extract->replaceAllUsesWith(ovrFail); - } else { - llvm_unreachable("Unknown index for a { iN, i1 } struct!"); - } - extract->dropAllReferences(); - extract->eraseFromParent(); - } - } - - call->dropAllReferences(); - call->eraseFromParent(); - } - - return true; -} - -std::unique_ptr gazer::checks::createDivisionByZeroCheck(ClangOptions& options) -{ - return std::make_unique(); -} - -std::unique_ptr gazer::checks::createAssertionFailCheck(ClangOptions& options) -{ - return std::make_unique(); -} - -std::unique_ptr gazer::checks::createSignedIntegerOverflowCheck(ClangOptions& options) -{ - options.addSanitizerFlag("signed-integer-overflow"); - return std::make_unique(); -} diff --git a/src/LLVM/Instrumentation/Intrinsics.cpp b/src/LLVM/Instrumentation/Intrinsics.cpp index 9b05dbb9..b6d298e2 100644 --- a/src/LLVM/Instrumentation/Intrinsics.cpp +++ b/src/LLVM/Instrumentation/Intrinsics.cpp @@ -108,7 +108,6 @@ llvm::FunctionCallee GazerIntrinsic::GetOrInsertOverflowCheck(llvm::Module& modu case Overflow::USub: name = USubNoOverflowPrefix; break; case Overflow::SMul: name = SMulNoOverflowPrefix; break; case Overflow::UMul: name = UMulNoOverflowPrefix; break; - case Overflow::SDiv: name = SDivNoOverflowPrefix; break; default: llvm_unreachable("Unknown overflow kind!"); } diff --git a/src/LLVM/LLVMFrontend.cpp b/src/LLVM/LLVMFrontend.cpp index b3debc1f..b85059b4 100644 --- a/src/LLVM/LLVMFrontend.cpp +++ b/src/LLVM/LLVMFrontend.cpp @@ -373,6 +373,7 @@ void LLVMFrontend::registerLateOptimizations() // to work properly as it relies on loop preheaders being available. mPassManager.add(llvm::createCFGSimplificationPass()); mPassManager.add(llvm::createLoopSimplifyPass()); + mPassManager.add(gazer::createCanonizeLoopExitsPass()); } auto LLVMFrontend::FromInputFile( diff --git a/src/LLVM/LLVMTraceBuilder.cpp b/src/LLVM/LLVMTraceBuilder.cpp index 07d12f74..269586e7 100644 --- a/src/LLVM/LLVMTraceBuilder.cpp +++ b/src/LLVM/LLVMTraceBuilder.cpp @@ -273,6 +273,9 @@ auto LLVMTraceBuilder::build( undefs.insert(call); } else if (callee->getName().startswith("gazer.dummy")) { // These functions are the part of an "invisible" instrumentation and should be ignored. + } else if (callee->getName().startswith(GazerIntrinsic::NoOverflowPrefix)) { + // Do not show the intrinsic functions here + // TODO: We could add some information about the overflow (e.g. the unrepresentable value). } else if (callee->isDeclaration() && !call->getType()->isVoidTy()) { // This is a function call to a nondetermistic function. auto variable = mCfaToLlvmTrace.getVariableForValue(loc->getAutomaton(), call); diff --git a/src/LLVM/Transform/LoopExitCanonizationPass.cpp b/src/LLVM/Transform/LoopExitCanonizationPass.cpp new file mode 100644 index 00000000..59f17048 --- /dev/null +++ b/src/LLVM/Transform/LoopExitCanonizationPass.cpp @@ -0,0 +1,115 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2020 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +#include "gazer/LLVM/Transform/Passes.h" + +#include +#include +#include + +namespace +{ + +class LoopExitCanonizationPass : public llvm::FunctionPass +{ +public: + static char ID; + + LoopExitCanonizationPass() + : FunctionPass(ID) + {} + + void getAnalysisUsage(llvm::AnalysisUsage& au) const override + { + au.addRequired(); + } + + bool runOnFunction(llvm::Function& function) override; +}; + +} // namespace + +char LoopExitCanonizationPass::ID; + +static void adjustPhiNodes(llvm::BasicBlock* succ, llvm::BasicBlock* oldBB, llvm::BasicBlock* newBB) +{ + auto it = succ->begin(); + while (auto phi = llvm::dyn_cast(it)) { + phi->replaceIncomingBlockWith(oldBB, newBB); + ++it; + } +} + +static bool transformExitsInLoop(llvm::LoopInfo& loopInfo, llvm::Loop* loop) +{ + llvm::Loop* parent = loop->getParentLoop(); + if (parent == nullptr) { + // This is a top-level loop, all possibly descendants are outside + return false; + } + + llvm::SmallVector exitingBlocks; + loop->getExitingBlocks(exitingBlocks); + + if (exitingBlocks.empty()) { + return false; + } + + for (llvm::BasicBlock* bb : exitingBlocks) { + // TODO: Switch instruction terminator + auto br = llvm::dyn_cast(bb->getTerminator()); + if (br == nullptr) { + continue; + } + + for (unsigned i = 0; i < br->getNumSuccessors(); ++i) { + auto succ = br->getSuccessor(i); + + if (!loop->contains(succ) && !parent->contains(succ)) { + // We have a successor outside of the loop and parent loop. Create a new block + // for the parent loop which will serve as the destination for this jump. + auto newBB = llvm::BasicBlock::Create(bb->getContext(), "loop_exit", bb->getParent()); + llvm::BranchInst::Create(succ, newBB); + + br->setSuccessor(i, newBB); + adjustPhiNodes(succ, bb, newBB); + parent->addBasicBlockToLoop(newBB, loopInfo); + } + } + } + + return true; +} + +bool LoopExitCanonizationPass::runOnFunction(llvm::Function& function) +{ + llvm::LoopInfo& loopInfo = getAnalysis().getLoopInfo(); + + auto loopsInPostorder = loopInfo.getLoopsInPreorder(); + llvm::reverse(loopsInPostorder); + + bool changed = false; + for (llvm::Loop* loop : loopsInPostorder) { + changed |= transformExitsInLoop(loopInfo, loop); + } + + return changed; +} + +llvm::Pass* gazer::createCanonizeLoopExitsPass() { + return new LoopExitCanonizationPass(); +} \ No newline at end of file diff --git a/test/lit.cfg b/test/lit.cfg index 48212f31..65ddff8d 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -13,7 +13,7 @@ config.excludes = [ ] try: - gazer_tools_dir = os.environ['GAZER_TOOLS_DIR'] + gazer_tools_dir = os.path.abspath(os.environ['GAZER_TOOLS_DIR']) except KeyError: lit_config.fatal('Missing GAZER_TOOLS_DIR environment variable.') diff --git a/test/theta/verif/overflow/overflow_loops.c b/test/theta/verif/overflow/overflow_loops.c new file mode 100644 index 00000000..6a810221 --- /dev/null +++ b/test/theta/verif/overflow/overflow_loops.c @@ -0,0 +1,23 @@ +// RUN: %theta -checks=signed-overflow "%s" | FileCheck "%s" + +// CHECK: Verification FAILED +// CHECK: Signed integer overflow + +int __VERIFIER_nondet_int(); + +int main(void) +{ + int x = 1; + int y = 1; + + while (1) { + x = x * 2 * __VERIFIER_nondet_int(); + y = y * 3 * __VERIFIER_nondet_int(); + if (x == 0) { + goto EXIT; + } + } + +EXIT: + return 0; +} diff --git a/test/theta/verif/overflow/overflow_simple.c b/test/theta/verif/overflow/overflow_simple.c new file mode 100644 index 00000000..caa45927 --- /dev/null +++ b/test/theta/verif/overflow/overflow_simple.c @@ -0,0 +1,14 @@ +// RUN: %theta -checks=signed-overflow "%s" | FileCheck "%s" + +// CHECK: Verification FAILED + +int __VERIFIER_nondet_int(); + +int main(void) +{ + int x = __VERIFIER_nondet_int(); + int y = __VERIFIER_nondet_int(); + + // CHECK: Signed integer overflow in {{.*}}overflow_simple.c at line [[# @LINE + 1]] column 14 + return x + y; +} diff --git a/test/verif/overflow/overflow_loops.c b/test/verif/overflow/overflow_loops.c new file mode 100644 index 00000000..41373a87 --- /dev/null +++ b/test/verif/overflow/overflow_loops.c @@ -0,0 +1,23 @@ +// RUN: %bmc -bound 1 -checks=signed-overflow "%s" | FileCheck "%s" + +// CHECK: Verification FAILED +// CHECK: Signed integer overflow + +int __VERIFIER_nondet_int(); + +int main(void) +{ + int x = 1; + int y = 1; + + while (1) { + x = x * 2 * __VERIFIER_nondet_int(); + y = y * 3 * __VERIFIER_nondet_int(); + if (x == 0) { + goto EXIT; + } + } + +EXIT: + return 0; +} diff --git a/test/verif/overflow/overflow_simple.c b/test/verif/overflow/overflow_simple.c new file mode 100644 index 00000000..1e648d72 --- /dev/null +++ b/test/verif/overflow/overflow_simple.c @@ -0,0 +1,15 @@ +// RUN: %bmc -bound 1 -checks=signed-overflow "%s" | FileCheck "%s" +// RUN: %bmc -bound 1 -checks=signed-overflow -math-int "%s" | FileCheck "%s" + +// CHECK: Verification FAILED + +int __VERIFIER_nondet_int(); + +int main(void) +{ + int x = __VERIFIER_nondet_int(); + int y = __VERIFIER_nondet_int(); + + // CHECK: Signed integer overflow in {{.*}}overflow_simple.c at line [[# @LINE + 1]] column 14 + return x + y; +} diff --git a/test/verif/svcomp/locks/test_locks_14_false.c b/test/verif/svcomp/locks/test_locks_14_false.c index 78bb82b4..2d89b2be 100644 --- a/test/verif/svcomp/locks/test_locks_14_false.c +++ b/test/verif/svcomp/locks/test_locks_14_false.c @@ -2,6 +2,8 @@ // RUN: %bmc -bound 10 -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED +// CHECK: Assertion failure in {{.*}}test_locks_14_false.c at line 223 column 10 + extern void __VERIFIER_error() __attribute__ ((__noreturn__)); extern int __VERIFIER_nondet_int(); From 6d3488d3d1aa2363ee5f0ee5619b918276fa74ed Mon Sep 17 00:00:00 2001 From: Gyula Sallai Date: Sun, 6 Sep 2020 18:51:59 +0200 Subject: [PATCH 36/70] Fix crash with long literals --- src/SolverZ3/Z3Solver.cpp | 8 +++++--- test/verif/regression/crash_on_long.c | 12 ++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 test/verif/regression/crash_on_long.c diff --git a/src/SolverZ3/Z3Solver.cpp b/src/SolverZ3/Z3Solver.cpp index acd07c9f..1d061d5e 100644 --- a/src/SolverZ3/Z3Solver.cpp +++ b/src/SolverZ3/Z3Solver.cpp @@ -19,6 +19,8 @@ #include "gazer/Support/Float.h" +#include + #include #include #include @@ -381,9 +383,9 @@ Z3Handle Z3ExprTransformer::handleTupleType(TupleType& tupTy) Z3AstHandle Z3ExprTransformer::translateLiteral(const ExprRef& expr) { if (auto bvLit = llvm::dyn_cast(expr)) { - return createHandle(Z3_mk_unsigned_int64( - mZ3Context, bvLit->getValue().getZExtValue(), typeToSort(bvLit->getType()) - )); + llvm::SmallString<20> buffer; + bvLit->getValue().toStringUnsigned(buffer, 10); + return createHandle(Z3_mk_numeral(mZ3Context, buffer.c_str(), typeToSort(bvLit->getType()))); } if (auto bl = llvm::dyn_cast(expr)) { diff --git a/test/verif/regression/crash_on_long.c b/test/verif/regression/crash_on_long.c new file mode 100644 index 00000000..8e9029a0 --- /dev/null +++ b/test/verif/regression/crash_on_long.c @@ -0,0 +1,12 @@ +// RUN: %bmc -checks=signed-overflow "%s" | FileCheck "%s" + +// CHECK: Verification SUCCESSFUL + +void a() __attribute__((__noreturn__)); +int b() { + int c; + if (c - 4L) + ; + a(); +} +int main() { b(); } From 84352b9bc6d24a2137d6a9afa4cf5f71fb69e588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:31:17 +0200 Subject: [PATCH 37/70] Add bitvectors to theta type converter --- tools/gazer-theta/CMakeLists.txt | 1 + tools/gazer-theta/lib/ThetaCfaGenerator.cpp | 24 ++------ tools/gazer-theta/lib/ThetaType.cpp | 66 +++++++++++++++++++++ tools/gazer-theta/lib/ThetaType.h | 39 ++++++++++++ 4 files changed, 110 insertions(+), 20 deletions(-) create mode 100644 tools/gazer-theta/lib/ThetaType.cpp create mode 100644 tools/gazer-theta/lib/ThetaType.h diff --git a/tools/gazer-theta/CMakeLists.txt b/tools/gazer-theta/CMakeLists.txt index c88d2b04..939ab49c 100644 --- a/tools/gazer-theta/CMakeLists.txt +++ b/tools/gazer-theta/CMakeLists.txt @@ -1,4 +1,5 @@ set(LIB_SOURCE_FILES + lib/ThetaType.cpp lib/ThetaCfaGenerator.cpp lib/ThetaExpr.cpp lib/ThetaVerifier.cpp diff --git a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp index 13a7ff07..ade8748f 100644 --- a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp +++ b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp @@ -16,6 +16,8 @@ // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" +#include "ThetaType.h" + #include "gazer/Core/LiteralExpr.h" #include "gazer/Automaton/CfaTransforms.h" @@ -191,24 +193,6 @@ void ThetaEdgeDecl::print(llvm::raw_ostream& os) const os << "}\n"; } -static std::string typeName(Type& type) -{ - switch (type.getTypeID()) { - case Type::IntTypeID: - return "int"; - case Type::RealTypeID: - return "rat"; - case Type::BoolTypeID: - return "bool"; - case Type::ArrayTypeID: { - auto& arrTy = llvm::cast(type); - return "[" + typeName(arrTy.getIndexType()) + "] -> " + typeName(arrTy.getElementType()); - } - default: - llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); - } -} - void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace) { Cfa* main = mSystem.getMainAutomaton(); @@ -234,7 +218,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace // Add variables for (auto& variable : main->locals()) { auto name = validName(variable.getName(), isValidVarName); - auto type = typeName(variable.getType()); + auto type = ThetaType::getThetaTypeName(variable.getType()); nameTrace.variables[name] = &variable; vars.try_emplace(&variable, std::make_unique(name, type)); @@ -242,7 +226,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace for (auto& variable : main->inputs()) { auto name = validName(variable.getName(), isValidVarName); - auto type = typeName(variable.getType()); + auto type = ThetaType::getThetaTypeName(variable.getType()); nameTrace.variables[name] = &variable; vars.try_emplace(&variable, std::make_unique(name, type)); diff --git a/tools/gazer-theta/lib/ThetaType.cpp b/tools/gazer-theta/lib/ThetaType.cpp new file mode 100644 index 00000000..71886e3d --- /dev/null +++ b/tools/gazer-theta/lib/ThetaType.cpp @@ -0,0 +1,66 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2019 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// + +#include "ThetaType.h" + +using namespace gazer; +using namespace gazer::theta; + +std::string ThetaType::getThetaTypeName(Type &type) +{ + switch (type.getTypeID()) { + case Type::IntTypeID: + return "int"; + case Type::RealTypeID: + return "rat"; + case Type::BoolTypeID: + return "bool"; + case Type::ArrayTypeID: { + auto& arrTy = llvm::cast(type); + return "[" + getThetaTypeName(arrTy.getIndexType()) + "] -> " + getThetaTypeName(arrTy.getElementType()); + } + case Type::BvTypeID: { + auto& bvTy = llvm::cast(type); + return "bv[" + std::to_string(bvTy.getWidth()) + "]"; + } + default: + llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); + } +} + +std::string ThetaType::getThetaTypeDefaultValue(Type &type) +{ + switch (type.getTypeID()) { + case Type::IntTypeID: + return "0"; + case Type::RealTypeID: + return "0%1"; + case Type::BoolTypeID: + return "false"; + case Type::ArrayTypeID: { + auto& arrTy = llvm::cast(type); + return "[<" + getThetaTypeName(arrTy.getIndexType()) + ">default <- " + getThetaTypeDefaultValue(arrTy.getElementType()) + "]"; + } + case Type::BvTypeID: { + auto& bvTy = llvm::cast(type); + return std::to_string(bvTy.getWidth()) + "'d0"; + } + default: + llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); + } +} diff --git a/tools/gazer-theta/lib/ThetaType.h b/tools/gazer-theta/lib/ThetaType.h new file mode 100644 index 00000000..8eb6f528 --- /dev/null +++ b/tools/gazer-theta/lib/ThetaType.h @@ -0,0 +1,39 @@ +//==-------------------------------------------------------------*- C++ -*--==// +// +// Copyright 2019 Contributors to the Gazer project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +#ifndef GAZER_TOOLS_GAZERTHETA_LIB_THETATYPE_H +#define GAZER_TOOLS_GAZERTHETA_LIB_THETATYPE_H + +#include "gazer/Core/Type.h" + +#include + +namespace gazer::theta +{ + +class ThetaType final +{ +public: + ThetaType() = delete; + + static std::string getThetaTypeName(Type& type); + static std::string getThetaTypeDefaultValue(Type& type); +}; + +} // end namespace gazer::theta + +#endif // GAZER_TOOLS_GAZERTHETA_LIB_THETATYPE_H From 4f1442dab319986eefc02a9868b65b451f9f6a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:35:45 +0200 Subject: [PATCH 38/70] Add bitvector expression conversion to theta converter --- tools/gazer-theta/lib/ThetaExpr.cpp | 120 +++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index d12b4bcf..aea64bcf 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -16,6 +16,7 @@ // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" +#include "ThetaType.h" #include "gazer/Core/Expr/ExprWalker.h" #include "gazer/ADT/StringUtils.h" @@ -23,9 +24,11 @@ #include +#include #include using namespace gazer; +using namespace gazer::theta; class ThetaExprPrinter : public ExprWalker { @@ -63,6 +66,11 @@ class ThetaExprPrinter : public ExprWalker return std::to_string(val.numerator()) + "%" + std::to_string(val.denominator()); } + if(auto bvLit = llvm::dyn_cast(expr)) { + auto exactValue = bvLit->getValue().getZExtValue(); + auto exactString = std::bitset(exactValue).to_string(); + return std::to_string(bvLit->getType().getWidth()) + "'b" + exactString.substr(exactString.length() - bvLit->getType().getWidth()); + } return visitExpr(expr); } @@ -81,24 +89,60 @@ class ThetaExprPrinter : public ExprWalker // Binary std::string visitAdd(const ExprRef& expr) { + if(expr->getType().isBvType()) { + return "(" + getOperand(0) + " bvadd " + getOperand(1) + ")"; + } + else { return "(" + getOperand(0) + " + " + getOperand(1) + ")"; } + } std::string visitSub(const ExprRef& expr) { + if(expr->getType().isBvType()) { + return "(" + getOperand(0) + " bvsub " + getOperand(1) + ")"; + } + else { return "(" + getOperand(0) + " - " + getOperand(1) + ")"; } + } std::string visitMul(const ExprRef& expr) { + if(expr->getType().isBvType()) { + return "(" + getOperand(0) + " bvmul " + getOperand(1) + ")"; + } + else { return "(" + getOperand(0) + " * " + getOperand(1) + ")"; } + } std::string visitDiv(const ExprRef& expr) { return "(" + getOperand(0) + " / " + getOperand(1) + ")"; } + std::string visitBvUDiv([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvudiv " + getOperand(1) + ")"; + } + + std::string visitBvSDiv([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsdiv " + getOperand(1) + ")"; + } + std::string visitMod(const ExprRef& expr) { + if(expr->getType().isBvType()) { + return "(" + getOperand(0) + " bvsmod " + getOperand(1) + ")"; + } + else { return "(" + getOperand(0) + " mod " + getOperand(1) + ")"; } + } + + std::string visitBvURem([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvurem " + getOperand(1) + ")"; + } + + std::string visitBvSRem([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsrem " + getOperand(1) + ")"; + } std::string visitAnd(const ExprRef& expr) { @@ -137,7 +181,49 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " imply " + getOperand(1) + ")"; } - std::string visitEq(const ExprRef& expr) { + std::string visitBvAnd([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvand " + getOperand(1) + ")"; + } + + std::string visitBvOr([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvor " + getOperand(1) + ")"; + } + + std::string visitBvXor([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvxor " + getOperand(1) + ")"; + } + + std::string visitShl([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvshl " + getOperand(1) + ")"; + } + + std::string visitAShr([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvashr " + getOperand(1) + ")"; + } + + std::string visitBvConcat([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " ++ " + getOperand(1) + ")"; + } + + std::string visitExtract(const ExprRef& expr) { + auto from = expr->getOffset(); + auto until = expr->getOffset() + expr->getWidth(); + return "(" + getOperand(0) + ")[" + std::to_string(until) + ":" + std::to_string(from) + "]"; + } + + std::string visitZExt(const ExprRef& expr) { + auto width = expr->getExtendedWidth(); + return "(" + getOperand(0) + " bv_zero_extend bv[" + std::to_string(width) + "])"; + } + + std::string visitSExt(const ExprRef& expr) { + auto width = expr->getExtendedWidth(); + return "(" + getOperand(0) + " bv_sign_extend bv[" + std::to_string(width) + "])"; + } + + std::string visitLShr([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvlshr " + getOperand(1) + ")"; + } return "(" + getOperand(0) + " = " + getOperand(1) + ")"; } @@ -161,7 +247,37 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " >= " + getOperand(1) + ")"; } - std::string visitSelect(const ExprRef& expr) { + std::string visitBvULt([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvult " + getOperand(1) + ")"; + } + + std::string visitBvULtEq([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvule " + getOperand(1) + ")"; + } + + std::string visitBvUGt([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvugt " + getOperand(1) + ")"; + } + + std::string visitBvUGtEq([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvuge " + getOperand(1) + ")"; + } + + std::string visitBvSLt([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvslt " + getOperand(1) + ")"; + } + + std::string visitBvSLtEq([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsle " + getOperand(1) + ")"; + } + + std::string visitBvSGt([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsgt " + getOperand(1) + ")"; + } + + std::string visitBvSGtEq([[maybe_unused]] const ExprRef& expr) { + return "(" + getOperand(0) + " bvsge " + getOperand(1) + ")"; + } return "(if " + getOperand(0) + " then " + getOperand(1) + " else " + getOperand(2) + ")"; } From 4cb9a98aef9328eddfe82c510113f0b971295125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:37:25 +0200 Subject: [PATCH 39/70] Add array literal conversion to theta converter --- tools/gazer-theta/lib/ThetaExpr.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index aea64bcf..4a924d01 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -71,6 +71,32 @@ class ThetaExprPrinter : public ExprWalker auto exactString = std::bitset(exactValue).to_string(); return std::to_string(bvLit->getType().getWidth()) + "'b" + exactString.substr(exactString.length() - bvLit->getType().getWidth()); } + + if(auto arrLit = llvm::dyn_cast(expr)) { + std::string arrLitStr = "["; + + const auto& kvPairs = arrLit->getMap(); + if(kvPairs.size() > 0) { + for(const auto& [index, elem] : kvPairs) { + arrLitStr += this->walk(index) + " <- " + this->walk(elem) + ", "; + } + arrLitStr += "default <- "; + } + else { + arrLitStr += "<" + ThetaType::getThetaTypeName(arrLit->getType().getIndexType()) + ">default <- "; + } + + if(arrLit->hasDefault()) { + arrLitStr += this->walk(arrLit->getDefault()); + } + else { + arrLitStr += ThetaType::getThetaTypeDefaultValue(arrLit->getType().getElementType()); + } + + arrLitStr += "]"; + return arrLitStr; + } + return visitExpr(expr); } From 0f6c7bb6ce36c909d27118700207461b274c1536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:37:57 +0200 Subject: [PATCH 40/70] Add [[maybe_unused]] to visitor parameters --- tools/gazer-theta/lib/ThetaExpr.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 4a924d01..729eab0b 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -109,7 +109,7 @@ class ThetaExprPrinter : public ExprWalker return expr->getVariable().getName(); } - std::string visitNot(const ExprRef& expr) { + std::string visitNot([[maybe_unused]] const ExprRef& expr) { return "(not " + getOperand(0) + ")"; } @@ -141,7 +141,7 @@ class ThetaExprPrinter : public ExprWalker } } - std::string visitDiv(const ExprRef& expr) { + std::string visitDiv([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " / " + getOperand(1) + ")"; } @@ -203,7 +203,7 @@ class ThetaExprPrinter : public ExprWalker return rso.str(); } - std::string visitImply(const ExprRef& expr) { + std::string visitImply([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " imply " + getOperand(1) + ")"; } @@ -250,26 +250,28 @@ class ThetaExprPrinter : public ExprWalker std::string visitLShr([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " bvlshr " + getOperand(1) + ")"; } + + std::string visitEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " = " + getOperand(1) + ")"; } - std::string visitNotEq(const ExprRef& expr) { + std::string visitNotEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " /= " + getOperand(1) + ")"; } - std::string visitLt(const ExprRef& expr) { + std::string visitLt([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " < " + getOperand(1) + ")"; } - std::string visitLtEq(const ExprRef& expr) { + std::string visitLtEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " <= " + getOperand(1) + ")"; } - std::string visitGt(const ExprRef& expr) { + std::string visitGt([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " > " + getOperand(1) + ")"; } - std::string visitGtEq(const ExprRef& expr) { + std::string visitGtEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " >= " + getOperand(1) + ")"; } @@ -304,14 +306,16 @@ class ThetaExprPrinter : public ExprWalker std::string visitBvSGtEq([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + " bvsge " + getOperand(1) + ")"; } + + std::string visitSelect([[maybe_unused]] const ExprRef& expr) { return "(if " + getOperand(0) + " then " + getOperand(1) + " else " + getOperand(2) + ")"; } - std::string visitArrayRead(const ExprRef& expr) { + std::string visitArrayRead([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + ")[" + getOperand(1) + "]"; } - std::string visitArrayWrite(const ExprRef& expr) { + std::string visitArrayWrite([[maybe_unused]] const ExprRef& expr) { return "(" + getOperand(0) + ")[" + getOperand(1) + " <- " + getOperand(2) + "]"; } From a568d070064ba4890d5e0cb8bfc440ff343ece8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:41:20 +0200 Subject: [PATCH 41/70] Add bitvector specific theta keywords --- tools/gazer-theta/lib/ThetaCfaGenerator.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp index ade8748f..17da3256 100644 --- a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp +++ b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp @@ -45,7 +45,14 @@ constexpr std::array ThetaKeywords = { "return", "havoc", "bool", "int", "rat", "if", "then", "else", "iff", "imply", "forall", "exists", "or", "and", "not", - "mod", "rem", "true", "false" + "mod", "rem", "true", "false", + "bvadd", "bvsub", "bvpos", "bvneg", + "bvmul", "bvudiv", "bvsdiv", + "bvsmod", "bvurem", "bvsrem", + "bvshl", "bvashr", "bvlshr", "bvrol", "bvror", + "bvult", "bvule", "bvugt", "bvuge", + "bvslt", "bvsle", "bvsgt", "bvsge", + "bv_zero_extend", "bv_sign_extend" }; struct ThetaAst From 9866f3f4172513287dcfefe4418c0830eee5e34b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:46:29 +0200 Subject: [PATCH 42/70] Refactor RecursiveToCyclicTransformer to support other types for the error field variable --- src/Automaton/RecursiveToCyclicCfa.cpp | 77 ++++++++++++++------------ 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/src/Automaton/RecursiveToCyclicCfa.cpp b/src/Automaton/RecursiveToCyclicCfa.cpp index c713d11a..c88ca288 100644 --- a/src/Automaton/RecursiveToCyclicCfa.cpp +++ b/src/Automaton/RecursiveToCyclicCfa.cpp @@ -42,15 +42,16 @@ class RecursiveToCyclicTransformer RecursiveToCyclicResult transform(); private: - void addUniqueErrorLocation(); void inlineCallIntoRoot(CallTransition* call, llvm::Twine suffix); + void createErrorTransition(Location* from, ExprPtr errorFieldExpr); + void createDummyErrorTransition(); private: Cfa* mRoot; CallGraph mCallGraph; llvm::SmallVector mTailRecursiveCalls; - Location* mError; - Variable* mErrorFieldVariable;; + Location* mError = nullptr; + Variable* mErrorFieldVariable = nullptr; llvm::DenseMap mInlinedLocations; llvm::DenseMap mInlinedVariables; std::unique_ptr mExprBuilder; @@ -61,8 +62,16 @@ class RecursiveToCyclicTransformer RecursiveToCyclicResult RecursiveToCyclicTransformer::transform() { - this->addUniqueErrorLocation(); + mError = mRoot->createErrorLocation(); + + // Connect error location + for (Location* loc : mRoot->nodes()) { + if (loc->isError() && loc != mError) { + this->createErrorTransition(loc, mRoot->getErrorFieldExpr(loc)); + } + } + // Collect tail-recursive calls for (Transition* edge : mRoot->edges()) { if (auto call = llvm::dyn_cast(edge)) { if (mCallGraph.isTailRecursive(call->getCalledAutomaton())) { @@ -78,6 +87,12 @@ RecursiveToCyclicResult RecursiveToCyclicTransformer::transform() this->inlineCallIntoRoot(call, "_inlined" + llvm::Twine(mInlineCnt++)); } + + if(mErrorFieldVariable == nullptr) { + // If there are no error locations, create one to use as goal + this->createDummyErrorTransition(); + } + mRoot->clearDisconnectedElements(); // Calculate the new call graph and remove unneeded automata. @@ -145,9 +160,7 @@ void RecursiveToCyclicTransformer::inlineCallIntoRoot(CallTransition* call, llvm locToLocMap[&*origLoc] = newLoc; mInlinedLocations[newLoc] = origLoc; if (origLoc->isError()) { - mRoot->createAssignTransition(newLoc, mError, mExprBuilder->True(), { - { mErrorFieldVariable, callee->getErrorFieldExpr(origLoc) } - }); + this->createErrorTransition(newLoc, callee->getErrorFieldExpr(origLoc)); } } @@ -279,39 +292,33 @@ void RecursiveToCyclicTransformer::inlineCallIntoRoot(CallTransition* call, llvm mRoot->disconnectEdge(call); } -void RecursiveToCyclicTransformer::addUniqueErrorLocation() +void RecursiveToCyclicTransformer::createErrorTransition(Location *from, ExprPtr errorFieldExpr) +{ + assert(mError != nullptr); + assert(mErrorFieldVariable == nullptr || mErrorFieldVariable->getType() == errorFieldExpr->getType()); + + if(mErrorFieldVariable == nullptr) { + mErrorFieldVariable = mRoot->createLocal("__gazer_error_field", errorFieldExpr->getType()); + } + + mRoot->createAssignTransition(from, mError, BoolLiteralExpr::True(mRoot->getParent().getContext()), { + VariableAssignment { mErrorFieldVariable, errorFieldExpr } + }); +} + +void RecursiveToCyclicTransformer::createDummyErrorTransition() { + assert(mError != nullptr); + assert(mErrorFieldVariable == nullptr); + auto& intTy = IntType::Get(mRoot->getParent().getContext()); auto& ctx = mRoot->getParent().getContext(); - llvm::SmallVector errors; - for (Location* loc : mRoot->nodes()) { - if (loc->isError()) { - errors.push_back(loc); - } - } - - mError = mRoot->createErrorLocation(); + // A dummy error location will be used as a goal as there are no error locations in the automaton mErrorFieldVariable = mRoot->createLocal("__gazer_error_field", intTy); - - if (errors.empty()) { - // If there are no error locations in the main automaton, they might still exist in a called CFA. - // A dummy error location will be used as a goal. - mRoot->createAssignTransition(mRoot->getEntry(), mError, BoolLiteralExpr::False(ctx), { - VariableAssignment{ mErrorFieldVariable, IntLiteralExpr::Get(intTy, 0) } - }); - } else { - // The error location will be directly reachable from already existing error locations. - for (Location* err : errors) { - auto errorExpr = mRoot->getErrorFieldExpr(err); - - assert(errorExpr->getType().isIntType() && "Error expression must be arithmetic integers in the theta backend!"); - - mRoot->createAssignTransition(err, mError, BoolLiteralExpr::True(ctx), { - VariableAssignment { mErrorFieldVariable, errorExpr } - }); - } - } + mRoot->createAssignTransition(mRoot->getEntry(), mError, BoolLiteralExpr::False(ctx), { + VariableAssignment{ mErrorFieldVariable, IntLiteralExpr::Get(intTy, 0) } + }); } RecursiveToCyclicResult gazer::TransformRecursiveToCyclic(Cfa* cfa) From 9cfaf7e8c73d1255841bbcb45a36cfc93946cc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:48:12 +0200 Subject: [PATCH 43/70] Parse bitvectors from cex --- tools/gazer-theta/lib/ThetaVerifier.cpp | 129 ++++++++++++++++++------ 1 file changed, 97 insertions(+), 32 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 4424a8d0..ae6144f2 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -30,6 +30,8 @@ #include #include +#include + using namespace gazer; using namespace gazer::theta; @@ -240,6 +242,100 @@ static void reportInvalidCex(llvm::StringRef message, llvm::StringRef cex, sexpr llvm::errs() << "Raw counterexample is: " << cex << "\n"; } +static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr; + +static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> boost::intrusive_ptr +{ + llvm::StringRef value = sexpr->asAtom(); + if (value.equals_lower("true")) { + return BoolLiteralExpr::True(varTy.getContext()); + } + else if (value.equals_lower("false")) { + return BoolLiteralExpr::False(varTy.getContext()); + } + else { + return nullptr; + } +} + +static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> boost::intrusive_ptr +{ + llvm::StringRef value = sexpr->asAtom(); + long long int intVal; + if (!value.getAsInteger(10, intVal)) { + return IntLiteralExpr::Get(varTy, intVal); + } + else { + return nullptr; + } +} + +static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusive_ptr +{ + llvm::StringRef value = sexpr->asAtom(); + llvm::APInt intVal; + + if (!value.getAsInteger(10, intVal)) { + return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); + } + else if (const auto lit = value.split("'"); std::get<1>(lit) != "") { + auto bvSizeStr = std::get<0>(lit); + auto bvLitForm = std::get<1>(lit)[0]; + auto bvLitValueStr = std::get<1>(lit).substr(1); + + unsigned bvSize; + auto [p, ec] = std::from_chars(bvSizeStr.data(), bvSizeStr.data() + bvSizeStr.size(), bvSize); + + if (ec == std::errc() && bvSize == varTy.getWidth()) { + switch (std::tolower(bvLitForm)) { + case 'b': + if (!bvLitValueStr.getAsInteger(2, intVal)) { + return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); + } + break; + case 'x': + if (!bvLitValueStr.getAsInteger(16, intVal)) { + return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); + } + break; + case 'd': + if (!bvLitValueStr.getAsInteger(10, intVal)) { + return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); + } + break; + } + + // Error while parsing + return nullptr; + } + else { + // Error while parsing the size + return nullptr; + } + } + else { + // Not supported format + return nullptr; + } +} +static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr +{ + switch (varTy.getTypeID()) { + case Type::BoolTypeID: { + return parseBoolLiteral(sexpr, cast(varTy)); + } + case Type::IntTypeID: { + return parseIntLiteral(sexpr, cast(varTy)); + } + case Type::BvTypeID: { + return parseBvLiteral(sexpr, cast(varTy)); + } + default: { + return nullptr; + } + } +} + std::unique_ptr ThetaVerifierImpl::parseCex(llvm::StringRef cex, unsigned* errorCode) { // TODO: The whole parsing process is very fragile. We should introduce some proper error cheks. @@ -276,7 +372,6 @@ std::unique_ptr ThetaVerifierImpl::parseCex(llvm::StringRef cex, unsigned std::vector assigns; for (size_t j = 1; j < actionList.size(); ++j) { llvm::StringRef varName = actionList[j]->asList()[0]->asAtom(); - llvm::StringRef value = actionList[j]->asList()[1]->asAtom(); Variable* variable = mNameMapping.variables.lookup(varName); assert(variable != nullptr && "Each variable must be present in the theta name mapping!"); @@ -286,37 +381,7 @@ std::unique_ptr ThetaVerifierImpl::parseCex(llvm::StringRef cex, unsigned origVariable = variable; } - ExprPtr rhs; - Type& varTy = origVariable->getType(); - - switch (varTy.getTypeID()) { - case Type::IntTypeID: { - long long int intVal; - if (!value.getAsInteger(10, intVal)) { - rhs = IntLiteralExpr::Get(cast(varTy), intVal); - } - break; - } - case Type::BvTypeID: { - llvm::APInt intVal; - if (!value.getAsInteger(10, intVal)) { - auto& bvTy = cast(varTy); - rhs = BvLiteralExpr::Get(bvTy, intVal.zextOrTrunc(bvTy.getWidth())); - } - break; - } - case Type::BoolTypeID: { - if (value.equals_lower("true")) { - rhs = BoolLiteralExpr::True(varTy.getContext()); - } else if (value.equals_lower("false")) { - rhs = BoolLiteralExpr::False(varTy.getContext()); - } - break; - } - default: - break; - } - + auto rhs = parseLiteral(actionList[j]->asList()[1], origVariable->getType()); if (rhs == nullptr) { reportInvalidCex("expected a valid integer or boolean value", cex, &*(actionList[j]->asList()[1])); return nullptr; From 01bf9f6303639aa129ff05dd11574b6682e41743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:48:23 +0200 Subject: [PATCH 44/70] Parse array literals from cex --- tools/gazer-theta/lib/ThetaVerifier.cpp | 30 ++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index ae6144f2..32b188cc 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -318,6 +318,31 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusi return nullptr; } } + +static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> boost::intrusive_ptr +{ + auto arrLitImpl = sexpr->asList(); + // The string "array" at the beginning + arrLitImpl.erase(arrLitImpl.begin()); + + ArrayLiteralExpr::MappingT entries; + ExprRef def = nullptr; + + for(auto arrEntryImpl : arrLitImpl) { + auto keyImpl = arrEntryImpl->asList()[0]; + auto valueImpl = arrEntryImpl->asList()[1]; + + if(keyImpl->isAtom() && keyImpl->asAtom() == "default") { + def = parseLiteral(valueImpl, varTy.getElementType()); + } + else { + entries[parseLiteral(keyImpl, varTy.getIndexType())] = parseLiteral(valueImpl, varTy.getElementType()); + } + } + + return ArrayLiteralExpr::Get(varTy, entries, def); +} + static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr { switch (varTy.getTypeID()) { @@ -330,6 +355,9 @@ static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_p case Type::BvTypeID: { return parseBvLiteral(sexpr, cast(varTy)); } + case Type::ArrayTypeID: { + return parseArrayLiteral(sexpr, cast(varTy)); + } default: { return nullptr; } @@ -383,7 +411,7 @@ std::unique_ptr ThetaVerifierImpl::parseCex(llvm::StringRef cex, unsigned auto rhs = parseLiteral(actionList[j]->asList()[1], origVariable->getType()); if (rhs == nullptr) { - reportInvalidCex("expected a valid integer or boolean value", cex, &*(actionList[j]->asList()[1])); + reportInvalidCex("expected a valid integer, bitvector, boolean or their array as value", cex, &*(actionList[j]->asList()[1])); return nullptr; } From 299023ef17d13dd66695fa0fa8100b3f6c050fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 7 Sep 2020 22:48:47 +0200 Subject: [PATCH 45/70] Remove forced int representation from gazer-theta --- tools/gazer-theta/gazer-theta.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gazer-theta/gazer-theta.cpp b/tools/gazer-theta/gazer-theta.cpp index 0bcdfd26..7dffd3ba 100644 --- a/tools/gazer-theta/gazer-theta.cpp +++ b/tools/gazer-theta/gazer-theta.cpp @@ -120,7 +120,8 @@ int main(int argc, char* argv[]) } // Force -math-int - config.getSettings().ints = IntRepresentation::Integers; + // TODO: Find a way to make this behavior default + // config.getSettings().ints = IntRepresentation::Integers; // Create the frontend object auto frontend = config.buildFrontend(InputFilenames); From b351cfe9c50cd19412db335b1c9797bd93b4d8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 13:28:29 +0200 Subject: [PATCH 46/70] Remove dependency --- tools/gazer-theta/lib/ThetaVerifier.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 32b188cc..4edb3f87 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -30,8 +30,6 @@ #include #include -#include - using namespace gazer; using namespace gazer::theta; @@ -284,9 +282,8 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusi auto bvLitValueStr = std::get<1>(lit).substr(1); unsigned bvSize; - auto [p, ec] = std::from_chars(bvSizeStr.data(), bvSizeStr.data() + bvSizeStr.size(), bvSize); - if (ec == std::errc() && bvSize == varTy.getWidth()) { + if (!bvSizeStr.getAsInteger(10, bvSize) && bvSize == varTy.getWidth()) { switch (std::tolower(bvLitForm)) { case 'b': if (!bvLitValueStr.getAsInteger(2, intVal)) { From f0e2fcc41fdb86f1b4b3b954f384f596093f8a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 14:25:53 +0200 Subject: [PATCH 47/70] Correct whitespace discrepancies --- tools/gazer-theta/lib/ThetaExpr.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 729eab0b..ee6991ee 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -119,8 +119,8 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " bvadd " + getOperand(1) + ")"; } else { - return "(" + getOperand(0) + " + " + getOperand(1) + ")"; - } + return "(" + getOperand(0) + " + " + getOperand(1) + ")"; + } } std::string visitSub(const ExprRef& expr) { @@ -128,8 +128,8 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " bvsub " + getOperand(1) + ")"; } else { - return "(" + getOperand(0) + " - " + getOperand(1) + ")"; - } + return "(" + getOperand(0) + " - " + getOperand(1) + ")"; + } } std::string visitMul(const ExprRef& expr) { @@ -137,8 +137,8 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " bvmul " + getOperand(1) + ")"; } else { - return "(" + getOperand(0) + " * " + getOperand(1) + ")"; - } + return "(" + getOperand(0) + " * " + getOperand(1) + ")"; + } } std::string visitDiv([[maybe_unused]] const ExprRef& expr) { @@ -158,8 +158,8 @@ class ThetaExprPrinter : public ExprWalker return "(" + getOperand(0) + " bvsmod " + getOperand(1) + ")"; } else { - return "(" + getOperand(0) + " mod " + getOperand(1) + ")"; - } + return "(" + getOperand(0) + " mod " + getOperand(1) + ")"; + } } std::string visitBvURem([[maybe_unused]] const ExprRef& expr) { From 6e8defa4acd81e7ead321af3b19a149d517b7c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 14:48:13 +0200 Subject: [PATCH 48/70] Add -math-int to theta functional tests --- test/theta/cfa/counter.c | 2 +- test/theta/verif/base/loops1.c | 2 +- test/theta/verif/base/loops2_fail.c | 2 +- test/theta/verif/base/loops3_fail.c | 2 +- test/theta/verif/base/main_no_assert.c | 2 +- test/theta/verif/base/separate_assert.c | 2 +- test/theta/verif/base/simple_fail.c | 2 +- test/theta/verif/base/uninitialized_var_false.c | 4 ++-- test/theta/verif/memory/arrays1.c | 2 +- test/theta/verif/memory/arrays2_fail.c | 2 +- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 2 +- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- test/theta/verif/svcomp/locks/test_locks_13_true.c | 2 +- test/theta/verif/svcomp/locks/test_locks_14_false.c | 2 +- test/theta/verif/svcomp/locks/test_locks_14_true.c | 2 +- test/theta/verif/svcomp/locks/test_locks_15_false.c | 2 +- test/theta/verif/svcomp/locks/test_locks_15_true.c | 2 +- 29 files changed, 30 insertions(+), 30 deletions(-) diff --git a/test/theta/cfa/counter.c b/test/theta/cfa/counter.c index 60e77f6e..2f26da35 100644 --- a/test/theta/cfa/counter.c +++ b/test/theta/cfa/counter.c @@ -1,4 +1,4 @@ -// RUN: %theta -model-only "%s" -o "%t" +// RUN: %theta -model-only -math-int "%s" -o "%t" // RUN: cat "%t" | /usr/bin/diff -B -Z "%p/Expected/counter.theta" - #include diff --git a/test/theta/verif/base/loops1.c b/test/theta/verif/base/loops1.c index f71e3fb3..aefc12bf 100644 --- a/test/theta/verif/base/loops1.c +++ b/test/theta/verif/base/loops1.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/base/loops2_fail.c b/test/theta/verif/base/loops2_fail.c index a5b671ea..3637712a 100644 --- a/test/theta/verif/base/loops2_fail.c +++ b/test/theta/verif/base/loops2_fail.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/loops3_fail.c b/test/theta/verif/base/loops3_fail.c index b704f1a5..999d4365 100644 --- a/test/theta/verif/base/loops3_fail.c +++ b/test/theta/verif/base/loops3_fail.c @@ -1,4 +1,4 @@ -// RUN: %theta -no-optimize -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -no-optimize -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/main_no_assert.c b/test/theta/verif/base/main_no_assert.c index 30201f2d..242f4305 100644 --- a/test/theta/verif/base/main_no_assert.c +++ b/test/theta/verif/base/main_no_assert.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/base/separate_assert.c b/test/theta/verif/base/separate_assert.c index dce49a26..5c60c34d 100644 --- a/test/theta/verif/base/separate_assert.c +++ b/test/theta/verif/base/separate_assert.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/base/simple_fail.c b/test/theta/verif/base/simple_fail.c index dba370e5..c9f6d830 100644 --- a/test/theta/verif/base/simple_fail.c +++ b/test/theta/verif/base/simple_fail.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/uninitialized_var_false.c b/test/theta/verif/base/uninitialized_var_false.c index c7731dd1..0c2b7e3c 100644 --- a/test/theta/verif/base/uninitialized_var_false.c +++ b/test/theta/verif/base/uninitialized_var_false.c @@ -1,5 +1,5 @@ -// RUN: %theta -no-optimize -memory=havoc "%s" | FileCheck "%s" -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -no-optimize -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/arrays1.c b/test/theta/verif/memory/arrays1.c index dae726e5..7daa50d7 100644 --- a/test/theta/verif/memory/arrays1.c +++ b/test/theta/verif/memory/arrays1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index 0cbb2c0f..c62fada8 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index 6579935e..92f2dbd1 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index 8eb281f2..5726e50c 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 10e3242e..847ba069 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index 5975a3c8..6c6e8adb 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index c7b8808d..82cc0f15 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 50213622..62a5f181 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index a4a054e0..2770d0dd 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index 0c44ad05..db466580 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index 1465eaf5..47ebe1bf 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index 8ac40ced..7bc4ad03 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index ef4d7024..39159c6c 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index f46abffe..807101dc 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index f562d97d..5bab01fd 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index 9debb018..e6a47b8c 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta "%s" -math-int | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/svcomp/locks/test_locks_13_true.c b/test/theta/verif/svcomp/locks/test_locks_13_true.c index 429ecf2a..5ebb658b 100644 --- a/test/theta/verif/svcomp/locks/test_locks_13_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_13_true.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_14_false.c b/test/theta/verif/svcomp/locks/test_locks_14_false.c index 85b90907..143f2a98 100644 --- a/test/theta/verif/svcomp/locks/test_locks_14_false.c +++ b/test/theta/verif/svcomp/locks/test_locks_14_false.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_14_true.c b/test/theta/verif/svcomp/locks/test_locks_14_true.c index daebc4c0..b53ff8a7 100644 --- a/test/theta/verif/svcomp/locks/test_locks_14_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_14_true.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_15_false.c b/test/theta/verif/svcomp/locks/test_locks_15_false.c index b7b83108..e3f77578 100644 --- a/test/theta/verif/svcomp/locks/test_locks_15_false.c +++ b/test/theta/verif/svcomp/locks/test_locks_15_false.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification FAILED extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_15_true.c b/test/theta/verif/svcomp/locks/test_locks_15_true.c index 4e2fc85b..3daa1e35 100644 --- a/test/theta/verif/svcomp/locks/test_locks_15_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_15_true.c @@ -1,4 +1,4 @@ -// RUN: %theta -memory=havoc "%s" | FileCheck "%s" +// RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); From 72f6aa9095d7b6769bb67f0cdd38f6f27cb478db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 16:03:14 +0200 Subject: [PATCH 49/70] Fix Ninja build error at ExternalProject_Add --- src/SolverZ3/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SolverZ3/CMakeLists.txt b/src/SolverZ3/CMakeLists.txt index 3406b682..aac20f66 100644 --- a/src/SolverZ3/CMakeLists.txt +++ b/src/SolverZ3/CMakeLists.txt @@ -4,20 +4,22 @@ set(SOURCE_FILES ) # Z3 + +set(Z3_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/vendor/src/z3_download/include") +set(Z3_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/vendor/src/z3_download/bin") + ExternalProject_Add(z3_download PREFIX vendor # Download URL https://github.com/Z3Prover/z3/releases/download/z3-4.8.6/z3-4.8.6-x64-ubuntu-16.04.zip URL_HASH SHA1=1663a7825c45f24642045dfcc5e100d65c1b6b1e + BUILD_BYPRODUCTS "${Z3_LIBRARY_DIR}/libz3.so" CONFIGURE_COMMAND "" BUILD_COMMAND "" UPDATE_COMMAND "" INSTALL_COMMAND "" ) -set(Z3_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/vendor/src/z3_download/include") -set(Z3_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/vendor/src/z3_download/bin") - message("Z3 includes are ${Z3_INCLUDE_DIR}") # Z3 From 2496208e866d9914197fe396ebadc7526232241e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 9 Sep 2020 20:17:51 +0200 Subject: [PATCH 50/70] Add bitvector related functional tests --- test/theta/verif/base/loops1.c | 2 ++ test/theta/verif/base/loops2_fail.c | 1 + test/theta/verif/base/loops3_fail.c | 1 + test/theta/verif/base/main_no_assert.c | 1 + test/theta/verif/base/separate_assert.c | 1 + test/theta/verif/base/simple_fail.c | 1 + test/theta/verif/base/uninitialized_var_false.c | 1 + test/theta/verif/memory/arrays1.c | 2 +- test/theta/verif/memory/arrays2_fail.c | 2 +- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 2 +- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- test/theta/verif/svcomp/locks/test_locks_13_true.c | 1 + test/theta/verif/svcomp/locks/test_locks_14_false.c | 1 + test/theta/verif/svcomp/locks/test_locks_14_true.c | 1 + test/theta/verif/svcomp/locks/test_locks_15_false.c | 1 + test/theta/verif/svcomp/locks/test_locks_15_true.c | 1 + 28 files changed, 29 insertions(+), 16 deletions(-) diff --git a/test/theta/verif/base/loops1.c b/test/theta/verif/base/loops1.c index aefc12bf..07ff225f 100644 --- a/test/theta/verif/base/loops1.c +++ b/test/theta/verif/base/loops1.c @@ -1,4 +1,6 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" + // CHECK: Verification SUCCESSFUL extern int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/base/loops2_fail.c b/test/theta/verif/base/loops2_fail.c index 3637712a..36e0804e 100644 --- a/test/theta/verif/base/loops2_fail.c +++ b/test/theta/verif/base/loops2_fail.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/loops3_fail.c b/test/theta/verif/base/loops3_fail.c index 999d4365..0951f34f 100644 --- a/test/theta/verif/base/loops3_fail.c +++ b/test/theta/verif/base/loops3_fail.c @@ -1,4 +1,5 @@ // RUN: %theta -no-optimize -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/main_no_assert.c b/test/theta/verif/base/main_no_assert.c index 242f4305..88ebd64a 100644 --- a/test/theta/verif/base/main_no_assert.c +++ b/test/theta/verif/base/main_no_assert.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/base/separate_assert.c b/test/theta/verif/base/separate_assert.c index 5c60c34d..cc0eaa79 100644 --- a/test/theta/verif/base/separate_assert.c +++ b/test/theta/verif/base/separate_assert.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/base/simple_fail.c b/test/theta/verif/base/simple_fail.c index c9f6d830..36338c76 100644 --- a/test/theta/verif/base/simple_fail.c +++ b/test/theta/verif/base/simple_fail.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED #include diff --git a/test/theta/verif/base/uninitialized_var_false.c b/test/theta/verif/base/uninitialized_var_false.c index 0c2b7e3c..cbdc7748 100644 --- a/test/theta/verif/base/uninitialized_var_false.c +++ b/test/theta/verif/base/uninitialized_var_false.c @@ -1,5 +1,6 @@ // RUN: %theta -no-optimize -memory=havoc "%s" -math-int | FileCheck "%s" // RUN: %theta -memory=havoc "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/arrays1.c b/test/theta/verif/memory/arrays1.c index 7daa50d7..c2769805 100644 --- a/test/theta/verif/memory/arrays1.c +++ b/test/theta/verif/memory/arrays1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index c62fada8..0cbb2c0f 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index 92f2dbd1..6579935e 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index 5726e50c..8eb281f2 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 847ba069..10e3242e 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index 6c6e8adb..5975a3c8 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index 82cc0f15..c7b8808d 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 62a5f181..50213622 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index 2770d0dd..a4a054e0 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index db466580..0c44ad05 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index 47ebe1bf..1465eaf5 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index 7bc4ad03..8ac40ced 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index 39159c6c..ef4d7024 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index 807101dc..f46abffe 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index 5bab01fd..f562d97d 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index e6a47b8c..9debb018 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta "%s" -math-int | FileCheck "%s" +// RUN: %theta "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/svcomp/locks/test_locks_13_true.c b/test/theta/verif/svcomp/locks/test_locks_13_true.c index 5ebb658b..92fae859 100644 --- a/test/theta/verif/svcomp/locks/test_locks_13_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_13_true.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_14_false.c b/test/theta/verif/svcomp/locks/test_locks_14_false.c index 143f2a98..9517a036 100644 --- a/test/theta/verif/svcomp/locks/test_locks_14_false.c +++ b/test/theta/verif/svcomp/locks/test_locks_14_false.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_14_true.c b/test/theta/verif/svcomp/locks/test_locks_14_true.c index b53ff8a7..5884fde9 100644 --- a/test/theta/verif/svcomp/locks/test_locks_14_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_14_true.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_15_false.c b/test/theta/verif/svcomp/locks/test_locks_15_false.c index e3f77578..e8d61a9c 100644 --- a/test/theta/verif/svcomp/locks/test_locks_15_false.c +++ b/test/theta/verif/svcomp/locks/test_locks_15_false.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED extern void __VERIFIER_error() __attribute__ ((__noreturn__)); diff --git a/test/theta/verif/svcomp/locks/test_locks_15_true.c b/test/theta/verif/svcomp/locks/test_locks_15_true.c index 3daa1e35..aec8ffe1 100644 --- a/test/theta/verif/svcomp/locks/test_locks_15_true.c +++ b/test/theta/verif/svcomp/locks/test_locks_15_true.c @@ -1,4 +1,5 @@ // RUN: %theta -memory=havoc -math-int "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL extern void __VERIFIER_error() __attribute__ ((__noreturn__)); From f408eaa79ba27bd0c663ba2e2bb23aeae9765799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 09:54:14 +0200 Subject: [PATCH 51/70] Refactor ThetaType to use free functions --- tools/gazer-theta/lib/ThetaCfaGenerator.cpp | 4 ++-- tools/gazer-theta/lib/ThetaExpr.cpp | 4 ++-- tools/gazer-theta/lib/ThetaType.cpp | 8 ++++---- tools/gazer-theta/lib/ThetaType.h | 10 ++-------- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp index 17da3256..65916319 100644 --- a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp +++ b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp @@ -225,7 +225,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace // Add variables for (auto& variable : main->locals()) { auto name = validName(variable.getName(), isValidVarName); - auto type = ThetaType::getThetaTypeName(variable.getType()); + auto type = thetaType(variable.getType()); nameTrace.variables[name] = &variable; vars.try_emplace(&variable, std::make_unique(name, type)); @@ -233,7 +233,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace for (auto& variable : main->inputs()) { auto name = validName(variable.getName(), isValidVarName); - auto type = ThetaType::getThetaTypeName(variable.getType()); + auto type = thetaType(variable.getType()); nameTrace.variables[name] = &variable; vars.try_emplace(&variable, std::make_unique(name, type)); diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index ee6991ee..ab67a404 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -83,14 +83,14 @@ class ThetaExprPrinter : public ExprWalker arrLitStr += "default <- "; } else { - arrLitStr += "<" + ThetaType::getThetaTypeName(arrLit->getType().getIndexType()) + ">default <- "; + arrLitStr += "<" + thetaType(arrLit->getType().getIndexType()) + ">default <- "; } if(arrLit->hasDefault()) { arrLitStr += this->walk(arrLit->getDefault()); } else { - arrLitStr += ThetaType::getThetaTypeDefaultValue(arrLit->getType().getElementType()); + arrLitStr += defaultValueForType(arrLit->getType().getElementType()); } arrLitStr += "]"; diff --git a/tools/gazer-theta/lib/ThetaType.cpp b/tools/gazer-theta/lib/ThetaType.cpp index 71886e3d..75f8276c 100644 --- a/tools/gazer-theta/lib/ThetaType.cpp +++ b/tools/gazer-theta/lib/ThetaType.cpp @@ -21,7 +21,7 @@ using namespace gazer; using namespace gazer::theta; -std::string ThetaType::getThetaTypeName(Type &type) +std::string gazer::theta::thetaType(Type &type) { switch (type.getTypeID()) { case Type::IntTypeID: @@ -32,7 +32,7 @@ std::string ThetaType::getThetaTypeName(Type &type) return "bool"; case Type::ArrayTypeID: { auto& arrTy = llvm::cast(type); - return "[" + getThetaTypeName(arrTy.getIndexType()) + "] -> " + getThetaTypeName(arrTy.getElementType()); + return "[" + thetaType(arrTy.getIndexType()) + "] -> " + thetaType(arrTy.getElementType()); } case Type::BvTypeID: { auto& bvTy = llvm::cast(type); @@ -43,7 +43,7 @@ std::string ThetaType::getThetaTypeName(Type &type) } } -std::string ThetaType::getThetaTypeDefaultValue(Type &type) +std::string gazer::theta::defaultValueForType(Type &type) { switch (type.getTypeID()) { case Type::IntTypeID: @@ -54,7 +54,7 @@ std::string ThetaType::getThetaTypeDefaultValue(Type &type) return "false"; case Type::ArrayTypeID: { auto& arrTy = llvm::cast(type); - return "[<" + getThetaTypeName(arrTy.getIndexType()) + ">default <- " + getThetaTypeDefaultValue(arrTy.getElementType()) + "]"; + return "[<" + thetaType(arrTy.getIndexType()) + ">default <- " + defaultValueForType(arrTy.getElementType()) + "]"; } case Type::BvTypeID: { auto& bvTy = llvm::cast(type); diff --git a/tools/gazer-theta/lib/ThetaType.h b/tools/gazer-theta/lib/ThetaType.h index 8eb6f528..582776db 100644 --- a/tools/gazer-theta/lib/ThetaType.h +++ b/tools/gazer-theta/lib/ThetaType.h @@ -25,14 +25,8 @@ namespace gazer::theta { -class ThetaType final -{ -public: - ThetaType() = delete; - - static std::string getThetaTypeName(Type& type); - static std::string getThetaTypeDefaultValue(Type& type); -}; +std::string thetaType(Type& type); +std::string defaultValueForType(Type& type); } // end namespace gazer::theta From 193c7555df1ff2711d334a9a81746196cff4a133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 09:57:26 +0200 Subject: [PATCH 52/70] Replace boost::intrusive_ptr with Gazer defined ExprRef --- tools/gazer-theta/lib/ThetaVerifier.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 4edb3f87..31b1dc60 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -240,9 +240,9 @@ static void reportInvalidCex(llvm::StringRef message, llvm::StringRef cex, sexpr llvm::errs() << "Raw counterexample is: " << cex << "\n"; } -static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr; +static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> ExprRef; -static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> boost::intrusive_ptr +static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> ExprRef { llvm::StringRef value = sexpr->asAtom(); if (value.equals_lower("true")) { @@ -256,7 +256,7 @@ static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> boost::int } } -static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> boost::intrusive_ptr +static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> ExprRef { llvm::StringRef value = sexpr->asAtom(); long long int intVal; @@ -268,7 +268,7 @@ static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> boost::intru } } -static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusive_ptr +static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> ExprRef { llvm::StringRef value = sexpr->asAtom(); llvm::APInt intVal; @@ -316,7 +316,7 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> boost::intrusi } } -static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> boost::intrusive_ptr +static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> ExprRef { auto arrLitImpl = sexpr->asList(); // The string "array" at the beginning @@ -340,7 +340,7 @@ static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> boost::i return ArrayLiteralExpr::Get(varTy, entries, def); } -static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> boost::intrusive_ptr +static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> ExprRef { switch (varTy.getTypeID()) { case Type::BoolTypeID: { From 7bbcefa3c521dad0dd9b943dd6ee7759c4450ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 10:02:56 +0200 Subject: [PATCH 53/70] Adhere to code formatting guidelines --- tools/gazer-theta/lib/ThetaExpr.cpp | 36 +++++++++++-------------- tools/gazer-theta/lib/ThetaVerifier.cpp | 25 +++++++---------- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index ab67a404..807a24aa 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -66,30 +66,28 @@ class ThetaExprPrinter : public ExprWalker return std::to_string(val.numerator()) + "%" + std::to_string(val.denominator()); } - if(auto bvLit = llvm::dyn_cast(expr)) { + if (auto bvLit = llvm::dyn_cast(expr)) { auto exactValue = bvLit->getValue().getZExtValue(); auto exactString = std::bitset(exactValue).to_string(); return std::to_string(bvLit->getType().getWidth()) + "'b" + exactString.substr(exactString.length() - bvLit->getType().getWidth()); } - if(auto arrLit = llvm::dyn_cast(expr)) { + if (auto arrLit = llvm::dyn_cast(expr)) { std::string arrLitStr = "["; const auto& kvPairs = arrLit->getMap(); - if(kvPairs.size() > 0) { - for(const auto& [index, elem] : kvPairs) { + if (kvPairs.size() > 0) { + for (const auto& [index, elem] : kvPairs) { arrLitStr += this->walk(index) + " <- " + this->walk(elem) + ", "; } arrLitStr += "default <- "; - } - else { + } else { arrLitStr += "<" + thetaType(arrLit->getType().getIndexType()) + ">default <- "; } - if(arrLit->hasDefault()) { + if (arrLit->hasDefault()) { arrLitStr += this->walk(arrLit->getDefault()); - } - else { + } else { arrLitStr += defaultValueForType(arrLit->getType().getElementType()); } @@ -115,28 +113,25 @@ class ThetaExprPrinter : public ExprWalker // Binary std::string visitAdd(const ExprRef& expr) { - if(expr->getType().isBvType()) { + if (expr->getType().isBvType()) { return "(" + getOperand(0) + " bvadd " + getOperand(1) + ")"; - } - else { + } else { return "(" + getOperand(0) + " + " + getOperand(1) + ")"; } } std::string visitSub(const ExprRef& expr) { - if(expr->getType().isBvType()) { + if (expr->getType().isBvType()) { return "(" + getOperand(0) + " bvsub " + getOperand(1) + ")"; - } - else { + } else { return "(" + getOperand(0) + " - " + getOperand(1) + ")"; } } std::string visitMul(const ExprRef& expr) { - if(expr->getType().isBvType()) { + if (expr->getType().isBvType()) { return "(" + getOperand(0) + " bvmul " + getOperand(1) + ")"; - } - else { + } else { return "(" + getOperand(0) + " * " + getOperand(1) + ")"; } } @@ -154,10 +149,9 @@ class ThetaExprPrinter : public ExprWalker } std::string visitMod(const ExprRef& expr) { - if(expr->getType().isBvType()) { + if (expr->getType().isBvType()) { return "(" + getOperand(0) + " bvsmod " + getOperand(1) + ")"; - } - else { + } else { return "(" + getOperand(0) + " mod " + getOperand(1) + ")"; } } diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 31b1dc60..f3705193 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -247,11 +247,9 @@ static auto parseBoolLiteral(sexpr::Value* sexpr, BoolType& varTy) -> ExprRef
  • asAtom(); if (value.equals_lower("true")) { return BoolLiteralExpr::True(varTy.getContext()); - } - else if (value.equals_lower("false")) { + } else if (value.equals_lower("false")) { return BoolLiteralExpr::False(varTy.getContext()); - } - else { + } else { return nullptr; } } @@ -262,8 +260,7 @@ static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> ExprRef ExprRef(lit) != "") { + } else if (const auto lit = value.split("'"); std::get<1>(lit) != "") { auto bvSizeStr = std::get<0>(lit); auto bvLitForm = std::get<1>(lit)[0]; auto bvLitValueStr = std::get<1>(lit).substr(1); @@ -304,13 +300,11 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> ExprRef ExprRef< ArrayLiteralExpr::MappingT entries; ExprRef def = nullptr; - for(auto arrEntryImpl : arrLitImpl) { + for (auto arrEntryImpl : arrLitImpl) { auto keyImpl = arrEntryImpl->asList()[0]; auto valueImpl = arrEntryImpl->asList()[1]; - if(keyImpl->isAtom() && keyImpl->asAtom() == "default") { + if (keyImpl->isAtom() && keyImpl->asAtom() == "default") { def = parseLiteral(valueImpl, varTy.getElementType()); - } - else { + } else { entries[parseLiteral(keyImpl, varTy.getIndexType())] = parseLiteral(valueImpl, varTy.getElementType()); } } From 993b361d59b9e72cf19374b205c5b9751b5d9b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 15:49:35 +0200 Subject: [PATCH 54/70] Remove dependency from std::bitset --- tools/gazer-theta/lib/ThetaExpr.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 807a24aa..21356ce2 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -12,7 +12,7 @@ // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and -// limitations under the License. +// limitations under the Lic without '0b' prefixense. // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" @@ -20,11 +20,11 @@ #include "gazer/Core/Expr/ExprWalker.h" #include "gazer/ADT/StringUtils.h" +#include #include #include -#include #include using namespace gazer; @@ -67,9 +67,16 @@ class ThetaExprPrinter : public ExprWalker } if (auto bvLit = llvm::dyn_cast(expr)) { - auto exactValue = bvLit->getValue().getZExtValue(); - auto exactString = std::bitset(exactValue).to_string(); - return std::to_string(bvLit->getType().getWidth()) + "'b" + exactString.substr(exactString.length() - bvLit->getType().getWidth()); + llvm::SmallString<64> exactString; + llvm::SmallString<64> paddedString; + + bvLit->getValue().toStringUnsigned(exactString, 2); // The bitvector may be signed, but only the bits are relevant + + auto paddingLength = std::max((bvLit->getType().getWidth() - exactString.size()), 0ul); + paddedString.append(paddingLength, '0'); // Leading zeros + paddedString.append(exactString); // Append literal + + return std::to_string(bvLit->getType().getWidth()) + "'b" + std::string(paddedString.data(), paddedString.data() + paddedString.size()); } if (auto arrLit = llvm::dyn_cast(expr)) { From 9df72961b6fdd312e45b292c131a50024bd706c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:09:08 +0200 Subject: [PATCH 55/70] Add tests in ThetaExprPrinter for bitvector transformation --- .../gazer-theta/ThetaExprPrinterTest.cpp | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp index f98234a5..9a5dc8af 100644 --- a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp +++ b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp @@ -18,6 +18,7 @@ #include "../../../tools/gazer-theta/lib/ThetaCfaGenerator.h" #include "gazer/Core/Expr/ExprBuilder.h" +#include "gazer/Core/Type.h" #include @@ -59,7 +60,33 @@ ThetaExprPrinterTest::ThetaExprPrinterTest() b->Lt(b->IntLit(1), b->IntLit(2)), b->Gt(b->IntLit(2), b->IntLit(1)) }), "((1 = 1) and (1 < 2) and (2 > 1))" }, - { b->Select(b->Eq(b->IntLit(1), b->IntLit(2)), b->IntLit(3), b->IntLit(4)), "(if (1 = 2) then 3 else 4)" } + { b->Select(b->Eq(b->IntLit(1), b->IntLit(2)), b->IntLit(3), b->IntLit(4)), "(if (1 = 2) then 3 else 4)" }, + { b->Add(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvadd 8'b00000011)" }, + { b->Sub(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsub 8'b00000011)" }, + { b->Mul(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvmul 8'b00000011)" }, + { b->BvUDiv(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvudiv 8'b00000011)" }, + { b->BvSDiv(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsdiv 8'b00000011)" }, + { b->Mod(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsmod 8'b00000011)" }, + { b->BvURem(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvurem 8'b00000011)" }, + { b->BvSRem(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsrem 8'b00000011)" }, + { b->BvAnd(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvand 8'b00000011)" }, + { b->BvOr(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvor 8'b00000011)" }, + { b->BvXor(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvxor 8'b00000011)" }, + { b->Shl(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvshl 8'b00000011)" }, + { b->AShr(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvashr 8'b00000011)" }, + { b->LShr(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvlshr 8'b00000011)" }, + { b->BvConcat(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 ++ 8'b00000011)" }, + { b->Extract(b->BvLit(2, 8), 3, 3), "(8'b00000010)[6:3]" }, + { b->ZExt(b->BvLit(2, 8), BvType::Get(ctx, 16)), "(8'b00000010 bv_zero_extend bv[16])" }, + { b->SExt(b->BvLit(2, 8), BvType::Get(ctx, 16)), "(8'b00000010 bv_sign_extend bv[16])" }, + { b->BvULt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvult 8'b00000011)" }, + { b->BvULtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvule 8'b00000011)" }, + { b->BvUGt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvugt 8'b00000011)" }, + { b->BvUGtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvuge 8'b00000011)" }, + { b->BvSLt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvslt 8'b00000011)" }, + { b->BvSLtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsle 8'b00000011)" }, + { b->BvSGt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsgt 8'b00000011)" }, + { b->BvSGtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsge 8'b00000011)" } }) {} From 2f136c803cdc4232a0ffb690badf584198e940f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:32:14 +0200 Subject: [PATCH 56/70] Add methods that create array literals to ExprBuilder --- include/gazer/Core/Expr/ExprBuilder.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/gazer/Core/Expr/ExprBuilder.h b/include/gazer/Core/Expr/ExprBuilder.h index e3ceab9c..c6eb7bf5 100644 --- a/include/gazer/Core/Expr/ExprBuilder.h +++ b/include/gazer/Core/Expr/ExprBuilder.h @@ -59,6 +59,22 @@ class ExprBuilder return IntLiteralExpr::Get(IntType::Get(mContext), value); } + ExprRef ArrayLit(ArrayType& arrTy, const ArrayLiteralExpr::MappingT& entries, const ExprRef& elze = nullptr) { + return ArrayLiteralExpr::Get(arrTy, entries, elze); + } + + ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries) { + assert(entries.size() > 0); + const auto& [index, elem] = *entries.begin(); + return ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, nullptr); + } + + ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries, const ExprRef& elze) { + assert(entries.size() > 0); + const auto& [index, elem] = *entries.begin(); + return ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, elze); + } + ExprRef BoolLit(bool value) { return value ? True() : False(); } ExprRef True() { return BoolLiteralExpr::True(BoolType::Get(mContext)); } ExprRef False() { return BoolLiteralExpr::False(BoolType::Get(mContext)); } From a48710120b2cf3d3e7ed17fc01996462b844704c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:32:40 +0200 Subject: [PATCH 57/70] Add tests targeting array literal transformation in ThetaExprPrinter --- unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp index 9a5dc8af..ef1cc857 100644 --- a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp +++ b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp @@ -86,7 +86,13 @@ ThetaExprPrinterTest::ThetaExprPrinterTest() { b->BvSLt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvslt 8'b00000011)" }, { b->BvSLtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsle 8'b00000011)" }, { b->BvSGt(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsgt 8'b00000011)" }, - { b->BvSGtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsge 8'b00000011)" } + { b->BvSGtEq(b->BvLit(2, 8), b->BvLit(3, 8)), "(8'b00000010 bvsge 8'b00000011)" }, + { b->ArrayLit({ + { b->BvLit(2, 4), b->BvLit(3, 4) }, + { b->BvLit(1, 4), b->BvLit(0, 4) } + }, b->BvLit(0, 4)), "[4'b0010 <- 4'b0011, 4'b0001 <- 4'b0000, default <- 4'b0000]" + }, + { b->ArrayLit(ArrayType::Get(BvType::Get(ctx, 8), BvType::Get(ctx, 4)), {}, b->BvLit(0, 4)), "[default <- 4'b0000]" } }) {} From 6ba4ce80fcde4d568ff5ce6790bf9804963fbf36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:33:05 +0200 Subject: [PATCH 58/70] Fix error regarding recursive usage of ThetaExprPrinter --- tools/gazer-theta/lib/ThetaExpr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 21356ce2..1dca127b 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -85,7 +85,7 @@ class ThetaExprPrinter : public ExprWalker const auto& kvPairs = arrLit->getMap(); if (kvPairs.size() > 0) { for (const auto& [index, elem] : kvPairs) { - arrLitStr += this->walk(index) + " <- " + this->walk(elem) + ", "; + arrLitStr += printThetaExpr(index, mReplacedNames) + " <- " + printThetaExpr(elem, mReplacedNames) + ", "; } arrLitStr += "default <- "; } else { @@ -93,7 +93,7 @@ class ThetaExprPrinter : public ExprWalker } if (arrLit->hasDefault()) { - arrLitStr += this->walk(arrLit->getDefault()); + arrLitStr += printThetaExpr(arrLit->getDefault(), mReplacedNames); } else { arrLitStr += defaultValueForType(arrLit->getType().getElementType()); } From a1954036d1d3cdd9f97ec75030d7c0fb11e56311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 16:44:21 +0200 Subject: [PATCH 59/70] Run functional tests requiring flat memory model with bitvector compatible algorithm --- test/theta/verif/memory/arrays2_fail.c | 2 +- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 2 +- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index 0cbb2c0f..c57993a0 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index 6579935e..f46a8b96 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index 8eb281f2..7240570a 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 10e3242e..20a93440 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index 5975a3c8..0b9ae027 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index c7b8808d..ad74958c 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 50213622..14cd59d5 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index a4a054e0..a234d8ce 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index 0c44ad05..6bf4320a 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index 1465eaf5..e69889aa 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index 8ac40ced..ebc6ace7 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index ef4d7024..96b10a3e 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index f46abffe..0b57f447 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index f562d97d..51a44080 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index 9debb018..1ee94812 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" // CHECK: Verification FAILED From a5b9dc9f45267dff0e0e864ca805863f6f1084b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 11 Sep 2020 17:47:40 +0200 Subject: [PATCH 60/70] Enable theta tests that require bitvector support --- test/theta/verif/memory/arrays1.c | 2 +- test/theta/verif/memory/arrays2_fail.c | 4 ++-- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/lit.local.cfg | 2 +- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 4 ++-- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/theta/verif/memory/arrays1.c b/test/theta/verif/memory/arrays1.c index c2769805..ae9ae021 100644 --- a/test/theta/verif/memory/arrays1.c +++ b/test/theta/verif/memory/arrays1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index c57993a0..127bc186 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); @@ -13,7 +13,7 @@ int main(void) x[i] = i; } - if (x[0] != 0) { + if (x[0] == 0) { __VERIFIER_error(); } diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index f46a8b96..de0a6dac 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index 7240570a..fdb10387 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 20a93440..75798691 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index 0b9ae027..aefbd9bf 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/lit.local.cfg b/test/theta/verif/memory/lit.local.cfg index 61864550..390d8959 100644 --- a/test/theta/verif/memory/lit.local.cfg +++ b/test/theta/verif/memory/lit.local.cfg @@ -4,4 +4,4 @@ import lit import pathlib # Disable these tests until we will have a theta-compatible memory model -config.unsupported = True +# config.unsupported = True diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index ad74958c..d5fa05ac 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 14cd59d5..90292589 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index a234d8ce..065fa831 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index 6bf4320a..9c48ee3c 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index e69889aa..bd9770e2 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index ebc6ace7..48ce0446 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index 96b10a3e..dd12fd88 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index 0b57f447..469ef2b2 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED @@ -20,7 +20,7 @@ int main(void) int prod; sumprod(a, b, &prod, &prod); - if (prod != 25) { + if (prod == 25) { __VERIFIER_error(); } diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index 51a44080..edf69d2f 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index 1ee94812..09f75915 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta --domain EXPL --refinement UNSAT_CORE "%s" | FileCheck "%s" +// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED From d4ded75985abb586b40e9ef209da7f0d5f157f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 11:55:05 +0200 Subject: [PATCH 61/70] Use more efficient refinement strategy for theta/memory functional tests --- test/theta/verif/memory/arrays2_fail.c | 2 +- test/theta/verif/memory/globals1.c | 2 +- test/theta/verif/memory/globals2.c | 2 +- test/theta/verif/memory/globals3.c | 2 +- test/theta/verif/memory/globals4.c | 2 +- test/theta/verif/memory/lit.local.cfg | 7 ------- test/theta/verif/memory/local_passbyref1_fail.c | 2 +- test/theta/verif/memory/passbyref1_false.c | 2 +- test/theta/verif/memory/passbyref2.c | 2 +- test/theta/verif/memory/passbyref3_fail.c | 2 +- test/theta/verif/memory/passbyref4.c | 2 +- test/theta/verif/memory/passbyref5.c | 2 +- test/theta/verif/memory/passbyref6.c | 2 +- test/theta/verif/memory/passbyref7_fail.c | 2 +- test/theta/verif/memory/pointers1.c | 2 +- test/theta/verif/memory/structs1.c | 2 +- 16 files changed, 15 insertions(+), 22 deletions(-) delete mode 100644 test/theta/verif/memory/lit.local.cfg diff --git a/test/theta/verif/memory/arrays2_fail.c b/test/theta/verif/memory/arrays2_fail.c index 127bc186..dad980af 100644 --- a/test/theta/verif/memory/arrays2_fail.c +++ b/test/theta/verif/memory/arrays2_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals1.c b/test/theta/verif/memory/globals1.c index de0a6dac..1dbdcb8f 100644 --- a/test/theta/verif/memory/globals1.c +++ b/test/theta/verif/memory/globals1.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL int __VERIFIER_nondet_int(void); diff --git a/test/theta/verif/memory/globals2.c b/test/theta/verif/memory/globals2.c index fdb10387..58dc1a71 100644 --- a/test/theta/verif/memory/globals2.c +++ b/test/theta/verif/memory/globals2.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals3.c b/test/theta/verif/memory/globals3.c index 75798691..484271d8 100644 --- a/test/theta/verif/memory/globals3.c +++ b/test/theta/verif/memory/globals3.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL #include diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c index aefbd9bf..1585a86c 100644 --- a/test/theta/verif/memory/globals4.c +++ b/test/theta/verif/memory/globals4.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/lit.local.cfg b/test/theta/verif/memory/lit.local.cfg deleted file mode 100644 index 390d8959..00000000 --- a/test/theta/verif/memory/lit.local.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# -*- Python -*- - -import lit -import pathlib - -# Disable these tests until we will have a theta-compatible memory model -# config.unsupported = True diff --git a/test/theta/verif/memory/local_passbyref1_fail.c b/test/theta/verif/memory/local_passbyref1_fail.c index d5fa05ac..f41b4d40 100644 --- a/test/theta/verif/memory/local_passbyref1_fail.c +++ b/test/theta/verif/memory/local_passbyref1_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED void __VERIFIER_error(void) __attribute__((__noreturn__)); diff --git a/test/theta/verif/memory/passbyref1_false.c b/test/theta/verif/memory/passbyref1_false.c index 90292589..ec18cab9 100644 --- a/test/theta/verif/memory/passbyref1_false.c +++ b/test/theta/verif/memory/passbyref1_false.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref2.c b/test/theta/verif/memory/passbyref2.c index 065fa831..950a73ae 100644 --- a/test/theta/verif/memory/passbyref2.c +++ b/test/theta/verif/memory/passbyref2.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref3_fail.c b/test/theta/verif/memory/passbyref3_fail.c index 9c48ee3c..a10af409 100644 --- a/test/theta/verif/memory/passbyref3_fail.c +++ b/test/theta/verif/memory/passbyref3_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/passbyref4.c b/test/theta/verif/memory/passbyref4.c index bd9770e2..36d4b3c4 100644 --- a/test/theta/verif/memory/passbyref4.c +++ b/test/theta/verif/memory/passbyref4.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c index 48ce0446..18b57519 100644 --- a/test/theta/verif/memory/passbyref5.c +++ b/test/theta/verif/memory/passbyref5.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c index dd12fd88..0ba7813a 100644 --- a/test/theta/verif/memory/passbyref6.c +++ b/test/theta/verif/memory/passbyref6.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/passbyref7_fail.c b/test/theta/verif/memory/passbyref7_fail.c index 469ef2b2..ef0a6b0a 100644 --- a/test/theta/verif/memory/passbyref7_fail.c +++ b/test/theta/verif/memory/passbyref7_fail.c @@ -1,5 +1,5 @@ // REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED diff --git a/test/theta/verif/memory/pointers1.c b/test/theta/verif/memory/pointers1.c index edf69d2f..85acf8ca 100644 --- a/test/theta/verif/memory/pointers1.c +++ b/test/theta/verif/memory/pointers1.c @@ -1,4 +1,4 @@ -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification SUCCESSFUL diff --git a/test/theta/verif/memory/structs1.c b/test/theta/verif/memory/structs1.c index 09f75915..c1d119a2 100644 --- a/test/theta/verif/memory/structs1.c +++ b/test/theta/verif/memory/structs1.c @@ -1,5 +1,5 @@ // REQUIRES: memory.structs -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" +// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" // CHECK: Verification FAILED From bd9802937082e6479c25829cb84b38b43bd45894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 15:53:44 +0200 Subject: [PATCH 62/70] Remove tests that timeout --- test/theta/verif/memory/globals4.c | 28 ------------------------- test/theta/verif/memory/passbyref6.c | 31 ---------------------------- 2 files changed, 59 deletions(-) delete mode 100644 test/theta/verif/memory/globals4.c delete mode 100644 test/theta/verif/memory/passbyref6.c diff --git a/test/theta/verif/memory/globals4.c b/test/theta/verif/memory/globals4.c deleted file mode 100644 index 1585a86c..00000000 --- a/test/theta/verif/memory/globals4.c +++ /dev/null @@ -1,28 +0,0 @@ -// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP -no-inline-globals "%s" | FileCheck "%s" - -// CHECK: Verification SUCCESSFUL - -int __VERIFIER_nondet_int(void); -void __VERIFIER_error(void) __attribute__((__noreturn__)); - -int a = 1; -int b = 1; -int c = 3; - -int main(void) -{ - int input = 1; - while (input != 0) { - input = __VERIFIER_nondet_int(); - if (input == 1) { - a = a + 1; - } - } - - if (a < b) { - __VERIFIER_error(); - } - - return 0; -} - diff --git a/test/theta/verif/memory/passbyref6.c b/test/theta/verif/memory/passbyref6.c deleted file mode 100644 index 0ba7813a..00000000 --- a/test/theta/verif/memory/passbyref6.c +++ /dev/null @@ -1,31 +0,0 @@ -// REQUIRES: memory.burstall -// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" - -// CHECK: Verification SUCCESSFUL - -int __VERIFIER_nondet_int(void); -void __VERIFIER_error(void) __attribute__((__noreturn__)); - -void sumprod(int* a, int* b, int *sum, int *prod) -{ - *sum = *a + *b; - *prod = *a * *b; -} - -int main(void) -{ - int a = __VERIFIER_nondet_int(); - int b = a + 1; - int c = __VERIFIER_nondet_int(); - - int* p = a == 0 ? &c : &a; - - int sum, prod; - sumprod(p, &b, &sum, &prod); - - if (a != 0 && b != 0 && prod == 0) { - __VERIFIER_error(); - } - - return 0; -} From 9dd49c15dff8a80e9a0d2561e4997aeaade84257 Mon Sep 17 00:00:00 2001 From: as3810t Date: Tue, 15 Sep 2020 17:20:18 +0200 Subject: [PATCH 63/70] Correct typo in licence Co-authored-by: Gyula Sallai --- tools/gazer-theta/lib/ThetaExpr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 1dca127b..098e66a6 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -12,7 +12,7 @@ // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and -// limitations under the Lic without '0b' prefixense. +// limitations under the License. // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" @@ -336,4 +336,4 @@ std::string gazer::theta::printThetaExpr(const ExprPtr& expr, std::function Date: Tue, 15 Sep 2020 17:25:02 +0200 Subject: [PATCH 64/70] Fix coding style issues Co-authored-by: Gyula Sallai --- include/gazer/Core/Expr/ExprBuilder.h | 2 +- tools/gazer-theta/lib/ThetaVerifier.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/gazer/Core/Expr/ExprBuilder.h b/include/gazer/Core/Expr/ExprBuilder.h index c6eb7bf5..b826ffcd 100644 --- a/include/gazer/Core/Expr/ExprBuilder.h +++ b/include/gazer/Core/Expr/ExprBuilder.h @@ -72,7 +72,7 @@ class ExprBuilder ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries, const ExprRef& elze) { assert(entries.size() > 0); const auto& [index, elem] = *entries.begin(); - return ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, elze); + return this->ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, elze); } ExprRef BoolLit(bool value) { return value ? True() : False(); } diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index f3705193..0d649336 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -260,9 +260,9 @@ static auto parseIntLiteral(sexpr::Value* sexpr, IntType& varTy) -> ExprRef ExprRef From c3912bc98a04273c3129045a2ef4850dfcd5d243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 4 Oct 2020 16:40:47 +0200 Subject: [PATCH 65/70] Refactor ThetaType --- tools/gazer-theta/CMakeLists.txt | 3 +- tools/gazer-theta/lib/ThetaType.cpp | 66 ---------------------------- tools/gazer-theta/lib/ThetaType.h | 67 ++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 70 deletions(-) delete mode 100644 tools/gazer-theta/lib/ThetaType.cpp diff --git a/tools/gazer-theta/CMakeLists.txt b/tools/gazer-theta/CMakeLists.txt index 939ab49c..13916695 100644 --- a/tools/gazer-theta/CMakeLists.txt +++ b/tools/gazer-theta/CMakeLists.txt @@ -1,6 +1,5 @@ set(LIB_SOURCE_FILES - lib/ThetaType.cpp - lib/ThetaCfaGenerator.cpp + lib/ThetaCfaGenerator.cpp lib/ThetaExpr.cpp lib/ThetaVerifier.cpp lib/ThetaCfaWriterPass.cpp) diff --git a/tools/gazer-theta/lib/ThetaType.cpp b/tools/gazer-theta/lib/ThetaType.cpp deleted file mode 100644 index 75f8276c..00000000 --- a/tools/gazer-theta/lib/ThetaType.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//==-------------------------------------------------------------*- C++ -*--==// -// -// Copyright 2019 Contributors to the Gazer project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// - -#include "ThetaType.h" - -using namespace gazer; -using namespace gazer::theta; - -std::string gazer::theta::thetaType(Type &type) -{ - switch (type.getTypeID()) { - case Type::IntTypeID: - return "int"; - case Type::RealTypeID: - return "rat"; - case Type::BoolTypeID: - return "bool"; - case Type::ArrayTypeID: { - auto& arrTy = llvm::cast(type); - return "[" + thetaType(arrTy.getIndexType()) + "] -> " + thetaType(arrTy.getElementType()); - } - case Type::BvTypeID: { - auto& bvTy = llvm::cast(type); - return "bv[" + std::to_string(bvTy.getWidth()) + "]"; - } - default: - llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); - } -} - -std::string gazer::theta::defaultValueForType(Type &type) -{ - switch (type.getTypeID()) { - case Type::IntTypeID: - return "0"; - case Type::RealTypeID: - return "0%1"; - case Type::BoolTypeID: - return "false"; - case Type::ArrayTypeID: { - auto& arrTy = llvm::cast(type); - return "[<" + thetaType(arrTy.getIndexType()) + ">default <- " + defaultValueForType(arrTy.getElementType()) + "]"; - } - case Type::BvTypeID: { - auto& bvTy = llvm::cast(type); - return std::to_string(bvTy.getWidth()) + "'d0"; - } - default: - llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); - } -} diff --git a/tools/gazer-theta/lib/ThetaType.h b/tools/gazer-theta/lib/ThetaType.h index 582776db..f18da19b 100644 --- a/tools/gazer-theta/lib/ThetaType.h +++ b/tools/gazer-theta/lib/ThetaType.h @@ -25,8 +25,71 @@ namespace gazer::theta { -std::string thetaType(Type& type); -std::string defaultValueForType(Type& type); +inline std::string thetaType(const Type &type) +{ + switch (type.getTypeID()) { + case Type::IntTypeID: + return "int"; + case Type::RealTypeID: + return "rat"; + case Type::BoolTypeID: + return "bool"; + case Type::ArrayTypeID: { + const auto& arrTy = llvm::cast(type); + return "[" + thetaType(arrTy.getIndexType()) + "] -> " + thetaType(arrTy.getElementType()); + } + case Type::BvTypeID: { + const auto& bvTy = llvm::cast(type); + return "bv[" + std::to_string(bvTy.getWidth()) + "]"; + } + default: + llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); + } +} + +inline std::string thetaEscapedType(const Type &type) +{ + switch (type.getTypeID()) { + case Type::IntTypeID: + return "int"; + case Type::RealTypeID: + return "rat"; + case Type::BoolTypeID: + return "bool"; + case Type::ArrayTypeID: { + const auto& arrTy = llvm::cast(type); + return "__" + thetaEscapedType(arrTy.getIndexType()) + "_" + thetaEscapedType(arrTy.getElementType()) + "__"; + } + case Type::BvTypeID: { + const auto& bvTy = llvm::cast(type); + return "bv_" + std::to_string(bvTy.getWidth()); + } + default: + llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); + } +} + +inline std::string defaultValueForType(const Type &type) +{ + switch (type.getTypeID()) { + case Type::IntTypeID: + return "0"; + case Type::RealTypeID: + return "0%1"; + case Type::BoolTypeID: + return "false"; + case Type::ArrayTypeID: { + const auto& arrTy = llvm::cast(type); + return "[<" + thetaType(arrTy.getIndexType()) + ">default <- " + defaultValueForType(arrTy.getElementType()) + "]"; + } + case Type::BvTypeID: { + const auto& bvTy = llvm::cast(type); + return std::to_string(bvTy.getWidth()) + "'d0"; + } + default: + llvm_unreachable("Types which are unsupported by theta should have been eliminated earlier!"); + } +} } // end namespace gazer::theta From 1b6143984e22c6736440e6b26da0023339d36ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 4 Oct 2020 16:41:35 +0200 Subject: [PATCH 66/70] Improve coding style --- include/gazer/Core/Expr/ExprBuilder.h | 10 +---- tools/gazer-theta/lib/ThetaVerifier.cpp | 49 ++++++++++++------------- 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/include/gazer/Core/Expr/ExprBuilder.h b/include/gazer/Core/Expr/ExprBuilder.h index b826ffcd..857a5ee9 100644 --- a/include/gazer/Core/Expr/ExprBuilder.h +++ b/include/gazer/Core/Expr/ExprBuilder.h @@ -63,14 +63,8 @@ class ExprBuilder return ArrayLiteralExpr::Get(arrTy, entries, elze); } - ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries) { - assert(entries.size() > 0); - const auto& [index, elem] = *entries.begin(); - return ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, nullptr); - } - - ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries, const ExprRef& elze) { - assert(entries.size() > 0); + ExprRef ArrayLit(const ArrayLiteralExpr::MappingT& entries, const ExprRef& elze = nullptr) { + assert(!entries.empty()); const auto& [index, elem] = *entries.begin(); return this->ArrayLit(ArrayType::Get(index->getType(), elem->getType()), entries, elze); } diff --git a/tools/gazer-theta/lib/ThetaVerifier.cpp b/tools/gazer-theta/lib/ThetaVerifier.cpp index 0d649336..63e31659 100644 --- a/tools/gazer-theta/lib/ThetaVerifier.cpp +++ b/tools/gazer-theta/lib/ThetaVerifier.cpp @@ -271,16 +271,25 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> ExprRef(lit) != "") { - auto bvSizeStr = std::get<0>(lit); - auto bvLitForm = std::get<1>(lit)[0]; - auto bvLitValueStr = std::get<1>(lit).substr(1); + } + + if (const auto lit = value.split("'"); !std::get<1>(lit).empty()) { + // Check if we have Theta literal format + + llvm::StringRef bvSizeStr = std::get<0>(lit); + char bvLitForm = std::get<1>(lit)[0]; + llvm::StringRef bvLitValueStr = std::get<1>(lit).substr(1); unsigned bvSize; if (!bvSizeStr.getAsInteger(10, bvSize) && bvSize == varTy.getWidth()) { + // Check if we have valid bitvector size + switch (std::tolower(bvLitForm)) { + // Check if we have valid bitvector literal type + case 'b': if (!bvLitValueStr.getAsInteger(2, intVal)) { return BvLiteralExpr::Get(varTy, intVal.zextOrTrunc(varTy.getWidth())); @@ -297,17 +306,10 @@ static auto parseBvLiteral(sexpr::Value* sexpr, BvType& varTy) -> ExprRef ExprRef @@ -319,9 +321,9 @@ static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> ExprRef< ArrayLiteralExpr::MappingT entries; ExprRef def = nullptr; - for (auto arrEntryImpl : arrLitImpl) { - auto keyImpl = arrEntryImpl->asList()[0]; - auto valueImpl = arrEntryImpl->asList()[1]; + for (auto *arrEntryImpl : arrLitImpl) { + auto *keyImpl = arrEntryImpl->asList()[0]; + auto *valueImpl = arrEntryImpl->asList()[1]; if (keyImpl->isAtom() && keyImpl->asAtom() == "default") { def = parseLiteral(valueImpl, varTy.getElementType()); @@ -336,21 +338,16 @@ static auto parseArrayLiteral(sexpr::Value* sexpr, ArrayType& varTy) -> ExprRef< static auto parseLiteral(sexpr::Value* sexpr, Type& varTy) -> ExprRef { switch (varTy.getTypeID()) { - case Type::BoolTypeID: { + case Type::BoolTypeID: return parseBoolLiteral(sexpr, cast(varTy)); - } - case Type::IntTypeID: { + case Type::IntTypeID: return parseIntLiteral(sexpr, cast(varTy)); - } - case Type::BvTypeID: { + case Type::BvTypeID: return parseBvLiteral(sexpr, cast(varTy)); - } - case Type::ArrayTypeID: { + case Type::ArrayTypeID: return parseArrayLiteral(sexpr, cast(varTy)); - } - default: { + default: return nullptr; - } } } From c4751ad4832568545aa277555214adebc64ac6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 4 Oct 2020 16:45:03 +0200 Subject: [PATCH 67/70] Add utils to collect array literals modeling uninitialized memory --- tools/gazer-theta/lib/ThetaCfaGenerator.h | 6 ++++- tools/gazer-theta/lib/ThetaExpr.cpp | 32 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/tools/gazer-theta/lib/ThetaCfaGenerator.h b/tools/gazer-theta/lib/ThetaCfaGenerator.h index 942d93d3..7663809c 100644 --- a/tools/gazer-theta/lib/ThetaCfaGenerator.h +++ b/tools/gazer-theta/lib/ThetaCfaGenerator.h @@ -18,11 +18,13 @@ #ifndef GAZER_TOOLS_GAZERTHETA_THETACFAGENERATOR_H #define GAZER_TOOLS_GAZERTHETA_THETACFAGENERATOR_H -#include "gazer/Automaton/Cfa.h" #include "gazer/Automaton/CallGraph.h" +#include "gazer/Automaton/Cfa.h" #include +#include + namespace llvm { class Pass; @@ -35,6 +37,8 @@ std::string printThetaExpr(const ExprPtr& expr); std::string printThetaExpr(const ExprPtr& expr, std::function variableNames); +llvm::SmallVector, 1> collectArrayLiteralsThetaExpr(const ExprPtr& expr); + /// \brief Perform pre-processing steps required by theta on the input CFA. /// /// This pass does the following transformations: diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index 098e66a6..f4becf35 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -337,3 +337,35 @@ std::string gazer::theta::printThetaExpr(const ExprPtr& expr, std::function { +public: + llvm::SmallVector, 1> getArrayLiterals() const { + return mArrayLiterals; + } + +public: + void* visitExpr(const ExprPtr& expr) { + return nullptr; + } + + void* visitLiteral(const ExprRef& expr) + { + if (auto *arrLit = llvm::dyn_cast(expr)) { + mArrayLiterals.push_back(arrLit); + } + + return nullptr; + } + +private: + llvm::SmallVector, 1> mArrayLiterals; +}; + +llvm::SmallVector, 1> gazer::theta::collectArrayLiteralsThetaExpr(const ExprPtr& expr) +{ + ThetaExprArrayLiteralCollector collector; + collector.walk(expr); + return collector.getArrayLiterals(); +} From 50fff828269ff05d0a61f9ffee11770365eaec31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 4 Oct 2020 16:45:22 +0200 Subject: [PATCH 68/70] Create locations in Theta CFA to model uninitialized memory --- tools/gazer-theta/lib/ThetaCfaGenerator.cpp | 40 +++++++++++++++++++-- tools/gazer-theta/lib/ThetaExpr.cpp | 39 +++++++++++--------- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp index 65916319..0344ba45 100644 --- a/tools/gazer-theta/lib/ThetaCfaGenerator.cpp +++ b/tools/gazer-theta/lib/ThetaCfaGenerator.cpp @@ -16,20 +16,22 @@ // //===----------------------------------------------------------------------===// #include "ThetaCfaGenerator.h" + #include "ThetaType.h" -#include "gazer/Core/LiteralExpr.h" #include "gazer/Automaton/CfaTransforms.h" +#include "gazer/Core/LiteralExpr.h" -#include #include +#include +#include #include #include #include +#include #include -#include using namespace gazer; using namespace gazer::theta; @@ -213,6 +215,7 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace llvm::DenseMap> locs; llvm::DenseMap> vars; std::vector> edges; + std::unordered_set uninitializedMemoryArrays; // Create a closure to test variable names auto isValidVarName = [&vars](const std::string& name) -> bool { @@ -265,6 +268,15 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace if (edge->getGuard() != BoolLiteralExpr::True(edge->getGuard()->getContext())) { stmts.push_back(ThetaStmt::Assume(edge->getGuard())); + + // Collect use of uninitialized memory + auto arrayLiterals = gazer::theta::collectArrayLiteralsThetaExpr(edge->getGuard()); + for (const auto& arrayLiteral : arrayLiterals) { + if (!arrayLiteral->hasDefault()) { + assert(arrayLiteral->getMap().empty()); + uninitializedMemoryArrays.insert(&ArrayType::Get(arrayLiteral->getType().getIndexType(), arrayLiteral->getType().getElementType())); + } + } } if (auto assignEdge = dyn_cast(edge)) { @@ -275,6 +287,15 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace stmts.push_back(ThetaStmt::Havoc(lhsName)); } else { stmts.push_back(ThetaStmt::Assign(lhsName, assignment.getValue())); + + // Collect use of uninitialized memory + auto arrayLiterals = gazer::theta::collectArrayLiteralsThetaExpr(assignment.getValue()); + for (const auto& arrayLiteral : arrayLiterals) { + if (!arrayLiteral->hasDefault()) { + assert(arrayLiteral->getMap().empty()); + uninitializedMemoryArrays.insert(&ArrayType::Get(arrayLiteral->getType().getIndexType(), arrayLiteral->getType().getElementType())); + } + } } } } else if (auto callEdge = dyn_cast(edge)) { @@ -284,6 +305,17 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace edges.emplace_back(std::make_unique(source, target, std::move(stmts))); } + // Add variables modeling uninitialized memory + for (const auto& memoryArrayType : uninitializedMemoryArrays) { + auto name = validName("__gazer_uninitialized_memory_" + gazer::theta::thetaEscapedType(*memoryArrayType), isValidVarName); + auto type = thetaType(*memoryArrayType); + + auto *variable = main->createLocal(name, *memoryArrayType); + + nameTrace.variables[name] = variable; + vars.try_emplace(variable, std::make_unique(name, type)); + } + auto INDENT = " "; auto INDENT2 = " "; @@ -325,11 +357,13 @@ void ThetaCfaGenerator::write(llvm::raw_ostream& os, ThetaNameMapping& nameTrace void operator()(const ExprPtr& expr) { mOS << "assume "; mOS << theta::printThetaExpr(expr, mCanonizeName); + assert(theta::collectArrayLiteralsThetaExpr(expr).size() >= 0); } void operator()(const std::pair& assign) { mOS << assign.first << " := "; mOS << theta::printThetaExpr(assign.second, mCanonizeName); + assert(theta::collectArrayLiteralsThetaExpr(assign.second).size() >= 0); } void operator()(const std::string& variable) { diff --git a/tools/gazer-theta/lib/ThetaExpr.cpp b/tools/gazer-theta/lib/ThetaExpr.cpp index f4becf35..f0e93e6b 100644 --- a/tools/gazer-theta/lib/ThetaExpr.cpp +++ b/tools/gazer-theta/lib/ThetaExpr.cpp @@ -52,21 +52,21 @@ class ThetaExprPrinter : public ExprWalker std::string visitLiteral(const ExprRef& expr) { - if (auto intLit = llvm::dyn_cast(expr)) { + if (auto *intLit = llvm::dyn_cast(expr)) { auto val = intLit->getValue(); return val < 0 ? "(" + std::to_string(val) + ")" : std::to_string(intLit->getValue()); } - if (auto boolLit = llvm::dyn_cast(expr)) { + if (auto *boolLit = llvm::dyn_cast(expr)) { return boolLit->getValue() ? "true" : "false"; } - if (auto realLit = llvm::dyn_cast(expr)) { + if (auto *realLit = llvm::dyn_cast(expr)) { auto val = realLit->getValue(); return std::to_string(val.numerator()) + "%" + std::to_string(val.denominator()); } - if (auto bvLit = llvm::dyn_cast(expr)) { + if (auto *bvLit = llvm::dyn_cast(expr)) { llvm::SmallString<64> exactString; llvm::SmallString<64> paddedString; @@ -79,26 +79,31 @@ class ThetaExprPrinter : public ExprWalker return std::to_string(bvLit->getType().getWidth()) + "'b" + std::string(paddedString.data(), paddedString.data() + paddedString.size()); } - if (auto arrLit = llvm::dyn_cast(expr)) { - std::string arrLitStr = "["; + if (auto *arrLit = llvm::dyn_cast(expr)) { + std::string arrLitStr; - const auto& kvPairs = arrLit->getMap(); - if (kvPairs.size() > 0) { - for (const auto& [index, elem] : kvPairs) { - arrLitStr += printThetaExpr(index, mReplacedNames) + " <- " + printThetaExpr(elem, mReplacedNames) + ", "; + if (arrLit->hasDefault()) { + arrLitStr += "["; + + const auto& kvPairs = arrLit->getMap(); + if (!kvPairs.empty()) { + for (const auto& [index, elem] : kvPairs) { + arrLitStr += printThetaExpr(index, mReplacedNames) + " <- " + printThetaExpr(elem, mReplacedNames) + ", "; + } + arrLitStr += "default <- "; + } else { + arrLitStr += "<" + thetaType(arrLit->getType().getIndexType()) + ">default <- "; } - arrLitStr += "default <- "; - } else { - arrLitStr += "<" + thetaType(arrLit->getType().getIndexType()) + ">default <- "; - } - if (arrLit->hasDefault()) { arrLitStr += printThetaExpr(arrLit->getDefault(), mReplacedNames); + + arrLitStr += "]"; } else { - arrLitStr += defaultValueForType(arrLit->getType().getElementType()); + assert(arrLit->getMap().empty()); + arrLitStr += + "__gazer_uninitialized_memory_" + gazer::theta::thetaEscapedType(arrLit->getType()); } - arrLitStr += "]"; return arrLitStr; } From 9579dbcf64354da5e59c3c1bb2f7a6f25c787771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 4 Oct 2020 16:45:37 +0200 Subject: [PATCH 69/70] Add tests for Theta uninitialized memory --- unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp index ef1cc857..0c178ecd 100644 --- a/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp +++ b/unittest/tools/gazer-theta/ThetaExprPrinterTest.cpp @@ -92,7 +92,8 @@ ThetaExprPrinterTest::ThetaExprPrinterTest() { b->BvLit(1, 4), b->BvLit(0, 4) } }, b->BvLit(0, 4)), "[4'b0010 <- 4'b0011, 4'b0001 <- 4'b0000, default <- 4'b0000]" }, - { b->ArrayLit(ArrayType::Get(BvType::Get(ctx, 8), BvType::Get(ctx, 4)), {}, b->BvLit(0, 4)), "[default <- 4'b0000]" } + { b->ArrayLit(ArrayType::Get(BvType::Get(ctx, 8), BvType::Get(ctx, 4)), {}, b->BvLit(0, 4)), "[default <- 4'b0000]" }, + { b->ArrayLit(ArrayType::Get(BvType::Get(ctx, 8), BvType::Get(ctx, 4)), {}), "__gazer_uninitialized_memory___bv_8_bv_4__" } }) {} From 8f9b379828cdcb2507016da67751ce24f7114f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 4 Oct 2020 16:45:47 +0200 Subject: [PATCH 70/70] Remove tests timing out --- test/theta/verif/memory/arrays1.c | 21 --------------------- test/theta/verif/memory/passbyref5.c | 28 ---------------------------- 2 files changed, 49 deletions(-) delete mode 100644 test/theta/verif/memory/arrays1.c delete mode 100644 test/theta/verif/memory/passbyref5.c diff --git a/test/theta/verif/memory/arrays1.c b/test/theta/verif/memory/arrays1.c deleted file mode 100644 index ae9ae021..00000000 --- a/test/theta/verif/memory/arrays1.c +++ /dev/null @@ -1,21 +0,0 @@ -// REQUIRES: memory.burstall -// RUN: %theta --domain EXPL --refinement NWT_IT_WP "%s" | FileCheck "%s" - -// CHECK: Verification SUCCESSFUL -int __VERIFIER_nondet_int(void); -void __VERIFIER_error(void) __attribute__((__noreturn__)); - -int main(void) -{ - int x[5]; - - for (int i = 0; i < 5; ++i) { - x[i] = i + 1; - } - - if (x[0] == 0) { - __VERIFIER_error(); - } - - return 0; -} \ No newline at end of file diff --git a/test/theta/verif/memory/passbyref5.c b/test/theta/verif/memory/passbyref5.c deleted file mode 100644 index 18b57519..00000000 --- a/test/theta/verif/memory/passbyref5.c +++ /dev/null @@ -1,28 +0,0 @@ -// REQUIRES: memory.burstall -// RUN: %theta --domain PRED_CART --refinement NWT_IT_WP "%s" | FileCheck "%s" - -// CHECK: Verification SUCCESSFUL - -int __VERIFIER_nondet_int(void); -void __VERIFIER_error(void) __attribute__((__noreturn__)); - -void sumprod(int* a, int* b, int *sum, int *prod) -{ - *sum = *a + *b; - *prod = *a * *b; -} - -int main(void) -{ - int a = __VERIFIER_nondet_int(); - int b = a + 1; - - int sum, prod; - sumprod(&a, &b, &sum, &prod); - - if (a != 0 && b != 0 && prod == 0) { - __VERIFIER_error(); - } - - return 0; -}