diff --git a/.gitignore b/.gitignore index d3c8b0cbc..7d5665f69 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ /Makefile.llvm.config /config.log /config.status +/configure.out # Generated by make Debug+Asserts @@ -28,4 +29,11 @@ bin/*.pyc .DS_Store # Backup files -*.orig \ No newline at end of file +*.orig + +# Generated by SMACK +a.bpl + +# Generated by Boogie +corral_out_trace.txt +corraldebug.out diff --git a/CMakeLists.txt b/CMakeLists.txt index 89ef5605f..150089667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,38 +1,43 @@ -# -# Copyright (c) 2013 Pantazis Deligiannis (p.deligiannis@imperial.ac.uk) +# # This file is distributed under the MIT License. See LICENSE for details. -# +# cmake_minimum_required(VERSION 2.8) project(smack) if (NOT WIN32 OR MSYS OR CYGWIN) find_program(LLVM_CONFIG_EXECUTABLE NAMES llvm-config PATHS ${LLVM_CONFIG} NO_DEFAULT_PATH DOC "llvm-config") - + if (LLVM_CONFIG_EXECUTABLE STREQUAL "LLVM_CONFIG_EXECUTABLE-NOTFOUND") message(FATAL_ERROR "llvm-config could not be found!") endif() - + execute_process( COMMAND ${LLVM_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE LLVM_CXXFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ) - + set(LLVM_CXXFLAGS "${LLVM_CXXFLAGS} -fno-exceptions -fno-rtti") - + execute_process( COMMAND ${LLVM_CONFIG_EXECUTABLE} --libs OUTPUT_VARIABLE LLVM_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE ) - + + execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --system-libs + OUTPUT_VARIABLE LLVM_SYSTEM_LIBS + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + execute_process( COMMAND ${LLVM_CONFIG_EXECUTABLE} --ldflags OUTPUT_VARIABLE LLVM_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ) - + else() set(LLVM_SRC "" CACHE PATH "LLVM source directory") set(LLVM_BUILD "" CACHE PATH "LLVM build directory") @@ -50,7 +55,7 @@ else() set(LLVM_CXXFLAGS "\"/I${LLVM_SRC}/include\" \"/I${LLVM_BUILD}/include\" -D_SCL_SECURE_NO_WARNINGS -wd4146 -wd4244 -wd4355 -wd4482 -wd4800") set(LLVM_LDFLAGS "") set(LLVM_LIBS "${LLVM_LIBDIR}/LLVMTransformUtils.lib" "${LLVM_LIBDIR}/LLVMipa.lib" "${LLVM_LIBDIR}/LLVMAnalysis.lib" "${LLVM_LIBDIR}/LLVMTarget.lib" "${LLVM_LIBDIR}/LLVMMC.lib" "${LLVM_LIBDIR}/LLVMObject.lib" "${LLVM_LIBDIR}/LLVMBitReader.lib" "${LLVM_LIBDIR}/LLVMCore.lib" "${LLVM_LIBDIR}/LLVMSupport.lib") - + endif() include_directories(include) @@ -136,26 +141,29 @@ add_library(dsa STATIC ) add_library(smackTranslator STATIC - include/smack/smack.h include/smack/BoogieAst.h include/smack/BplFilePrinter.h include/smack/BplPrinter.h + include/smack/Contracts.h include/smack/DSAAliasAnalysis.h + include/smack/Naming.h + include/smack/Slicing.h include/smack/SmackInstGenerator.h include/smack/SmackModuleGenerator.h include/smack/SmackOptions.h include/smack/SmackRep.h - include/smack/SmackRep2dMem.h include/smack/SmackRepFlatMem.h lib/smack/BoogieAst.cpp lib/smack/BplFilePrinter.cpp lib/smack/BplPrinter.cpp + lib/smack/Contracts.cpp lib/smack/DSAAliasAnalysis.cpp + lib/smack/Naming.cpp + lib/smack/Slicing.cpp lib/smack/SmackInstGenerator.cpp lib/smack/SmackModuleGenerator.cpp lib/smack/SmackOptions.cpp lib/smack/SmackRep.cpp - lib/smack/SmackRep2dMem.cpp lib/smack/SmackRepFlatMem.cpp ) @@ -166,22 +174,28 @@ add_executable(smack set_target_properties(smack smackTranslator assistDS dsa PROPERTIES COMPILE_FLAGS "${LLVM_CXXFLAGS}") -target_link_libraries(smackTranslator ${LLVM_LIBS} ${LLVM_LDFLAGS}) +target_link_libraries(smackTranslator ${LLVM_LIBS} ${LLVM_SYSTEM_LIBS} ${LLVM_LDFLAGS}) target_link_libraries(smack smackTranslator assistDS dsa) -INSTALL(TARGETS smack smackTranslator assistDS dsa +INSTALL(TARGETS smack RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib ) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/bin/boogie - ${CMAKE_CURRENT_SOURCE_DIR}/bin/corral - ${CMAKE_CURRENT_SOURCE_DIR}/bin/llvm2bpl.py - ${CMAKE_CURRENT_SOURCE_DIR}/bin/smackgen.py - ${CMAKE_CURRENT_SOURCE_DIR}/bin/smackverify.py - PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ - GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + ${CMAKE_CURRENT_SOURCE_DIR}/bin/corral + ${CMAKE_CURRENT_SOURCE_DIR}/bin/llvm2bpl.py + ${CMAKE_CURRENT_SOURCE_DIR}/bin/smackgen.py + ${CMAKE_CURRENT_SOURCE_DIR}/bin/smackverify.py + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION bin ) - + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/smack/smack.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/smack/smack-contracts.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/smack/smack-svcomp.h + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + DESTINATION include/smack +) + diff --git a/LICENSE b/LICENSE index c4c0611e4..d039a329e 100644 --- a/LICENSE +++ b/LICENSE @@ -2,6 +2,9 @@ The MIT License Copyright (c) 2008-2014 Zvonimir Rakamaric (zvonimir@cs.utah.edu), Michael Emmi (michael.emmi@gmail.com) +Modified work Copyright (c) 2013-2014 Pantazis Deligiannis, + Montgomery Carter, + Arvind Haran Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -38,3 +41,12 @@ poolalloc include/assistDS include/dsa lib/AssistDS lib/DSA + +In addition, a binary distribution of SMACK contains at least the following +tools and packages, which come with their own licenses: +- LLVM, clang, LLVM runtime (http://llvm.org/) +- mono (http://www.mono-project.com/) +- Boogie (http://boogie.codeplex.com/) +- Corral (http://corral.codeplex.com/) +- Z3 (http://z3.codeplex.com/), Non-Commercial Use Only + diff --git a/Makefile.common.in b/Makefile.common.in index 103c0c86f..6245445c4 100644 --- a/Makefile.common.in +++ b/Makefile.common.in @@ -1,6 +1,6 @@ # Set the name of the project here PROJECT_NAME := smack -PROJ_VERSION := 1.4.1 +PROJ_VERSION := 1.5.0 # Set this variable to the top of the LLVM source tree. LLVM_SRC_ROOT = @LLVM_SRC@ @@ -27,3 +27,5 @@ include $(PROJ_OBJ_ROOT)/Makefile.llvm.config # Include all of the build rules used for making LLVM include $(PROJ_SRC_ROOT)/Makefile.llvm.rules +# SMACK-specific scripts +include $(PROJ_SRC_ROOT)/Makefile.smack.scripts diff --git a/Makefile.llvm.config.in b/Makefile.llvm.config.in index 68f496fd7..57bb07eb0 100644 --- a/Makefile.llvm.config.in +++ b/Makefile.llvm.config.in @@ -59,7 +59,7 @@ PROJ_SRC_DIR := $(call realpath, $(PROJ_SRC_ROOT)/$(patsubst $(PROJ_OBJ_ROOT)%,% prefix := $(PROJ_INSTALL_ROOT) PROJ_prefix := $(prefix) ifndef PROJ_VERSION -PROJ_VERSION := 1.4.1 +PROJ_VERSION := 1.5.0 endif PROJ_bindir := $(PROJ_prefix)/bin diff --git a/Makefile.llvm.rules b/Makefile.llvm.rules index 98407b641..d135922e2 100644 --- a/Makefile.llvm.rules +++ b/Makefile.llvm.rules @@ -42,7 +42,7 @@ VPATH=$(PROJ_SRC_DIR) # Reset the list of suffixes we know how to build. #-------------------------------------------------------------------- .SUFFIXES: -.SUFFIXES: .c .cpp .cc .h .hpp .o .a .bc .td .ps .dot .ll .m .mm +.SUFFIXES: .c .cpp .cc .h .hpp .o .a .td .ps .dot .m .mm .SUFFIXES: $(SHLIBEXT) $(SUFFIXES) #-------------------------------------------------------------------- @@ -57,6 +57,81 @@ VPATH=$(PROJ_SRC_DIR) $(UserTargets):: +#------------------------------------------------------------------------ +# LLVMBuild Integration +#------------------------------------------------------------------------ +# +# We use llvm-build to generate all the data required by the Makefile based +# build system in one swoop: +# +# - We generate a file (a Makefile fragment) in the object root which contains +# all the definitions that are required by Makefiles across the entire +# project. +# +# - We generate the library table used by llvm-config. +# +# - We generate the dependencies for the Makefile fragment, so that we will +# automatically reconfigure outselves. + +# The path to the llvm-build tool itself. +LLVMBuildTool := $(PROJ_SRC_ROOT)/utils/llvm-build/llvm-build + +# The files we are going to generate using llvm-build. +LLVMBuildMakeFrag := $(PROJ_OBJ_ROOT)/Makefile.llvmbuild +LLVMBuildCMakeFrag := $(PROJ_OBJ_ROOT)/LLVMBuild.cmake +LLVMBuildCMakeExportsFrag := $(PROJ_OBJ_ROOT)/cmake/modules/LLVMBuildExports.cmake +LLVMBuildMakeFrags := \ + $(LLVMBuildMakeFrag) \ + $(LLVMBuildCMakeFrag) \ + $(LLVMBuildCMakeExportsFrag) +LLVMConfigLibraryDependenciesInc := \ + $(PROJ_OBJ_ROOT)/tools/llvm-config/LibraryDependencies.inc + +# This is for temporary backwards compatibility. +ifndef TARGET_NATIVE_ARCH +TARGET_NATIVE_ARCH := $(ARCH) +endif + +# The rule to create the LLVMBuild Makefile fragment as well as the llvm-config +# library table. +# +# Note that this target gets its real dependencies generated for us by +# llvm-build. +# +# We include a dependency on this Makefile to ensure that changes to the +# generation command get picked up. +$(LLVMBuildMakeFrags): $(PROJ_SRC_ROOT)/Makefile.rules \ + $(PROJ_OBJ_ROOT)/Makefile.config + $(Echo) Constructing LLVMBuild project information. + $(Verb)$(PYTHON) $(LLVMBuildTool) \ + --native-target "$(TARGET_NATIVE_ARCH)" \ + --enable-targets "$(TARGETS_TO_BUILD)" \ + --enable-optional-components "$(OPTIONAL_COMPONENTS)" \ + --write-library-table $(LLVMConfigLibraryDependenciesInc) \ + --write-make-fragment $(LLVMBuildMakeFrag) \ + --write-cmake-fragment $(LLVMBuildCMakeFrag) \ + --write-cmake-exports-fragment $(LLVMBuildCMakeExportsFrag) + +# For completeness, let Make know how the extra files are generated. +$(LLVMConfigLibraryDependenciesInc): $(LLVMBuildMakeFrags) + +# Include the generated Makefile fragment. +# +# We currently only include the dependencies for the fragment itself if we are +# at the top-level. Otherwise, recursive invocations would ends up doing +# substantially more redundant stat'ing. +# +# This means that we won't properly regenerate things for developers used to +# building from a subdirectory, but that is always somewhat unreliable. +ifeq ($(LEVEL),.) +LLVMBUILD_INCLUDE_DEPENDENCIES := 1 + +# Clean the generated makefile fragment at the top-level. +clean-local:: + -$(Verb) $(RM) -f $(LLVMBuildMakeFrags) +endif +-include $(LLVMBuildMakeFrag) + ################################################################################ # PRECONDITIONS: that which must be built/checked first ################################################################################ @@ -207,18 +282,10 @@ CPP.Defines := ifeq ($(ENABLE_OPTIMIZED),1) BuildMode := Release # Don't use -fomit-frame-pointer on Darwin or FreeBSD. - ifneq ($(HOST_OS),FreeBSD) - ifneq ($(HOST_OS),Darwin) + ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin Darwin DragonFly FreeBSD GNU/kFreeBSD)) OmitFramePointer := -fomit-frame-pointer endif - endif - # Darwin requires -fstrict-aliasing to be explicitly enabled. - # Avoid -fstrict-aliasing on Darwin for now, there are unresolved issues - # with -fstrict-aliasing and ipa-type-escape radr://6756684 - #ifeq ($(HOST_OS),Darwin) - # EXTRA_OPTIONS += -fstrict-aliasing -Wstrict-aliasing - #endif CXX.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) C.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) LD.Flags += $(OPTIMIZE_OPTION) @@ -226,7 +293,6 @@ ifeq ($(ENABLE_OPTIMIZED),1) BuildMode := $(BuildMode)+Debug CXX.Flags += -g C.Flags += -g - LD.Flags += -g KEEP_SYMBOLS := 1 endif else @@ -234,13 +300,16 @@ else BuildMode := Unoptimized CXX.Flags += C.Flags += - LD.Flags += KEEP_SYMBOLS := 1 else BuildMode := Debug + ifeq ($(ENABLE_SPLIT_DWARF), 1) + CXX.Flags += -gsplit-dwarf + C.Flags += -gsplit-dwarf + else CXX.Flags += -g C.Flags += -g - LD.Flags += -g + endif KEEP_SYMBOLS := 1 endif endif @@ -250,17 +319,34 @@ ifeq ($(ENABLE_LIBCPP),1) LD.Flags += -stdlib=libc++ endif +ifeq ($(ENABLE_CXX1Y),1) + CXX.Flags += -std=c++1y +else + ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + # MinGW and Cygwin are a bit stricter and lack things like + # 'strdup', 'stricmp', etc in c++11 mode. + CXX.Flags += -std=gnu++11 + else + CXX.Flags += -std=c++11 + endif +endif + +ifeq ($(ENABLE_WERROR),1) + CXX.Flags += -Werror + C.Flags += -Werror +endif + ifeq ($(ENABLE_PROFILING),1) BuildMode := $(BuildMode)+Profile CXX.Flags := $(filter-out -fomit-frame-pointer,$(CXX.Flags)) -pg -g C.Flags := $(filter-out -fomit-frame-pointer,$(C.Flags)) -pg -g - LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) -pg -g + LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) -pg KEEP_SYMBOLS := 1 endif -#ifeq ($(ENABLE_VISIBILITY_INLINES_HIDDEN),1) -# CXX.Flags += -fvisibility-inlines-hidden -#endif +ifeq ($(ENABLE_VISIBILITY_INLINES_HIDDEN),1) + CXX.Flags += -fvisibility-inlines-hidden +endif ifdef ENABLE_EXPENSIVE_CHECKS # GNU libstdc++ uses RTTI if you define _GLIBCXX_DEBUG, which we did above. @@ -291,6 +377,7 @@ ifeq ($(ENABLE_COVERAGE),1) BuildMode := $(BuildMode)+Coverage CXX.Flags += -ftest-coverage -fprofile-arcs C.Flags += -ftest-coverage -fprofile-arcs + LD.Flags += -ftest-coverage -fprofile-arcs endif # If DISABLE_ASSERTIONS=1 is specified (make command line or configured), @@ -427,31 +514,14 @@ ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) endif #-------------------------------------------------------------------- -# LLVM Capable Compiler +# Full Paths To Compiled Tools and Utilities #-------------------------------------------------------------------- - -ifneq ($(findstring llvm-gcc,$(LLVMCC_OPTION)),) - LLVMCC := $(LLVMGCC) - LLVMCXX := $(LLVMGXX) -else - ifneq ($(findstring clang,$(LLVMCC_OPTION)),) - ifneq ($(CLANGPATH),) - LLVMCC := $(CLANGPATH) - LLVMCXX := $(CLANGXXPATH) - else - ifeq ($(ENABLE_BUILT_CLANG),1) - LLVMCC := $(LLVMToolDir)/clang - LLVMCXX := $(LLVMToolDir)/clang++ - endif - endif - endif +EchoCmd := $(ECHO) llvm[$(MAKELEVEL)]: +ifdef BUILD_DIRS_ONLY +EchoCmd := $(EchoCmd) "(build tools)": endif -#-------------------------------------------------------------------- -# Full Paths To Compiled Tools and Utilities -#-------------------------------------------------------------------- -EchoCmd = $(ECHO) llvm[$(MAKELEVEL)]: -Echo = @$(EchoCmd) +Echo := @$(EchoCmd) ifndef LLVMAS LLVMAS := $(LLVMToolDir)/llvm-as$(EXEEXT) endif @@ -462,7 +532,11 @@ ifndef LLVM_TBLGEN LLVM_TBLGEN := $(LLVMToolDir)/llvm-tblgen$(EXEEXT) endif endif -LLVM_CONFIG := $(LLVMToolDir)/llvm-config +ifeq ($(LLVM_CROSS_COMPILING),1) + LLVM_CONFIG := $(BuildLLVMToolDir)/llvm-config$(BUILD_EXEEXT) +else + LLVM_CONFIG := $(LLVMToolDir)/llvm-config$(EXEEXT) +endif ifndef LLVMDIS LLVMDIS := $(LLVMToolDir)/llvm-dis$(EXEEXT) endif @@ -478,30 +552,45 @@ endif ifndef LBUGPOINT LBUGPOINT := $(LLVMToolDir)/bugpoint$(EXEEXT) endif +ifndef LLVMLINK +LLVMLINK := $(LLVMToolDir)/llvm-link$(EXEEXT) +endif #-------------------------------------------------------------------- # Adjust to user's request #-------------------------------------------------------------------- ifeq ($(HOST_OS),Darwin) + ifdef MACOSX_DEPLOYMENT_TARGET + DARWIN_VERSION := $(MACOSX_DEPLOYMENT_TARGET) + else DARWIN_VERSION := `sw_vers -productVersion` + endif # Strip a number like 10.4.7 to 10.4 - DARWIN_VERSION := $(shell echo $(DARWIN_VERSION)| sed -E 's/(10.[0-9]).*/\1/') + DARWIN_VERSION := $(shell echo $(DARWIN_VERSION)| sed -E 's/(10.[0-9]+).*/\1/') # Get "4" out of 10.4 for later pieces in the makefile. - DARWIN_MAJVERS := $(shell echo $(DARWIN_VERSION)| sed -E 's/10.([0-9]).*/\1/') + DARWIN_MAJVERS := $(shell echo $(DARWIN_VERSION)| sed -E 's/10.([0-9]+).*/\1/') LoadableModuleOptions := -Wl,-flat_namespace -Wl,-undefined,suppress SharedLinkOptions := -dynamiclib - ifneq ($(ARCH),ARM) - SharedLinkOptions += -mmacosx-version-min=$(DARWIN_VERSION) + ifdef DEPLOYMENT_TARGET + SharedLinkOptions += $(DEPLOYMENT_TARGET) + else + ifneq ($(ARCH),ARM) + SharedLinkOptions += -mmacosx-version-min=$(DARWIN_VERSION) + endif endif else SharedLinkOptions=-shared endif ifeq ($(TARGET_OS),Darwin) - ifneq ($(ARCH),ARM) - TargetCommonOpts += -mmacosx-version-min=$(DARWIN_VERSION) + ifdef DEPLOYMENT_TARGET + TargetCommonOpts += $(DEPLOYMENT_TARGET) + else + ifneq ($(ARCH),ARM) + TargetCommonOpts += -mmacosx-version-min=$(DARWIN_VERSION) + endif endif endif @@ -509,6 +598,8 @@ ifdef SHARED_LIBRARY ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) ifneq ($(HOST_OS),Darwin) LD.Flags += $(RPATH) -Wl,'$$ORIGIN' +else + LD.Flags += -Wl,-install_name -Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)" endif endif endif @@ -536,29 +627,43 @@ ifndef KEEP_SYMBOLS Install.StripFlag += -s endif -ifdef TOOL_NO_EXPORTS - DynamicFlags := -else - DynamicFlag := $(RDYNAMIC) +# By default, strip dead symbols at link time +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +ifneq ($(HOST_OS),Darwin) +ifneq ($(HOST_ARCH),Mips) + CXX.Flags += -ffunction-sections -fdata-sections +endif +endif +endif +ifndef NO_DEAD_STRIP + ifeq ($(HOST_OS),Darwin) + LD.Flags += -Wl,-dead_strip + else + ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + LD.Flags += -Wl,--gc-sections + endif + endif endif # Adjust linker flags for building an executable ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) -ifneq ($(HOST_OS), Darwin) -ifdef TOOLNAME - LD.Flags += $(RPATH) -Wl,'$$ORIGIN/../lib' - ifdef EXAMPLE_TOOL - LD.Flags += $(RPATH) -Wl,$(ExmplDir) $(DynamicFlag) + ifndef TOOL_NO_EXPORTS + LD.Flags += $(RDYNAMIC) + endif + ifneq ($(HOST_OS), Darwin) + ifdef TOOLNAME + LD.Flags += $(RPATH) -Wl,'$$ORIGIN/../lib' + endif else - LD.Flags += $(RPATH) -Wl,$(ToolDir) $(DynamicFlag) + ifneq ($(DARWIN_MAJVERS),4) + LD.Flags += $(RPATH) -Wl,@executable_path/../lib + endif + ifeq ($(RC_XBS),YES) + TempFile := $(shell mkdir -p ${OBJROOT}/dSYMs ; mktemp ${OBJROOT}/dSYMs/llvm-lto.XXXXXX) + LD.Flags += -Wl,-object_path_lto -Wl,$(TempFile) + endif endif endif -else -ifneq ($(DARWIN_MAJVERS),4) - LD.Flags += $(RPATH) -Wl,@executable_path/../lib -endif -endif -endif #---------------------------------------------------------- @@ -573,7 +678,9 @@ ifndef NO_PEDANTIC CompileCommonOpts += -pedantic -Wno-long-long endif CompileCommonOpts += -Wall -W -Wno-unused-parameter -Wwrite-strings \ - $(EXTRA_OPTIONS) $(COVERED_SWITCH_DEFAULT) + $(EXTRA_OPTIONS) $(COVERED_SWITCH_DEFAULT) \ + $(NO_UNINITIALIZED) $(NO_MAYBE_UNINITIALIZED) \ + $(NO_MISSING_FIELD_INITIALIZERS) # Enable cast-qual for C++; the workaround is to use const_cast. CXX.Flags += -Wcast-qual @@ -581,13 +688,13 @@ ifeq ($(HOST_OS),HP-UX) CompileCommonOpts := -D_REENTRANT -D_HPUX_SOURCE endif -# If we are building a universal binary on Mac OS/X, pass extra options. This +# If we are building a universal binary on Mac OS X, pass extra options. This # is useful to people that want to link the LLVM libraries into their universal # apps. # # The following can be optionally specified: # UNIVERSAL_SDK_PATH variable can be specified as a path to the SDK to use. -# For Mac OS/X 10.4 Intel machines, the traditional one is: +# For Mac OS X 10.4 Intel machines, the traditional one is: # UNIVERSAL_SDK_PATH=/Developer/SDKs/MacOSX10.4u.sdk/ # UNIVERSAL_ARCH can be optionally specified to be a list of architectures # to build for, e.g. UNIVERSAL_ARCH="i386 ppc ppc64". This defaults to @@ -597,9 +704,9 @@ ifdef UNIVERSAL UNIVERSAL_ARCH := i386 ppc endif UNIVERSAL_ARCH_OPTIONS := $(UNIVERSAL_ARCH:%=-arch %) - CompileCommonOpts += $(UNIVERSAL_ARCH_OPTIONS) + TargetCommonOpts += $(UNIVERSAL_ARCH_OPTIONS) ifdef UNIVERSAL_SDK_PATH - CompileCommonOpts += -isysroot $(UNIVERSAL_SDK_PATH) + TargetCommonOpts += -isysroot $(UNIVERSAL_SDK_PATH) endif # Building universal cannot compute dependencies automatically. @@ -624,7 +731,13 @@ ifeq ($(HOST_OS),AuroraUX) CPP.BaseFlags += -include llvm/Support/Solaris.h endif # !HOST_OS - AuroraUX. -LD.Flags += -L$(LibDir) -L$(LLVMLibDir) +# On Windows, SharedLibDir != LibDir. The order is important. +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + LD.Flags += -L$(SharedLibDir) -L$(LibDir) -L$(LLVMToolDir) -L$(LLVMLibDir) +else + LD.Flags += -L$(LibDir) -L$(LLVMLibDir) +endif + CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS # All -I flags should go here, so that they don't confuse llvm-config. CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \ @@ -633,6 +746,10 @@ CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \ $(LLVM_OBJ_ROOT) $(LLVM_SRC_ROOT))) \ $(CPP.BaseFlags) +ifeq ($(INCLUDE_BUILD_DIR),1) + CPP.Flags += -I$(ObjDir) +endif + # SHOW_DIAGNOSTICS support. ifeq ($(SHOW_DIAGNOSTICS),1) Compile.Wrapper := env CC_LOG_DIAGNOSTICS=1 \ @@ -641,44 +758,22 @@ else Compile.Wrapper := endif -ifeq ($(BUILD_COMPONENT), 1) - Compile.C = $(Compile.Wrapper) \ - $(BUILD_CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ - $(TargetCommonOpts) $(CompileCommonOpts) -c - Compile.CXX = $(Compile.Wrapper) \ - $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ - $(CPPFLAGS) \ - $(TargetCommonOpts) $(CompileCommonOpts) -c - Preprocess.CXX= $(Compile.Wrapper) \ - $(BUILD_CXX) $(CPP.Flags) $(CPPFLAGS) $(TargetCommonOpts) \ - $(CompileCommonOpts) $(CXX.Flags) -E - Link = $(Compile.Wrapper) \ - $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ - $(LD.Flags) $(LDFLAGS) \ - $(TargetCommonOpts) $(CompileCommonOpts) $(Strip) -else - Compile.C = $(Compile.Wrapper) \ +Compile.C = $(Compile.Wrapper) \ $(CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ - $(TargetCommonOpts) $(CompileCommonOpts) -c - Compile.CXX = $(Compile.Wrapper) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c +Compile.CXX = $(Compile.Wrapper) \ $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ - $(TargetCommonOpts) $(CompileCommonOpts) -c - Preprocess.CXX= $(Compile.Wrapper) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c +Preprocess.CXX= $(Compile.Wrapper) \ $(CXX) $(CPP.Flags) $(TargetCommonOpts) $(CPPFLAGS) \ - $(CompileCommonOpts) $(CXX.Flags) -E - Link = $(Compile.Wrapper) \ - $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(LD.Flags) \ - $(LDFLAGS) $(TargetCommonOpts) $(CompileCommonOpts) $(Strip) -endif + $(CompileCommonOpts) $(CXX.Flags) -E +Link = $(Compile.Wrapper) \ + $(CXX) $(CXXFLAGS) $(LD.Flags) $(LDFLAGS) \ + $(TargetCommonOpts) $(Strip) -BCCompile.C = $(LLVMCC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ - $(TargetCommonOpts) $(CompileCommonOpts) Preprocess.C = $(CC) $(CPP.Flags) $(C.Flags) $(CPPFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) -E -BCCompile.CXX = $(LLVMCXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ - $(TargetCommonOpts) $(CompileCommonOpts) - ProgInstall = $(INSTALL) $(Install.StripFlag) -m 0755 ScriptInstall = $(INSTALL) -m 0755 DataInstall = $(INSTALL) -m 0644 @@ -693,14 +788,13 @@ TableGen.Flags= -I $(call SYSPATH, $(PROJ_SRC_DIR)) \ LLVMTableGen = $(LLVM_TBLGEN) $(TableGen.Flags) Archive = $(AR) $(AR.Flags) -LArchive = $(LLVMToolDir)/llvm-ar rcsf ifdef RANLIB Ranlib = $(RANLIB) else Ranlib = ranlib endif -AliasTool = ln -s +AliasTool = ln -sf #---------------------------------------------------------- # Get the list of source files and compute object file @@ -719,9 +813,10 @@ Sources += $(filter %.cpp %.c %.cc,$(BUILT_SOURCES)) endif BaseNameSources := $(sort $(basename $(Sources))) +SourceDirs := $(sort $(dir $(Sources))) ObjectsO := $(BaseNameSources:%=$(ObjDir)/%.o) -ObjectsBC := $(BaseNameSources:%=$(ObjDir)/%.bc) +ObjectDirs := $(SourceDirs:%=$(ObjDir)/%) #---------------------------------------------------------- # For Mingw MSYS bash and Python/w32: @@ -736,7 +831,7 @@ ObjectsBC := $(BaseNameSources:%=$(ObjDir)/%.bc) #---------------------------------------------------------- ifeq (-mingw32,$(findstring -mingw32,$(BUILD_TRIPLE))) - ECHOPATH := $(Verb)python -u -c "import sys;print ' '.join(sys.argv[1:])" + ECHOPATH := $(Verb)$(PYTHON) -u -c "import sys;print ' '.join(sys.argv[1:])" else ECHOPATH := $(Verb)$(ECHO) endif @@ -758,9 +853,18 @@ $(DESTDIR)$(PROJ_bindir) $(DESTDIR)$(PROJ_libdir) $(DESTDIR)$(PROJ_includedir) $ $(Verb) $(MKDIR) $* > /dev/null $(Verb) $(DOTDIR_TIMESTAMP_COMMAND) > $@ -.PRECIOUS: $(ObjDir)/.dir $(LibDir)/.dir $(ToolDir)/.dir $(ExmplDir)/.dir +.PRECIOUS: $(LibDir)/.dir $(ToolDir)/.dir $(ExmplDir)/.dir .PRECIOUS: $(LLVMLibDir)/.dir $(LLVMToolDir)/.dir $(LLVMExmplDir)/.dir +#--------------------------------------------------------- +# Collect the object directories (as there may be more +# than one if the source code is spread across +# subdirectories). +#--------------------------------------------------------- + +OBJECT_DIRS := $(ObjDir)/.dir $(ObjectDirs:%=%/.dir) +.PRECIOUS: $(OBJECT_DIRS) + #--------------------------------------------------------- # Handle the DIRS options for sequential construction #--------------------------------------------------------- @@ -808,7 +912,7 @@ endif # Handle the OPTIONAL_PARALLEL_DIRS options for optional parallel construction #----------------------------------------------------------- ifdef OPTIONAL_PARALLEL_DIRS - PARALLEL_DIRS += $(foreach T,$(OPTIONAL_PARALLEL_DIRS),$(shell test -d $(PROJ_SRC_DIR)/$(T) && echo "$(T)")) + PARALLEL_DIRS += $(foreach T,$(OPTIONAL_PARALLEL_DIRS),$(shell test -d $(PROJ_SRC_DIR)/$(T) -o -f $(T)/Makefile && echo "$(T)")) endif #----------------------------------------------------------- @@ -830,13 +934,20 @@ unitcheck:: $(addsuffix /.makeunitcheck,$(PARALLEL_DIRS)) ParallelTargets := $(foreach T,$(RecursiveTargets),%/.make$(T)) $(ParallelTargets) : - $(Verb) if ([ ! -f $(@D)/Makefile ] || \ - command test $(@D)/Makefile -ot \ - $(PROJ_SRC_DIR)/$(@D)/Makefile ); then \ - $(MKDIR) $(@D); \ - $(CP) $(PROJ_SRC_DIR)/$(@D)/Makefile $(@D)/Makefile; \ + $(Verb) \ + SD=$(PROJ_SRC_DIR)/$(@D); \ + DD=$(@D); \ + if [ ! -f $$SD/Makefile ]; then \ + SD=$(@D); \ + DD=$(notdir $(@D)); \ + fi; \ + if ([ ! -f $$DD/Makefile ] || \ + command test $$DD/Makefile -ot \ + $$SD/Makefile ); then \ + $(MKDIR) $$DD; \ + $(CP) $$SD/Makefile $$DD/Makefile; \ fi; \ - $(MAKE) -C $(@D) $(subst $(@D)/.make,,$@) + $(MAKE) -C $$DD $(subst $(@D)/.make,,$@) endif #--------------------------------------------------------- @@ -953,8 +1064,9 @@ ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) LLVMLibsOptions += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc \ -L $(SharedLibDir) endif -LLVMLibsOptions += -lLLVM-$(LLVMVersion) -LLVMLibsPaths += $(LLVMSharedLibDir)/$(SharedPrefix)LLVM-$(LLVMVersion)$(SHLIBEXT) +LLVM_SO_NAME = LLVM-$(LLVM_VERSION_MAJOR).$(LLVM_VERSION_MINOR)$(LLVM_VERSION_SUFFIX) +LLVMLibsOptions += -l$(LLVM_SO_NAME) +LLVMLibsPaths += $(SharedLibDir)/$(SharedPrefix)$(LLVM_SO_NAME)$(SHLIBEXT) else ifndef NO_LLVM_CONFIG @@ -993,7 +1105,7 @@ ifeq ($(HAVE_LINK_VERSION_SCRIPT),1) NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE)).map $(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir $(Verb) echo "{" > $@ - $(Verb) grep -q "\<" $< && echo " global:" >> $@ || : + $(Verb) grep -q '[[:alnum:]_]' $< && echo " global:" >> $@ || : $(Verb) sed -e 's/$$/;/' -e 's/^/ /' < $< >> $@ ifneq ($(HOST_OS),OpenBSD) $(Verb) echo " local: *;" >> $@ @@ -1042,83 +1154,25 @@ endif # Library Build Rules: Four ways to build a library ############################################################################### -#--------------------------------------------------------- -# Bytecode Module Targets: -# If the user set MODULE_NAME then they want to build a -# bytecode module from the sources. We compile all the -# sources and link it together into a single bytecode -# module. -#--------------------------------------------------------- - -ifdef MODULE_NAME -ifeq ($(strip $(LLVMCC)),) -$(warning Modules require LLVM capable compiler but none is available ****) -else - -Module := $(LibDir)/$(MODULE_NAME).bc -LinkModule := $(LLVMLD) -r - - -ifdef EXPORTED_SYMBOL_FILE -LinkModule += -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) -endif - -$(Module): $(BUILT_SOURCES) $(ObjectsBC) $(LibDir)/.dir $(LLVMLD) - $(Echo) Building $(BuildMode) Bytecode Module $(notdir $@) - $(Verb) $(LinkModule) -o $@ $(ObjectsBC) - -all-local:: $(Module) - -clean-local:: -ifneq ($(strip $(Module)),) - -$(Verb) $(RM) -f $(Module) -endif - -ifdef BYTECODE_DESTINATION -ModuleDestDir := $(BYTECODE_DESTINATION) -else -ModuleDestDir := $(DESTDIR)$(PROJ_libdir) -endif - -ifdef NO_INSTALL -install-local:: - $(Echo) Install circumvented with NO_INSTALL -uninstall-local:: - $(Echo) Uninstall circumvented with NO_INSTALL -else -DestModule := $(ModuleDestDir)/$(MODULE_NAME).bc - -install-module:: $(DestModule) -install-local:: $(DestModule) - -$(DestModule): $(ModuleDestDir) $(Module) - $(Echo) Installing $(BuildMode) Bytecode Module $(DestModule) - $(Verb) $(DataInstall) $(Module) $(DestModule) - -uninstall-local:: - $(Echo) Uninstalling $(BuildMode) Bytecode Module $(DestModule) - -$(Verb) $(RM) -f $(DestModule) -endif - -endif -endif - # if we're building a library ... ifdef LIBRARYNAME # Make sure there isn't any extraneous whitespace on the LIBRARYNAME option LIBRARYNAME := $(strip $(LIBRARYNAME)) +LIBRARYALIASNAME := $(strip $(LIBRARYALIASNAME)) ifdef LOADABLE_MODULE BaseLibName.A := $(LIBRARYNAME).a BaseLibName.SO := $(LIBRARYNAME)$(SHLIBEXT) +BaseAliasName.SO := $(LIBRARYALIASNAME)$(SHLIBEXT) else BaseLibName.A := lib$(LIBRARYNAME).a BaseLibName.SO := $(SharedPrefix)$(LIBRARYNAME)$(SHLIBEXT) +BaseAliasName.SO := $(SharedPrefix)$(LIBRARYALIASNAME)$(SHLIBEXT) endif LibName.A := $(LibDir)/$(BaseLibName.A) LibName.SO := $(SharedLibDir)/$(BaseLibName.SO) +AliasName.SO := $(SharedLibDir)/$(BaseAliasName.SO) LibName.O := $(LibDir)/$(LIBRARYNAME).o -LibName.BCA:= $(LibDir)/lib$(LIBRARYNAME).bca #--------------------------------------------------------- # Shared Library Targets: @@ -1128,7 +1182,12 @@ LibName.BCA:= $(LibDir)/lib$(LIBRARYNAME).bca #--------------------------------------------------------- ifdef SHARED_LIBRARY -all-local:: $(LibName.SO) +all-local:: $(AliasName.SO) + +$(AliasName.SO): $(LibName.SO) +ifdef SHARED_ALIAS + $(Verb) $(AliasTool) $(BaseLibName.SO) $(AliasName.SO) +endif ifdef EXPORTED_SYMBOL_FILE $(LibName.SO): $(NativeExportsFile) @@ -1145,7 +1204,7 @@ $(LibName.SO): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) $(SharedLibDir)/.di $(Echo) Linking $(BuildMode) $(SharedLibKindMessage) \ $(notdir $@) $(Verb) $(Link) $(SharedLinkOptions) -o $@ $(ObjectsO) \ - $(ProjLibsOptions) -L$(LLVMSharedLibDir) $(LLVMLibsOptions) $(LIBS) + $(ProjLibsOptions) $(LLVMLibsOptions) $(LIBS) else $(LibName.SO): $(ObjectsO) $(SharedLibDir)/.dir $(Echo) Linking $(BuildMode) Shared Library $(notdir $@) @@ -1171,81 +1230,23 @@ else DestSharedLibDir := $(DESTDIR)$(PROJ_libdir) endif DestSharedLib := $(DestSharedLibDir)/$(BaseLibName.SO) +DestSharedAlias := $(DestSharedLibDir)/$(BaseAliasName.SO) install-local:: $(DestSharedLib) $(DestSharedLib): $(LibName.SO) $(DestSharedLibDir) $(Echo) Installing $(BuildMode) Shared Library $(DestSharedLib) $(Verb) $(INSTALL) $(LibName.SO) $(DestSharedLib) - -uninstall-local:: - $(Echo) Uninstalling $(BuildMode) Shared Library $(DestSharedLib) - -$(Verb) $(RM) -f $(DestSharedLibDir)/$(SharedPrefix)$(LIBRARYNAME).* -endif -endif - -#--------------------------------------------------------- -# Bytecode Library Targets: -# If the user asked for a bytecode library to be built -# with the BYTECODE_LIBRARY variable, then we provide -# targets for building them. -#--------------------------------------------------------- -ifdef BYTECODE_LIBRARY -ifeq ($(strip $(LLVMCC)),) -$(warning Bytecode libraries require LLVM capable compiler but none is available ****) -else - -all-local:: $(LibName.BCA) - -ifdef EXPORTED_SYMBOL_FILE -BCLinkLib = $(LLVMLD) -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) - -$(LibName.BCA): $(ObjectsBC) $(LibDir)/.dir $(LLVMLD) \ - $(LLVMToolDir)/llvm-ar - $(Echo) Building $(BuildMode) Bytecode Archive $(notdir $@) \ - "(internalize)" - $(Verb) $(BCLinkLib) -o $(ObjDir)/$(LIBRARYNAME).internalize $(ObjectsBC) - $(Verb) $(RM) -f $@ - $(Verb) $(LArchive) $@ $(ObjDir)/$(LIBRARYNAME).internalize.bc -else -$(LibName.BCA): $(ObjectsBC) $(LibDir)/.dir \ - $(LLVMToolDir)/llvm-ar - $(Echo) Building $(BuildMode) Bytecode Archive $(notdir $@) - $(Verb) $(RM) -f $@ - $(Verb) $(LArchive) $@ $(ObjectsBC) - -endif - -clean-local:: -ifneq ($(strip $(LibName.BCA)),) - -$(Verb) $(RM) -f $(LibName.BCA) +ifdef SHARED_ALIAS + $(Echo) Creating alias from $(DestSharedLib) to $(DestSharedAlias) + $(Verb) $(AliasTool) $(BaseLibName.SO) $(DestSharedAlias) endif -ifdef BYTECODE_DESTINATION -BytecodeDestDir := $(BYTECODE_DESTINATION) -else -BytecodeDestDir := $(DESTDIR)$(PROJ_libdir) -endif - -DestBytecodeLib = $(BytecodeDestDir)/lib$(LIBRARYNAME).bca - -install-bytecode-local:: $(DestBytecodeLib) - -ifdef NO_INSTALL -install-local:: - $(Echo) Install circumvented with NO_INSTALL -uninstall-local:: - $(Echo) Uninstall circumvented with NO_INSTALL -else -install-local:: $(DestBytecodeLib) - -$(DestBytecodeLib): $(LibName.BCA) $(BytecodeDestDir) - $(Echo) Installing $(BuildMode) Bytecode Archive $(DestBytecodeLib) - $(Verb) $(DataInstall) $(LibName.BCA) $(DestBytecodeLib) - uninstall-local:: - $(Echo) Uninstalling $(BuildMode) Bytecode Archive $(DestBytecodeLib) - -$(Verb) $(RM) -f $(DestBytecodeLib) + $(Echo) Uninstalling $(BuildMode) Shared Library $(DestSharedLib) + -$(Verb) $(RM) -f $(DestSharedLib) +ifdef SHARED_ALIAS + -$(Verb) $(RM) -f $(DestSharedAlias) endif endif endif @@ -1355,9 +1356,9 @@ LD.Flags += -Wl,-exported_symbol,_main endif endif -ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux NetBSD FreeBSD)) +ifeq ($(HOST_OS), $(filter $(HOST_OS), DragonFly Linux NetBSD FreeBSD GNU/kFreeBSD GNU)) ifneq ($(ARCH), Mips) - LD.Flags += -Wl,--version-script=$(PROJ_SRC_ROOT)/autoconf/ExportMap.map + LD.Flags += -Wl,--version-script=$(LLVM_SRC_ROOT)/autoconf/ExportMap.map endif endif endif @@ -1415,18 +1416,31 @@ else $(ToolBuildPath): $(ToolDir)/.dir endif +ifdef CODESIGN_TOOLS +TOOL_CODESIGN_IDENTITY ?= - + $(ToolBuildPath): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) $(Echo) Linking $(BuildMode) executable $(TOOLNAME) $(StripWarnMsg) $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \ $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) $(Echo) ======= Finished Linking $(BuildMode) Executable $(TOOLNAME) \ $(StripWarnMsg) + $(Echo) ======= Code-Signing $(BuildMode) Executable $(TOOLNAME) + $(Verb) codesign -s $(TOOL_CODESIGN_IDENTITY) $@ +else +$(ToolBuildPath): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) + $(Echo) Linking $(BuildMode) executable $(TOOLNAME) $(StripWarnMsg) + $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \ + $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) + $(Echo) ======= Finished Linking $(BuildMode) Executable $(TOOLNAME) \ + $(StripWarnMsg) +endif ifneq ($(strip $(ToolAliasBuildPath)),) $(ToolAliasBuildPath): $(ToolBuildPath) $(Echo) Creating $(BuildMode) Alias $(TOOLALIAS) $(StripWarnMsg) $(Verb) $(RM) -f $(ToolAliasBuildPath) - $(Verb) $(AliasTool) $(TOOLEXENAME) $(ToolAliasBuildPath) + $(Verb) $(AliasTool) $(notdir $(ToolBuildPath)) $(ToolAliasBuildPath) $(Echo) ======= Finished Creating $(BuildMode) Alias $(TOOLALIAS) \ $(StripWarnMsg) endif @@ -1437,12 +1451,19 @@ install-local:: uninstall-local:: $(Echo) Uninstall circumvented with NO_INSTALL else -DestTool = $(DESTDIR)$(PROJ_bindir)/$(program_prefix)$(TOOLEXENAME) + +ifdef INTERNAL_TOOL +ToolBinDir = $(DESTDIR)$(PROJ_internal_prefix)/bin +else +ToolBinDir = $(DESTDIR)$(PROJ_bindir) +endif +DestTool = $(ToolBinDir)/$(program_prefix)$(TOOLEXENAME) install-local:: $(DestTool) -$(DestTool): $(ToolBuildPath) $(DESTDIR)$(PROJ_bindir) +$(DestTool): $(ToolBuildPath) $(Echo) Installing $(BuildMode) $(DestTool) + $(Verb) $(MKDIR) $(ToolBinDir) $(Verb) $(ProgInstall) $(ToolBuildPath) $(DestTool) uninstall-local:: @@ -1451,14 +1472,14 @@ uninstall-local:: # TOOLALIAS install. ifdef TOOLALIAS -DestToolAlias = $(DESTDIR)$(PROJ_bindir)/$(program_prefix)$(TOOLALIAS)$(EXEEXT) +DestToolAlias = $(ToolBinDir)/$(program_prefix)$(TOOLALIAS)$(EXEEXT) install-local:: $(DestToolAlias) $(DestToolAlias): $(DestTool) $(Echo) Installing $(BuildMode) $(DestToolAlias) $(Verb) $(RM) -f $(DestToolAlias) - $(Verb) $(AliasTool) $(TOOLEXENAME) $(DestToolAlias) + $(Verb) $(AliasTool) $(notdir $(DestTool)) $(DestToolAlias) uninstall-local:: $(Echo) Uninstalling $(BuildMode) $(DestToolAlias) @@ -1477,6 +1498,8 @@ ifeq ($(HOST_OS),HP-UX) DISABLE_AUTO_DEPENDENCIES=1 endif +COMPILE_DEPS = $(OBJECT_DIRS) $(BUILT_SOURCES) $(PROJ_MAKEFILE) + # Provide rule sets for when dependency generation is enabled ifndef DISABLE_AUTO_DEPENDENCIES @@ -1492,182 +1515,98 @@ DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.d.tmp" \ DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.d.tmp" "$(ObjDir)/$*.d"; \ else $(RM) "$(ObjDir)/$*.d.tmp"; exit 1; fi -$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) +$(ObjDir)/%.o: %.cpp $(COMPILE_DEPS) $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ $(DEPEND_MOVEFILE) -$(ObjDir)/%.o: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) +$(ObjDir)/%.o: %.mm $(COMPILE_DEPS) $(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG) $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ $(DEPEND_MOVEFILE) -$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) +$(ObjDir)/%.o: %.cc $(COMPILE_DEPS) $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ $(DEPEND_MOVEFILE) -$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) +$(ObjDir)/%.o: %.c $(COMPILE_DEPS) $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ $(DEPEND_MOVEFILE) -$(ObjDir)/%.o: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) +$(ObjDir)/%.o: %.m $(COMPILE_DEPS) $(Echo) "Compiling $*.m for $(BuildMode) build" $(PIC_FLAG) $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ $(DEPEND_MOVEFILE) -#--------------------------------------------------------- -# Create .bc files in the ObjDir directory from .cpp .cc and .c files... -#--------------------------------------------------------- - -BC_DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.bc.d.tmp" \ - -MT "$(ObjDir)/$*.ll" -MT "$(ObjDir)/$*.bc.d" - -# If the build succeeded, move the dependency file over, otherwise -# remove it. -BC_DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.bc.d.tmp" "$(ObjDir)/$*.bc.d"; \ - else $(RM) "$(ObjDir)/$*.bc.d.tmp"; exit 1; fi - -$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) - $(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)" - $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ - $< -o $(ObjDir)/$*.ll -S $(LLVMCC_EMITIR_FLAG) ; \ - $(BC_DEPEND_MOVEFILE) - -$(ObjDir)/%.ll: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) - $(Echo) "Compiling $*.mm for $(BuildMode) build (bytecode)" - $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ - $< -o $(ObjDir)/$*.ll -S $(LLVMCC_EMITIR_FLAG) ; \ - $(BC_DEPEND_MOVEFILE) - -$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) - $(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)" - $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ - $< -o $(ObjDir)/$*.ll -S $(LLVMCC_EMITIR_FLAG) ; \ - $(BC_DEPEND_MOVEFILE) - -$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) - $(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)" - $(Verb) if $(BCCompile.C) $(BC_DEPEND_OPTIONS) \ - $< -o $(ObjDir)/$*.ll -S $(LLVMCC_EMITIR_FLAG) ; \ - $(BC_DEPEND_MOVEFILE) - -$(ObjDir)/%.ll: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) - $(Echo) "Compiling $*.m for $(BuildMode) build (bytecode)" - $(Verb) if $(BCCompile.C) $(BC_DEPEND_OPTIONS) \ - $< -o $(ObjDir)/$*.ll -S $(LLVMCC_EMITIR_FLAG) ; \ - $(BC_DEPEND_MOVEFILE) - # Provide alternate rule sets if dependencies are disabled else -$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.cpp $(COMPILE_DEPS) $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -$(ObjDir)/%.o: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.mm $(COMPILE_DEPS) $(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.cc $(COMPILE_DEPS) $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.c $(COMPILE_DEPS) $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) $(Compile.C) $< -o $@ -$(ObjDir)/%.o: %.m $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.m $(COMPILE_DEPS) $(Echo) "Compiling $*.m for $(BuildMode) build" $(PIC_FLAG) $(Compile.C) $< -o $@ - -$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) - $(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)" - $(BCCompile.CXX) $< -o $@ -S $(LLVMCC_EMITIR_FLAG) - -$(ObjDir)/%.ll: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) - $(Echo) "Compiling $*.mm for $(BuildMode) build (bytecode)" - $(BCCompile.CXX) $< -o $@ -S $(LLVMCC_EMITIR_FLAG) - -$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) - $(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)" - $(BCCompile.CXX) $< -o $@ -S $(LLVMCC_EMITIR_FLAG) - -$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) - $(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)" - $(BCCompile.C) $< -o $@ -S $(LLVMCC_EMITIR_FLAG) - -$(ObjDir)/%.ll: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) - $(Echo) "Compiling $*.m for $(BuildMode) build (bytecode)" - $(BCCompile.C) $< -o $@ -S $(LLVMCC_EMITIR_FLAG) - endif ## Rules for building preprocessed (.i/.ii) outputs. -$(BuildMode)/%.ii: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.ii: %.cpp $(COMPILE_DEPS) $(Echo) "Compiling $*.cpp for $(BuildMode) build to .ii file" $(Verb) $(Preprocess.CXX) $< -o $@ -$(BuildMode)/%.ii: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.ii: %.mm $(COMPILE_DEPS) $(Echo) "Compiling $*.mm for $(BuildMode) build to .ii file" $(Verb) $(Preprocess.CXX) $< -o $@ -$(BuildMode)/%.ii: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.ii: %.cc $(COMPILE_DEPS) $(Echo) "Compiling $*.cc for $(BuildMode) build to .ii file" $(Verb) $(Preprocess.CXX) $< -o $@ -$(BuildMode)/%.i: %.c $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.i: %.c $(COMPILE_DEPS) $(Echo) "Compiling $*.c for $(BuildMode) build to .i file" $(Verb) $(Preprocess.C) $< -o $@ -$(BuildMode)/%.i: %.m $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.i: %.m $(COMPILE_DEPS) $(Echo) "Compiling $*.m for $(BuildMode) build to .i file" $(Verb) $(Preprocess.C) $< -o $@ -$(ObjDir)/%.s: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.cpp $(COMPILE_DEPS) $(Echo) "Compiling $*.cpp to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -S -$(ObjDir)/%.s: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.mm $(COMPILE_DEPS) $(Echo) "Compiling $*.mm to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -S -$(ObjDir)/%.s: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.cc $(COMPILE_DEPS) $(Echo) "Compiling $*.cc to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -S -$(ObjDir)/%.s: %.c $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.c $(COMPILE_DEPS) $(Echo) "Compiling $*.c to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.C) $< -o $@ -S -$(ObjDir)/%.s: %.m $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.m $(COMPILE_DEPS) $(Echo) "Compiling $*.m to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.C) $< -o $@ -S - -# make the C and C++ compilers strip debug info out of bytecode libraries. -ifdef DEBUG_RUNTIME -$(ObjectsBC): $(ObjDir)/%.bc: $(ObjDir)/%.ll $(LOPT) - $(Echo) "Compiling $*.ll to $*.bc for $(BuildMode) build (bytecode)" - $(Verb) $(LOPT) $< -std-compile-opts -o $@ -else -$(ObjectsBC): $(ObjDir)/%.bc: $(ObjDir)/%.ll $(LOPT) - $(Echo) "Compiling $*.ll to $*.bc for $(BuildMode) build (bytecode)" - $(Verb) $(LOPT) $< -std-compile-opts -strip-debug -o $@ -endif - - -#--------------------------------------------------------- -# Provide rule to build .bc files from .ll sources, -# regardless of dependencies -#--------------------------------------------------------- -$(ObjDir)/%.bc: %.ll $(ObjDir)/.dir $(LLVMAS) - $(Echo) "Compiling $*.ll for $(BuildMode) build" - $(Verb) $(LLVMAS) $< -f -o $@ - ############################################################################### # TABLEGEN: Provide rules for running tblgen to produce *.inc files ############################################################################### @@ -1701,7 +1640,7 @@ TDFiles := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td) \ $(LLVM_SRC_ROOT)/include/llvm/Target/TargetSchedule.td \ $(LLVM_SRC_ROOT)/include/llvm/Target/TargetSelectionDAG.td \ $(LLVM_SRC_ROOT)/include/llvm/CodeGen/ValueTypes.td) \ - $(wildcard $(LLVM_SRC_ROOT)/include/llvm/Intrinsics*.td) + $(wildcard $(LLVM_SRC_ROOT)/include/llvm/IR/Intrinsics*.td) # All .inc.tmp files depend on the .td files. $(INCTMPFiles) : $(TDFiles) @@ -1756,11 +1695,6 @@ $(ObjDir)/%GenDisassemblerTables.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN) $(Echo) "Building $(.td.expanded. This is useful for debugging. +$(TARGET:%=%.td.expanded): \ +%.td.expanded : %.td $(LLVM_TBLGEN) $(TDFiles) + $(Echo) "Building a fully expanded version of $( test.c +echo int main\(void\) \{ >> test.c +echo int a\; >> test.c +echo a = 2\; >> test.c +echo assert\(a == 3\)\; >> test.c +echo return 0\; >> test.c +echo \} >> test.c + +# Run SMACK with CDE +../cde_2011-08-15_64bit smackverify.py test.c --verifier boogie +../cde_2011-08-15_64bit smackverify.py test.c --verifier corral +../cde_2011-08-15_64bit smackverify.py test.c --verifier duality + +# Clean up temporary files +rm corral* a.bpl test.* cde.options + +# Copy license file +cp ../../LICENSE . + +# Create wrapper script +echo \#\!/bin/sh > smackverify.sh +echo HERE=\"\$\(dirname \"\$\(readlink -f \"\$\{0\}\"\)\"\)\" >> smackverify.sh +echo \$HERE/cde-package/cde-exec \'smackverify.py\' \"\$\@\" >> smackverify.sh +chmod u+x smackverify.sh + +# Package it up +cd .. +tar -cvzf $PACKAGE.tgz $PACKAGE + diff --git a/bin/smackgen.py b/bin/smackgen.py index 37c89c6db..d5c3bf7cf 100755 --- a/bin/smackgen.py +++ b/bin/smackgen.py @@ -1,4 +1,7 @@ -#! /usr/bin/env python +#!/usr/bin/env python +# +# This file is distributed under the MIT License. See LICENSE for details. +# from os import path import sys @@ -7,21 +10,21 @@ import platform from llvm2bpl import * -VERSION = '1.4.1' +VERSION = '1.5.0' def smackParser(): parser = argparse.ArgumentParser(add_help=False, parents=[llvm2bplParser()]) parser.add_argument('--clang', dest='clang', default='', help='pass arguments to clang (e.g., --clang="-w -g")') - parser.add_argument('--verifier', dest='verifier', choices=['boogie-plain', 'boogie-inline', 'corral'], default='boogie-inline', + parser.add_argument('--verifier', dest='verifier', choices=['boogie', 'corral', 'duality'], default='corral', help='set the underlying verifier format') parser.add_argument('--entry-points', metavar='PROC', dest='entryPoints', default='main', nargs='+', help='specify entry procedures') - parser.add_argument('--unroll', metavar='N', dest='unroll', default='2', type=int, + parser.add_argument('--unroll', metavar='N', dest='unroll', type=int, help='unroll loops/recursion in Boogie/Corral N number of times') - parser.add_argument('--mem-mod', dest='memmod', choices=['no-reuse', 'no-reuse-impls', 'reuse'], default='no-reuse', - help='set the memory model (no-reuse=never reallocate the same address, reuse=reallocate freed addresses)') + parser.add_argument('--bc', dest='bcfile', metavar='', type=str, + help='output clang (bc) file') return parser @@ -45,33 +48,42 @@ def addEntryPoint(match, entryPoints): return procDef -def clang(scriptPathName, inputFile, memoryModel, clangArgs): +def clang(scriptPathName, inputFile, bcFileName, outputFileName, memoryModel, clangArgs): scriptFullPath = path.abspath(scriptPathName) smackRoot = path.dirname(scriptFullPath) smackHeaders = path.join(smackRoot, 'include', 'smack') - fileName = path.splitext(inputFile.name)[0] + fileName, fileExtension = path.splitext(path.basename(inputFile.name)) + + if bcFileName is None: + bcFileName = path.join(path.dirname(path.abspath(outputFileName)), + fileName) + '.bc' + + if fileExtension in ['.c']: + clangCommand = ['clang'] + elif fileExtension in ['.cc', '.cpp']: + clangCommand = ['clang++'] + else: + sys.exit('Unexpected source file extension `' + fileExtension + '\'') - clangCommand = ['clang'] clangCommand += ['-c', '-emit-llvm', '-O0', '-g', '-gcolumn-info', '-DMEMORY_MODEL_' + memoryModel.upper().replace('-','_'), - '-I' + smackHeaders] + '-I' + smackHeaders, + '-include' + 'smack.h'] clangCommand += clangArgs.split() - clangCommand += [inputFile.name, '-o', fileName + '.bc'] + clangCommand += [inputFile.name, '-o', bcFileName] #Redirect stderr to stdout, then grab stdout (communicate() calls wait()) #This should more or less maintain stdout/stderr interleaving order #However, this will be problematic if any callers want to differentiate # between clangs stdout and stderr. p = subprocess.Popen(clangCommand, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - clangStdout, clangStderr = p.communicate() - clangOutput = clangStdout + clangOutput = p.communicate()[0] - if p.returncode != 0: - print clangOutput - sys.exit("SMACK encountered a clang error. Exiting...") + if p.returncode: + print >> sys.stderr, clangOutput + sys.exit("SMACK encountered an error when invoking clang. Exiting...") - inputFileName = path.join(path.curdir, fileName + '.bc') - inputFile = open(inputFileName, 'r') + inputFile = open(bcFileName, 'r') return inputFile, clangOutput @@ -82,10 +94,11 @@ def smackGenerate(sysArgv): args = parser.parse_args(sysArgv[1:]) inputFile = args.infile scriptPathName = path.dirname(sysArgv[0]) + clangOutput = None fileExtension = path.splitext(inputFile.name)[1] options = [] - if fileExtension == '.c': + if fileExtension in ['.c','.cc','.cpp']: # if input file is .c, then search for options in comments and compile it with clang lines = inputFile.readlines() for line in lines: @@ -93,18 +106,29 @@ def smackGenerate(sysArgv): if optionsMatch: options = optionsMatch.group(1).split() args = parser.parse_args(options + sysArgv[1:]) - inputFile, clangOutput = clang(scriptPathName, inputFile, args.memmod, args.clang) + inputFile, clangOutput = clang(scriptPathName, inputFile, args.bcfile, args.outfile, args.memmod, args.clang) + + elif fileExtension in ['.bc', '.ll']: + pass # do nothing + else: + sys.exit('Unexpected source file extension `' + fileExtension + '\'') - bpl = llvm2bpl(inputFile, args.debug, "impls" in args.memmod) + bpl = llvm2bpl(inputFile, args.outfile, args.debug, "impls" in args.memmod) inputFile.close() p = re.compile('procedure\s+([^\s(]*)\s*\(') - if args.verifier == 'boogie-inline': + si = re.compile('procedure\s+(\$static_init|__SMACK_.*|assert_|assume_|__VERIFIER_.*)\s*\(') + + if args.verifier == 'boogie' and args.unroll is None: + bpl = si.sub(lambda match: addInline(match, args.entryPoints, 1), bpl) + + elif args.verifier == 'boogie': # put inline on procedures bpl = p.sub(lambda match: addInline(match, args.entryPoints, args.unroll), bpl) - elif args.verifier == 'corral': + elif args.verifier == 'corral' or args.verifier == 'duality': # annotate entry points bpl = p.sub(lambda match: addEntryPoint(match, args.entryPoints), bpl) + return bpl, options, clangOutput @@ -115,9 +139,11 @@ def smackGenerate(sysArgv): args = parser.parse_args() bpl, options, clangOutput = smackGenerate(sys.argv) - print clangOutput + if clangOutput is not None: + print clangOutput # write final output - args.outfile.write(bpl) - args.outfile.close() + with open(args.outfile, 'w') as outputFile: + outputFile.write(bpl) + outputFile.close() diff --git a/bin/smackreach.py b/bin/smackreach.py old mode 100644 new mode 100755 index 1afa131ac..406d475b6 --- a/bin/smackreach.py +++ b/bin/smackreach.py @@ -1,4 +1,7 @@ -#! /usr/bin/env python +#!/usr/bin/env python +# +# This file is distributed under the MIT License. See LICENSE for details. +# import argparse import re @@ -8,7 +11,7 @@ from smackgen import * from smackverify import * -VERSION = '1.4.1' +VERSION = '1.5.0' def reachParser(): parser = argparse.ArgumentParser(add_help=False, parents=[verifyParser()]) @@ -161,7 +164,7 @@ def UpdateSourceInfo(corralOutput, sourceInfo, verifier): parser = argparse.ArgumentParser(description='Checks the input LLVM file for code reachability.', parents=[reachParser()]) parser.parse_args() # just check if arguments are looking good - #!!!!!!START COPY OF SECTION FROM smack-verify.py!!!!!!!!!!! + #!!!!!!START COPY OF SECTION FROM smackverify.py!!!!!!!!!!! # Probably should pull into subroutine or something # remove arguments not recognized by lower scripts # not sure of a better way to do this @@ -182,6 +185,6 @@ def UpdateSourceInfo(corralOutput, sourceInfo, verifier): # write final output args.outfile.write(bpl) args.outfile.close() - #!!!!!!END COPY OF SECTION FROM smack-verify.py!!!!!!!!!!! + #!!!!!!END COPY OF SECTION FROM smackverify.py!!!!!!!!!!! GetCodeCoverage(args.verifier, args.outfile.name, args.timeLimit, args.unroll, args.debug, args.smackd, clangOutput) diff --git a/bin/smackverify.py b/bin/smackverify.py index 5d0433df8..dbdecda7a 100755 --- a/bin/smackverify.py +++ b/bin/smackverify.py @@ -1,4 +1,7 @@ -#! /usr/bin/env python +#!/usr/bin/env python +# +# This file is distributed under the MIT License. See LICENSE for details. +# from os import path import json @@ -9,12 +12,13 @@ import platform from smackgen import * -VERSION = '1.4.1' +VERSION = '1.5.0' def verifyParser(): # parse command line arguments parser = argparse.ArgumentParser(add_help=False, parents=[smackParser()]) - + parser.add_argument('--verifier-options', dest='verifierOptions', default='', + help='pass arguments to the backend verifier (e.g., --verifier-options="/trackAllVars /staticInlining")') parser.add_argument('--time-limit', metavar='N', dest='timeLimit', default='1200', type=int, help='Boogie time limit in seconds') parser.add_argument('--smackd', dest='smackd', action="store_true", default=False, @@ -117,14 +121,19 @@ def smackdOutput(corralOutput): json_string = json.dumps(json_data) print json_string -def verify(verifier, bplFileName, timeLimit, unroll, debug, smackd): - if verifier == 'boogie-plain' or verifier == 'boogie-inline': +def verify(verifier, bplFileName, timeLimit, unroll, debug, verifierOptions, smackd): + if verifier == 'boogie': # invoke Boogie - p = subprocess.Popen(['boogie', bplFileName, '/nologo', '/timeLimit:' + str(timeLimit), '/loopUnroll:' + str(unroll)], stdout=subprocess.PIPE) + boogieCommand = ['boogie', bplFileName, '/nologo', '/errorLimit:1', '/timeLimit:' + str(timeLimit)] + if unroll is not None: + boogieCommand += ['/loopUnroll:' + str(unroll)] + boogieCommand += verifierOptions.split() + p = subprocess.Popen(boogieCommand, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) boogieOutput = p.communicate()[0] + if p.returncode: - return boogieOutput - sys.exit("SMACK encountered an error invoking Boogie. Exiting...") + print >> sys.stderr, boogieOutput + sys.exit("SMACK encountered an error when invoking Boogie. Exiting...") if debug: return boogieOutput sourceTrace = generateSourceErrorTrace(boogieOutput, bplFileName) @@ -132,17 +141,37 @@ def verify(verifier, bplFileName, timeLimit, unroll, debug, smackd): return sourceTrace else: return boogieOutput - else: + elif verifier == 'corral': # invoke Corral - p = subprocess.Popen(['corral', bplFileName, '/recursionBound:' + str(unroll), '/tryCTrace'], stdout=subprocess.PIPE) + corralCommand = ['corral', bplFileName, '/tryCTrace'] + if unroll is not None: + corralCommand += ['/recursionBound:' + str(unroll)] + corralCommand += verifierOptions.split() + p = subprocess.Popen(corralCommand, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) corralOutput = p.communicate()[0] + if p.returncode: - return corralOutput - sys.exit("SMACK encountered an error invoking Corral. Exiting...") + print >> sys.stderr, corralOutput + sys.exit("SMACK encountered an error when invoking Corral. Exiting...") if smackd: smackdOutput(corralOutput) else: return corralOutput + else: + # invoke Duality + dualityCommand = ['corral', bplFileName, '/tryCTrace', '/useDuality'] + dualityCommand += ['/recursionBound:10000'] # hack for providing infinite recursion bound + dualityCommand += verifierOptions.split() + p = subprocess.Popen(dualityCommand, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + dualityOutput = p.communicate()[0] + + if p.returncode: + print >> sys.stderr, dualityOutput + sys.exit("SMACK encountered an error when invoking Duality. Exiting...") + if smackd: + smackdOutput(dualityOutput) + else: + return dualityOutput if __name__ == '__main__': parser = argparse.ArgumentParser(description='Checks the input LLVM file for assertion violations.', parents=[verifyParser()]) @@ -154,16 +183,20 @@ def verify(verifier, bplFileName, timeLimit, unroll, debug, smackd): for i in reversed(range(len(sysArgv))): if sysArgv[i] == '--smackd': del sysArgv[i] - elif sys.argv[i] == '--time-limit': + elif sysArgv[i] == '--time-limit': + del sysArgv[i] del sysArgv[i] + elif sysArgv[i].startswith('--verifier-options'): del sysArgv[i] bpl, options, clangOutput = smackGenerate(sysArgv) args = parser.parse_args(options + sys.argv[1:]) # write final output - args.outfile.write(bpl) - args.outfile.close() + with open(args.outfile, 'w') as outputFile: + outputFile.write(bpl) + outputFile.close() - print(verify(args.verifier, args.outfile.name, args.timeLimit, args.unroll, args.debug, args.smackd)) + print(verify(args.verifier, args.outfile, args.timeLimit, args.unroll, + args.debug, args.verifierOptions, args.smackd)) diff --git a/configure b/configure index fc30c9c93..d436cce1d 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for SMACK 1.4.1. +# Generated by GNU Autoconf 2.68 for SMACK 1.5.0. # # Report bugs to . # @@ -560,8 +560,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='SMACK' PACKAGE_TARNAME='smack' -PACKAGE_VERSION='1.4.1' -PACKAGE_STRING='SMACK 1.4.1' +PACKAGE_VERSION='1.5.0' +PACKAGE_STRING='SMACK 1.5.0' PACKAGE_BUGREPORT='smack-dev@googlegroups.com' PACKAGE_URL='http://github.com/smackers/smack' @@ -1391,7 +1391,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures SMACK 1.4.1 to adapt to many kinds of systems. +\`configure' configures SMACK 1.5.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1457,7 +1457,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of SMACK 1.4.1:";; + short | recursive ) echo "Configuration of SMACK 1.5.0:";; esac cat <<\_ACEOF @@ -1612,7 +1612,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -SMACK configure 1.4.1 +SMACK configure 1.5.0 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2161,7 +2161,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by SMACK $as_me 1.4.1, which was +It was created by SMACK $as_me 1.5.0, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -13692,7 +13692,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by SMACK $as_me 1.4.1, which was +This file was extended by SMACK $as_me 1.5.0, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13750,7 +13750,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -SMACK config.status 1.4.1 +SMACK config.status 1.5.0 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff --git a/examples/failing/atomic_cas.c b/examples/failing/atomic_cas.c index 52aceb4d0..3d07ca8d1 100644 --- a/examples/failing/atomic_cas.c +++ b/examples/failing/atomic_cas.c @@ -7,6 +7,6 @@ int main() { int y = 0; int *z = x; CAS(&z,x,&y); // if (z == x) z = &y; - __SMACK_assert(*z == y); + assert(*z == y); return 0; } diff --git a/examples/failing/extern_mem2.c b/examples/failing/extern_mem2.c index 75b8abe6b..9cc82b16f 100644 --- a/examples/failing/extern_mem2.c +++ b/examples/failing/extern_mem2.c @@ -15,5 +15,5 @@ int main() { *x = 1; *z = 2; - __SMACK_assert(x != z); + assert(x != z); } \ No newline at end of file diff --git a/examples/failing/globals_func_ptr.c b/examples/failing/globals_func_ptr.c index c76cd1d46..94e26c96e 100644 --- a/examples/failing/globals_func_ptr.c +++ b/examples/failing/globals_func_ptr.c @@ -42,7 +42,7 @@ int main() { fp = my_ops.iops->incr; x = fp(x); - __SMACK_assert(x == 1); + assert(x == 1); return 0; } diff --git a/examples/rise4fun/rise_simple.c b/examples/rise4fun/rise_simple.c index 8eb1bda62..cebf44d13 100644 --- a/examples/rise4fun/rise_simple.c +++ b/examples/rise4fun/rise_simple.c @@ -6,6 +6,6 @@ int main(void) { x = 10; y = 20; z = x + y; - __SMACK_assert(z == 30); + assert(z == 30); return 0; } diff --git a/examples/rise4fun/rise_simple_buggy.c b/examples/rise4fun/rise_simple_buggy.c index 892fa2f7b..b9d8c7ec8 100644 --- a/examples/rise4fun/rise_simple_buggy.c +++ b/examples/rise4fun/rise_simple_buggy.c @@ -6,6 +6,6 @@ int main(void) { x = 10; y = 20; z = x + y; - __SMACK_assert(z != 30); + assert(z != 30); return 0; } diff --git a/examples/simple/simple.c b/examples/simple/simple.c index 16bf72076..8fd140d34 100644 --- a/examples/simple/simple.c +++ b/examples/simple/simple.c @@ -10,7 +10,7 @@ int main(void) { a = 1; a = incr(a); - __SMACK_assert(a == 2); + assert(a == 2); return 0; } diff --git a/examples/svcomp/locks/regtest-corral.py b/examples/svcomp/locks/regtest-corral.py deleted file mode 100755 index 56854f01e..000000000 --- a/examples/svcomp/locks/regtest-corral.py +++ /dev/null @@ -1,63 +0,0 @@ -#! /usr/bin/env python - -import subprocess -import re -import time - -# list of regression tests with the expected outputs -tests = [ - ('test_locks_5_true', r'Program has no bugs'), - ('test_locks_6_true', r'Program has no bugs'), - ('test_locks_7_true', r'Program has no bugs'), - ('test_locks_8_true', r'Program has no bugs'), - ('test_locks_9_true', r'Program has no bugs'), - ('test_locks_10_true', r'Program has no bugs'), - ('test_locks_11_true', r'Program has no bugs'), - ('test_locks_12_true', r'Program has no bugs'), - ('test_locks_13_true', r'Program has no bugs'), - ('test_locks_14_true', r'Program has no bugs'), - ('test_locks_14_false', r'This assertion can fail'), - ('test_locks_15_true', r'Program has no bugs'), - ('test_locks_15_false', r'This assertion can fail') -] - -def red(text): - return '\033[0;31m' + text + '\033[0m' - -def green(text): - return '\033[0;32m' + text + '\033[0m' - -def runtests(): - passed = failed = 0 - for test in tests: - - for mem in ['no-reuse', 'no-reuse-impls', 'reuse']: - - print "{0:>20} {1:>16}:".format(test[0], "(" + mem + ")"), - - # invoke SMACK - t0 = time.time() - p = subprocess.Popen(['smackverify.py', test[0] + '.c', '--verifier=corral', - '--mem-mod=' + mem, '-o', test[0] +'.bpl'], - stdout=subprocess.PIPE) - - smackOutput = p.communicate()[0] - elapsed = time.time() - t0 - - # check SMACK output - if re.search(test[1], smackOutput): - print green('PASSED') + ' [%.2fs]' % round(elapsed, 2) - passed += 1 - else: - print red('FAILED') - failed += 1 - - return passed, failed - -if __name__ == '__main__': - - passed, failed = runtests() - - print '\nPASSED count: ', passed - print 'FAILED count: ', failed - diff --git a/examples/svcomp/locks/regtest.py b/examples/svcomp/locks/regtest.py index bc4068a41..ffe524ccd 100755 --- a/examples/svcomp/locks/regtest.py +++ b/examples/svcomp/locks/regtest.py @@ -2,62 +2,74 @@ import subprocess import re +import argparse import time +from collections import namedtuple + +RegTest = namedtuple('RegTest', 'name boogie corral duality unroll') # list of regression tests with the expected outputs tests = [ - ('test_locks_5_true', r'1 verified, 0 errors?'), - ('test_locks_6_true', r'1 verified, 0 errors?'), - ('test_locks_7_true', r'1 verified, 0 errors?'), - ('test_locks_8_true', r'1 verified, 0 errors?'), - ('test_locks_9_true', r'1 verified, 0 errors?'), - ('test_locks_10_true', r'1 verified, 0 errors?'), - ('test_locks_11_true', r'1 verified, 0 errors?'), - ('test_locks_12_true', r'1 verified, 0 errors?'), - ('test_locks_13_true', r'1 verified, 0 errors?'), - ('test_locks_14_true', r'1 verified, 0 errors?'), - ('test_locks_14_false', r'0 verified, 1 errors?'), - ('test_locks_15_true', r'1 verified, 0 errors?'), - ('test_locks_15_false', r'0 verified, 1 errors?') + RegTest('test_locks_5_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_6_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_7_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_8_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_9_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_10_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_11_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_12_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_13_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_14_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_14_false', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('test_locks_15_true', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('test_locks_15_false', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2) ] def red(text): return '\033[0;31m' + text + '\033[0m' - + def green(text): return '\033[0;32m' + text + '\033[0m' -def runtests(): +def runtests(verifier): passed = failed = 0 for test in tests: - + for mem in ['no-reuse', 'no-reuse-impls', 'reuse']: - - print "{0:>20} {1:>16}:".format(test[0], "(" + mem + ")"), + + print "{0:>25} {1:>16}:".format(test.name, "(" + mem + ")"), # invoke SMACK t0 = time.time() - p = subprocess.Popen(['smackverify.py', test[0] + '.c', '--verifier=boogie-inline', - '--mem-mod=' + mem, '-o', test[0] +'.bpl'], + p = subprocess.Popen(['smackverify.py', test.name + '.c', '--verifier=' + verifier, + '--unroll=' + str(test.unroll), '--mem-mod=' + mem, '-o', test.name +'.bpl'], stdout=subprocess.PIPE) - + smackOutput = p.communicate()[0] elapsed = time.time() - t0 # check SMACK output - if re.search(test[1], smackOutput): + if re.search(getattr(test, verifier), smackOutput): print green('PASSED') + ' [%.2fs]' % round(elapsed, 2) passed += 1 else: print red('FAILED') failed += 1 - + return passed, failed if __name__ == '__main__': - passed, failed = runtests() - - print '\nPASSED count: ', passed - print 'FAILED count: ', failed + # parse command line arguments + parser = argparse.ArgumentParser(description='Runs regressions in this folder.') + parser.add_argument('--verifier', dest='verifier', choices=['boogie', 'corral', 'duality'], default=['corral'], nargs='*', + help='choose verifiers to be used') + args = parser.parse_args() + + for verifier in args.verifier: + print '\nRunning regressions using', verifier + passed, failed = runtests(verifier) + + print '\nPASSED count: ', passed + print 'FAILED count: ', failed diff --git a/examples/svcomp/locks/test_locks_10_true.c b/examples/svcomp/locks/test_locks_10_true.c index aca0fe98a..e99195b07 100644 --- a/examples/svcomp/locks/test_locks_10_true.c +++ b/examples/svcomp/locks/test_locks_10_true.c @@ -157,7 +157,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_11_true.c b/examples/svcomp/locks/test_locks_11_true.c index c41644275..fedfcf7d7 100644 --- a/examples/svcomp/locks/test_locks_11_true.c +++ b/examples/svcomp/locks/test_locks_11_true.c @@ -171,7 +171,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_12_true.c b/examples/svcomp/locks/test_locks_12_true.c index b054b7807..c29582f6f 100644 --- a/examples/svcomp/locks/test_locks_12_true.c +++ b/examples/svcomp/locks/test_locks_12_true.c @@ -185,7 +185,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_13_true.c b/examples/svcomp/locks/test_locks_13_true.c index 4aefa710e..a17d47d9b 100644 --- a/examples/svcomp/locks/test_locks_13_true.c +++ b/examples/svcomp/locks/test_locks_13_true.c @@ -199,7 +199,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_14_false.c b/examples/svcomp/locks/test_locks_14_false.c index ce33f7708..f60b00e71 100644 --- a/examples/svcomp/locks/test_locks_14_false.c +++ b/examples/svcomp/locks/test_locks_14_false.c @@ -213,7 +213,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_14_true.c b/examples/svcomp/locks/test_locks_14_true.c index a8e547625..a60609164 100644 --- a/examples/svcomp/locks/test_locks_14_true.c +++ b/examples/svcomp/locks/test_locks_14_true.c @@ -213,7 +213,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_15_false.c b/examples/svcomp/locks/test_locks_15_false.c index 4e232fc50..8bcd0eb88 100644 --- a/examples/svcomp/locks/test_locks_15_false.c +++ b/examples/svcomp/locks/test_locks_15_false.c @@ -227,7 +227,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_15_true.c b/examples/svcomp/locks/test_locks_15_true.c index a1e4da50b..8b21f5cd6 100644 --- a/examples/svcomp/locks/test_locks_15_true.c +++ b/examples/svcomp/locks/test_locks_15_true.c @@ -227,7 +227,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_5_true.c b/examples/svcomp/locks/test_locks_5_true.c index fc23676d9..720547c2a 100644 --- a/examples/svcomp/locks/test_locks_5_true.c +++ b/examples/svcomp/locks/test_locks_5_true.c @@ -87,7 +87,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_6_true.c b/examples/svcomp/locks/test_locks_6_true.c index 5b5c94d7d..75bfcb309 100644 --- a/examples/svcomp/locks/test_locks_6_true.c +++ b/examples/svcomp/locks/test_locks_6_true.c @@ -101,7 +101,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_7_true.c b/examples/svcomp/locks/test_locks_7_true.c index 5b11fcd3d..b50892d95 100644 --- a/examples/svcomp/locks/test_locks_7_true.c +++ b/examples/svcomp/locks/test_locks_7_true.c @@ -115,7 +115,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_8_true.c b/examples/svcomp/locks/test_locks_8_true.c index 1d6bdf10d..478bcb355 100644 --- a/examples/svcomp/locks/test_locks_8_true.c +++ b/examples/svcomp/locks/test_locks_8_true.c @@ -129,7 +129,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/locks/test_locks_9_true.c b/examples/svcomp/locks/test_locks_9_true.c index 4ac6bcd72..d9d66c368 100644 --- a/examples/svcomp/locks/test_locks_9_true.c +++ b/examples/svcomp/locks/test_locks_9_true.c @@ -143,7 +143,7 @@ int main() } out: return 0; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return 0; } diff --git a/examples/svcomp/ntdrivers-simplified/cdaudio_simpl1_false.cil.c b/examples/svcomp/ntdrivers-simplified/cdaudio_simpl1_false.cil.c index ab8c63d4d..9e42783f1 100644 --- a/examples/svcomp/ntdrivers-simplified/cdaudio_simpl1_false.cil.c +++ b/examples/svcomp/ntdrivers-simplified/cdaudio_simpl1_false.cil.c @@ -33,7 +33,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); #line 60 return; } diff --git a/examples/svcomp/ntdrivers-simplified/cdaudio_simpl1_true.cil.c b/examples/svcomp/ntdrivers-simplified/cdaudio_simpl1_true.cil.c index a1ad31390..d166519a2 100644 --- a/examples/svcomp/ntdrivers-simplified/cdaudio_simpl1_true.cil.c +++ b/examples/svcomp/ntdrivers-simplified/cdaudio_simpl1_true.cil.c @@ -33,7 +33,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); #line 60 return; } diff --git a/examples/svcomp/ntdrivers-simplified/diskperf_simpl1_true.cil.c b/examples/svcomp/ntdrivers-simplified/diskperf_simpl1_true.cil.c index 146ca5ad8..f36862899 100644 --- a/examples/svcomp/ntdrivers-simplified/diskperf_simpl1_true.cil.c +++ b/examples/svcomp/ntdrivers-simplified/diskperf_simpl1_true.cil.c @@ -31,7 +31,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); #line 58 return; } diff --git a/examples/svcomp/ntdrivers-simplified/floppy_simpl3_false.cil.c b/examples/svcomp/ntdrivers-simplified/floppy_simpl3_false.cil.c index 67955ecaf..15177cc9d 100644 --- a/examples/svcomp/ntdrivers-simplified/floppy_simpl3_false.cil.c +++ b/examples/svcomp/ntdrivers-simplified/floppy_simpl3_false.cil.c @@ -35,7 +35,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return; } } diff --git a/examples/svcomp/ntdrivers-simplified/floppy_simpl3_true.cil.c b/examples/svcomp/ntdrivers-simplified/floppy_simpl3_true.cil.c index cc09ba1d5..74d712679 100644 --- a/examples/svcomp/ntdrivers-simplified/floppy_simpl3_true.cil.c +++ b/examples/svcomp/ntdrivers-simplified/floppy_simpl3_true.cil.c @@ -35,7 +35,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); return; } } diff --git a/examples/svcomp/ntdrivers-simplified/floppy_simpl4_false.cil.c b/examples/svcomp/ntdrivers-simplified/floppy_simpl4_false.cil.c index 3758376b3..5715fd475 100644 --- a/examples/svcomp/ntdrivers-simplified/floppy_simpl4_false.cil.c +++ b/examples/svcomp/ntdrivers-simplified/floppy_simpl4_false.cil.c @@ -2160,7 +2160,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); #line 53 return; } diff --git a/examples/svcomp/ntdrivers-simplified/floppy_simpl4_true.cil.c b/examples/svcomp/ntdrivers-simplified/floppy_simpl4_true.cil.c index 9ae66f5de..0964718d7 100644 --- a/examples/svcomp/ntdrivers-simplified/floppy_simpl4_true.cil.c +++ b/examples/svcomp/ntdrivers-simplified/floppy_simpl4_true.cil.c @@ -2160,7 +2160,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); #line 53 return; } diff --git a/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl1_true.cil.c b/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl1_true.cil.c index 2ea7cb4e7..56036ba2d 100644 --- a/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl1_true.cil.c +++ b/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl1_true.cil.c @@ -761,7 +761,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); #line 23 return; } diff --git a/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl2_false.cil.c b/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl2_false.cil.c index b756eba21..ff452becb 100644 --- a/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl2_false.cil.c +++ b/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl2_false.cil.c @@ -1324,7 +1324,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); #line 29 return; } diff --git a/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl2_true.cil.c b/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl2_true.cil.c index e269af808..9bf431a8d 100644 --- a/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl2_true.cil.c +++ b/examples/svcomp/ntdrivers-simplified/kbfiltr_simpl2_true.cil.c @@ -1322,7 +1322,7 @@ void errorFn(void) { goto ERROR; - ERROR: __SMACK_assert(0); + ERROR: assert(0); #line 29 return; } diff --git a/examples/svcomp/ntdrivers-simplified/regtest-corral.py b/examples/svcomp/ntdrivers-simplified/regtest-corral.py deleted file mode 100755 index a98f6ef70..000000000 --- a/examples/svcomp/ntdrivers-simplified/regtest-corral.py +++ /dev/null @@ -1,60 +0,0 @@ -#! /usr/bin/env python - -import subprocess -import re -import time - -# list of regression tests with the expected outputs -tests = [ - ('cdaudio_simpl1_true.cil', r'Program has no bugs'), - ('cdaudio_simpl1_false.cil', r'This assertion can fail'), - ('diskperf_simpl1_true.cil', r'Program has no bugs'), - ('floppy_simpl3_true.cil', r'Program has no bugs'), - ('floppy_simpl3_false.cil', r'This assertion can fail'), - ('floppy_simpl4_true.cil', r'Program has no bugs'), - ('floppy_simpl4_false.cil', r'This assertion can fail'), - ('kbfiltr_simpl1_true.cil', r'Program has no bugs'), - ('kbfiltr_simpl2_true.cil', r'Program has no bugs'), - ('kbfiltr_simpl2_false.cil', r'This assertion can fail') -] - -def red(text): - return '\033[0;31m' + text + '\033[0m' - -def green(text): - return '\033[0;32m' + text + '\033[0m' - -def runtests(): - passed = failed = 0 - for test in tests: - - for mem in ['no-reuse', 'no-reuse-impls', 'reuse']: - - print "{0:>25} {1:>16}:".format(test[0], "(" + mem + ")"), - - # invoke SMACK - t0 = time.time() - p = subprocess.Popen(['smackverify.py', test[0] + '.c', '--verifier=corral', - '--mem-mod=' + mem, '--clang=-w', '-o', test[0] +'.bpl'], - stdout=subprocess.PIPE) - - smackOutput = p.communicate()[0] - elapsed = time.time() - t0 - - # check SMACK output - if re.search(test[1], smackOutput): - print green('PASSED') + ' [%.2fs]' % round(elapsed, 2) - passed += 1 - else: - print red('FAILED') - failed += 1 - - return passed, failed - -if __name__ == '__main__': - - passed, failed = runtests() - - print '\nPASSED count: ', passed - print 'FAILED count: ', failed - diff --git a/examples/svcomp/ntdrivers-simplified/regtest.py b/examples/svcomp/ntdrivers-simplified/regtest.py index 2f48da038..247759502 100755 --- a/examples/svcomp/ntdrivers-simplified/regtest.py +++ b/examples/svcomp/ntdrivers-simplified/regtest.py @@ -2,20 +2,24 @@ import subprocess import re +import argparse import time +from collections import namedtuple + +RegTest = namedtuple('RegTest', 'name boogie corral duality unroll') # list of regression tests with the expected outputs tests = [ - ('cdaudio_simpl1_true.cil', r'1 verified, 0 errors?'), - ('cdaudio_simpl1_false.cil', r'0 verified, 1 errors?'), - ('diskperf_simpl1_true.cil', r'1 verified, 0 errors?'), - ('floppy_simpl3_true.cil', r'1 verified, 0 errors?'), - ('floppy_simpl3_false.cil', r'0 verified, 1 errors?'), - ('floppy_simpl4_true.cil', r'1 verified, 0 errors?'), - ('floppy_simpl4_false.cil', r'0 verified, 1 errors?'), - ('kbfiltr_simpl1_true.cil', r'1 verified, 0 errors?'), - ('kbfiltr_simpl2_true.cil', r'1 verified, 0 errors?'), - ('kbfiltr_simpl2_false.cil', r'0 verified, 1 errors?') + RegTest('cdaudio_simpl1_true.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('cdaudio_simpl1_false.cil', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('diskperf_simpl1_true.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('floppy_simpl3_true.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('floppy_simpl3_false.cil', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('floppy_simpl4_true.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('floppy_simpl4_false.cil', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('kbfiltr_simpl1_true.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('kbfiltr_simpl2_true.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('kbfiltr_simpl2_false.cil', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2) ] def red(text): @@ -24,37 +28,45 @@ def red(text): def green(text): return '\033[0;32m' + text + '\033[0m' -def runtests(): +def runtests(verifier): passed = failed = 0 for test in tests: - + for mem in ['no-reuse', 'no-reuse-impls', 'reuse']: - - print "{0:>25} {1:>16}:".format(test[0], "(" + mem + ")"), + + print "{0:>25} {1:>16}:".format(test.name, "(" + mem + ")"), # invoke SMACK t0 = time.time() - p = subprocess.Popen(['smackverify.py', test[0] + '.c', '--verifier=boogie-inline', - '--mem-mod=' + mem, '--clang=-w', '-o', test[0] +'.bpl'], + p = subprocess.Popen(['smackverify.py', test.name + '.c', '--verifier=' + verifier, + '--unroll=' + str(test.unroll), '--mem-mod=' + mem, '-o', test.name +'.bpl'], stdout=subprocess.PIPE) - + smackOutput = p.communicate()[0] elapsed = time.time() - t0 # check SMACK output - if re.search(test[1], smackOutput): + if re.search(getattr(test, verifier), smackOutput): print green('PASSED') + ' [%.2fs]' % round(elapsed, 2) passed += 1 else: print red('FAILED') failed += 1 - + return passed, failed if __name__ == '__main__': - passed, failed = runtests() - - print '\nPASSED count: ', passed - print 'FAILED count: ', failed + # parse command line arguments + parser = argparse.ArgumentParser(description='Runs regressions in this folder.') + parser.add_argument('--verifier', dest='verifier', choices=['boogie', 'corral', 'duality'], default=['corral'], nargs='*', + help='choose verifiers to be used') + args = parser.parse_args() + + for verifier in args.verifier: + print '\nRunning regressions using', verifier + passed, failed = runtests(verifier) + + print '\nPASSED count: ', passed + print 'FAILED count: ', failed diff --git a/examples/svcomp/ntdrivers/cdaudio_true.i.cil.c b/examples/svcomp/ntdrivers/cdaudio_true.i.cil.c index b70e01776..083a71063 100644 --- a/examples/svcomp/ntdrivers/cdaudio_true.i.cil.c +++ b/examples/svcomp/ntdrivers/cdaudio_true.i.cil.c @@ -2836,7 +2836,7 @@ void errorFn(void) { { - ERROR: __SMACK_assert(0); + ERROR: assert(0); goto ERROR; } } diff --git a/examples/svcomp/ntdrivers/diskperf_false.i.cil.c b/examples/svcomp/ntdrivers/diskperf_false.i.cil.c index b3f35b780..e14c48125 100644 --- a/examples/svcomp/ntdrivers/diskperf_false.i.cil.c +++ b/examples/svcomp/ntdrivers/diskperf_false.i.cil.c @@ -1983,7 +1983,7 @@ void errorFn(void) { { - ERROR: __SMACK_assert(0); + ERROR: assert(0); goto ERROR; } } diff --git a/examples/svcomp/ntdrivers/diskperf_true.i.cil.c b/examples/svcomp/ntdrivers/diskperf_true.i.cil.c index 4bc35fc27..ec068004c 100644 --- a/examples/svcomp/ntdrivers/diskperf_true.i.cil.c +++ b/examples/svcomp/ntdrivers/diskperf_true.i.cil.c @@ -1983,7 +1983,7 @@ void errorFn(void) { { - ERROR: __SMACK_assert(0); + ERROR: assert(0); goto ERROR; } } diff --git a/examples/svcomp/ntdrivers/floppy2_true.i.cil.c b/examples/svcomp/ntdrivers/floppy2_true.i.cil.c index 82b8ac9ac..a096ac36b 100644 --- a/examples/svcomp/ntdrivers/floppy2_true.i.cil.c +++ b/examples/svcomp/ntdrivers/floppy2_true.i.cil.c @@ -2431,32 +2431,32 @@ extern PKTHREAD ( __attribute__((__stdcall__)) KeGetCurrentThread)() ; #line 28 "C:/NTDDK/inc/poppack.h" #pragma warning(disable:4103) #line 1136 "C:/NTDDK/inc/ddk/ntddk.h" - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) RtlQueryRegistryValues)(ULONG RelativeTo , +NTSTATUS ( __attribute__((__stdcall__)) RtlQueryRegistryValues)(ULONG RelativeTo , PCWSTR Path , PRTL_QUERY_REGISTRY_TABLE QueryTable , PVOID Context , PVOID Environment ) ; #line 1159 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) RtlDeleteRegistryValue)(ULONG RelativeTo , +NTSTATUS ( __attribute__((__stdcall__)) RtlDeleteRegistryValue)(ULONG RelativeTo , PCWSTR Path , PCWSTR ValueName ) ; #line 1264 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) RtlInitString)(PSTRING DestinationString , +void ( __attribute__((__stdcall__)) RtlInitString)(PSTRING DestinationString , PCSZ SourceString ) ; #line 1280 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) RtlInitUnicodeString)(PUNICODE_STRING DestinationString , +void ( __attribute__((__stdcall__)) RtlInitUnicodeString)(PUNICODE_STRING DestinationString , PCWSTR SourceString ) ; #line 1335 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) RtlAnsiStringToUnicodeString)(PUNICODE_STRING DestinationString , +NTSTATUS ( __attribute__((__stdcall__)) RtlAnsiStringToUnicodeString)(PUNICODE_STRING DestinationString , PANSI_STRING SourceString , BOOLEAN AllocateDestinationString ) ; #line 1394 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) RtlCopyUnicodeString)(PUNICODE_STRING DestinationString , +void ( __attribute__((__stdcall__)) RtlCopyUnicodeString)(PUNICODE_STRING DestinationString , PUNICODE_STRING SourceString ) ; #line 1429 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) RtlFreeUnicodeString)(PUNICODE_STRING UnicodeString ) ; +void ( __attribute__((__stdcall__)) RtlFreeUnicodeString)(PUNICODE_STRING UnicodeString ) ; #line 1516 - __attribute__((__dllimport__)) SIZE_T ( __attribute__((__stdcall__)) RtlCompareMemory)(void const *Source1 , +SIZE_T ( __attribute__((__stdcall__)) RtlCompareMemory)(void const *Source1 , void const *Source2 , SIZE_T Length ) ; #line 1718 "C:/NTDDK/inc/ddk/ntddk.h" @@ -2674,7 +2674,7 @@ __inline LUID ( __attribute__((__stdcall__)) RtlConvertUlongToLuid)(ULONG Ulong } } #line 5211 -extern __attribute__((__dllimport__)) LONG ( __attribute__((__fastcall__)) InterlockedExchange)(PLONG Target , +extern LONG ( __attribute__((__fastcall__)) InterlockedExchange)(PLONG Target , LONG Value ) ; #line 5253 #pragma warning(disable:4035) @@ -2706,62 +2706,62 @@ __inline ULONG KeGetCurrentProcessorNumber(void) #line 28 "C:/NTDDK/inc/poppack.h" #pragma warning(disable:4103) #line 9415 "C:/NTDDK/inc/ddk/ntddk.h" - __attribute__((__dllimport__)) void KeInitializeEvent(PRKEVENT Event , EVENT_TYPE Type , +void KeInitializeEvent(PRKEVENT Event , EVENT_TYPE Type , BOOLEAN State ) ; #line 9451 - __attribute__((__dllimport__)) LONG KeSetEvent(PRKEVENT Event , KPRIORITY Increment , +LONG KeSetEvent(PRKEVENT Event , KPRIORITY Increment , BOOLEAN Wait ) ; #line 9483 - __attribute__((__dllimport__)) void KeInitializeSemaphore(PRKSEMAPHORE Semaphore , +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore , LONG Count , LONG Limit ) ; #line 9497 - __attribute__((__dllimport__)) LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore , KPRIORITY Increment , +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore , KPRIORITY Increment , LONG Adjustment , BOOLEAN Wait ) ; #line 9506 - __attribute__((__dllimport__)) NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode , +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode , BOOLEAN Alertable , PLARGE_INTEGER Interval ) ; #line 9527 -extern __attribute__((__dllimport__)) KPRIORITY KeSetPriorityThread(PKTHREAD Thread , +extern KPRIORITY KeSetPriorityThread(PKTHREAD Thread , KPRIORITY Priority ) ; #line 9681 - __attribute__((__dllimport__)) NTSTATUS KeWaitForSingleObject(PVOID Object , KWAIT_REASON WaitReason , +NTSTATUS KeWaitForSingleObject(PVOID Object , KWAIT_REASON WaitReason , KPROCESSOR_MODE WaitMode , BOOLEAN Alertable , PLARGE_INTEGER Timeout ) ; #line 9711 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) KeInitializeSpinLock)(PKSPIN_LOCK SpinLock ) ; +void ( __attribute__((__stdcall__)) KeInitializeSpinLock)(PKSPIN_LOCK SpinLock ) ; #line 9737 -extern __attribute__((__dllimport__)) KIRQL ( __attribute__((__fastcall__)) KfAcquireSpinLock)(PKSPIN_LOCK SpinLock ) ; +extern KIRQL ( __attribute__((__fastcall__)) KfAcquireSpinLock)(PKSPIN_LOCK SpinLock ) ; #line 9744 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) KfReleaseSpinLock)(PKSPIN_LOCK SpinLock , +void ( __attribute__((__fastcall__)) KfReleaseSpinLock)(PKSPIN_LOCK SpinLock , KIRQL NewIrql ) ; #line 10159 - __attribute__((__dllimport__)) PVOID ( __attribute__((__stdcall__)) ExAllocatePoolWithTag)(POOL_TYPE PoolType , +PVOID ( __attribute__((__stdcall__)) ExAllocatePoolWithTag)(POOL_TYPE PoolType , SIZE_T NumberOfBytes , ULONG Tag ) ; #line 10236 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) ExFreePool)(PVOID P ) ; +void ( __attribute__((__stdcall__)) ExFreePool)(PVOID P ) ; #line 10315 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) ExAcquireFastMutex)(PFAST_MUTEX FastMutex ) ; +void ( __attribute__((__fastcall__)) ExAcquireFastMutex)(PFAST_MUTEX FastMutex ) ; #line 10322 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) ExReleaseFastMutex)(PFAST_MUTEX FastMutex ) ; +void ( __attribute__((__fastcall__)) ExReleaseFastMutex)(PFAST_MUTEX FastMutex ) ; #line 10406 - __attribute__((__dllimport__)) PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertHeadList)(PLIST_ENTRY ListHead , +PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertHeadList)(PLIST_ENTRY ListHead , PLIST_ENTRY ListEntry , PKSPIN_LOCK Lock ) ; #line 10415 - __attribute__((__dllimport__)) PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertTailList)(PLIST_ENTRY ListHead , +PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertTailList)(PLIST_ENTRY ListHead , PLIST_ENTRY ListEntry , PKSPIN_LOCK Lock ) ; #line 10424 - __attribute__((__dllimport__)) PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedRemoveHeadList)(PLIST_ENTRY ListHead , +PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedRemoveHeadList)(PLIST_ENTRY ListHead , PKSPIN_LOCK Lock ) ; #line 10547 -extern __attribute__((__dllimport__)) PSINGLE_LIST_ENTRY ( __attribute__((__fastcall__)) ExInterlockedPopEntrySList)(PSLIST_HEADER ListHead , +extern PSINGLE_LIST_ENTRY ( __attribute__((__fastcall__)) ExInterlockedPopEntrySList)(PSLIST_HEADER ListHead , PKSPIN_LOCK Lock ) ; #line 10555 -extern __attribute__((__dllimport__)) PSINGLE_LIST_ENTRY ( __attribute__((__fastcall__)) ExInterlockedPushEntrySList)(PSLIST_HEADER ListHead , +extern PSINGLE_LIST_ENTRY ( __attribute__((__fastcall__)) ExInterlockedPushEntrySList)(PSLIST_HEADER ListHead , PSINGLE_LIST_ENTRY ListEntry , PKSPIN_LOCK Lock ) ; #line 10643 "C:/NTDDK/inc/ddk/ntddk.h" @@ -3083,29 +3083,29 @@ __inline void ExFreeToNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside , PVO } } #line 11906 -extern __attribute__((__dllimport__)) void MmProbeAndLockPages(PMDL MemoryDescriptorList , +extern void MmProbeAndLockPages(PMDL MemoryDescriptorList , KPROCESSOR_MODE AccessMode , LOCK_OPERATION Operation ) ; #line 11915 - __attribute__((__dllimport__)) void MmUnlockPages(PMDL MemoryDescriptorList ) ; +void MmUnlockPages(PMDL MemoryDescriptorList ) ; #line 11979 - __attribute__((__dllimport__)) PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList , +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList , KPROCESSOR_MODE AccessMode , MEMORY_CACHING_TYPE CacheType , PVOID BaseAddress , ULONG BugCheckOnFailure , MM_PAGE_PRIORITY Priority ) ; #line 12084 - __attribute__((__dllimport__)) PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes , +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes , PHYSICAL_ADDRESS HighestAcceptableAddress ) ; #line 12101 - __attribute__((__dllimport__)) void MmFreeContiguousMemory(PVOID BaseAddress ) ; +void MmFreeContiguousMemory(PVOID BaseAddress ) ; #line 12172 - __attribute__((__dllimport__)) void MmResetDriverPaging(PVOID AddressWithinSection ) ; +void MmResetDriverPaging(PVOID AddressWithinSection ) ; #line 12179 - __attribute__((__dllimport__)) PVOID MmPageEntireDriver(PVOID AddressWithinSection ) ; +PVOID MmPageEntireDriver(PVOID AddressWithinSection ) ; #line 12552 - __attribute__((__dllimport__)) NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle , +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle , ULONG DesiredAccess , POBJECT_ATTRIBUTES ObjectAttributes , HANDLE ProcessHandle , @@ -3113,27 +3113,27 @@ extern __attribute__((__dllimport__)) void MmProbeAndLockPages(PMDL MemoryDescr void (*StartRoutine)(PVOID StartContext ) , PVOID StartContext ) ; #line 12564 - __attribute__((__dllimport__)) NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus ) ; +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus ) ; #line 25 "C:/NTDDK/inc/pshpack4.h" #pragma warning(disable:4103) #line 28 "C:/NTDDK/inc/poppack.h" #pragma warning(disable:4103) #line 14734 "C:/NTDDK/inc/ddk/ntddk.h" - __attribute__((__dllimport__)) PMDL IoAllocateMdl(PVOID VirtualAddress , ULONG Length , +PMDL IoAllocateMdl(PVOID VirtualAddress , ULONG Length , BOOLEAN SecondaryBuffer , BOOLEAN ChargeQuota , PIRP Irp ) ; #line 14807 - __attribute__((__dllimport__)) PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice , +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice , PDEVICE_OBJECT TargetDevice ) ; #line 14814 - __attribute__((__dllimport__)) PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction , +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction , PDEVICE_OBJECT DeviceObject , PVOID Buffer , ULONG Length , PLARGE_INTEGER StartingOffset , PIO_STATUS_BLOCK IoStatusBlock ) ; #line 14825 - __attribute__((__dllimport__)) PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode , +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode , PDEVICE_OBJECT DeviceObject , PVOID InputBuffer , ULONG InputBufferLength , @@ -3143,34 +3143,34 @@ extern __attribute__((__dllimport__)) void MmProbeAndLockPages(PMDL MemoryDescr PKEVENT Event , PIO_STATUS_BLOCK IoStatusBlock ) ; #line 14875 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__fastcall__)) IofCallDriver)(PDEVICE_OBJECT DeviceObject , +NTSTATUS ( __attribute__((__fastcall__)) IofCallDriver)(PDEVICE_OBJECT DeviceObject , PIRP Irp ) ; #line 14903 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) IofCompleteRequest)(PIRP Irp , +void ( __attribute__((__fastcall__)) IofCompleteRequest)(PIRP Irp , CCHAR PriorityBoost ) ; #line 14942 - __attribute__((__dllimport__)) NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject , +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject , ULONG DeviceExtensionSize , PUNICODE_STRING DeviceName , ULONG DeviceType , ULONG DeviceCharacteristics , BOOLEAN Exclusive , PDEVICE_OBJECT *DeviceObject ) ; #line 14993 - __attribute__((__dllimport__)) NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName , +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName , PUNICODE_STRING DeviceName ) ; #line 15057 - __attribute__((__dllimport__)) void IoDeleteDevice(PDEVICE_OBJECT DeviceObject ) ; +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject ) ; #line 15063 - __attribute__((__dllimport__)) NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName ) ; +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName ) ; #line 15069 - __attribute__((__dllimport__)) void IoDetachDevice(PDEVICE_OBJECT TargetDevice ) ; +void IoDetachDevice(PDEVICE_OBJECT TargetDevice ) ; #line 15092 - __attribute__((__dllimport__)) void IoFreeIrp(PIRP Irp ) ; +void IoFreeIrp(PIRP Irp ) ; #line 15098 - __attribute__((__dllimport__)) void IoFreeMdl(PMDL Mdl ) ; +void IoFreeMdl(PMDL Mdl ) ; #line 15110 - __attribute__((__dllimport__)) PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) ; +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) ; #line 15234 -extern __attribute__((__dllimport__)) void IoGetStackLimits(PULONG_PTR LowLimit , +extern void IoGetStackLimits(PULONG_PTR LowLimit , PULONG_PTR HighLimit ) ; #line 15246 "C:/NTDDK/inc/ddk/ntddk.h" __inline ULONG_PTR IoGetRemainingStackSize(void) @@ -3198,7 +3198,7 @@ __inline ULONG_PTR IoGetRemainingStackSize(void) } } #line 15426 - __attribute__((__dllimport__)) NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType , +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType , PULONG BusNumber , PCONFIGURATION_TYPE ControllerType , PULONG ControllerNumber , @@ -3217,37 +3217,37 @@ __inline ULONG_PTR IoGetRemainingStackSize(void) PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ) , PVOID Context ) ; #line 15492 - __attribute__((__dllimport__)) void IoReleaseCancelSpinLock(KIRQL Irql ) ; +void IoReleaseCancelSpinLock(KIRQL Irql ) ; #line 15641 - __attribute__((__dllimport__)) void IoSetHardErrorOrVerifyDevice(PIRP Irp , PDEVICE_OBJECT DeviceObject ) ; +void IoSetHardErrorOrVerifyDevice(PIRP Irp , PDEVICE_OBJECT DeviceObject ) ; #line 16436 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) IoRegisterDeviceInterface)(PDEVICE_OBJECT PhysicalDeviceObject , +NTSTATUS ( __attribute__((__stdcall__)) IoRegisterDeviceInterface)(PDEVICE_OBJECT PhysicalDeviceObject , GUID const *InterfaceClassGuid , PUNICODE_STRING ReferenceString , PUNICODE_STRING SymbolicLinkName ) ; #line 16456 - __attribute__((__dllimport__)) NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName , +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName , BOOLEAN Enable ) ; #line 17779 #pragma warning(disable:4200) #line 17785 #pragma warning(default:4200) #line 18271 - __attribute__((__dllimport__)) NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject , +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject , PIRP Irp ) ; #line 18278 - __attribute__((__dllimport__)) void PoStartNextPowerIrp(PIRP Irp ) ; +void PoStartNextPowerIrp(PIRP Irp ) ; #line 18326 - __attribute__((__dllimport__)) NTSTATUS ObReferenceObjectByHandle(HANDLE Handle , +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle , ACCESS_MASK DesiredAccess , POBJECT_TYPE ObjectType , KPROCESSOR_MODE AccessMode , PVOID *Object , POBJECT_HANDLE_INFORMATION HandleInformation ) ; #line 18359 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) ObfDereferenceObject)(PVOID Object ) ; +void ( __attribute__((__fastcall__)) ObfDereferenceObject)(PVOID Object ) ; #line 19155 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) ZwClose)(HANDLE Handle ) ; +NTSTATUS ( __attribute__((__stdcall__)) ZwClose)(HANDLE Handle ) ; #line 25 "C:/NTDDK/inc/pshpack1.h" #pragma warning(disable:4103) #line 28 "C:/NTDDK/inc/poppack.h" @@ -6173,7 +6173,7 @@ NTSTATUS FlAcpiConfigureFloppy(PDISKETTE_EXTENSION DisketteExtension , PFDC_INFO #line 949 void __VERIFIER_assert(int cond) { if (!(cond)) { - ERROR: __SMACK_assert(0); goto ERROR; + ERROR: assert(0); goto ERROR; } return; } @@ -29890,7 +29890,7 @@ char *malloc(int i ) } } #line 230 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) ExAcquireFastMutex)(PFAST_MUTEX FastMutex ) ; +void ( __attribute__((__fastcall__)) ExAcquireFastMutex)(PFAST_MUTEX FastMutex ) ; #line 230 "../slam-kernel.c" void ( __attribute__((__fastcall__)) ExAcquireFastMutex)(PFAST_MUTEX FastMutex ) { @@ -29901,7 +29901,7 @@ void ( __attribute__((__fastcall__)) ExAcquireFastMutex)(PFAST_MUTEX FastMutex ) } } #line 240 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) ExReleaseFastMutex)(PFAST_MUTEX FastMutex ) ; +void ( __attribute__((__fastcall__)) ExReleaseFastMutex)(PFAST_MUTEX FastMutex ) ; #line 240 "../slam-kernel.c" void ( __attribute__((__fastcall__)) ExReleaseFastMutex)(PFAST_MUTEX FastMutex ) { @@ -29912,7 +29912,7 @@ void ( __attribute__((__fastcall__)) ExReleaseFastMutex)(PFAST_MUTEX FastMutex ) } } #line 264 - __attribute__((__dllimport__)) PVOID ( __attribute__((__stdcall__)) ExAllocatePoolWithTag)(POOL_TYPE PoolType , +PVOID ( __attribute__((__stdcall__)) ExAllocatePoolWithTag)(POOL_TYPE PoolType , SIZE_T NumberOfBytes , ULONG Tag ) ; #line 264 "../slam-kernel.c" @@ -29936,7 +29936,7 @@ PVOID ( __attribute__((__stdcall__)) ExAllocatePoolWithTag)(POOL_TYPE PoolType , } } #line 279 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) ExFreePool)(PVOID P ) ; +void ( __attribute__((__stdcall__)) ExFreePool)(PVOID P ) ; #line 279 "../slam-kernel.c" void ( __attribute__((__stdcall__)) ExFreePool)(PVOID P ) { @@ -29947,7 +29947,7 @@ void ( __attribute__((__stdcall__)) ExFreePool)(PVOID P ) } } #line 288 - __attribute__((__dllimport__)) PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertHeadList)(PLIST_ENTRY ListHead , +PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertHeadList)(PLIST_ENTRY ListHead , PLIST_ENTRY ListEntry , PKSPIN_LOCK Lock ) ; #line 288 "../slam-kernel.c" @@ -29966,7 +29966,7 @@ PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertHeadList)(PLIST_ } } #line 299 - __attribute__((__dllimport__)) PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertTailList)(PLIST_ENTRY ListHead , +PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertTailList)(PLIST_ENTRY ListHead , PLIST_ENTRY ListEntry , PKSPIN_LOCK Lock ) ; #line 299 "../slam-kernel.c" @@ -29985,7 +29985,7 @@ PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedInsertTailList)(PLIST_ } } #line 311 - __attribute__((__dllimport__)) PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedRemoveHeadList)(PLIST_ENTRY ListHead , +PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedRemoveHeadList)(PLIST_ENTRY ListHead , PKSPIN_LOCK Lock ) ; #line 311 "../slam-kernel.c" PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedRemoveHeadList)(PLIST_ENTRY ListHead , @@ -30002,7 +30002,7 @@ PLIST_ENTRY ( __attribute__((__fastcall__)) ExfInterlockedRemoveHeadList)(PLIST_ } } #line 335 - __attribute__((__dllimport__)) PMDL IoAllocateMdl(PVOID VirtualAddress , ULONG Length , +PMDL IoAllocateMdl(PVOID VirtualAddress , ULONG Length , BOOLEAN SecondaryBuffer , BOOLEAN ChargeQuota , PIRP Irp ) ; #line 335 "../slam-kernel.c" @@ -30051,7 +30051,7 @@ PMDL IoAllocateMdl(PVOID VirtualAddress , ULONG Length , BOOLEAN SecondaryBuffer } } #line 352 - __attribute__((__dllimport__)) PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice , +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice , PDEVICE_OBJECT TargetDevice ) ; #line 352 "../slam-kernel.c" PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice , PDEVICE_OBJECT TargetDevice ) @@ -30085,7 +30085,7 @@ PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice , PDEVICE } } #line 366 - __attribute__((__dllimport__)) PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction , +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction , PDEVICE_OBJECT DeviceObject , PVOID Buffer , ULONG Length , @@ -30140,7 +30140,7 @@ PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction , PDEVICE_OBJECT DeviceOb } } #line 397 - __attribute__((__dllimport__)) PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode , +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode , PDEVICE_OBJECT DeviceObject , PVOID InputBuffer , ULONG InputBufferLength , @@ -30199,7 +30199,7 @@ PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode , PDEVICE_OBJECT DeviceOb } } #line 420 - __attribute__((__dllimport__)) NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject , +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject , ULONG DeviceExtensionSize , PUNICODE_STRING DeviceName , ULONG DeviceType , ULONG DeviceCharacteristics , @@ -30246,7 +30246,7 @@ NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject , ULONG DeviceExtensionSize } } #line 446 - __attribute__((__dllimport__)) NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName , +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName , PUNICODE_STRING DeviceName ) ; #line 446 "../slam-kernel.c" NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName , PUNICODE_STRING DeviceName ) @@ -30275,7 +30275,7 @@ NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName , PUNICODE_STRING } } #line 460 - __attribute__((__dllimport__)) void IoDeleteDevice(PDEVICE_OBJECT DeviceObject ) ; +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject ) ; #line 460 "../slam-kernel.c" void IoDeleteDevice(PDEVICE_OBJECT DeviceObject ) { @@ -30286,7 +30286,7 @@ void IoDeleteDevice(PDEVICE_OBJECT DeviceObject ) } } #line 469 - __attribute__((__dllimport__)) NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName ) ; +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName ) ; #line 469 "../slam-kernel.c" NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName ) { int __BLAST_NONDET = __VERIFIER_nondet_int() ; @@ -30314,7 +30314,7 @@ NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName ) } } #line 482 - __attribute__((__dllimport__)) void IoDetachDevice(PDEVICE_OBJECT TargetDevice ) ; +void IoDetachDevice(PDEVICE_OBJECT TargetDevice ) ; #line 482 "../slam-kernel.c" void IoDetachDevice(PDEVICE_OBJECT TargetDevice ) { @@ -30325,7 +30325,7 @@ void IoDetachDevice(PDEVICE_OBJECT TargetDevice ) } } #line 491 - __attribute__((__dllimport__)) void IoFreeIrp(PIRP Irp ) ; +void IoFreeIrp(PIRP Irp ) ; #line 491 "../slam-kernel.c" void IoFreeIrp(PIRP Irp ) { @@ -30336,7 +30336,7 @@ void IoFreeIrp(PIRP Irp ) } } #line 500 - __attribute__((__dllimport__)) void IoFreeMdl(PMDL Mdl ) ; +void IoFreeMdl(PMDL Mdl ) ; #line 500 "../slam-kernel.c" void IoFreeMdl(PMDL Mdl ) { @@ -30347,7 +30347,7 @@ void IoFreeMdl(PMDL Mdl ) } } #line 509 - __attribute__((__dllimport__)) PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) ; +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) ; #line 509 "../slam-kernel.c" PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) { char *tmp ; @@ -30370,7 +30370,7 @@ PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) } } #line 517 - __attribute__((__dllimport__)) NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType , +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType , PULONG BusNumber , PCONFIGURATION_TYPE ControllerType , PULONG ControllerNumber , @@ -30428,7 +30428,7 @@ NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType , PULONG BusNumber , P } } #line 537 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) IoRegisterDeviceInterface)(PDEVICE_OBJECT PhysicalDeviceObject , +NTSTATUS ( __attribute__((__stdcall__)) IoRegisterDeviceInterface)(PDEVICE_OBJECT PhysicalDeviceObject , GUID const *InterfaceClassGuid , PUNICODE_STRING ReferenceString , PUNICODE_STRING SymbolicLinkName ) ; @@ -30462,7 +30462,7 @@ NTSTATUS ( __attribute__((__stdcall__)) IoRegisterDeviceInterface)(PDEVICE_OBJEC } } #line 554 - __attribute__((__dllimport__)) void IoReleaseCancelSpinLock(KIRQL Irql ) ; +void IoReleaseCancelSpinLock(KIRQL Irql ) ; #line 554 "../slam-kernel.c" void IoReleaseCancelSpinLock(KIRQL Irql ) { @@ -30473,7 +30473,7 @@ void IoReleaseCancelSpinLock(KIRQL Irql ) } } #line 563 - __attribute__((__dllimport__)) NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName , +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName , BOOLEAN Enable ) ; #line 563 "../slam-kernel.c" NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName , BOOLEAN Enable ) @@ -30502,7 +30502,7 @@ NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName , BOOLEAN En } } #line 582 - __attribute__((__dllimport__)) void IoSetHardErrorOrVerifyDevice(PIRP Irp , PDEVICE_OBJECT DeviceObject ) ; +void IoSetHardErrorOrVerifyDevice(PIRP Irp , PDEVICE_OBJECT DeviceObject ) ; #line 582 "../slam-kernel.c" void IoSetHardErrorOrVerifyDevice(PIRP Irp , PDEVICE_OBJECT DeviceObject ) { @@ -30532,7 +30532,7 @@ void stubMoreProcessingRequired(void) } } #line 602 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__fastcall__)) IofCallDriver)(PDEVICE_OBJECT DeviceObject , +NTSTATUS ( __attribute__((__fastcall__)) IofCallDriver)(PDEVICE_OBJECT DeviceObject , PIRP Irp ) ; #line 602 "../slam-kernel.c" NTSTATUS ( __attribute__((__fastcall__)) IofCallDriver)(PDEVICE_OBJECT DeviceObject , @@ -30643,7 +30643,7 @@ NTSTATUS ( __attribute__((__fastcall__)) IofCallDriver)(PDEVICE_OBJECT DeviceObj } } #line 665 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) IofCompleteRequest)(PIRP Irp , +void ( __attribute__((__fastcall__)) IofCompleteRequest)(PIRP Irp , CCHAR PriorityBoost ) ; #line 665 "../slam-kernel.c" void ( __attribute__((__fastcall__)) IofCompleteRequest)(PIRP Irp , CCHAR PriorityBoost ) @@ -30665,9 +30665,9 @@ void ( __attribute__((__fastcall__)) IofCompleteRequest)(PIRP Irp , CCHAR Priori } } #line 677 - __attribute__((__dllimport__)) KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock ) ; +KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock ) ; #line 677 - __attribute__((__dllimport__)) KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock ) ; +KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock ) ; #line 677 "../slam-kernel.c" KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock ) { @@ -30678,7 +30678,7 @@ KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock ) } } #line 686 - __attribute__((__dllimport__)) NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode , +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode , BOOLEAN Alertable , PLARGE_INTEGER Interval ) ; #line 686 "../slam-kernel.c" @@ -30708,7 +30708,7 @@ NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode , BOOLEAN Alertable , P } } #line 706 - __attribute__((__dllimport__)) void KeInitializeEvent(PRKEVENT Event , EVENT_TYPE Type , +void KeInitializeEvent(PRKEVENT Event , EVENT_TYPE Type , BOOLEAN State ) ; #line 706 "../slam-kernel.c" void KeInitializeEvent(PRKEVENT Event , EVENT_TYPE Type , BOOLEAN State ) @@ -30720,7 +30720,7 @@ void KeInitializeEvent(PRKEVENT Event , EVENT_TYPE Type , BOOLEAN State ) } } #line 717 - __attribute__((__dllimport__)) void KeInitializeSemaphore(PRKSEMAPHORE Semaphore , +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore , LONG Count , LONG Limit ) ; #line 717 "../slam-kernel.c" void KeInitializeSemaphore(PRKSEMAPHORE Semaphore , LONG Count , LONG Limit ) @@ -30732,7 +30732,7 @@ void KeInitializeSemaphore(PRKSEMAPHORE Semaphore , LONG Count , LONG Limit ) } } #line 728 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) KeInitializeSpinLock)(PKSPIN_LOCK SpinLock ) ; +void ( __attribute__((__stdcall__)) KeInitializeSpinLock)(PKSPIN_LOCK SpinLock ) ; #line 728 "../slam-kernel.c" void ( __attribute__((__stdcall__)) KeInitializeSpinLock)(PKSPIN_LOCK SpinLock ) { @@ -30743,7 +30743,7 @@ void ( __attribute__((__stdcall__)) KeInitializeSpinLock)(PKSPIN_LOCK SpinLock ) } } #line 738 - __attribute__((__dllimport__)) LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore , KPRIORITY Increment , +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore , KPRIORITY Increment , LONG Adjustment , BOOLEAN Wait ) ; #line 738 "../slam-kernel.c" LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore , KPRIORITY Increment , LONG Adjustment , @@ -30756,7 +30756,7 @@ LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore , KPRIORITY Increment , LONG Adju } } #line 751 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) KfReleaseSpinLock)(PKSPIN_LOCK SpinLock , +void ( __attribute__((__fastcall__)) KfReleaseSpinLock)(PKSPIN_LOCK SpinLock , KIRQL NewIrql ) ; #line 751 "../slam-kernel.c" void ( __attribute__((__fastcall__)) KfReleaseSpinLock)(PKSPIN_LOCK SpinLock , KIRQL NewIrql ) @@ -30768,7 +30768,7 @@ void ( __attribute__((__fastcall__)) KfReleaseSpinLock)(PKSPIN_LOCK SpinLock , K } } #line 762 - __attribute__((__dllimport__)) LONG KeSetEvent(PRKEVENT Event , KPRIORITY Increment , +LONG KeSetEvent(PRKEVENT Event , KPRIORITY Increment , BOOLEAN Wait ) ; #line 762 "../slam-kernel.c" LONG KeSetEvent(PRKEVENT Event , KPRIORITY Increment , BOOLEAN Wait ) @@ -30782,7 +30782,7 @@ LONG KeSetEvent(PRKEVENT Event , KPRIORITY Increment , BOOLEAN Wait ) } } #line 777 - __attribute__((__dllimport__)) NTSTATUS KeWaitForSingleObject(PVOID Object , KWAIT_REASON WaitReason , +NTSTATUS KeWaitForSingleObject(PVOID Object , KWAIT_REASON WaitReason , KPROCESSOR_MODE WaitMode , BOOLEAN Alertable , PLARGE_INTEGER Timeout ) ; @@ -30845,7 +30845,7 @@ NTSTATUS KeWaitForSingleObject(PVOID Object , KWAIT_REASON WaitReason , KPROCESS } } #line 810 - __attribute__((__dllimport__)) PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes , +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes , PHYSICAL_ADDRESS HighestAcceptableAddress ) ; #line 810 "../slam-kernel.c" PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes , PHYSICAL_ADDRESS HighestAcceptableAddress ) @@ -30886,7 +30886,7 @@ PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes , PHYSICAL_ADDRESS Highest } } #line 823 - __attribute__((__dllimport__)) void MmFreeContiguousMemory(PVOID BaseAddress ) ; +void MmFreeContiguousMemory(PVOID BaseAddress ) ; #line 823 "../slam-kernel.c" void MmFreeContiguousMemory(PVOID BaseAddress ) { @@ -30897,7 +30897,7 @@ void MmFreeContiguousMemory(PVOID BaseAddress ) } } #line 832 - __attribute__((__dllimport__)) PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList , +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList , KPROCESSOR_MODE AccessMode , MEMORY_CACHING_TYPE CacheType , PVOID BaseAddress , @@ -30915,7 +30915,7 @@ PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList , KPROCESSOR_MODE A } } #line 846 - __attribute__((__dllimport__)) PVOID MmPageEntireDriver(PVOID AddressWithinSection ) ; +PVOID MmPageEntireDriver(PVOID AddressWithinSection ) ; #line 846 "../slam-kernel.c" PVOID MmPageEntireDriver(PVOID AddressWithinSection ) { @@ -30926,7 +30926,7 @@ PVOID MmPageEntireDriver(PVOID AddressWithinSection ) } } #line 855 - __attribute__((__dllimport__)) void MmResetDriverPaging(PVOID AddressWithinSection ) ; +void MmResetDriverPaging(PVOID AddressWithinSection ) ; #line 855 "../slam-kernel.c" void MmResetDriverPaging(PVOID AddressWithinSection ) { @@ -30937,7 +30937,7 @@ void MmResetDriverPaging(PVOID AddressWithinSection ) } } #line 865 - __attribute__((__dllimport__)) void MmUnlockPages(PMDL MemoryDescriptorList ) ; +void MmUnlockPages(PMDL MemoryDescriptorList ) ; #line 865 "../slam-kernel.c" void MmUnlockPages(PMDL MemoryDescriptorList ) { @@ -30948,7 +30948,7 @@ void MmUnlockPages(PMDL MemoryDescriptorList ) } } #line 874 - __attribute__((__dllimport__)) NTSTATUS ObReferenceObjectByHandle(HANDLE Handle , +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle , ACCESS_MASK DesiredAccess , POBJECT_TYPE ObjectType , KPROCESSOR_MODE AccessMode , @@ -30982,7 +30982,7 @@ NTSTATUS ObReferenceObjectByHandle(HANDLE Handle , ACCESS_MASK DesiredAccess , P } } #line 899 - __attribute__((__dllimport__)) void ( __attribute__((__fastcall__)) ObfDereferenceObject)(PVOID Object ) ; +void ( __attribute__((__fastcall__)) ObfDereferenceObject)(PVOID Object ) ; #line 899 "../slam-kernel.c" void ( __attribute__((__fastcall__)) ObfDereferenceObject)(PVOID Object ) { @@ -30993,7 +30993,7 @@ void ( __attribute__((__fastcall__)) ObfDereferenceObject)(PVOID Object ) } } #line 909 - __attribute__((__dllimport__)) NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject , +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject , PIRP Irp ) ; #line 909 "../slam-kernel.c" NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject , PIRP Irp ) @@ -31100,7 +31100,7 @@ NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject , PIRP Irp ) } } #line 956 - __attribute__((__dllimport__)) void PoStartNextPowerIrp(PIRP Irp ) ; +void PoStartNextPowerIrp(PIRP Irp ) ; #line 956 "../slam-kernel.c" void PoStartNextPowerIrp(PIRP Irp ) { @@ -31111,7 +31111,7 @@ void PoStartNextPowerIrp(PIRP Irp ) } } #line 965 - __attribute__((__dllimport__)) NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle , +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle , ULONG DesiredAccess , POBJECT_ATTRIBUTES ObjectAttributes , HANDLE ProcessHandle , @@ -31147,7 +31147,7 @@ NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle , ULONG DesiredAccess , POBJE } } #line 984 - __attribute__((__dllimport__)) NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus ) ; +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus ) ; #line 984 "../slam-kernel.c" NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus ) { int __BLAST_NONDET = __VERIFIER_nondet_int() ; @@ -31175,7 +31175,7 @@ NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus ) } } #line 998 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) RtlAnsiStringToUnicodeString)(PUNICODE_STRING DestinationString , +NTSTATUS ( __attribute__((__stdcall__)) RtlAnsiStringToUnicodeString)(PUNICODE_STRING DestinationString , PANSI_STRING SourceString , BOOLEAN AllocateDestinationString ) ; #line 998 "../slam-kernel.c" @@ -31207,7 +31207,7 @@ NTSTATUS ( __attribute__((__stdcall__)) RtlAnsiStringToUnicodeString)(PUNICODE_S } } #line 1014 - __attribute__((__dllimport__)) SIZE_T ( __attribute__((__stdcall__)) RtlCompareMemory)(void const *Source1 , +SIZE_T ( __attribute__((__stdcall__)) RtlCompareMemory)(void const *Source1 , void const *Source2 , SIZE_T Length ) ; #line 1014 "../slam-kernel.c" @@ -31221,7 +31221,7 @@ SIZE_T ( __attribute__((__stdcall__)) RtlCompareMemory)(void const *Source1 , } } #line 1027 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) RtlCopyUnicodeString)(PUNICODE_STRING DestinationString , +void ( __attribute__((__stdcall__)) RtlCopyUnicodeString)(PUNICODE_STRING DestinationString , PUNICODE_STRING SourceString ) ; #line 1027 "../slam-kernel.c" void ( __attribute__((__stdcall__)) RtlCopyUnicodeString)(PUNICODE_STRING DestinationString , @@ -31234,7 +31234,7 @@ void ( __attribute__((__stdcall__)) RtlCopyUnicodeString)(PUNICODE_STRING Destin } } #line 1038 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) RtlDeleteRegistryValue)(ULONG RelativeTo , +NTSTATUS ( __attribute__((__stdcall__)) RtlDeleteRegistryValue)(ULONG RelativeTo , PCWSTR Path , PCWSTR ValueName ) ; #line 1038 "../slam-kernel.c" @@ -31265,7 +31265,7 @@ NTSTATUS ( __attribute__((__stdcall__)) RtlDeleteRegistryValue)(ULONG RelativeTo } } #line 1054 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) RtlFreeUnicodeString)(PUNICODE_STRING UnicodeString ) ; +void ( __attribute__((__stdcall__)) RtlFreeUnicodeString)(PUNICODE_STRING UnicodeString ) ; #line 1054 "../slam-kernel.c" void ( __attribute__((__stdcall__)) RtlFreeUnicodeString)(PUNICODE_STRING UnicodeString ) { @@ -31276,7 +31276,7 @@ void ( __attribute__((__stdcall__)) RtlFreeUnicodeString)(PUNICODE_STRING Unicod } } #line 1064 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) RtlInitString)(PSTRING DestinationString , +void ( __attribute__((__stdcall__)) RtlInitString)(PSTRING DestinationString , PCSZ SourceString ) ; #line 1064 "../slam-kernel.c" void ( __attribute__((__stdcall__)) RtlInitString)(PSTRING DestinationString , PCSZ SourceString ) @@ -31288,7 +31288,7 @@ void ( __attribute__((__stdcall__)) RtlInitString)(PSTRING DestinationString , P } } #line 1075 - __attribute__((__dllimport__)) void ( __attribute__((__stdcall__)) RtlInitUnicodeString)(PUNICODE_STRING DestinationString , +void ( __attribute__((__stdcall__)) RtlInitUnicodeString)(PUNICODE_STRING DestinationString , PCWSTR SourceString ) ; #line 1075 "../slam-kernel.c" void ( __attribute__((__stdcall__)) RtlInitUnicodeString)(PUNICODE_STRING DestinationString , @@ -31301,7 +31301,7 @@ void ( __attribute__((__stdcall__)) RtlInitUnicodeString)(PUNICODE_STRING Destin } } #line 1087 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) RtlQueryRegistryValues)(ULONG RelativeTo , +NTSTATUS ( __attribute__((__stdcall__)) RtlQueryRegistryValues)(ULONG RelativeTo , PCWSTR Path , PRTL_QUERY_REGISTRY_TABLE QueryTable , PVOID Context , @@ -31335,7 +31335,7 @@ NTSTATUS ( __attribute__((__stdcall__)) RtlQueryRegistryValues)(ULONG RelativeTo } } #line 1109 - __attribute__((__dllimport__)) NTSTATUS ( __attribute__((__stdcall__)) ZwClose)(HANDLE Handle ) ; +NTSTATUS ( __attribute__((__stdcall__)) ZwClose)(HANDLE Handle ) ; #line 1109 "../slam-kernel.c" NTSTATUS ( __attribute__((__stdcall__)) ZwClose)(HANDLE Handle ) { int __BLAST_NONDET = __VERIFIER_nondet_int() ; diff --git a/examples/svcomp/ntdrivers/floppy_false.i.cil.c b/examples/svcomp/ntdrivers/floppy_false.i.cil.c index ecc90cc3b..68748d2a5 100644 --- a/examples/svcomp/ntdrivers/floppy_false.i.cil.c +++ b/examples/svcomp/ntdrivers/floppy_false.i.cil.c @@ -2096,7 +2096,7 @@ void errorFn(void) { { - ERROR: __SMACK_assert(0); + ERROR: assert(0); goto ERROR; } } diff --git a/examples/svcomp/ntdrivers/floppy_true.i.cil.c b/examples/svcomp/ntdrivers/floppy_true.i.cil.c index 8c3b92755..db12115e6 100644 --- a/examples/svcomp/ntdrivers/floppy_true.i.cil.c +++ b/examples/svcomp/ntdrivers/floppy_true.i.cil.c @@ -2097,7 +2097,7 @@ void errorFn(void) { { - ERROR: __SMACK_assert(0); + ERROR: assert(0); goto ERROR; } } diff --git a/examples/svcomp/ntdrivers/kbfiltr_false.i.cil.c b/examples/svcomp/ntdrivers/kbfiltr_false.i.cil.c index faf23a58b..d7909ca32 100644 --- a/examples/svcomp/ntdrivers/kbfiltr_false.i.cil.c +++ b/examples/svcomp/ntdrivers/kbfiltr_false.i.cil.c @@ -1639,7 +1639,7 @@ void errorFn(void) { { - ERROR: __SMACK_assert(0); + ERROR: assert(0); goto ERROR; } } diff --git a/examples/svcomp/ntdrivers/parport_false.i.cil.c b/examples/svcomp/ntdrivers/parport_false.i.cil.c index f07fbefcd..2026f09aa 100644 --- a/examples/svcomp/ntdrivers/parport_false.i.cil.c +++ b/examples/svcomp/ntdrivers/parport_false.i.cil.c @@ -2246,7 +2246,7 @@ void errorFn(void) { { - ERROR: __SMACK_assert(0); + ERROR: assert(0); goto ERROR; } } diff --git a/examples/svcomp/ntdrivers/parport_true.i.cil.c b/examples/svcomp/ntdrivers/parport_true.i.cil.c index caf844d5e..3e0be9724 100644 --- a/examples/svcomp/ntdrivers/parport_true.i.cil.c +++ b/examples/svcomp/ntdrivers/parport_true.i.cil.c @@ -2246,7 +2246,7 @@ void errorFn(void) { { - ERROR: __SMACK_assert(0); + ERROR: assert(0); goto ERROR; } } diff --git a/examples/svcomp/ntdrivers/regtest-corral.py b/examples/svcomp/ntdrivers/regtest-corral.py deleted file mode 100755 index 181c2b579..000000000 --- a/examples/svcomp/ntdrivers/regtest-corral.py +++ /dev/null @@ -1,59 +0,0 @@ -#! /usr/bin/env python - -import subprocess -import re -import time - -# list of regression tests with the expected outputs -tests = [ - ('cdaudio_true.i.cil', r'Program has no bugs'), - ('diskperf_true.i.cil', r'Program has no bugs'), - ('diskperf_false.i.cil', r'This assertion can fail'), - ('floppy2_true.i.cil', r'Program has no bugs'), - ('floppy_true.i.cil', r'Program has no bugs'), - ('floppy_false.i.cil', r'This assertion can fail'), - ('kbfiltr_false.i.cil', r'This assertion can fail'), - ('parport_true.i.cil', r'Program has no bugs'), - ('parport_false.i.cil', r'This assertion can fail') -] - -def red(text): - return '\033[0;31m' + text + '\033[0m' - -def green(text): - return '\033[0;32m' + text + '\033[0m' - -def runtests(): - passed = failed = 0 - for test in tests: - - for mem in ['no-reuse', 'no-reuse-impls', 'reuse']: - - print "{0:>25} {1:>16}:".format(test[0], "(" + mem + ")"), - - # invoke SMACK - t0 = time.time() - p = subprocess.Popen(['smackverify.py', test[0] + '.c', '--verifier=corral', - '--mem-mod=' + mem, '--clang=-w', '-o', test[0] +'.bpl'], - stdout=subprocess.PIPE) - - smackOutput = p.communicate()[0] - elapsed = time.time() - t0 - - # check SMACK output - if re.search(test[1], smackOutput): - print green('PASSED') + ' [%.2fs]' % round(elapsed, 2) - passed += 1 - else: - print red('FAILED') - failed += 1 - - return passed, failed - -if __name__ == '__main__': - - passed, failed = runtests() - - print '\nPASSED count: ', passed - print 'FAILED count: ', failed - diff --git a/examples/svcomp/ntdrivers/regtest.py b/examples/svcomp/ntdrivers/regtest.py index 6a0a53482..6f5a221dd 100755 --- a/examples/svcomp/ntdrivers/regtest.py +++ b/examples/svcomp/ntdrivers/regtest.py @@ -2,19 +2,23 @@ import subprocess import re +import argparse import time +from collections import namedtuple + +RegTest = namedtuple('RegTest', 'name boogie corral duality unroll') # list of regression tests with the expected outputs tests = [ - ('cdaudio_true.i.cil', r'1 verified, 0 errors?'), -# ('diskperf_true.i.cil', r'1 verified, 0 errors?'), -# ('diskperf_false.i.cil', r'0 verified, 1 errors?'), - ('floppy2_true.i.cil', r'1 verified, 0 errors?'), - ('floppy_true.i.cil', r'1 verified, 0 errors?'), - ('floppy_false.i.cil', r'0 verified, 1 errors?'), - ('kbfiltr_false.i.cil', r'0 verified, 1 errors?'), - ('parport_true.i.cil', r'1 verified, 0 errors?'), - ('parport_false.i.cil', r'0 verified, 1 errors?') + RegTest('cdaudio_true.i.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('diskperf_true.i.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('diskperf_false.i.cil', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('floppy2_true.i.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('floppy_true.i.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('floppy_false.i.cil', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('kbfiltr_false.i.cil', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('parport_true.i.cil', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('parport_false.i.cil', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2) ] def red(text): @@ -23,37 +27,45 @@ def red(text): def green(text): return '\033[0;32m' + text + '\033[0m' -def runtests(): +def runtests(verifier): passed = failed = 0 for test in tests: - + for mem in ['no-reuse', 'no-reuse-impls', 'reuse']: - - print "{0:>25} {1:>16}:".format(test[0], "(" + mem + ")"), + + print "{0:>25} {1:>16}:".format(test.name, "(" + mem + ")"), # invoke SMACK t0 = time.time() - p = subprocess.Popen(['smackverify.py', test[0] + '.c', '--verifier=boogie-inline', - '--mem-mod=' + mem, '--clang=-w', '-o', test[0] +'.bpl'], + p = subprocess.Popen(['smackverify.py', test.name + '.c', '--verifier=' + verifier, + '--unroll=' + str(test.unroll), '--mem-mod=' + mem, '-o', test.name +'.bpl'], stdout=subprocess.PIPE) - + smackOutput = p.communicate()[0] elapsed = time.time() - t0 # check SMACK output - if re.search(test[1], smackOutput): + if re.search(getattr(test, verifier), smackOutput): print green('PASSED') + ' [%.2fs]' % round(elapsed, 2) passed += 1 else: print red('FAILED') failed += 1 - + return passed, failed if __name__ == '__main__': - passed, failed = runtests() + # parse command line arguments + parser = argparse.ArgumentParser(description='Runs regressions in this folder.') + parser.add_argument('--verifier', dest='verifier', choices=['boogie', 'corral', 'duality'], default=['corral'], nargs='*', + help='choose verifiers to be used') + args = parser.parse_args() - print '\nPASSED count: ', passed - print 'FAILED count: ', failed + for verifier in args.verifier: + print '\nRunning regressions using', verifier + passed, failed = runtests(verifier) + + print '\nPASSED count: ', passed + print 'FAILED count: ', failed diff --git a/include/assistDS/DataStructureCallGraph.h b/include/assistDS/DataStructureCallGraph.h index 67e66609b..b204a1d84 100644 --- a/include/assistDS/DataStructureCallGraph.h +++ b/include/assistDS/DataStructureCallGraph.h @@ -25,7 +25,7 @@ namespace llvm { -class DataStructureCallGraph : public CallGraph { +class DataStructureCallGraph : public CallGraphWrapperPass { // Root is root of the call graph, or the external node if a 'main' function // couldn't be found. CallGraphNode *Root; @@ -61,7 +61,7 @@ class DataStructureCallGraph : public CallGraph { OS << "<>\n"; } - CallGraph::print(OS, 0); + CallGraphWrapperPass::print(OS, 0); } virtual void releaseMemory() { @@ -73,7 +73,7 @@ class DataStructureCallGraph : public CallGraph { // override this to adjust the this pointer as needed for the specified pass // info. virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { - if (PI == &CallGraph::ID) + if (PI == &CallGraphAnalysis::ID) return (CallGraph*)this; return this; } @@ -95,11 +95,11 @@ class DataStructureCallGraph : public CallGraph { virtual void destroy() { // CallsExternalNode is not in the function map, delete it explicitly. if (CallsExternalNode) { - CallsExternalNode->allReferencesDropped(); + // CallsExternalNode->allReferencesDropped(); FIXME FIXME FIXME FIXME delete CallsExternalNode; CallsExternalNode = 0; } - CallGraph::releaseMemory(); + CallGraphWrapperPass::releaseMemory(); } }; diff --git a/include/assistDS/Devirt.h b/include/assistDS/Devirt.h index ee386aca9..0dba3ac81 100644 --- a/include/assistDS/Devirt.h +++ b/include/assistDS/Devirt.h @@ -21,7 +21,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/InstVisitor.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/IR/DataLayout.h" using namespace llvm; @@ -41,7 +41,7 @@ namespace llvm { dsa::CallTargetFinder *CTF; // Access to the target data analysis pass - DataLayout * TD; + const DataLayout * TD; // Worklist of call sites to transform std::vector Worklist; @@ -63,7 +63,7 @@ namespace llvm { virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired >(); - AU.addRequired(); + AU.addRequired(); } // Visitor methods for analyzing instructions diff --git a/include/assistDS/Int2PtrCmp.h b/include/assistDS/Int2PtrCmp.h index eca1d42a9..414b2ed0d 100644 --- a/include/assistDS/Int2PtrCmp.h +++ b/include/assistDS/Int2PtrCmp.h @@ -26,13 +26,13 @@ namespace llvm { // class Int2PtrCmp : public ModulePass { private: - DataLayout * TD; + const DataLayout * TD; public: static char ID; Int2PtrCmp() : ModulePass(ID) {} virtual bool runOnModule(Module& M); virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); } }; diff --git a/include/assistDS/SimplifyGEP.h b/include/assistDS/SimplifyGEP.h index 12a77979e..550150997 100644 --- a/include/assistDS/SimplifyGEP.h +++ b/include/assistDS/SimplifyGEP.h @@ -22,13 +22,13 @@ namespace llvm { // class SimplifyGEP : public ModulePass { private: - DataLayout * TD; + const DataLayout * TD; public: static char ID; SimplifyGEP() : ModulePass(ID) {} virtual bool runOnModule(Module& M); virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); } }; } diff --git a/include/assistDS/TypeChecks.h b/include/assistDS/TypeChecks.h index 279edd256..92de3b6ff 100644 --- a/include/assistDS/TypeChecks.h +++ b/include/assistDS/TypeChecks.h @@ -20,8 +20,8 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Function.h" #include "llvm/Pass.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Analysis/Dominators.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Dominators.h" #include "llvm/Analysis/LoopInfo.h" #include @@ -49,7 +49,7 @@ class TypeChecks : public ModulePass { std::map BitCast_MD_Map; // Analysis from other passes. - DataLayout *TD; + const DataLayout *TD; AddressTakenAnalysis* addrAnalysis; unsigned int getTypeMarker(Type*); @@ -100,8 +100,8 @@ class TypeChecks : public ModulePass { virtual void print(raw_ostream &OS, const Module *M) const; virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.addRequired(); + AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.addRequired(); } diff --git a/include/assistDS/TypeChecksOpt.h b/include/assistDS/TypeChecksOpt.h index b2ae7415c..0bf0e5dda 100644 --- a/include/assistDS/TypeChecksOpt.h +++ b/include/assistDS/TypeChecksOpt.h @@ -19,7 +19,7 @@ #include "llvm/Pass.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Instructions.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" #include diff --git a/include/dsa/CallTargets.h b/include/dsa/CallTargets.h index 344cc54d0..7130340d7 100644 --- a/include/dsa/CallTargets.h +++ b/include/dsa/CallTargets.h @@ -16,7 +16,7 @@ #define LLVM_ANALYSIS_CALLTARGETS_H #include "llvm/Pass.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" #include "dsa/DataStructure.h" #include diff --git a/include/dsa/DSCallGraph.h b/include/dsa/DSCallGraph.h index 062bea6da..b39a662f3 100644 --- a/include/dsa/DSCallGraph.h +++ b/include/dsa/DSCallGraph.h @@ -19,7 +19,7 @@ #include #include "llvm/ADT/EquivalenceClasses.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" #include #include diff --git a/include/dsa/DSSupport.h b/include/dsa/DSSupport.h index d233bb060..8d58bb434 100644 --- a/include/dsa/DSSupport.h +++ b/include/dsa/DSSupport.h @@ -20,7 +20,7 @@ #include #include "llvm/ADT/DenseSet.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" namespace llvm { diff --git a/include/dsa/DataStructure.h b/include/dsa/DataStructure.h index d27085a98..bd2be4871 100644 --- a/include/dsa/DataStructure.h +++ b/include/dsa/DataStructure.h @@ -22,7 +22,7 @@ #include "llvm/Pass.h" #include "llvm/IR/DataLayout.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" #include "llvm/ADT/EquivalenceClasses.h" #include "llvm/ADT/DenseSet.h" @@ -45,7 +45,7 @@ class DataStructures : public ModulePass { typedef std::map DSInfoTy; /// DataLayout, comes in handy - DataLayout* TD; + const DataLayout* TD; /// Pass to get Graphs from DataStructures* GraphSource; @@ -87,7 +87,7 @@ class DataStructures : public ModulePass { std::vector GlobalFunctionList; void init(DataStructures* D, bool clone, bool useAuxCalls, bool copyGlobalAuxCalls, bool resetAux); - void init(DataLayout* T); + void init(const DataLayout* T); void formGlobalECs(); @@ -139,7 +139,7 @@ class DataStructures : public ModulePass { EquivalenceClasses &getGlobalECs() { return GlobalECs; } - DataLayout& getDataLayout() const { return *TD; } + const DataLayout& getDataLayout() const { return *TD; } const DSCallGraph& getCallGraph() const { return callgraph; } @@ -165,7 +165,7 @@ class BasicDataStructures : public DataStructures { /// getAnalysisUsage - This obviously provides a data structure graph. /// virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); AU.setPreservesAll(); } }; @@ -188,7 +188,7 @@ class LocalDataStructures : public DataStructures { /// getAnalysisUsage - This obviously provides a data structure graph. /// virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.setPreservesAll(); } diff --git a/include/dsa/TypeSafety.h b/include/dsa/TypeSafety.h index ee0740250..3317997b2 100644 --- a/include/dsa/TypeSafety.h +++ b/include/dsa/TypeSafety.h @@ -49,7 +49,7 @@ struct TypeSafety : public ModulePass { bool typeFieldsOverlap (const DSNode * N); // Pointers to prerequisite passes - DataLayout * TD; + const DataLayout * TD; dsa * dsaPass; // Data structures @@ -65,7 +65,7 @@ struct TypeSafety : public ModulePass { } virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.setPreservesAll(); } diff --git a/include/smack/BoogieAst.h b/include/smack/BoogieAst.h index 62b52a575..e6ce71cda 100644 --- a/include/smack/BoogieAst.h +++ b/include/smack/BoogieAst.h @@ -1,6 +1,4 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // #ifndef BOOGIEAST_H @@ -15,12 +13,13 @@ namespace smack { using namespace std; -class Block; class Program; class Expr { public: virtual void print(ostream& os) const = 0; + static const Expr* exists(string v, string t, const Expr* e); + static const Expr* forall(string v, string t, const Expr* e); static const Expr* and_(const Expr* l, const Expr* r); static const Expr* cond(const Expr* c, const Expr* t, const Expr* e); static const Expr* eq(const Expr* l, const Expr* r); @@ -28,6 +27,7 @@ class Expr { static const Expr* fn(string f, const Expr* x); static const Expr* fn(string f, const Expr* x, const Expr* y); static const Expr* fn(string f, const Expr* x, const Expr* y, const Expr* z); + static const Expr* fn(string f, vector args); static const Expr* id(string x); static const Expr* impl(const Expr* l, const Expr* r); static const Expr* lit(int i); @@ -100,10 +100,13 @@ class NotExpr : public Expr { class QuantExpr : public Expr { public: - enum Quantifier { Forall, Exists }; + enum Quantifier { Exists, Forall }; private: - Quantifier q; + Quantifier quant; + vector< pair > vars; + const Expr* expr; public: + QuantExpr(Quantifier q, vector< pair > vs, const Expr* e) : quant(q), vars(vs), expr(e) {} void print(ostream& os) const; }; @@ -181,6 +184,7 @@ class Stmt { static const Stmt* assume(const Expr* e, const Attr* attr); static const Stmt* call(string p); static const Stmt* call(string p, const Expr* x); + static const Stmt* call(string p, const Expr* x, const Attr* attr); static const Stmt* call(string p, const Expr* x, string r); static const Stmt* call(string p, const Expr* x, const Expr* y, string r); static const Stmt* call(string p, vector ps); @@ -193,6 +197,7 @@ class Stmt { static const Stmt* goto_(vector ts); static const Stmt* havoc(string x); static const Stmt* return_(); + static const Stmt* return_(const Expr* e); static const Stmt* skip(); static const Stmt* code(string s); virtual void print(ostream& os) const = 0; @@ -258,8 +263,9 @@ class HavocStmt : public Stmt { }; class ReturnStmt : public Stmt { + const Expr* expr; public: - ReturnStmt() {} + ReturnStmt(const Expr* e = nullptr) : expr(e) {} void print(ostream& os) const; }; @@ -285,9 +291,11 @@ class Decl { unsigned getId() const { return id; } string getName() const { return name; } virtual kind getKind() const = 0; + void addAttr(const Attr* a) { attrs.push_back(a); } static Decl* typee(string name, string type); static Decl* axiom(const Expr* e); + static Decl* function(string name, vector< pair > args, string type, const Expr* e); static Decl* constant(string name, string type); static Decl* constant(string name, string type, bool unique); static Decl* constant(string name, string type, vector ax, bool unique); @@ -341,8 +349,9 @@ class FuncDecl : public Decl { string type; const Expr* body; public: - FuncDecl(string n, vector< pair > ps, string t, Expr* b) - : Decl(n), params(ps), type(t), body(b) {} + FuncDecl(string n, vector ax, vector< pair > ps, + string t, const Expr* b) + : Decl(n,ax), params(ps), type(t), body(b) {} kind getKind() const { return FUNC; } void print(ostream& os) const; }; @@ -355,20 +364,72 @@ class VarDecl : public Decl { void print(ostream& os) const; }; -class ProcDecl : public Decl { +class Block { + string name; + vector stmts; +public: + Block() : name("") {} + Block(string n) : name(n) {} + void print(ostream& os) const; + void insert(const Stmt* s) { + stmts.insert(stmts.begin(), s); + } + void addStmt(const Stmt* s) { + stmts.push_back(s); + } + string getName() { + return name; + } +}; + +class CodeContainer { +protected: Program& prog; + set decls; + vector blocks; + vector mods; + CodeContainer(Program& p) : prog(p) {} +public: + Program& getProg() const { + return prog; + } + void addDecl(Decl* d) { + decls.insert(d); + } + void insert(const Stmt* s) { + blocks.front()->insert(s); + } + void addBlock(Block* b) { + blocks.push_back(b); + } + bool hasBody() { + return decls.size() > 0 || blocks.size() > 0; + } + void addMod(string m) { + mods.push_back(m); + } + void addMods(vector ms) { + for (unsigned i = 0; i < ms.size(); i++) + addMod(ms[i]); + } + virtual bool isProc() { return false; } +}; + +class CodeExpr : public Expr, public CodeContainer { +public: + CodeExpr(Program& p) : CodeContainer(p) {} + void print(ostream& os) const; +}; + +class ProcDecl : public Decl, public CodeContainer { vector< pair > params; vector< pair > rets; - vector mods; vector requires; vector ensures; - set decls; - vector blocks; public: ProcDecl(Program& p, string n, vector< pair > ps, vector< pair > rs) - : Decl(n), prog(p), params(ps), rets(rs) {} + : Decl(n), CodeContainer(p), params(ps), rets(rs) {} kind getKind() const { return PROC; } - Program& getProg() const { return prog; } void addParam(string x, string t) { params.push_back(make_pair(x, t)); } @@ -378,28 +439,13 @@ class ProcDecl : public Decl { vector< pair > getRets() { return rets; } - void addMod(string m) { - mods.push_back(m); - } - void addMods(vector ms) { - for (unsigned i = 0; i < ms.size(); i++) - addMod(ms[i]); - } void addRequires(const Expr* e) { requires.push_back(e); } void addEnsures(const Expr* e) { ensures.push_back(e); } - void addDecl(Decl* d) { - decls.insert(d); - } - void addBlock(Block* b) { - blocks.push_back(b); - } - bool hasBody() { - return decls.size() > 0 || blocks.size() > 0; - } + bool isProc() { return true; } void print(ostream& os) const; }; @@ -410,23 +456,6 @@ class CodeDecl : public Decl { void print(ostream& os) const; }; -class Block { - ProcDecl& proc; - string name; - vector stmts; -public: - Block(ProcDecl& p) : proc(p), name("") {} - Block(ProcDecl& p, string n) : proc(p), name(n) {} - void print(ostream& os) const; - ProcDecl& getProc() const { return proc; } - void addStmt(const Stmt* s) { - stmts.push_back(s); - } - string getName() { - return name; - } -}; - class Program { // TODO While I would prefer that a program is just a set or sequence of // declarations, putting the Prelude in a CodeDeclaration does not work, diff --git a/include/smack/BplFilePrinter.h b/include/smack/BplFilePrinter.h index 4e28b8291..0e2415580 100644 --- a/include/smack/BplFilePrinter.h +++ b/include/smack/BplFilePrinter.h @@ -1,6 +1,4 @@ // -// Copyright (c) 2008 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Pantazis Deligiannis (p.deligiannis@imperial.ac.uk) // This file is distributed under the MIT License. See LICENSE for details. // #ifndef BPLFILEPRINTER_H diff --git a/include/smack/BplPrinter.h b/include/smack/BplPrinter.h index 833a04ae7..2979c97a9 100644 --- a/include/smack/BplPrinter.h +++ b/include/smack/BplPrinter.h @@ -1,5 +1,4 @@ // -// Copyright (c) 2008 Zvonimir Rakamaric (zvonimir@cs.utah.edu) // This file is distributed under the MIT License. See LICENSE for details. // #ifndef BPLPRINTER_H diff --git a/include/smack/Contracts.h b/include/smack/Contracts.h new file mode 100644 index 000000000..4d36251b0 --- /dev/null +++ b/include/smack/Contracts.h @@ -0,0 +1,37 @@ +// +// This file is distributed under the MIT License. See LICENSE for details. +// + +#include "llvm/IR/InstVisitor.h" +#include "llvm/IR/CFG.h" +#include "smack/Slicing.h" +#include "smack/SmackRep.h" +#include "smack/SmackInstGenerator.h" +#include "smack/BoogieAst.h" + +namespace smack { +using namespace llvm; + +class ContractsExtractor : public InstVisitor { +private: + SmackRep& rep; + ProcDecl& proc; + Naming& naming; + Slices& slices; + static unsigned uniqueSliceId; + +public: + ContractsExtractor(SmackRep& R, ProcDecl& P, Naming& N, Slices& S) + : rep(R), proc(P), naming(N), slices(S) {} + + void visitCallInst(CallInst& ci); + +private: + Slice* extractSlice(Value* v); + + Value* sliceIdx(LLVMContext& ctx) { + return ConstantInt::get(Type::getInt32Ty(ctx),slices.size()); + } +}; + +} diff --git a/include/smack/DSAAliasAnalysis.h b/include/smack/DSAAliasAnalysis.h index bec471ab1..218e70cb4 100644 --- a/include/smack/DSAAliasAnalysis.h +++ b/include/smack/DSAAliasAnalysis.h @@ -15,16 +15,16 @@ #ifndef LLVM_ANALYSIS_DATA_STRUCTURE_AA_H #define LLVM_ANALYSIS_DATA_STRUCTURE_AA_H -#include "llvm/InstVisitor.h" +#include "assistDS/DSNodeEquivs.h" +#include "dsa/DataStructure.h" +#include "dsa/DSGraph.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/Passes.h" +#include "llvm/ADT/EquivalenceClasses.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/IR/Module.h" -#include "dsa/DataStructure.h" -#include "dsa/DSGraph.h" - -#include "assistDS/DSNodeEquivs.h" namespace smack { @@ -95,6 +95,7 @@ class DSAAliasAnalysis : public llvm::ModulePass, public llvm::AliasAnalysis { llvm::DSNode *getNode(const llvm::Value* v); bool isAlloced(const llvm::Value* v); bool isExternal(const llvm::Value* v); + bool isSingletonGlobal(const llvm::Value *V); virtual AliasResult alias(const Location &LocA, const Location &LocB); diff --git a/include/smack/Naming.h b/include/smack/Naming.h new file mode 100644 index 000000000..14efdfab6 --- /dev/null +++ b/include/smack/Naming.h @@ -0,0 +1,53 @@ +// +// This file is distributed under the MIT License. See LICENSE for details. +// + +#ifndef NAMING_H +#define NAMING_H + +#include "llvm/Support/Regex.h" +#include "llvm/IR/Value.h" +#include +#include + +namespace smack { + +using namespace std; +using llvm::Regex; +using llvm::Value; + +class Naming { + static Regex BPL_KW; + static Regex SMACK_NAME; + + typedef map NameMap; + stack nameStack; + unsigned blockNum; + unsigned varNum; + +public: + static const string BLOCK_LBL; + static const string RET_VAR; + static const string EXN_VAR; + static const string EXN_VAL_VAR; + static const string BOOL_VAR; + static const string FLOAT_VAR; + static const string PTR_VAR; + static const string UNDEF_SYM; + + Naming() : blockNum(0), varNum(0) { } + void enter(); + void leave(); + string get(const Value& V); + string freshBlockName(); + string freshVarName(const Value& V); + + static bool isBplKeyword(string s); + static bool isSmackName(string s); + static bool isSmackGeneratedName(string s); + static string escape(string s); +}; + +} + +#endif diff --git a/include/smack/Slicing.h b/include/smack/Slicing.h new file mode 100644 index 000000000..26879e58b --- /dev/null +++ b/include/smack/Slicing.h @@ -0,0 +1,47 @@ +// +// This file is distributed under the MIT License. See LICENSE for details. +// + +#ifndef SLICING_H +#define SLICING_H + +#include "llvm/IR/InstVisitor.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "smack/BoogieAst.h" +#include "smack/Naming.h" +#include "smack/SmackRep.h" +#include + +using namespace std; +using namespace llvm; + +namespace smack { + +class Slice; +typedef vector Slices; + +class Slice { + Value& value; + BasicBlock& block; + Function& function; + LLVMContext& context; + Slices& slices; + string name; + + unordered_set inputs; + unordered_set values; + +public: + Slice(Instruction& I, Slices& S, string name = ""); + + void remove(); + + string getName(); + const Expr* getCode(Naming& naming, SmackRep& rep); + const Decl* getBoogieDecl(Naming& naming, SmackRep& rep); + const Expr* getBoogieExpression(Naming& naming, SmackRep& rep); +}; + +} + +#endif diff --git a/include/smack/SmackInstGenerator.h b/include/smack/SmackInstGenerator.h index 3aa99ad67..38a466b9b 100644 --- a/include/smack/SmackInstGenerator.h +++ b/include/smack/SmackInstGenerator.h @@ -1,5 +1,4 @@ // -// Copyright (c) 2008 Zvonimir Rakamaric (zvonimir@cs.utah.edu) // This file is distributed under the MIT License. See LICENSE for details. // #ifndef SMACKINSTVISITOR_H @@ -7,62 +6,84 @@ #include "smack/BoogieAst.h" #include "smack/SmackRep.h" -#include "llvm/InstVisitor.h" +#include "smack/Naming.h" +#include "smack/Slicing.h" +#include "llvm/IR/InstVisitor.h" +#include #include namespace smack { - + +typedef vector Slices; + class SmackInstGenerator : public llvm::InstVisitor { private: SmackRep& rep; - ProcDecl& proc; + CodeContainer& proc; + Naming& naming; + Slices& slices; + Block* currBlock; - map& blockMap; - int blockNum; - int varNum; + map blockMap; + map sourceNames; + + Block* createBlock(); + Block* getBlock(llvm::BasicBlock* bb); void generatePhiAssigns(llvm::TerminatorInst& i); void generateGotoStmts(llvm::Instruction& i, - vector > target); + vector > target); void processInstruction(llvm::Instruction& i); void nameInstruction(llvm::Instruction& i); void annotate(llvm::Instruction& i, Block* b); -public: - SmackInstGenerator(SmackRep& r, ProcDecl& p, - map& bm) - : rep(r), proc(p), - blockMap(bm), blockNum(0), varNum(0) {} + void addDecl(Decl* d) { proc.addDecl(d); } + void addMod(string x) { proc.addMod(x); } + void addTopDecl(Decl* d) { proc.getProg().addDecl(d); } + void addBlock(Block* b) { proc.addBlock(b); } - Block* createBlock(); - void setCurrBlock(Block* b) { - currBlock = b; - } - Block* getCurrBlock() { - return currBlock; +public: + void emit(const Stmt* s) { + // stringstream str; + // s->print(str); + // DEBUG(llvm::errs() << "emit: " << str.str() << "\n"); + currBlock->addStmt(s); } - string createVar(); +public: + SmackInstGenerator(SmackRep& R, CodeContainer& P, Naming& N, Slices& S) + : rep(R), proc(P), naming(N), slices(S) {} + Slice* getSlice(llvm::Value* V) { + using namespace llvm; + if (ConstantInt* CI = dyn_cast(V)) { + uint64_t i = CI->getLimitedValue(); + assert(slices.size() > i && "Did not find expression."); + return slices[i]; + } + assert(false && "Unexpected value."); + } + + void visitBasicBlock(llvm::BasicBlock& bb); void visitInstruction(llvm::Instruction& i); void visitReturnInst(llvm::ReturnInst& i); void visitBranchInst(llvm::BranchInst& i); void visitSwitchInst(llvm::SwitchInst& i); // TODO implement indirectbr - // TODO implement invoke - // TODO implement resume + void visitInvokeInst(llvm::InvokeInst& i); + void visitResumeInst(llvm::ResumeInst& i); void visitUnreachableInst(llvm::UnreachableInst& i); - void visitBinaryOperator(llvm::BinaryOperator& i); + void visitBinaryOperator(llvm::BinaryOperator& I); // TODO implement extractelement // TODO implement insertelement // TODO implement shufflevector - // TODO implement extractvalue - // TODO implement insertvalue + void visitExtractValueInst(llvm::ExtractValueInst& i); + void visitInsertValueInst(llvm::InsertValueInst& i); void visitAllocaInst(llvm::AllocaInst& i); void visitLoadInst(llvm::LoadInst& i); @@ -72,27 +93,14 @@ class SmackInstGenerator : public llvm::InstVisitor { void visitAtomicRMWInst(llvm::AtomicRMWInst& i); void visitGetElementPtrInst(llvm::GetElementPtrInst& i); - void visitTruncInst(llvm::TruncInst& i); - void visitZExtInst(llvm::ZExtInst& i); - void visitSExtInst(llvm::SExtInst& i); - void visitFPTruncInst(llvm::FPTruncInst& i); - void visitFPExtInst(llvm::FPExtInst& i); - void visitFPToUIInst(llvm::FPToUIInst& i); - void visitFPToSIInst(llvm::FPToSIInst& i); - void visitUIToFPInst(llvm::UIToFPInst& i); - void visitSIToFPInst(llvm::SIToFPInst& i); - void visitPtrToIntInst(llvm::PtrToIntInst& i); - void visitIntToPtrInst(llvm::IntToPtrInst& i); - void visitBitCastInst(llvm::BitCastInst& i); - // TODO implement addrspacecast - - void visitICmpInst(llvm::ICmpInst& i); - void visitFCmpInst(llvm::FCmpInst& i); + void visitCastInst(llvm::CastInst& I); + void visitCmpInst(llvm::CmpInst& I); + void visitPHINode(llvm::PHINode& i); void visitSelectInst(llvm::SelectInst& i); void visitCallInst(llvm::CallInst& i); // TODO implement va_arg - // TODO landingpad + void visitLandingPadInst(llvm::LandingPadInst& i); void visitMemCpyInst(llvm::MemCpyInst& i); void visitMemSetInst(llvm::MemSetInst& i); diff --git a/include/smack/SmackModuleGenerator.h b/include/smack/SmackModuleGenerator.h index 19fcafb24..2d40d8964 100644 --- a/include/smack/SmackModuleGenerator.h +++ b/include/smack/SmackModuleGenerator.h @@ -1,5 +1,4 @@ // -// Copyright (c) 2008 Zvonimir Rakamaric (zvonimir@cs.utah.edu) // This file is distributed under the MIT License. See LICENSE for details. // #ifndef SMACKMODULEGENERATOR_H @@ -10,7 +9,7 @@ #include "smack/DSAAliasAnalysis.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/IR/DataLayout.h" -#include "llvm/Support/CFG.h" +#include "llvm/IR/CFG.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/GraphWriter.h" @@ -33,17 +32,16 @@ class SmackModuleGenerator : public llvm::ModulePass { virtual void getAnalysisUsage(llvm::AnalysisUsage& AU) const { AU.setPreservesAll(); - AU.addRequired(); + AU.addRequired(); AU.addRequired(); } virtual bool runOnModule(llvm::Module& m) { - SmackRep* rep = new SmackRep(&getAnalysis()); - generateProgram(m,rep); + generateProgram(m); return false; } - void generateProgram(llvm::Module& m, SmackRep* rep); + void generateProgram(llvm::Module& m); Program& getProgram() { return program; diff --git a/include/smack/SmackOptions.h b/include/smack/SmackOptions.h index a980ef592..3c781ceb3 100644 --- a/include/smack/SmackOptions.h +++ b/include/smack/SmackOptions.h @@ -1,6 +1,4 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // diff --git a/include/smack/SmackRep.h b/include/smack/SmackRep.h index 6d64c429f..635b2005a 100644 --- a/include/smack/SmackRep.h +++ b/include/smack/SmackRep.h @@ -1,19 +1,18 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // #ifndef SMACKREP_H #define SMACKREP_H +#include "smack/Naming.h" #include "smack/BoogieAst.h" #include "smack/SmackOptions.h" #include "smack/DSAAliasAnalysis.h" -#include "llvm/InstVisitor.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InstrTypes.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/Regex.h" #include @@ -28,11 +27,6 @@ using namespace std; class SmackRep { public: - static const string BLOCK_LBL; - static const string RET_VAR; - static const string BOOL_VAR; - static const string FLOAT_VAR; - static const string PTR_VAR; static const string BOOL_TYPE; static const string FLOAT_TYPE; static const string NULL_VAL; @@ -42,77 +36,9 @@ class SmackRep { static const string FREE; static const string MEMCPY; - static const string PTR; - static const string OBJ; - static const string OFF; - static const string PA; - - static const string FP; - - static const string TRUNC; - static const string B2P; - static const string I2P; - static const string P2I; static const string I2B; static const string B2I; - - static const string FP2SI; - static const string FP2UI; - static const string SI2FP; - static const string UI2FP; - - static const string ADD; - static const string SUB; - static const string MUL; - static const string SDIV; - static const string UDIV; - static const string SREM; - static const string UREM; - static const string AND; - static const string OR; - static const string XOR; - static const string LSHR; - static const string ASHR; - static const string SHL; - - static const string FADD; - static const string FSUB; - static const string FMUL; - static const string FDIV; - static const string FREM; - - static const string SGE; - static const string UGE; - static const string SLE; - static const string ULE; - static const string SLT; - static const string ULT; - static const string SGT; - static const string UGT; - - static const string NAND; - static const string MAX; - static const string MIN; - static const string UMAX; - static const string UMIN; - - static const string FFALSE; - static const string FOEQ; - static const string FOGE; - static const string FOGT; - static const string FOLE; - static const string FOLT; - static const string FONE; - static const string FORD; - static const string FTRUE; - static const string FUEQ; - static const string FUGE; - static const string FUGT; - static const string FULE; - static const string FULT; - static const string FUNE; - static const string FUNO; static const string MEM_OP; static const string REC_MEM_OP; @@ -127,23 +53,34 @@ class SmackRep { protected: DSAAliasAnalysis* aliasAnalysis; + Naming& naming; + Program& program; vector bplGlobals; - vector< pair > memoryRegions; + + struct Region { + const llvm::Value* representative; + bool isAllocated; + bool isSingletonGlobal; + Region(const llvm::Value* r, bool a, bool s) : + representative(r), isAllocated(a), isSingletonGlobal(s) {} + }; + + vector memoryRegions; const llvm::DataLayout* targetData; - Program* program; int globalsBottom; vector staticInits; unsigned uniqueFpNum; - unsigned uniqueUndefNum; public: - SmackRep(DSAAliasAnalysis* aa) - : aliasAnalysis(aa), targetData(aa->getDataLayout()), globalsBottom(0) { + SmackRep(DSAAliasAnalysis* aa, Naming& N, Program& P) + : aliasAnalysis(aa), naming(N), program(P), + targetData(aa->getDataLayout()), globalsBottom(0) { uniqueFpNum = 0; - uniqueUndefNum = 0; - } + } + DSAAliasAnalysis* getAliasAnalysis() { return aliasAnalysis; } + Program& getProgram() { return program; } private: void addInit(unsigned region, const Expr* addr, const llvm::Constant* val); @@ -157,61 +94,58 @@ class SmackRep { const Expr* b2i(const llvm::Value* v); public: - void setProgram(Program* p) { program = p; } - - bool isSmackName(string n); - bool isSmackGeneratedName(string n); - bool isMallocOrFree(llvm::Function* f); - bool isIgnore(llvm::Function* f); + bool isMallocOrFree(const llvm::Function* f); + bool isIgnore(const llvm::Function* f); bool isInt(const llvm::Type* t); bool isInt(const llvm::Value* v); - bool isBool(llvm::Type* t); + bool isBool(const llvm::Type* t); bool isBool(const llvm::Value* v); - bool isFloat(llvm::Type* t); - bool isFloat(llvm::Value* v); + bool isFloat(const llvm::Type* t); + bool isFloat(const llvm::Value* v); unsigned storageSize(llvm::Type* t); unsigned fieldOffset(llvm::StructType* t, unsigned fieldNo); unsigned getRegion(const llvm::Value* v); string memReg(unsigned i); + string memType(unsigned r); bool isExternal(const llvm::Value* v); void collectRegions(llvm::Module &M); - virtual string type(llvm::Type* t); - virtual string type(llvm::Value* v); + virtual string type(const llvm::Type* t); + virtual string type(const llvm::Value* v); const Expr* mem(const llvm::Value* v); const Expr* mem(unsigned region, const Expr* addr); - string id(const llvm::Value* v); - const Expr* undef(); const Expr* lit(const llvm::Value* v); const Expr* lit(unsigned v); const Expr* ptrArith(const llvm::Value* p, vector ps, vector ts); const Expr* expr(const llvm::Value* v); string getString(const llvm::Value* v); - const Expr* op(const llvm::User* v); - const Expr* pred(llvm::CmpInst& ci); - + + string cast2fn(unsigned opcode); + string bop2fn(unsigned opcode); + string armwop2fn(unsigned opcode); + string pred2fn(unsigned predicate); + + const Expr* cast(const llvm::Instruction* I); + const Expr* cast(const llvm::ConstantExpr* CE); + const Expr* cast(unsigned opcode, const llvm::Value* v, const llvm::Type* t); + + const Expr* bop(const llvm::BinaryOperator* BO); + const Expr* bop(const llvm::ConstantExpr* CE); + const Expr* bop(unsigned opcode, const llvm::Value* lhs, const llvm::Value* rhs, const llvm::Type* t); + + const Expr* cmp(const llvm::CmpInst* I); + const Expr* cmp(const llvm::ConstantExpr* CE); + const Expr* cmp(unsigned predicate, const llvm::Value* lhs, const llvm::Value* rhs); + const Expr* arg(llvm::Function* f, unsigned pos, llvm::Value* v); - const Stmt* call(llvm::Function* f, llvm::CallInst& ci); + const Stmt* call(llvm::Function* f, llvm::User& u); string code(llvm::CallInst& ci); ProcDecl* proc(llvm::Function* f, int n); - - virtual const Expr* trunc(const llvm::Value* v, llvm::Type* t); - virtual const Expr* zext(const llvm::Value* v, llvm::Type* t); - virtual const Expr* sext(const llvm::Value* v, llvm::Type* t); - virtual const Expr* fptrunc(const llvm::Value* v, llvm::Type* t); - virtual const Expr* fpext(const llvm::Value* v, llvm::Type* t); - virtual const Expr* fp2ui(const llvm::Value* v); - virtual const Expr* fp2si(const llvm::Value* v); - virtual const Expr* ui2fp(const llvm::Value* v); - virtual const Expr* si2fp(const llvm::Value* v); - virtual const Expr* p2i(const llvm::Value* v); - virtual const Expr* i2p(const llvm::Value* v); - virtual const Expr* bitcast(const llvm::Value* v, llvm::Type* t); virtual const Stmt* alloca(llvm::AllocaInst& i); virtual const Stmt* memcpy(const llvm::MemCpyInst& msi); @@ -239,10 +173,29 @@ class RegionCollector : public llvm::InstVisitor { public: RegionCollector(SmackRep& r) : rep(r) {} - void visitAllocaInst(llvm::AllocaInst& i) { rep.getRegion(&i); } - void visitCallInst(llvm::CallInst& i) { - if (i.getType()->isPointerTy()) - rep.getRegion(&i); + void visitModule(llvm::Module& M) { + for (llvm::Module::const_global_iterator + G = M.global_begin(), E = M.global_end(); G != E; ++G) + rep.getRegion(G); + } + void visitAllocaInst(llvm::AllocaInst& I) { + rep.getRegion(&I); + } + void visitLoadInst(llvm::LoadInst& I) { + rep.getRegion(I.getPointerOperand()); + } + void visitStoreInst(llvm::StoreInst& I) { + rep.getRegion(I.getPointerOperand()); + } + void visitAtomicCmpXchgInst(llvm::AtomicCmpXchgInst &I) { + rep.getRegion(I.getPointerOperand()); + } + void visitAtomicRMWInst(llvm::AtomicRMWInst &I) { + rep.getRegion(I.getPointerOperand()); + } + void visitCallInst(llvm::CallInst& I) { + if (I.getType()->isPointerTy()) + rep.getRegion(&I); } }; diff --git a/include/smack/SmackRepFlatMem.h b/include/smack/SmackRepFlatMem.h index efbd551a3..b196a070d 100644 --- a/include/smack/SmackRepFlatMem.h +++ b/include/smack/SmackRepFlatMem.h @@ -1,6 +1,4 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // #ifndef SMACKREPFLATMEM_H diff --git a/include/smack/prelude-bv.bpl b/include/smack/prelude-bv.bpl deleted file mode 100644 index 1ed5fe594..000000000 --- a/include/smack/prelude-bv.bpl +++ /dev/null @@ -1,128 +0,0 @@ -// SMACK-PRELUDE-BEGIN - -// SMACK Memory Model - -type $ref; -type $ptr; - -function $ptr($ref, int) returns ($ptr); -function $static($ref) returns (bool); -function $size($ref) returns (bv32); -function $obj($ptr) returns ($ref); -function $off($ptr) returns (bv32); - -axiom(forall x:$ptr :: {$obj(x)}{$off(x)} x == $ptr($obj(x), $off(x))); -axiom(forall x_obj:$ref, x_off:bv32 :: {$ptr(x_obj, x_off)} x_obj == $obj($ptr(x_obj, x_off))); -axiom(forall x_obj:$ref, x_off:bv32 :: {$ptr(x_obj, x_off)} x_off == $off($ptr(x_obj, x_off))); - -type $name; -const unique $UNALLOCATED: $name; -const unique $ALLOCATED: $name; -var $Mem: [$ptr] $ptr; -var $Alloc: [$ref] $name; -const unique $NULL: $ref; -axiom $static($NULL); -const $UNDEF: $ptr; - -procedure $alloca(obj_size: bv32) returns (new:$ptr); -modifies $Alloc; -ensures old($Alloc)[$obj(new)] == $UNALLOCATED && $Alloc[$obj(new)] == $ALLOCATED; -ensures !$static($obj(new)); -ensures $off(new) == 0bv32; -ensures $size($obj(new)) == obj_size; -ensures (forall x_obj:$ref :: {$Alloc[x_obj]} x_obj == $obj(new) || old($Alloc)[x_obj] == $Alloc[x_obj]); - -procedure $malloc(obj_size: bv32) returns (new:$ptr); -modifies $Alloc; -ensures old($Alloc)[$obj(new)] == $UNALLOCATED && $Alloc[$obj(new)] == $ALLOCATED; -ensures !$static($obj(new)); -ensures $off(new) == 0bv32; -ensures $size($obj(new)) == obj_size; -ensures (forall x_obj:$ref :: {$Alloc[x_obj]} x_obj == $obj(new) || old($Alloc)[x_obj] == $Alloc[x_obj]); - -procedure $free(pointer: $ptr); -modifies $Alloc; -requires $Alloc[$obj(pointer)] == $ALLOCATED; -// requires !$static($obj(pointer)); -requires $off(pointer) == 0bv32; -ensures $Alloc[$obj(pointer)] != $UNALLOCATED; -ensures (forall x:$ref :: {$Alloc[x]} $obj(pointer) == x || old($Alloc)[x] == $Alloc[x]); - -// SMACK Arithmetic Predicates - -function {:bvbuiltin "bvadd"} $add(p1:bv32, p2:bv32) returns (bv32); -function {:bvbuiltin "bvsub"} $sub(p1:bv32, p2:bv32) returns (bv32); -function {:bvbuiltin "bvmul"} $mul(p1:bv32, p2:bv32) returns (bv32); -function $sdiv(p1:bv32, p2:bv32) returns (bv32); -function $udiv(p1:bv32, p2:bv32) returns (bv32); -function $srem(p1:bv32, p2:bv32) returns (bv32); -function $urem(p1:bv32, p2:bv32) returns (bv32); -function $and(p1:bv32, p2:bv32) returns (bv32); -function $or(p1:bv32, p2:bv32) returns (bv32); -function $xor(p1:bv32, p2:bv32) returns (bv32); -function $lshr(p1:bv32, p2:bv32) returns (bv32); -function $ashr(p1:bv32, p2:bv32) returns (bv32); -function $shl(p1:bv32, p2:bv32) returns (bv32); -function {:bvbuiltin "bvult"} $ult(p1:bv32, p2:bv32) returns (bool); -function {:bvbuiltin "bvugt"} $ugt(p1:bv32, p2:bv32) returns (bool); -function {:bvbuiltin "bvule"} $ule(p1:bv32, p2:bv32) returns (bool); -function {:bvbuiltin "bvuge"} $uge(p1:bv32, p2:bv32) returns (bool); -function {:bvbuiltin "bvslt"} $slt(p1:bv32, p2:bv32) returns (bool); -function {:bvbuiltin "bvsgt"} $sgt(p1:bv32, p2:bv32) returns (bool); -function {:bvbuiltin "bvsle"} $sle(p1:bv32, p2:bv32) returns (bool); -function {:bvbuiltin "bvsge"} $sge(p1:bv32, p2:bv32) returns (bool); - -function $pa(pointer: $ptr, offset: bv32, size: bv32) returns ($ptr); -function $trunc(p:$ptr) returns ($ptr); -function $p2i(p: $ptr) returns ($ptr); -function $i2p(p: $ptr) returns ($ptr); -function $p2b(p: $ptr) returns (bool); -function $b2p(b: bool) returns ($ptr); -function $i2b(i: bv32) returns (bool); -function $b2i(b: bool) returns (bv32); - -// SMACK Arithmetic Axioms - -axiom $and(0bv32,0bv32) == 0bv32; -axiom $and(0bv32,1bv32) == 0bv32; -axiom $and(1bv32,0bv32) == 0bv32; -axiom $and(1bv32,1bv32) == 1bv32; - -axiom $or(0bv32,0bv32) == 0bv32; -axiom $or(0bv32,1bv32) == 1bv32; -axiom $or(1bv32,0bv32) == 1bv32; -axiom $or(1bv32,1bv32) == 1bv32; - -axiom $xor(0bv32,0bv32) == 0bv32; -axiom $xor(0bv32,1bv32) == 1bv32; -axiom $xor(1bv32,0bv32) == 1bv32; -axiom $xor(1bv32,1bv32) == 0bv32; - -axiom (forall p:$ptr, o:bv32, s:bv32 :: {$pa(p,o,s)} $pa(p,o,s) == $ptr($obj(p), $off(p) + o * s)); -axiom (forall p:$ptr, o:bv32, s:bv32 :: {$pa(p,o,s)} $obj($pa(p,o,s)) == $obj(p)); -axiom (forall p:$ptr :: $trunc(p) == p); - -axiom $b2i(true) == 1bv32; -axiom $b2i(false) == 0bv32; -axiom $b2p(true) == $ptr($NULL,1bv32); -axiom $b2p(false) == $ptr($NULL,0bv32); - -axiom (forall i:bv32 :: $i2b(i) <==> i != 0bv32); -axiom $i2b(0bv32) == false; -axiom (forall r:$ref, i:bv32 :: $p2b($ptr(r,i)) <==> i != 0bv32); -axiom $p2b($ptr($NULL,0bv32)) == false; -axiom (forall r:$ref, i:bv32 :: $p2i($ptr(r,i)) == $ptr($NULL,i)); -axiom (forall i:bv32 :: (exists r:$ref :: $i2p($ptr($NULL,i)) == $ptr(r,i))); - -// SMACK Library Procedures - -procedure __SMACK_nondet() returns (p: $ptr); -procedure __SMACK_nondetInt() returns (p: $ptr); -ensures $obj(p) == $NULL; - -procedure boogie_si_record_int(i: bv32); -procedure boogie_si_record_obj(o: $ref); -procedure boogie_si_record_ptr(p: $ptr); - -// SMACK-PRELUDE-END - diff --git a/include/smack/smack-contracts.h b/include/smack/smack-contracts.h new file mode 100644 index 000000000..7a2366e83 --- /dev/null +++ b/include/smack/smack-contracts.h @@ -0,0 +1,19 @@ +// +// This file is distributed under the MIT License. See LICENSE for details. +// +#ifndef SMACK_CONTRACTS_H_ +#define SMACK_CONTRACTS_H_ + +#include + +void requires(bool expr); +void ensures(bool expr); +void invariant(bool expr); + +bool forall(const char *var, bool expr); +bool exists(const char *var, bool expr); +int qvar(const char *var); +int old(int term); +int result(void); + +#endif diff --git a/include/smack/smack-svcomp.h b/include/smack/smack-svcomp.h new file mode 100644 index 000000000..2596e49c5 --- /dev/null +++ b/include/smack/smack-svcomp.h @@ -0,0 +1,75 @@ +// +// This file is distributed under the MIT License. See LICENSE for details. +// +#ifndef SMACK_SVCOMP_H_ +#define SMACK_SVCOMP_H_ + +#include "smack.h" + +#define __inline // Remove the inline attribute +#define __builtin_expect __builtinx_expect // Rewrite so that clang does not complain +#define __builtin_memcpy __builtinx_memcpy // Rewrite so that clang does not complain +#define __builtin_va_start __builtinx_va_start // Rewrite so that clang does not complain +#define __builtin_object_size __builtinx_object_size // Rewrite so that clang does not complain + +void __VERIFIER_error(void) { + assert(0); +} + +void __VERIFIER_assume(int v) { + assume(v); +} + +void exit(int x) { + assume(0); +} + +// Types to be overloaded for: {bool, float, loff_t, pchar, +// pthread_t, sector_t, size_t, u32} + +char __VERIFIER_nondet_char(void) { + return (char)__SMACK_nondet(); +} + +short __VERIFIER_nondet_short(void) { + return (short)__SMACK_nondet(); +} + +int __VERIFIER_nondet_int(void) { + return __SMACK_nondet(); +} + +long __VERIFIER_nondet_long(void) { + return (long)__SMACK_nondet(); +} + +unsigned char __VERIFIER_nondet_uchar(void) { + char x = (char)__SMACK_nondet(); + assume(x >= 0); + return (unsigned char)x; +} + +unsigned short __VERIFIER_nondet_ushort(void) { + short x = (short)__SMACK_nondet(); + assume(x >= 0); + return (unsigned short)x; +} + +unsigned __VERIFIER_nondet_uint(void) { + int x = __SMACK_nondet(); + assume(x >= 0); + return (unsigned)x; +} + +unsigned long __VERIFIER_nondet_ulong(void) { + long x = (long)__SMACK_nondet(); + assume(x >= 0); + return (unsigned long)x; +} + +void* __VERIFIER_nondet_pointer(void) { + return (void*)__SMACK_nondet(); +} + +#endif + diff --git a/include/smack/smack.h b/include/smack/smack.h index ef6509d66..ff4571766 100644 --- a/include/smack/smack.h +++ b/include/smack/smack.h @@ -1,6 +1,4 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // #ifndef SMACK_H_ @@ -30,19 +28,17 @@ * */ -#include - void __SMACK_code(const char *fmt, ...); void __SMACK_mod(const char *fmt, ...); void __SMACK_decl(const char *fmt, ...); void __SMACK_top_decl(const char *fmt, ...); -void __SMACK_assert(bool v) { - __SMACK_code("assert {@} != 0;", v); +void assert(int v) { + __SMACK_code("assert @ != 0;", v); } -void __SMACK_assume(bool v) { - __SMACK_code("assume {@} != 0;", v); +void assume(int v) { + __SMACK_code("assume @ != 0;", v); } //// PROBLEM: in the 2D memory model, the declaration of boogie_si_record_int @@ -63,13 +59,13 @@ void __SMACK_decls() { #define D(d) __SMACK_top_decl(d) // Integer arithmetic - D("function $add(p1:int, p2:int) returns (int) {p1 + p2}"); - D("function $sub(p1:int, p2:int) returns (int) {p1 - p2}"); - D("function $mul(p1:int, p2:int) returns (int) {p1 * p2}"); - D("function $sdiv(p1:int, p2:int) returns (int);"); - D("function $udiv(p1:int, p2:int) returns (int);"); - D("function $srem(p1:int, p2:int) returns (int);"); - D("function $urem(p1:int, p2:int) returns (int);"); + D("function {:inline} $add(p1:int, p2:int) returns (int) {p1 + p2}"); + D("function {:inline} $sub(p1:int, p2:int) returns (int) {p1 - p2}"); + D("function {:inline} $mul(p1:int, p2:int) returns (int) {p1 * p2}"); + D("function {:builtin \"div\"} $sdiv(p1:int, p2:int) returns (int);"); + D("function {:builtin \"div\"} $udiv(p1:int, p2:int) returns (int);"); + D("function {:builtin \"rem\"} $srem(p1:int, p2:int) returns (int);"); + D("function {:builtin \"rem\"} $urem(p1:int, p2:int) returns (int);"); D("function $and(p1:int, p2:int) returns (int);"); D("axiom $and(0,0) == 0;"); D("axiom $and(0,1) == 0;"); @@ -88,36 +84,32 @@ void __SMACK_decls() { D("function $lshr(p1:int, p2:int) returns (int);"); D("function $ashr(p1:int, p2:int) returns (int);"); D("function $shl(p1:int, p2:int) returns (int);"); - D("function $ult(p1:int, p2:int) returns (bool) {p1 < p2}"); - D("function $ugt(p1:int, p2:int) returns (bool) {p1 > p2}"); - D("function $ule(p1:int, p2:int) returns (bool) {p1 <= p2}"); - D("function $uge(p1:int, p2:int) returns (bool) {p1 >= p2}"); - D("function $slt(p1:int, p2:int) returns (bool) {p1 < p2}"); - D("function $sgt(p1:int, p2:int) returns (bool) {p1 > p2}"); - D("function $sle(p1:int, p2:int) returns (bool) {p1 <= p2}"); - D("function $sge(p1:int, p2:int) returns (bool) {p1 >= p2}"); + D("function {:inline} $ult(p1:int, p2:int) returns (bool) {p1 < p2}"); + D("function {:inline} $ugt(p1:int, p2:int) returns (bool) {p1 > p2}"); + D("function {:inline} $ule(p1:int, p2:int) returns (bool) {p1 <= p2}"); + D("function {:inline} $uge(p1:int, p2:int) returns (bool) {p1 >= p2}"); + D("function {:inline} $slt(p1:int, p2:int) returns (bool) {p1 < p2}"); + D("function {:inline} $sgt(p1:int, p2:int) returns (bool) {p1 > p2}"); + D("function {:inline} $sle(p1:int, p2:int) returns (bool) {p1 <= p2}"); + D("function {:inline} $sge(p1:int, p2:int) returns (bool) {p1 >= p2}"); D("function $nand(p1:int, p2:int) returns (int);"); - D("function $max(p1:int, p2:int) returns (int);"); - D("function $min(p1:int, p2:int) returns (int);"); - D("function $umax(p1:int, p2:int) returns (int);"); - D("function $umin(p1:int, p2:int) returns (int);"); - D("function $i2b(i: int) returns (bool);"); - D("axiom (forall i:int :: $i2b(i) <==> i != 0);"); - D("axiom $i2b(0) == false;"); - D("function $b2i(b: bool) returns (int);"); - D("axiom $b2i(true) == 1;"); - D("axiom $b2i(false) == 0;"); + D("function {:inline} $max(p1:int, p2:int) returns (int) {if p1 > p2 then p1 else p2}"); + D("function {:inline} $min(p1:int, p2:int) returns (int) {if p1 > p2 then p2 else p1}"); + D("function {:inline} $umax(p1:int, p2:int) returns (int) {if p1 > p2 then p1 else p2}"); + D("function {:inline} $umin(p1:int, p2:int) returns (int) {if p1 > p2 then p2 else p1}"); + D("function {:inline} $i2b(i: int) returns (bool) {i != 0}"); + D("function {:inline} $b2i(b: bool) returns (int) {if b then 1 else 0}"); // Floating point D("type float;"); - D("function $fp(a:int) returns (float);"); - D("const $ffalse: float;"); - D("const $ftrue: float;"); + D("function $fp(ipart:int, fpart:int, epart:int) returns (float);"); D("function $fadd(f1:float, f2:float) returns (float);"); D("function $fsub(f1:float, f2:float) returns (float);"); D("function $fmul(f1:float, f2:float) returns (float);"); D("function $fdiv(f1:float, f2:float) returns (float);"); D("function $frem(f1:float, f2:float) returns (float);"); + D("function $ffalse(f1:float, f2:float) returns (bool);"); + D("function $ftrue(f1:float, f2:float) returns (bool);"); D("function $foeq(f1:float, f2:float) returns (bool);"); D("function $foge(f1:float, f2:float) returns (bool);"); D("function $fogt(f1:float, f2:float) returns (bool);"); @@ -137,40 +129,36 @@ void __SMACK_decls() { D("function $si2fp(i:int) returns (float);"); D("function $ui2fp(i:int) returns (float);"); + D("axiom (forall f1, f2: float :: f1 != f2 || $foeq(f1,f2));"); + D("axiom (forall i: int :: $fp2ui($ui2fp(i)) == i);"); + D("axiom (forall f: float :: $ui2fp($fp2ui(f)) == f);"); + D("axiom (forall i: int :: $fp2si($si2fp(i)) == i);"); + D("axiom (forall f: float :: $si2fp($fp2si(f)) == f);"); + // Memory Model - D("function $ptr(obj:int, off:int) returns (int) {obj + off}"); - D("function $obj(int) returns (int);"); - D("function $off(ptr:int) returns (int) {ptr}"); + D("function $base(int) returns (int);"); D("const unique $NULL: int;"); D("axiom $NULL == 0;"); D("const $UNDEF: int;"); - D("function $pa(pointer: int, index: int, size: int) returns (int);"); - D("function $trunc(p: int, size: int) returns (int);"); - D("function $p2i(p: int) returns (int);"); - D("function $i2p(p: int) returns (int);"); - D("function $p2b(p: int) returns (bool);"); - D("function $b2p(b: bool) returns (int);"); - - D("axiom (forall p:int, i:int, s:int :: {$pa(p,i,s)} $pa(p,i,s) == p + i * s);"); - D("axiom (forall p,s:int :: $trunc(p,s) == p);"); - - D("axiom $b2p(true) == 1;"); - D("axiom $b2p(false) == 0;"); - D("axiom (forall i:int :: $p2b(i) <==> i != 0);"); - D("axiom $p2b(0) == false;"); - D("axiom (forall i:int :: $p2i(i) == i);"); - D("axiom (forall i:int :: $i2p(i) == i);"); + D("function {:inline} $pa(pointer: int, index: int, size: int) returns (int) {pointer + index * size}"); + D("function {:inline} $trunc(p: int, size: int) returns (int) {p}"); + D("function {:inline} $p2i(p: int) returns (int) {p}"); + D("function {:inline} $i2p(p: int) returns (int) {p}"); + D("function {:inline} $p2b(p: int) returns (bool) {p != 0}"); + D("function {:inline} $b2p(b: bool) returns (int) {if b then 1 else 0}"); // Memory debugging symbols D("type $mop;"); D("procedure boogie_si_record_mop(m: $mop);"); + D("procedure boogie_si_record_bool(b: bool);"); D("procedure boogie_si_record_int(i: int);"); + D("procedure boogie_si_record_float(f: float);"); D("const $MOP: $mop;"); D("const $GLOBALS_BOTTOM: int;"); - D("function $isExternal(p: int) returns (bool) { p < $GLOBALS_BOTTOM - 32768 }"); + D("function {:inline} $isExternal(p: int) returns (bool) { p < $GLOBALS_BOTTOM - 32768 }"); #if MEMORY_MODEL_NO_REUSE_IMPLS D("var $Alloc: [int] bool;"); @@ -221,7 +209,7 @@ void __SMACK_decls() { "ensures $Size[p] == n;\n" "ensures (forall q: int :: {$Size[q]} q != p ==> $Size[q] == old($Size[q]));\n" "ensures (forall q: int :: {$Alloc[q]} q != p ==> $Alloc[q] == old($Alloc[q]));\n" - "ensures n >= 0 ==> (forall q: int :: {$obj(q)} p <= q && q < p+n ==> $obj(q) == p);"); + "ensures n >= 0 ==> (forall q: int :: {$base(q)} p <= q && q < p+n ==> $base(q) == p);"); D("procedure $free(p: int);\n" "modifies $Alloc;\n" @@ -237,7 +225,7 @@ void __SMACK_decls() { "ensures $Size[p] == n;\n" "ensures (forall q: int :: {$Size[q]} q != p ==> $Size[q] == old($Size[q]));\n" "ensures (forall q: int :: {$Alloc[q]} q != p ==> $Alloc[q] == old($Alloc[q]));\n" - "ensures n >= 0 ==> (forall q: int :: {$obj(q)} p <= q && q < p+n ==> $obj(q) == p);"); + "ensures n >= 0 ==> (forall q: int :: {$base(q)} p <= q && q < p+n ==> $base(q) == p);"); #else // NO_REUSE does not reuse previously-allocated addresses D("var $Alloc: [int] bool;"); @@ -251,7 +239,7 @@ void __SMACK_decls() { "ensures n >= 0 ==> $CurrAddr >= old($CurrAddr) + n;\n" "ensures $Alloc[p];\n" "ensures (forall q: int :: {$Alloc[q]} q != p ==> $Alloc[q] == old($Alloc[q]));\n" - "ensures n >= 0 ==> (forall q: int :: {$obj(q)} p <= q && q < p+n ==> $obj(q) == p);"); + "ensures n >= 0 ==> (forall q: int :: {$base(q)} p <= q && q < p+n ==> $base(q) == p);"); D("procedure $free(p: int);\n" "modifies $Alloc;\n" @@ -266,9 +254,13 @@ void __SMACK_decls() { "ensures n >= 0 ==> $CurrAddr >= old($CurrAddr) + n;\n" "ensures $Alloc[p];\n" "ensures (forall q: int :: {$Alloc[q]} q != p ==> $Alloc[q] == old($Alloc[q]));\n" - "ensures n >= 0 ==> (forall q: int :: {$obj(q)} p <= q && q < p+n ==> $obj(q) == p);"); + "ensures n >= 0 ==> (forall q: int :: {$base(q)} p <= q && q < p+n ==> $base(q) == p);"); #endif + D("var $exn: bool;"); + D("var $exnv: int;"); + D("function $extractvalue(p: int, i: int) returns (int);"); + #undef D } diff --git a/lib/AssistDS/ArgCast.cpp b/lib/AssistDS/ArgCast.cpp index 3b931cdb7..8154526f2 100644 --- a/lib/AssistDS/ArgCast.cpp +++ b/lib/AssistDS/ArgCast.cpp @@ -56,7 +56,7 @@ bool ArgCast::runOnModule(Module& M) { if (I->mayBeOverridden()) continue; // Find all uses of this function - for(Value::use_iterator ui = I->use_begin(), ue = I->use_end(); ui != ue; ) { + for(Value::user_iterator ui = I->user_begin(), ue = I->user_end(); ui != ue; ) { // check if is ever casted to a different function type ConstantExpr *CE = dyn_cast(*ui++); if(!CE) @@ -78,8 +78,8 @@ bool ArgCast::runOnModule(Module& M) { if(FTy->getNumParams() != I->arg_size() && !FTy->isVarArg()) continue; - for(Value::use_iterator uii = CE->use_begin(), - uee = CE->use_end(); uii != uee; ++uii) { + for(Value::user_iterator uii = CE->user_begin(), + uee = CE->user_end(); uii != uee; ++uii) { // Find all uses of the casted value, and check if it is // used in a Call Instruction if (CallInst* CI = dyn_cast(*uii)) { diff --git a/lib/AssistDS/ArgSimplify.cpp b/lib/AssistDS/ArgSimplify.cpp index c11b26dd3..26459eb80 100644 --- a/lib/AssistDS/ArgSimplify.cpp +++ b/lib/AssistDS/ArgSimplify.cpp @@ -34,14 +34,14 @@ namespace { static void simplify(Function *F, unsigned arg_count, Type* type) { // Go through all uses of the function - for(Value::use_iterator ui = F->use_begin(), ue = F->use_end(); + for(Value::user_iterator ui = F->user_begin(), ue = F->user_end(); ui != ue; ++ui) { if (Constant *C = dyn_cast(*ui)) { if (ConstantExpr *CE = dyn_cast(C)) { if (CE->getOpcode() == Instruction::BitCast) { if(CE->getOperand(0) == F) { - for(Value::use_iterator uii = CE->use_begin(), uee = CE->use_end(); + for(Value::user_iterator uii = CE->user_begin(), uee = CE->user_end(); uii != uee; ) { // check if it is ever used as a call (bitcast F to ...)() if (CallInst* CI = dyn_cast(*uii++)) { @@ -150,7 +150,7 @@ namespace { for (Function::arg_iterator ii = I->arg_begin(), ee = I->arg_end(); ii != ee; ++ii) { bool change = true; - for(Value::use_iterator ui = ii->use_begin(), ue = ii->use_end(); + for(Value::user_iterator ui = ii->user_begin(), ue = ii->user_end(); ui != ue; ++ui) { // check if the argument is used exclusively in ICmp Instructions if(!isa(*ui)){ diff --git a/lib/AssistDS/DSNodeEquivs.cpp b/lib/AssistDS/DSNodeEquivs.cpp index d0bed286d..eaa3c3a47 100644 --- a/lib/AssistDS/DSNodeEquivs.cpp +++ b/lib/AssistDS/DSNodeEquivs.cpp @@ -12,11 +12,12 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "DSNodeEquivs" #include "assistDS/DSNodeEquivs.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Module.h" -#include "llvm/Support/InstIterator.h" +#include "llvm/IR/InstIterator.h" #include "llvm/ADT/SmallSet.h" #include @@ -245,11 +246,10 @@ const DSNode *DSNodeEquivs::getMemberForValue(const Value *V) { std::deque WL; SmallSet Visited; - // BEGIN BANDAGE: caught a bug here after upgrade to OSX Mavericks - // ORIGINAL: WL.insert(WL.end(), V->use_begin(), V->use_end()); - for ( llvm::Value::const_use_iterator i = V->use_begin(); i != V->use_end(); ++i ) + // FIXME FIXME FIXME for some reason the first attempt segfaults + // WL.insert(WL.end(), V->user_begin(), V->user_end()); + for (llvm::Value::const_user_iterator i = V->user_begin(), e = V->user_end(); i != e; ++i) WL.push_back(*i); - // END BANDAGE do { const User *TheUser = WL.front(); @@ -276,7 +276,7 @@ const DSNode *DSNodeEquivs::getMemberForValue(const Value *V) { // // If this use is of some other nature, look at the users of this use. // - WL.insert(WL.end(), TheUser->use_begin(), TheUser->use_end()); + WL.insert(WL.end(), TheUser->user_begin(), TheUser->user_end()); } } while (!WL.empty()); } diff --git a/lib/AssistDS/DataStructureCallGraph.cpp b/lib/AssistDS/DataStructureCallGraph.cpp index adddd1f99..7f039a17a 100644 --- a/lib/AssistDS/DataStructureCallGraph.cpp +++ b/lib/AssistDS/DataStructureCallGraph.cpp @@ -19,8 +19,8 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/InstIterator.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/InstIterator.h" using namespace llvm; @@ -31,7 +31,7 @@ namespace { static RegisterPass X("dsa-cg", "DSA-based CallGraph implementation"); -RegisterAnalysisGroup Y(X); +RegisterAnalysisGroup Y(X); } diff --git a/lib/AssistDS/Devirt.cpp b/lib/AssistDS/Devirt.cpp index 4a860a28f..b861a8f04 100644 --- a/lib/AssistDS/Devirt.cpp +++ b/lib/AssistDS/Devirt.cpp @@ -399,7 +399,7 @@ Devirtualize::runOnModule (Module & M) { // Get information on the target system. // // - TD = &getAnalysis(); + TD = &getAnalysis().getDataLayout(); // Visit all of the call instructions in this function and record those that // are indirect function calls. diff --git a/lib/AssistDS/DynCount.cpp b/lib/AssistDS/DynCount.cpp index c0e9d0391..bdcac72c1 100644 --- a/lib/AssistDS/DynCount.cpp +++ b/lib/AssistDS/DynCount.cpp @@ -34,7 +34,7 @@ class Dyncount : public ModulePass { } virtual bool runOnModule (Module & M); virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); AU.addRequired >(); } }; diff --git a/lib/AssistDS/FuncSpec.cpp b/lib/AssistDS/FuncSpec.cpp index 8f4077d1a..2d6b4bd7d 100644 --- a/lib/AssistDS/FuncSpec.cpp +++ b/lib/AssistDS/FuncSpec.cpp @@ -69,7 +69,7 @@ bool FuncSpec::runOnModule(Module& M) { } } // Now find all call sites that it is called from - for(Value::use_iterator ui = I->use_begin(), ue = I->use_end(); + for(Value::user_iterator ui = I->user_begin(), ue = I->user_end(); ui != ue; ++ui) { if (CallInst* CI = dyn_cast(*ui)) { // Check that it is the called value (and not an argument) diff --git a/lib/AssistDS/GEPExprArgs.cpp b/lib/AssistDS/GEPExprArgs.cpp index 13bd4b905..5a65e7af3 100644 --- a/lib/AssistDS/GEPExprArgs.cpp +++ b/lib/AssistDS/GEPExprArgs.cpp @@ -16,10 +16,10 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Use.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/ADT/Statistic.h" -#include "llvm/ADT/ValueMap.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" #include diff --git a/lib/AssistDS/IndCloner.cpp b/lib/AssistDS/IndCloner.cpp index eab32df42..2618385bd 100644 --- a/lib/AssistDS/IndCloner.cpp +++ b/lib/AssistDS/IndCloner.cpp @@ -71,7 +71,7 @@ IndClone::runOnModule(Module& M) { // function by the linker. // if (!I->isDeclaration() && !I->mayBeOverridden()) { - for (Value::use_iterator ui = I->use_begin(), ue = I->use_end(); + for (Value::user_iterator ui = I->user_begin(), ue = I->user_end(); ui != ue; ++ui) { if (!isa(*ui) && !isa(*ui)) { if(!ui->use_empty()) @@ -146,8 +146,8 @@ IndClone::runOnModule(Module& M) { // Find all uses of the function that use it as a direct call. Change // them to use the clone. // - for (Value::use_iterator ui = Original->use_begin(), - ue = Original->use_end(); + for (Value::user_iterator ui = Original->user_begin(), + ue = Original->user_end(); ui != ue; ) { CallInst *CI = dyn_cast(*ui); ui++; diff --git a/lib/AssistDS/Int2PtrCmp.cpp b/lib/AssistDS/Int2PtrCmp.cpp index f6cd44d04..7242f12b4 100644 --- a/lib/AssistDS/Int2PtrCmp.cpp +++ b/lib/AssistDS/Int2PtrCmp.cpp @@ -18,7 +18,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/PatternMatch.h" +#include "llvm/IR/PatternMatch.h" #include #include @@ -45,7 +45,7 @@ using namespace PatternMatch; // false - The module was not modified. // bool Int2PtrCmp::runOnModule(Module& M) { - TD = &getAnalysis(); + TD = &getAnalysis().getDataLayout(); for (Module::iterator F = M.begin(); F != M.end(); ++F) { for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { diff --git a/lib/AssistDS/LoadArgs.cpp b/lib/AssistDS/LoadArgs.cpp index 4039ec0d4..595b82b02 100644 --- a/lib/AssistDS/LoadArgs.cpp +++ b/lib/AssistDS/LoadArgs.cpp @@ -17,10 +17,10 @@ #include "assistDS/LoadArgs.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Use.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/ADT/Statistic.h" -#include "llvm/ADT/ValueMap.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" #include diff --git a/lib/AssistDS/MergeGEP.cpp b/lib/AssistDS/MergeGEP.cpp index 2378a33eb..70739ced3 100644 --- a/lib/AssistDS/MergeGEP.cpp +++ b/lib/AssistDS/MergeGEP.cpp @@ -18,7 +18,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Module.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/FormattedStream.h" diff --git a/lib/AssistDS/SVADevirt.cpp b/lib/AssistDS/SVADevirt.cpp index 070ba3e35..53fe10856 100644 --- a/lib/AssistDS/SVADevirt.cpp +++ b/lib/AssistDS/SVADevirt.cpp @@ -176,7 +176,7 @@ namespace { std::set safecalls; std::vector toDelete; - for (Value::use_iterator ii = ams->use_begin(), ee = ams->use_end(); + for (Value::user_iterator ii = ams->user_begin(), ee = ams->user_end(); ii != ee; ++ii) { if (CallInst* CI = dyn_cast(*ii)) { std::cerr << "Found safe call site in " @@ -195,7 +195,7 @@ namespace { for(std::set::iterator i = safecalls.begin(), e = safecalls.end(); i != e; ++i) { - for (Value::use_iterator uii = (*i)->use_begin(), uie = (*i)->use_end(); + for (Value::user_iterator uii = (*i)->user_begin(), uie = (*i)->user_end(); uii != uie; ++uii) { CallSite cs = CallSite::get(*uii); bool isSafeCall = cs.getInstruction() && diff --git a/lib/AssistDS/SimplifyExtractValue.cpp b/lib/AssistDS/SimplifyExtractValue.cpp index 8a62ee557..5a4eb9597 100644 --- a/lib/AssistDS/SimplifyExtractValue.cpp +++ b/lib/AssistDS/SimplifyExtractValue.cpp @@ -20,7 +20,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/PatternMatch.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/IR/DataLayout.h" #include diff --git a/lib/AssistDS/SimplifyGEP.cpp b/lib/AssistDS/SimplifyGEP.cpp index 08257ba56..7aa3bf2cd 100644 --- a/lib/AssistDS/SimplifyGEP.cpp +++ b/lib/AssistDS/SimplifyGEP.cpp @@ -15,7 +15,7 @@ #define DEBUG_TYPE "simplify-gep" #include "assistDS/SimplifyGEP.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" #include "llvm/IR/Constants.h" @@ -75,7 +75,7 @@ static void preprocess(Module& M) { // false - The module was not modified. // bool SimplifyGEP::runOnModule(Module& M) { - TD = &getAnalysis(); + TD = &getAnalysis().getDataLayout(); preprocess(M); for (Module::iterator F = M.begin(); F != M.end(); ++F){ for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { diff --git a/lib/AssistDS/SimplifyInsertValue.cpp b/lib/AssistDS/SimplifyInsertValue.cpp index 9944cd000..b4f7053c6 100644 --- a/lib/AssistDS/SimplifyInsertValue.cpp +++ b/lib/AssistDS/SimplifyInsertValue.cpp @@ -18,7 +18,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/PatternMatch.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/IR/DataLayout.h" #include diff --git a/lib/AssistDS/SimplifyLoad.cpp b/lib/AssistDS/SimplifyLoad.cpp index df01be878..1716d6e3c 100644 --- a/lib/AssistDS/SimplifyLoad.cpp +++ b/lib/AssistDS/SimplifyLoad.cpp @@ -16,7 +16,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/PatternMatch.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/IR/DataLayout.h" #include diff --git a/lib/AssistDS/StructReturnToPointer.cpp b/lib/AssistDS/StructReturnToPointer.cpp index f7dd4fe9a..323a29122 100644 --- a/lib/AssistDS/StructReturnToPointer.cpp +++ b/lib/AssistDS/StructReturnToPointer.cpp @@ -18,7 +18,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/ADT/Statistic.h" -#include "llvm/ADT/ValueMap.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" @@ -119,7 +119,7 @@ bool StructRet::runOnModule(Module& M) { } } - for(Value::use_iterator ui = F->use_begin(), ue = F->use_end(); + for(Value::user_iterator ui = F->user_begin(), ue = F->user_end(); ui != ue; ) { CallInst *CI = dyn_cast(*ui++); if(!CI) diff --git a/lib/AssistDS/TypeChecks.cpp b/lib/AssistDS/TypeChecks.cpp index 7d1a1e873..051836c59 100644 --- a/lib/AssistDS/TypeChecks.cpp +++ b/lib/AssistDS/TypeChecks.cpp @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "dsa-type-checks" #include "assistDS/TypeChecks.h" #include "llvm/IR/Constants.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" -#include "llvm/Assembly/Writer.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/InstIterator.h" +#include "llvm/IR/InstIterator.h" #include "llvm/Support/raw_ostream.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/CommandLine.h" @@ -152,7 +152,7 @@ bool TypeChecks::runOnModule(Module &M) { bool modified = false; // Flags whether we modified the module. bool transformIndirectCalls = true; - TD = &getAnalysis(); + TD = &getAnalysis().getDataLayout(); addrAnalysis = &getAnalysis(); // Create the necessary prototypes @@ -257,7 +257,7 @@ bool TypeChecks::runOnModule(Module &M) { Function &F = *MI; if(F.isDeclaration()) continue; - DominatorTree & DT = getAnalysis(F); + DominatorTree & DT = getAnalysis(F).getDomTree(); std::deque Worklist; Worklist.push_back (DT.getRootNode()); while(Worklist.size()) { @@ -321,8 +321,8 @@ bool TypeChecks::runOnModule(Module &M) { Constant *CNew = ConstantExpr::getBitCast(FI->second, F->getType()); std::set toReplace; - for(Function::use_iterator User = F->use_begin(); - User != F->use_end();++User) { + for(Function::user_iterator User = F->user_begin(); + User != F->user_end();++User) { toReplace.insert(*User); } for(std::set::iterator userI = toReplace.begin(); userI != toReplace.end(); ++userI) { @@ -330,8 +330,8 @@ bool TypeChecks::runOnModule(Module &M) { if(Constant *C = dyn_cast(user)) { if(!isa(C)) { bool changeUse = true; - for(Value::use_iterator II = user->use_begin(); - II != user->use_end(); II++) { + for(Value::user_iterator II = user->user_begin(); + II != user->user_end(); II++) { if(CallInst *CI = dyn_cast(*II)) if(CI->getCalledFunction()) { if(CI->getCalledFunction()->isDeclaration()) @@ -506,7 +506,7 @@ void TypeChecks::optimizeChecks(Module &M) { Function &F = *MI; if(F.isDeclaration()) continue; - DominatorTree & DT = getAnalysis(F); + DominatorTree & DT = getAnalysis(F).getDomTree(); std::deque Worklist; Worklist.push_back (DT.getRootNode()); while(Worklist.size()) { @@ -520,7 +520,7 @@ void TypeChecks::optimizeChecks(Module &M) { if(CI->getCalledFunction() != checkTypeInst) continue; std::listtoDelete; - for(Value::use_iterator User = CI->getOperand(3)->use_begin(); User != CI->getOperand(3)->use_end(); ++User) { + for(Value::user_iterator User = CI->getOperand(3)->user_begin(); User != CI->getOperand(3)->user_end(); ++User) { CallInst *CI2 = dyn_cast(*User); if(!CI2) continue; @@ -550,7 +550,7 @@ void TypeChecks::optimizeChecks(Module &M) { Function &F = *MI; if(F.isDeclaration()) continue; - DominatorTree & DT = getAnalysis(F); + DominatorTree & DT = getAnalysis(F).getDomTree(); LoopInfo & LI = getAnalysis(F); std::deque Worklist; Worklist.push_back (DT.getRootNode()); @@ -697,7 +697,7 @@ bool TypeChecks::visitAddressTakenFunction(Module &M, Function &F) { std::vectortoDelete; // Find all uses of the function - for(Value::use_iterator ui = F.use_begin(), ue = F.use_end(); + for(Value::user_iterator ui = F.user_begin(), ue = F.user_end(); ui != ue;++ui) { if(InvokeInst *II = dyn_cast(*ui)) { if(II->getCalledValue()->stripPointerCasts() != &F) @@ -927,7 +927,7 @@ bool TypeChecks::visitInternalVarArgFunction(Module &M, Function &F) { std::vectortoDelete; // Find all uses of the function - for(Value::use_iterator ui = F.use_begin(), ue = F.use_end(); + for(Value::user_iterator ui = F.user_begin(), ue = F.user_end(); ui != ue;ui ++) { // Check for call sites @@ -1051,7 +1051,7 @@ bool TypeChecks::visitInternalByValFunction(Module &M, Function &F) { // Update the call sites std::vectortoDelete; - for(Value::use_iterator ui = F.use_begin(), ue = F.use_end(); + for(Value::user_iterator ui = F.user_begin(), ue = F.user_end(); ui != ue; ui++) { // Check that F is the called value if(InvokeInst *II = dyn_cast(*ui)) { @@ -2124,7 +2124,7 @@ bool TypeChecks::visitLoadInst(Module &M, LoadInst &LI) { // BCI - ptr // I - instruction whose uses to instrument bool TypeChecks::visitUses(Instruction *I, Instruction *AI, Value *BCI) { - for(Value::use_iterator II = I->use_begin(); II != I->use_end(); ++II) { + for(Value::user_iterator II = I->user_begin(); II != I->user_end(); ++II) { if(DisablePtrCmpChecks) { if(isa(*II)) { if(I->getType()->isPointerTy()) diff --git a/lib/AssistDS/TypeChecksOpt.cpp b/lib/AssistDS/TypeChecksOpt.cpp index a78a3be9d..b8ec53b73 100644 --- a/lib/AssistDS/TypeChecksOpt.cpp +++ b/lib/AssistDS/TypeChecksOpt.cpp @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "dsa-type-checks-opt" #include "assistDS/TypeChecksOpt.h" #include "llvm/IR/Constants.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" -#include "llvm/Assembly/Writer.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/InstIterator.h" +#include "llvm/IR/InstIterator.h" #include "llvm/Support/raw_ostream.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/CommandLine.h" @@ -136,7 +136,7 @@ bool TypeChecksOpt::runOnModule(Module &M) { NULL); MallocFunc = M.getFunction("malloc"); - for(Value::use_iterator User = trackGlobal->use_begin(); User != trackGlobal->use_end(); ++User) { + for(Value::user_iterator User = trackGlobal->user_begin(); User != trackGlobal->user_end(); ++User) { CallInst *CI = dyn_cast(*User); assert(CI); if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) { @@ -149,7 +149,7 @@ bool TypeChecksOpt::runOnModule(Module &M) { } } - for(Value::use_iterator User = checkTypeInst->use_begin(); User != checkTypeInst->use_end(); ++User) { + for(Value::user_iterator User = checkTypeInst->user_begin(); User != checkTypeInst->user_end(); ++User) { CallInst *CI = dyn_cast(*User); assert(CI); @@ -158,7 +158,7 @@ bool TypeChecksOpt::runOnModule(Module &M) { } } - for(Value::use_iterator User = trackStoreInst->use_begin(); User != trackStoreInst->use_end(); ++User) { + for(Value::user_iterator User = trackStoreInst->user_begin(); User != trackStoreInst->user_end(); ++User) { CallInst *CI = dyn_cast(*User); assert(CI); @@ -169,7 +169,7 @@ bool TypeChecksOpt::runOnModule(Module &M) { // for alloca's if they are type known // assume initialized with TOP - for(Value::use_iterator User = trackUnInitInst->use_begin(); User != trackUnInitInst->use_end(); ) { + for(Value::user_iterator User = trackUnInitInst->user_begin(); User != trackUnInitInst->user_end(); ) { CallInst *CI = dyn_cast(*(User++)); assert(CI); @@ -190,7 +190,7 @@ bool TypeChecksOpt::runOnModule(Module &M) { } if(MallocFunc) { - for(Value::use_iterator User = MallocFunc->use_begin(); User != MallocFunc->use_end(); User ++) { + for(Value::user_iterator User = MallocFunc->user_begin(); User != MallocFunc->user_end(); User ++) { CallInst *CI = dyn_cast(*User); if(!CI) continue; @@ -212,7 +212,7 @@ bool TypeChecksOpt::runOnModule(Module &M) { // also do for mallocs/calloc/other allocators??? // other allocators?? - for(Value::use_iterator User = copyTypeInfo->use_begin(); User != copyTypeInfo->use_end(); ++User) { + for(Value::user_iterator User = copyTypeInfo->user_begin(); User != copyTypeInfo->user_end(); ++User) { CallInst *CI = dyn_cast(*User); assert(CI); @@ -225,7 +225,7 @@ bool TypeChecksOpt::runOnModule(Module &M) { toDelete.push_back(CI); } } - for(Value::use_iterator User = setTypeInfo->use_begin(); User != setTypeInfo->use_end(); ++User) { + for(Value::user_iterator User = setTypeInfo->user_begin(); User != setTypeInfo->user_end(); ++User) { CallInst *CI = dyn_cast(*User); assert(CI); @@ -239,7 +239,7 @@ bool TypeChecksOpt::runOnModule(Module &M) { } } - for(Value::use_iterator User = getTypeTag->use_begin(); User != getTypeTag->use_end(); ++User) { + for(Value::user_iterator User = getTypeTag->user_begin(); User != getTypeTag->user_end(); ++User) { CallInst *CI = dyn_cast(*User); assert(CI); if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) { diff --git a/lib/DSA/AddressTakenAnalysis.cpp b/lib/DSA/AddressTakenAnalysis.cpp index 7c5ed38e6..f106f20cc 100644 --- a/lib/DSA/AddressTakenAnalysis.cpp +++ b/lib/DSA/AddressTakenAnalysis.cpp @@ -22,7 +22,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" #include #include @@ -35,8 +35,8 @@ using namespace llvm; AddressTakenAnalysis::~AddressTakenAnalysis() {} static bool isAddressTaken(Value* V) { - for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { - User *U = *I; + for (Value::const_use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { + User *U = I->getUser(); if(isa(U)) return true; if (!isa(U) && !isa(U)) { @@ -60,7 +60,7 @@ static bool isAddressTaken(Value* V) { // are never used } else { llvm::CallSite CS(cast(U)); - if (!CS.isCallee(I)) + if (!CS.isCallee(&*I)) return true; } } diff --git a/lib/DSA/AllocatorIdentification.cpp b/lib/DSA/AllocatorIdentification.cpp index 292b95001..bc7f9b8e9 100644 --- a/lib/DSA/AllocatorIdentification.cpp +++ b/lib/DSA/AllocatorIdentification.cpp @@ -62,7 +62,7 @@ bool AllocIdentify::flowsFrom(Value *Dest,Value *Src) { bool isNotStored(Value *V) { // check that V is not stored to a location that is accessible outside this fn - for(Value::use_iterator ui = V->use_begin(), ue = V->use_end(); + for(Value::user_iterator ui = V->user_begin(), ue = V->user_end(); ui != ue; ++ui) { if(isa(*ui)) return false; @@ -93,12 +93,12 @@ AllocIdentify::~AllocIdentify() {} bool AllocIdentify::runOnModule(Module& M) { - allocators.insert("malloc"); - allocators.insert("calloc"); - //allocators.insert("realloc"); - //allocators.insert("memset"); - deallocators.insert("free"); - deallocators.insert("cfree"); + allocators.emplace("malloc"); + allocators.emplace("calloc"); + //allocators.emplace("realloc"); + //allocators.emplace("memset"); + deallocators.emplace("free"); + deallocators.emplace("cfree"); bool changed; do { @@ -110,7 +110,7 @@ bool AllocIdentify::runOnModule(Module& M) { Function* F = M.getFunction(*it); if(!F) continue; - for(Value::use_iterator ui = F->use_begin(), ue = F->use_end(); + for(Value::user_iterator ui = F->user_begin(), ue = F->user_end(); ui != ue; ++ui) { // iterate though all calls to malloc if (CallInst* CI = dyn_cast(*ui)) { @@ -143,7 +143,7 @@ bool AllocIdentify::runOnModule(Module& M) { changed = (allocators.find(WrapperF->getName()) == allocators.end()); if(changed) { ++numAllocators; - allocators.insert(WrapperF->getName()); + allocators.emplace(WrapperF->getName()); DEBUG(errs() << WrapperF->getName().str() << "\n"); } } @@ -162,7 +162,7 @@ bool AllocIdentify::runOnModule(Module& M) { if(!F) continue; - for(Value::use_iterator ui = F->use_begin(), ue = F->use_end(); + for(Value::user_iterator ui = F->user_begin(), ue = F->user_end(); ui != ue; ++ui) { // iterate though all calls to malloc if (CallInst* CI = dyn_cast(*ui)) { @@ -178,7 +178,7 @@ bool AllocIdentify::runOnModule(Module& M) { changed = (deallocators.find(WrapperF->getName()) == deallocators.end()); if(changed) { ++numDeallocators; - deallocators.insert(WrapperF->getName()); + deallocators.emplace(WrapperF->getName()); DEBUG(errs() << WrapperF->getName().str() << "\n"); } } diff --git a/lib/DSA/Basic.cpp b/lib/DSA/Basic.cpp index 7c109f891..6f127f833 100644 --- a/lib/DSA/Basic.cpp +++ b/lib/DSA/Basic.cpp @@ -15,15 +15,15 @@ #include "dsa/DataStructure.h" #include "dsa/DSGraph.h" -#include "llvm/InstVisitor.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/InstIterator.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" using namespace llvm; @@ -33,7 +33,7 @@ X("dsa-basic", "Basic Data Structure Analysis(No Analysis)"); char BasicDataStructures::ID = 0; bool BasicDataStructures::runOnModule(Module &M) { - init(&getAnalysis()); + init(&getAnalysis().getDataLayout()); // // Create a void pointer type. This is simply a pointer to an 8 bit value. diff --git a/lib/DSA/CallTargets.cpp b/lib/DSA/CallTargets.cpp index 72d0f523b..0814a43f8 100644 --- a/lib/DSA/CallTargets.cpp +++ b/lib/DSA/CallTargets.cpp @@ -17,6 +17,7 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "call-targets" #include "llvm/IR/Module.h" #include "llvm/IR/Instructions.h" #include "dsa/DataStructure.h" diff --git a/lib/DSA/DSGraph.cpp b/lib/DSA/DSGraph.cpp index 866ef1d94..3f75c776b 100644 --- a/lib/DSA/DSGraph.cpp +++ b/lib/DSA/DSGraph.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "DSGraph" #include "dsa/DSGraphTraits.h" #include "dsa/DataStructure.h" #include "dsa/DSGraph.h" @@ -23,7 +24,6 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DataLayout.h" -#include "llvm/Assembly/Writer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/ADT/DepthFirstIterator.h" diff --git a/lib/DSA/DSTest.cpp b/lib/DSA/DSTest.cpp index 036746d0f..7d50f7da9 100644 --- a/lib/DSA/DSTest.cpp +++ b/lib/DSA/DSTest.cpp @@ -45,7 +45,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" #include "llvm/IR/ValueSymbolTable.h" -#include "llvm/Assembly/Writer.h" using namespace llvm; namespace { diff --git a/lib/DSA/DataStructure.cpp b/lib/DSA/DataStructure.cpp index 7aaa26921..b7acac7e4 100644 --- a/lib/DSA/DataStructure.cpp +++ b/lib/DSA/DataStructure.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "data-structure" #include "dsa/DSGraphTraits.h" #include "dsa/DataStructure.h" #include "dsa/DSGraph.h" @@ -22,7 +23,6 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DataLayout.h" -#include "llvm/Assembly/Writer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/ADT/DepthFirstIterator.h" @@ -1496,7 +1496,7 @@ void DataStructures::init(DataStructures* D, bool clone, bool useAuxCalls, if (!clone) D->DSGraphsStolen = true; } -void DataStructures::init(DataLayout* T) { +void DataStructures::init(const DataLayout* T) { assert (!TD && "Already init"); GraphSource = 0; Clone = false; diff --git a/lib/DSA/DataStructureStats.cpp b/lib/DSA/DataStructureStats.cpp index 9da70bbb5..c1d2e0dfc 100644 --- a/lib/DSA/DataStructureStats.cpp +++ b/lib/DSA/DataStructureStats.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "DSStats" #include "dsa/DataStructure.h" #include "dsa/DSGraph.h" #include "dsa/TypeSafety.h" @@ -18,7 +19,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" -#include "llvm/InstVisitor.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/Pass.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" @@ -80,7 +81,7 @@ namespace { void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); - AU.addRequired(); + AU.addRequired(); AU.addRequired >(); } @@ -236,7 +237,7 @@ void DSGraphStats::visitStore(StoreInst &SI) { bool DSGraphStats::runOnFunction(Function& F) { DS = &getAnalysis(); - TD = &getAnalysis(); + TD = &getAnalysis().getDataLayout(); TS = &getAnalysis >(); TDGraph = DS->getDSGraph(F); countCallees(F); diff --git a/lib/DSA/EquivClassGraphs.cpp b/lib/DSA/EquivClassGraphs.cpp index 0cf08b2df..a92abb649 100644 --- a/lib/DSA/EquivClassGraphs.cpp +++ b/lib/DSA/EquivClassGraphs.cpp @@ -20,7 +20,7 @@ #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "dsa/DSGraph.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" #include "llvm/Support/Debug.h" #include "llvm/ADT/SCCIterator.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/DSA/Local.cpp b/lib/DSA/Local.cpp index 87ee031a6..e80c4d6c1 100644 --- a/lib/DSA/Local.cpp +++ b/lib/DSA/Local.cpp @@ -31,8 +31,8 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" -#include "llvm/InstVisitor.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/Support/Timer.h" #include @@ -1440,7 +1440,7 @@ void handleMagicSections(DSGraph* GlobalsGraph, Module& M) { char LocalDataStructures::ID; bool LocalDataStructures::runOnModule(Module &M) { - init(&getAnalysis()); + init(&getAnalysis().getDataLayout()); addrAnalysis = &getAnalysis(); // First step, build the globals graph. diff --git a/lib/DSA/Printer.cpp b/lib/DSA/Printer.cpp index 6a1e0d446..67698a6cd 100644 --- a/lib/DSA/Printer.cpp +++ b/lib/DSA/Printer.cpp @@ -18,11 +18,11 @@ #include "dsa/DSGraphTraits.h" #include "llvm/IR/Module.h" #include "llvm/IR/Constants.h" -#include "llvm/Assembly/Writer.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/GraphWriter.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Config/config.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/FormattedStream.h" #include using namespace llvm; @@ -116,7 +116,7 @@ static std::string getCaption(const DSNode *N, const DSGraph *G) { for (DSNode::globals_iterator i = N->globals_begin(), e = N->globals_end(); i != e; ++i) { - WriteAsOperand(OS, *i, false, M); + (*i)->printAsOperand(OS,false,M); // Figure out how many globals are equivalent to this one. if (GlobalECs) { @@ -214,7 +214,7 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { if (!isa(I->first)) { std::string OS_str; llvm::raw_string_ostream OS(OS_str); - WriteAsOperand(OS, I->first, false, CurMod); + I->first->printAsOperand(OS, false, CurMod); GW.emitSimpleNode(I->first, "", OS.str()); // Add edge from return node to real destination @@ -305,7 +305,7 @@ void DSGraph::writeGraphToFile(llvm::raw_ostream &O, O << "Writing '" << Filename << "'..."; if (!DontPrintGraphs) { std::string Error; - llvm::raw_fd_ostream F(Filename.c_str(), Error); + llvm::raw_fd_ostream F(Filename.c_str(), Error, sys::fs::F_None); if (Error.size()) { O << " error opening file for writing! " << Error << "\n"; diff --git a/lib/DSA/StdLibPass.cpp b/lib/DSA/StdLibPass.cpp index beca6d872..a902b779a 100644 --- a/lib/DSA/StdLibPass.cpp +++ b/lib/DSA/StdLibPass.cpp @@ -10,6 +10,7 @@ // may query it. //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "stdlib-pass" #include "llvm/ADT/Statistic.h" #include "dsa/DataStructure.h" #include "dsa/AllocatorIdentification.h" @@ -18,7 +19,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/DataLayout.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -451,7 +452,7 @@ void StdLibDataStructures::eraseCallsTo(Function* F) { typedef std::pair RemovalPair; DenseSet ToRemove; - for (Value::use_iterator ii = F->use_begin(), ee = F->use_end(); + for (Value::user_iterator ii = F->user_begin(), ee = F->user_end(); ii != ee; ++ii) if (CallInst* CI = dyn_cast(*ii)){ if (CI->getCalledValue() == F) { @@ -471,7 +472,7 @@ StdLibDataStructures::eraseCallsTo(Function* F) { } } else if(ConstantExpr *CE = dyn_cast(*ii)) { if(CE->isCast()) { - for (Value::use_iterator ci = CE->use_begin(), ce = CE->use_end(); + for (Value::user_iterator ci = CE->user_begin(), ce = CE->user_end(); ci != ce; ++ci) { if (CallInst* CI = dyn_cast(*ci)){ if(CI->getCalledValue() == CE) { @@ -522,7 +523,7 @@ StdLibDataStructures::processRuntimeCheck (Module & M, // Scan through all direct calls to the function (there should only be direct // calls) and process each one. // - for (Value::use_iterator ii = F->use_begin(), ee = F->use_end(); + for (Value::user_iterator ii = F->user_begin(), ee = F->user_end(); ii != ee; ++ii) { if (CallInst* CI = dyn_cast(*ii)) { if (CI->getCalledValue() == F) { @@ -677,8 +678,9 @@ StdLibDataStructures::runOnModule (Module &M) { void StdLibDataStructures::processFunction(int x, Function *F) { - for (Value::use_iterator ii = F->use_begin(), ee = F->use_end(); + for (Value::user_iterator ii = F->user_begin(), ee = F->user_end(); ii != ee; ++ii) + if (CallInst* CI = dyn_cast(*ii)){ if (CI->getCalledValue() == F) { DSGraph* Graph = getDSGraph(*CI->getParent()->getParent()); @@ -825,7 +827,7 @@ void StdLibDataStructures::processFunction(int x, Function *F) { } } else if(ConstantExpr *CE = dyn_cast(*ii)) { if(CE->isCast()) - for (Value::use_iterator ci = CE->use_begin(), ce = CE->use_end(); + for (Value::user_iterator ci = CE->user_begin(), ce = CE->user_end(); ci != ce; ++ci) { if (CallInst* CI = dyn_cast(*ci)){ diff --git a/lib/DSA/TypeSafety.cpp b/lib/DSA/TypeSafety.cpp index 969e1d0bd..0c0f6f8c4 100644 --- a/lib/DSA/TypeSafety.cpp +++ b/lib/DSA/TypeSafety.cpp @@ -333,7 +333,7 @@ TypeSafety::runOnModule(Module & M) { // // Get access to prerequisite passes. // - TD = &getAnalysis(); + TD = &getAnalysis().getDataLayout(); dsaPass = &getAnalysis(); // diff --git a/lib/smack/BoogieAst.cpp b/lib/smack/BoogieAst.cpp index b4b1d190a..0cc225533 100644 --- a/lib/smack/BoogieAst.cpp +++ b/lib/smack/BoogieAst.cpp @@ -1,6 +1,4 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // #include "smack/BoogieAst.h" @@ -13,6 +11,18 @@ using namespace std; unsigned Decl::uniqueId = 0; +const Expr* Expr::exists(string v, string t, const Expr* e) { + vector< pair > vars; + vars.push_back(make_pair(v,t)); + return new QuantExpr(QuantExpr::Exists, vars, e); +} + +const Expr* Expr::forall(string v, string t, const Expr* e) { + vector< pair > vars; + vars.push_back(make_pair(v,t)); + return new QuantExpr(QuantExpr::Forall, vars, e); +} + const Expr* Expr::and_(const Expr* l, const Expr* r) { return new BinExpr(BinExpr::And, l, r); } @@ -29,6 +39,10 @@ const Expr* Expr::lt(const Expr* l, const Expr* r) { return new BinExpr(BinExpr::Lt, l, r); } +const Expr* Expr::fn(string f, vector args) { + return new FunExpr(f, args); +} + const Expr* Expr::fn(string f, const Expr* x) { return new FunExpr(f, vector(1, x)); } @@ -165,6 +179,10 @@ const Stmt* Stmt::call(string p, const Expr* x) { return call(p, vector(1, x), vector()); } +const Stmt* Stmt::call(string p, const Expr* x, const Attr* attr) { + return call(p, vector(1, x), vector(), vector(1, attr)); +} + const Stmt* Stmt::call(string p, const Expr* x, string r) { return call(p, vector(1, x), vector(1, r)); } @@ -219,6 +237,10 @@ const Stmt* Stmt::havoc(string x) { return new HavocStmt(vector(1, x)); } +const Stmt* Stmt::return_(const Expr* e) { + return new ReturnStmt(e); +} + const Stmt* Stmt::return_() { return new ReturnStmt(); } @@ -237,6 +259,9 @@ Decl* Decl::typee(string name, string type) { Decl* Decl::axiom(const Expr* e) { return new AxiomDecl(e); } +Decl* Decl::function(string name, vector< pair > args, string type, const Expr* e) { + return new FuncDecl(name,vector(),args,type,e); +} Decl* Decl::constant(string name, string type) { return Decl::constant(name, type, vector(), false); } @@ -301,6 +326,11 @@ ostream& operator<<(ostream& os, Program& p) { return os; } +template ostream& operator<<(ostream& os, pair p) { + os << p.first << ": " << p.second; + return os; +} + template void print_seq(ostream& os, vector ts, string init, string sep, string term) { @@ -430,16 +460,16 @@ void NotExpr::print(ostream& os) const { void QuantExpr::print(ostream& os) const { os << "("; - switch (q) { + switch (quant) { case Forall: - os << "forall"; + os << "forall "; break; case Exists: - os << "exists"; + os << "exists "; break; } - os << " -- ToDo: Implement quantified expressions. "; - os << ")"; + print_seq< pair >(os, vars, ","); + os << " :: " << expr << ")"; } void SelExpr::print(ostream& os) const { @@ -457,6 +487,14 @@ void VarExpr::print(ostream& os) const { os << var; } +void CodeExpr::print(ostream& os) const { + os << "|{" << endl; + if (decls.size() > 0) + print_set(os, decls, " ", "\n ", "\n"); + print_seq(os, blocks, "\n"); + os << endl << "}|"; +} + void StrVal::print(ostream& os) const { os << "\"" << val << "\""; } @@ -518,7 +556,10 @@ void HavocStmt::print(ostream& os) const { } void ReturnStmt::print(ostream& os) const { - os << "return;"; + os << "return"; + if (expr) + os << " " << expr; + os << ";"; } void CodeStmt::print(ostream& os) const { @@ -550,13 +591,18 @@ void ConstDecl::print(ostream& os) const { } void FuncDecl::print(ostream& os) const { - os << "function " << name; + os << "function "; if (attrs.size() > 0) print_seq(os, attrs, "", " ", " "); + os << name << "("; for (unsigned i = 0; i < params.size(); i++) os << params[i].first << ": " << params[i].second << (i < params.size() - 1 ? ", " : ""); - os << ": " << type << " { " << body << " };"; + os << ") returns (" << type << ")"; + if (body) + os << " { " << body << " }"; + else + os << ";"; } void VarDecl::print(ostream& os) const { diff --git a/lib/smack/BplFilePrinter.cpp b/lib/smack/BplFilePrinter.cpp index 575eda631..efed9795e 100644 --- a/lib/smack/BplFilePrinter.cpp +++ b/lib/smack/BplFilePrinter.cpp @@ -1,6 +1,4 @@ // -// Copyright (c) 2008 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Pantazis Deligiannis (p.deligiannis@imperial.ac.uk) // This file is distributed under the MIT License. See LICENSE for details. // #include "smack/BplFilePrinter.h" diff --git a/lib/smack/BplPrinter.cpp b/lib/smack/BplPrinter.cpp index c6f79591e..fdbf35047 100644 --- a/lib/smack/BplPrinter.cpp +++ b/lib/smack/BplPrinter.cpp @@ -1,5 +1,4 @@ // -// Copyright (c) 2008 Zvonimir Rakamaric (zvonimir@cs.utah.edu) // This file is distributed under the MIT License. See LICENSE for details. // #include "smack/BplPrinter.h" diff --git a/lib/smack/Contracts.cpp b/lib/smack/Contracts.cpp new file mode 100644 index 000000000..d8aa53c3d --- /dev/null +++ b/lib/smack/Contracts.cpp @@ -0,0 +1,95 @@ +// +// This file is distributed under the MIT License. See LICENSE for details. +// + +#include "smack/Contracts.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/Analysis/CFG.h" + +using namespace llvm; + +namespace smack { + +unsigned ContractsExtractor::uniqueSliceId = 0; + +Slice* ContractsExtractor::extractSlice(Value* V) { + Instruction* I = dyn_cast(V); + assert(I && "Expected instruction."); + + stringstream name; + name << "$expr" << uniqueSliceId++; + Slice* S = new Slice(*I, slices, name.str()); + if (Decl* D = (Decl*) S->getBoogieDecl(naming,rep)) + rep.getProgram().addDecl(D); + S->remove(); + return S; +} + +typedef SmallVector< pair, 10 > EdgeList; + +bool looksLikeLoopHead(BasicBlock* B) { + EdgeList backedges; + FindFunctionBackedges(*B->getParent(), backedges); + for (pred_iterator A = pred_begin(B), Z = pred_end(B); A != Z; ++A) + for (EdgeList::iterator E = backedges.begin(), End = backedges.end(); E != End; ++E) + if (E->first == *A && E->second == B) + return true; + return false; +} + +void ContractsExtractor::visitCallInst(CallInst& ci) { + Function* f = ci.getCalledFunction(); + string name = f && f->hasName() ? f->getName().str() : ""; + + if (name == "forall") { + assert(ci.getNumArgOperands() == 2 && "Unexpected operands to forall."); + Value* arg = ci.getArgOperand(1); + ci.setArgOperand(1,sliceIdx(ci.getContext())); + slices.push_back(extractSlice(arg)); + + } else if (name == "exists") { + assert(ci.getNumArgOperands() == 2 && "Unexpected operands to exists."); + Value* arg = ci.getArgOperand(1); + ci.setArgOperand(1,sliceIdx(ci.getContext())); + slices.push_back(extractSlice(arg)); + + } else if (name == "requires") { + assert(ci.getNumArgOperands() == 1 && "Unexpected operands to requires."); + Value* V = ci.getArgOperand(0); + ci.setArgOperand(0,ConstantInt::getTrue(ci.getContext())); + proc.addRequires(extractSlice(V)->getBoogieExpression(naming,rep)); + ci.eraseFromParent(); + + } else if (name == "ensures") { + assert(ci.getNumArgOperands() == 1 && "Unexpected operands to ensures."); + Value* V = ci.getArgOperand(0); + ci.setArgOperand(0,ConstantInt::getTrue(ci.getContext())); + proc.addEnsures(extractSlice(V)->getBoogieExpression(naming,rep)); + ci.eraseFromParent(); + + } else if (name == "invariant") { + assert(ci.getNumArgOperands() == 1 && "Unexpected operands to invariant."); + + BasicBlock* body = ci.getParent(); + BasicBlock* head = body; + do { + pred_iterator P = pred_begin(head); + assert(P != pred_end(head) && "Expected predecessors!"); + head = *P; + } while (!looksLikeLoopHead(head)); + + Value* V = ci.getArgOperand(0); + ci.setArgOperand(0,sliceIdx(ci.getContext())); + slices.push_back(extractSlice(V)); + ci.removeFromParent(); + + // NOTE Boogie only considers only assertions at the beginning of the loop + // head block to be loop invariants. Therefore we push this instruction to + // the front -- just after any Phi nodes. + BasicBlock::iterator I = head->begin(); + while (isa(I)) ++I; + head->getInstList().insert(I,&ci); + } +} + +} diff --git a/lib/smack/DSAAliasAnalysis.cpp b/lib/smack/DSAAliasAnalysis.cpp index 9ddb52104..d64a3c3e6 100644 --- a/lib/smack/DSAAliasAnalysis.cpp +++ b/lib/smack/DSAAliasAnalysis.cpp @@ -12,13 +12,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Module.h" -#include "dsa/DataStructure.h" -#include "dsa/DSGraph.h" #include "smack/DSAAliasAnalysis.h" namespace smack { @@ -124,17 +117,53 @@ bool DSAAliasAnalysis::isExternal(const Value* v) { return N && N->isExternalNode(); } +bool DSAAliasAnalysis::isSingletonGlobal(const Value *V) { + const DSNode *N = getNode(V); + if (!N || !N->isGlobalNode() || N->numGlobals() > 1) + return false; + + // Ensure this node has a unique scalar type... (?) + DSNode::const_type_iterator TSi = N->type_begin(); + if (TSi == N->type_end()) return false; + svset::const_iterator Ti = TSi->second->begin(); + if (Ti == TSi->second->end()) return false; + const Type* T = *Ti; + while (T->isPointerTy()) T = T->getPointerElementType(); + if (!T->isSingleValueType()) return false; + ++Ti; + if (Ti != TSi->second->end()) return false; + ++TSi; + if (TSi != N->type_end()) return false; + + // Ensure this node is in its own class... (?) + const EquivalenceClasses &Cs = nodeEqs->getEquivalenceClasses(); + EquivalenceClasses::iterator C = Cs.findValue(N); + assert(C != Cs.end() && "Did not find value."); + EquivalenceClasses::member_iterator I = Cs.member_begin(C); + if (I == Cs.member_end()) + return false; + ++I; + if (I != Cs.member_end()) + return false; + + return true; +} + AliasAnalysis::AliasResult DSAAliasAnalysis::alias(const Location &LocA, const Location &LocB) { - if (LocA.Ptr == LocB.Ptr) + if (LocA.Ptr == LocB.Ptr) return MustAlias; const DSNode *N1 = nodeEqs->getMemberForValue(LocA.Ptr); const DSNode *N2 = nodeEqs->getMemberForValue(LocB.Ptr); - + + assert(N1 && "Expected non-null node."); + assert(N2 && "Expected non-null node."); + if ((N1->isCompleteNode() || N2->isCompleteNode()) && !(N1->isExternalNode() && N2->isExternalNode()) && !(N1->isUnknownNode() || N2->isUnknownNode())) { + if (!equivNodes(N1,N2)) return NoAlias; diff --git a/lib/smack/Naming.cpp b/lib/smack/Naming.cpp new file mode 100644 index 000000000..65be7ea76 --- /dev/null +++ b/lib/smack/Naming.cpp @@ -0,0 +1,127 @@ +// +// This file is distributed under the MIT License. See LICENSE for details. +// + +#include "smack/Naming.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Constants.h" +#include + +namespace smack { + +const string Naming::BLOCK_LBL = "$bb"; +const string Naming::RET_VAR = "$r"; +const string Naming::EXN_VAR = "$exn"; +const string Naming::EXN_VAL_VAR = "$exnv"; +const string Naming::BOOL_VAR = "$b"; +const string Naming::FLOAT_VAR = "$f"; +const string Naming::PTR_VAR = "$p"; +const string Naming::UNDEF_SYM = "$u"; + +Regex Naming::BPL_KW( + "^(bool|int|false|true|old|forall|exists|requires|modifies|ensures|invariant|free" + "|unique|finite|complete|type|const|function|axiom|var|procedure" + "|implementation|where|returns|assume|assert|havoc|call|return|while" + "|break|goto|if|else|div|mod|yield|par|async)$"); + +Regex Naming::SMACK_NAME(".*__SMACK_.*"); + +bool Naming::isBplKeyword(string s) { + return BPL_KW.match(s); +} + +bool Naming::isSmackName(string n) { + return SMACK_NAME.match(n); +} + +bool Naming::isSmackGeneratedName(string n) { + return n.size() > 0 && n[0] == '$'; +} + +string Naming::escape(string s) { + string Str(llvm::DOT::EscapeString(s)); + for (unsigned i = 0; i != Str.length(); ++i) + switch (Str[i]) { + case '\01': + Str[i] = '_'; + break; + case '@': + Str[i] = '.'; + break; + } + return Str; +} + +void Naming::enter() { + NameMap N; + nameStack.push(N); +} + +void Naming::leave() { + assert(nameStack.size() > 0 && "Name stack should not be empty."); + nameStack.pop(); + if (nameStack.size() == 0) { + varNum = 0; + blockNum = 0; + } +} + +string Naming::get(const llvm::Value& V) { + + if (nameStack.size() > 0 && nameStack.top().count(&V)) + return nameStack.top()[&V]; + + string name; + + if (V.hasName() && !llvm::isa(&V)) { + name = escape(V.getName().str()); + if (isBplKeyword(name)) + name = name + "_"; + + } else if (llvm::isa(&V)) { + assert(nameStack.size() > 0 && "Name stack should not be empty."); + name = freshBlockName(); + + } else if (llvm::isa(&V)) { + return freshVarName(V); + + } else if (llvm::isa(&V)) { + assert(nameStack.size() > 0 && "Name stack should not be empty."); + name = freshVarName(V); + + } else { + name = ""; + } + + if (nameStack.size() > 0) + nameStack.top()[&V] = name; + return name; +} + +string Naming::freshBlockName() { + stringstream s; + s << BLOCK_LBL << blockNum++; + return s.str(); +} + +string Naming::freshVarName(const llvm::Value& V) { + stringstream s; + + if (llvm::isa(&V)) + s << UNDEF_SYM; + + else if (V.getType()->isIntegerTy(1)) + s << BOOL_VAR; + + else if (V.getType()->isFloatingPointTy()) + s << FLOAT_VAR; + + else + s << PTR_VAR; + + s << varNum++; + return s.str(); +} + +} diff --git a/lib/smack/Slicing.cpp b/lib/smack/Slicing.cpp new file mode 100644 index 000000000..eae175a45 --- /dev/null +++ b/lib/smack/Slicing.cpp @@ -0,0 +1,269 @@ +// +// This file is distributed under the MIT License. See LICENSE for details. +// + +#include "smack/Slicing.h" +#include "smack/SmackInstGenerator.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Analysis/CFG.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/Debug.h" +#include +#include +#include + +using namespace std; +using namespace llvm; + +namespace smack { + +typedef SmallVector< pair, 10 > EdgeList; + +bool contains(EdgeList& backedges, const BasicBlock* src, const BasicBlock* tgt) { + for (EdgeList::iterator E = backedges.begin(), End = backedges.end(); E != End; ++E) { + if (E->first == src && E->second == tgt) + return true; + } + return false; +} + +bool hasIncomingBackEdge(PHINode* Phi, EdgeList& backedges) { + for (PHINode::block_iterator B = Phi->block_begin(); B != Phi->block_end(); ++B) { + if (contains(backedges,*B,Phi->getParent())) + return true; + } + return false; +} + +Value* getQuantifiedVariable(Instruction* I) { + if (CallInst* CI = dyn_cast(I)) + if (Function* F = CI->getCalledFunction()) + if (F->hasName() && F->getName().find("qvar") != string::npos) + if (ConstantExpr* CE = dyn_cast(CI->getArgOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr) + if (GlobalValue* G = dyn_cast(CE->getOperand(0))) + if (ConstantDataSequential* S = dyn_cast(G->getOperand(0))) + return S; + return 0; +} + +GlobalValue* usedGlobal(User* U) { + GlobalValue* G = 0; + for (User::op_iterator V = U->op_begin(), E = U->op_end(); V != E; ++V) { + if (dyn_cast(V)) + continue; + if ((G = dyn_cast(V))) + break; + if ((U = dyn_cast(V)) && (G = usedGlobal(U))) + break; + } + return G; +} + +Slice* getSubslice(Instruction* I, Slices& slices) { + if (CallInst* CI = dyn_cast(I)) + if (Function* F = CI->getCalledFunction()) + if (F->hasName()) + if (F->getName().find("forall") != string::npos || + F->getName().find("exists") != string::npos) + if (ConstantInt* C = dyn_cast(CI->getArgOperand(1))) { + uint64_t i = C->getLimitedValue(); + assert(slices.size() > i && "Did not find expression."); + return slices[i]; + } + + return 0; +} + +pair getParameter(Value* V, Naming& naming, SmackRep& rep) { + + if (GlobalVariable* G = dyn_cast(V)) { + unsigned r = rep.getRegion(G); + return make_pair(rep.memReg(r), rep.memType(r)); + } + + else if (ConstantDataSequential* S = dyn_cast(V)) + return make_pair(S->getAsCString(), "int"); + + else if (V->hasName() && V->getName().find("result") != string::npos) + return make_pair(Naming::RET_VAR, rep.type(V)); + + else + return make_pair(naming.get(*V), rep.type(V)); +} + +Slice::Slice(Instruction& I, Slices& S, string name) + : value(I), block(*I.getParent()), function(*block.getParent()), + context(function.getContext()), slices(S), name(name) { + + EdgeList backedges; + FindFunctionBackedges(function, backedges); + + queue workList; + workList.push(&I); + + while (!workList.empty()) { + Instruction* I = workList.front(); + workList.pop(); + if (values.count(I) || inputs.count(I)) + continue; + + if (PHINode* Phi = dyn_cast(I)) { + if (hasIncomingBackEdge(Phi, backedges)) { + inputs.insert(I); + continue; + } + } + + if (GlobalValue* G = usedGlobal(I)) + inputs.insert(G); + + if (Value* Q = getQuantifiedVariable(I)) + inputs.insert(Q); + + // Add inputs from any subslices, excluding quantified variables + if (Slice* S = getSubslice(I,slices)) + for (unordered_set::iterator V = S->inputs.begin(), + E = S->inputs.end(); V != E; ++V) + if (!inputs.count(*V) && !dyn_cast(*V)) + inputs.insert(*V); + + values.insert(I); + values.insert(I->getParent()); + + // ENSURE EACH BLOCK HAS A TERMINATOR + if (BranchInst* Br = dyn_cast(I->getParent()->getTerminator())) + if (I->getParent() != &block) + workList.push(Br); + + if (BranchInst* Br = dyn_cast(I)) { + if (Br->isConditional()) { + if (Instruction* J = dyn_cast(Br->getCondition())) { + workList.push(J); + } + values.insert(Br->getSuccessor(1)); + } + values.insert(Br->getSuccessor(0)); + continue; + } + + if (PHINode* Phi = dyn_cast(I)) { + for (PHINode::block_iterator B = Phi->block_begin(); B != Phi->block_end(); ++B) { + workList.push( (*B)->getTerminator() ); + } + } + + for (User::op_iterator U = I->op_begin(); U != I->op_end(); ++U) { + if (Instruction* J = dyn_cast(U)) { + if (!contains(backedges,J->getParent(),I->getParent())) { + workList.push(J); + } + } + } + } + +} + +void Slice::remove() { + // Instruction* I = dyn_cast(&value); + // assert(I && "Expected instruction value."); + + // map succ; + + queue workList; + set deleted; + workList.push(&value); + + while (!workList.empty()) { + Value* V = workList.front(); + workList.pop(); + + if (deleted.count(V)) + continue; + + if (V->getNumUses() > 0) + continue; + + if (User* U = dyn_cast(V)) + for (User::op_iterator W = U->op_begin(); W != U->op_end(); ++W) + workList.push(*W); + + if (PHINode* I = dyn_cast(V)) + for (PHINode::block_iterator A = I->block_begin(), Z = I->block_end(); + A != Z; ++ A) + workList.push((*A)->getTerminator()); + + if (BranchInst* I = dyn_cast(V)) { + if (I->isConditional()) { + Value* C = I->getCondition(); + workList.push(C); + I->setCondition(UndefValue::get(C->getType())); + } + continue; + } + + if (Instruction* I = dyn_cast(V)) + I->eraseFromParent(); + + deleted.insert(V); + } +} + +string Slice::getName() { + return name; +} + +const Expr* Slice::getCode(Naming& naming, SmackRep& rep) { + CodeExpr* code = new CodeExpr(rep.getProgram()); + SmackInstGenerator igen(rep, *code, naming, slices); + + for (Function::iterator B = function.begin(), E = function.end(); B != E; ++B) { + if (!values.count(B)) + continue; + igen.visitBasicBlock(*B); + + for (BasicBlock::iterator I = B->begin(), G = B->end(); I != G; ++I) { + if (!values.count(&*I)) + continue; + igen.visit(*I); + } + + if (B == block) { + igen.emit(Stmt::return_(rep.expr(&value))); + + } else if (!values.count(B->getTerminator())) { + igen.emit(Stmt::assume(Expr::lit(false))); + igen.emit(Stmt::return_(Expr::lit(true))); + } + } + return code; +} + +const Decl* Slice::getBoogieDecl(Naming& naming, SmackRep& rep) { + if (name == "") + return 0; + naming.enter(); + vector< pair > params; + for (unordered_set::iterator V = inputs.begin(), E = inputs.end(); V != E; ++V) + params.push_back(getParameter(*V,naming,rep)); + Decl* D = Decl::function(getName(),params,"bool",getCode(naming,rep)); + D->addAttr(Attr::attr("inline")); + naming.leave(); + return D; +} + +const Expr* Slice::getBoogieExpression(Naming& naming, SmackRep& rep) { + if (name == "") { + naming.enter(); + const Expr* code = getCode(naming,rep); + naming.leave(); + return code; + } + + vector args; + for (unordered_set::iterator V = inputs.begin(), E = inputs.end(); V != E; ++V) + args.push_back(Expr::id(getParameter(*V,naming,rep).first)); + return Expr::fn(getName(),args); +} + +} diff --git a/lib/smack/SmackInstGenerator.cpp b/lib/smack/SmackInstGenerator.cpp index a0c9f289d..4c2f57238 100644 --- a/lib/smack/SmackInstGenerator.cpp +++ b/lib/smack/SmackInstGenerator.cpp @@ -1,13 +1,14 @@ // -// Copyright (c) 2008 Zvonimir Rakamaric (zvonimir@cs.utah.edu) // This file is distributed under the MIT License. See LICENSE for details. // +#define DEBUG_TYPE "smack-inst-gen" #include "smack/SmackInstGenerator.h" #include "smack/SmackOptions.h" -#include "llvm/InstVisitor.h" -#include "llvm/DebugInfo.h" +#include "smack/Slicing.h" +#include "llvm/IR/InstVisitor.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/Support/GraphWriter.h" #include @@ -22,9 +23,9 @@ const bool CODE_WARN = true; const bool SHOW_ORIG = false; #define WARN(str) \ - if (CODE_WARN) currBlock->addStmt(Stmt::comment(string("WARNING: ") + str)) + if (CODE_WARN) emit(Stmt::comment(string("WARNING: ") + str)) #define ORIG(ins) \ - if (SHOW_ORIG) currBlock->addStmt(Stmt::comment(i2s(ins))) + if (SHOW_ORIG) emit(Stmt::comment(i2s(ins))) Regex VAR_DECL("^[[:space:]]*var[[:space:]]+([[:alpha:]_.$#'`~^\\?][[:alnum:]_.$#'`~^\\?]*):.*;"); @@ -37,57 +38,56 @@ string i2s(llvm::Instruction& i) { } Block* SmackInstGenerator::createBlock() { - stringstream s; - s << SmackRep::BLOCK_LBL << blockNum++; - Block* b = new Block(proc, s.str()); - proc.addBlock(b); + Block* b = new Block(naming.freshBlockName()); + addBlock(b); return b; } -string SmackInstGenerator::createVar() { - stringstream s; - s << "$x" << varNum++; - string name = s.str(); - proc.addDecl(Decl::variable(name, rep.getPtrType())); - return name; +Block* SmackInstGenerator::getBlock(llvm::BasicBlock* bb) { + if (blockMap.count(bb) == 0) + blockMap[bb] = createBlock(); + return blockMap[bb]; } void SmackInstGenerator::nameInstruction(llvm::Instruction& inst) { - if (!inst.getType()->isVoidTy()) { - if (!inst.hasName() || !rep.isSmackGeneratedName(inst.getName())) { - if (rep.isBool(&inst)) - inst.setName(SmackRep::BOOL_VAR); - else if (rep.isFloat(&inst)) - inst.setName(SmackRep::FLOAT_VAR); - else - inst.setName(SmackRep::PTR_VAR); + if (inst.getType()->isVoidTy()) + return; + + addDecl(Decl::variable(naming.get(inst), rep.type(&inst))); +} + +void SmackInstGenerator::annotate(llvm::Instruction& I, Block* B) { + + // do not generate sourceloc from calls to llvm.debug since + // those point to variable declaration lines and such + if (llvm::CallInst* ci = llvm::dyn_cast(&I)) { + llvm::Function* f = ci->getCalledFunction(); + string name = f && f->hasName() ? f->getName().str() : ""; + if (name.find("llvm.dbg.") != string::npos) { + return; } - proc.addDecl(Decl::variable(rep.id(&inst), rep.type(&inst))); } -} -void SmackInstGenerator::annotate(llvm::Instruction& i, Block* b) { + if (llvm::MDNode* M = I.getMetadata("dbg")) { + llvm::DILocation L(M); - if (llvm::MDNode* n = i.getMetadata("dbg")) { - llvm::DILocation l(n); - if (SmackOptions::SourceLocSymbols) - b->addStmt(Stmt::annot( - Attr::attr("sourceloc", - l.getFilename().str(), - l.getLineNumber(), - l.getColumnNumber()))); + B->addStmt(Stmt::annot(Attr::attr("sourceloc", L.getFilename().str(), + L.getLineNumber(), L.getColumnNumber()))); } } void SmackInstGenerator::processInstruction(llvm::Instruction& inst) { DEBUG(errs() << "Inst: " << inst << "\n"); - DEBUG(errs() << "Inst name: " << inst.getName().str() << "\n"); annotate(inst, currBlock); ORIG(inst); nameInstruction(inst); } +void SmackInstGenerator::visitBasicBlock(llvm::BasicBlock& bb) { + currBlock = getBlock(&bb); +} + void SmackInstGenerator::visitInstruction(llvm::Instruction& inst) { DEBUG(errs() << "Instruction not handled: " << inst << "\n"); assert(false && "Instruction not handled"); @@ -107,8 +107,7 @@ void SmackInstGenerator::generatePhiAssigns(llvm::TerminatorInst& ti) { phi->getIncomingValueForBlock(block)) { nameInstruction(*phi); - currBlock->addStmt(Stmt::assign( - rep.expr(phi), rep.expr(v))); + emit(Stmt::assign(rep.expr(phi), rep.expr(v))); } } } @@ -116,7 +115,7 @@ void SmackInstGenerator::generatePhiAssigns(llvm::TerminatorInst& ti) { void SmackInstGenerator::generateGotoStmts( llvm::Instruction& inst, - vector > targets) { + vector > targets) { assert(targets.size() > 0); @@ -124,17 +123,27 @@ void SmackInstGenerator::generateGotoStmts( vector dispatch; for (unsigned i = 0; i < targets.size(); i++) { - Block* b = createBlock(); - annotate(inst, b); - b->addStmt(Stmt::assume(targets[i].first)); - b->addStmt(Stmt::goto_(targets[i].second)); - dispatch.push_back(b->getName()); + const Expr* condition = targets[i].first; + llvm::BasicBlock* target = targets[i].second; + + if (target->getUniquePredecessor() == inst.getParent()) { + Block* b = getBlock(target); + b->insert(Stmt::assume(condition)); + dispatch.push_back(b->getName()); + + } else { + Block* b = createBlock(); + annotate(inst, b); + b->addStmt(Stmt::assume(condition)); + b->addStmt(Stmt::goto_(getBlock(target)->getName())); + dispatch.push_back(b->getName()); + } } - currBlock->addStmt(Stmt::goto_(dispatch)); + emit(Stmt::goto_(dispatch)); } else - currBlock->addStmt(Stmt::goto_(targets[0].second)); + emit(Stmt::goto_(getBlock(targets[0].second)->getName())); } /******************************************************************************/ @@ -144,38 +153,37 @@ void SmackInstGenerator::generateGotoStmts( void SmackInstGenerator::visitReturnInst(llvm::ReturnInst& ri) { processInstruction(ri); - if (llvm::Value* v = ri.getReturnValue()) - currBlock->addStmt(Stmt::assign( - Expr::id(SmackRep::RET_VAR), rep.expr(v))); + llvm::Value* v = ri.getReturnValue(); - currBlock->addStmt(Stmt::return_()); + if (proc.isProc()) { + if (v) + emit(Stmt::assign(Expr::id(Naming::RET_VAR), rep.expr(v))); + emit(Stmt::assign(Expr::id(Naming::EXN_VAR), Expr::lit(false))); + emit(Stmt::return_()); + } else { + assert (v && "Expected return value."); + emit(Stmt::return_(rep.expr(v))); + } } void SmackInstGenerator::visitBranchInst(llvm::BranchInst& bi) { processInstruction(bi); // Collect the list of tarets - vector > targets; + vector > targets; if (bi.getNumSuccessors() == 1) { // Unconditional branch - assert(blockMap.count(bi.getSuccessor(0)) != 0); - targets.push_back(make_pair(Expr::lit(true), - blockMap[bi.getSuccessor(0)]->getName())); + targets.push_back(make_pair(Expr::lit(true),bi.getSuccessor(0))); } else { // Conditional branch assert(bi.getNumSuccessors() == 2); - assert(blockMap.count(bi.getSuccessor(0)) != 0); - assert(blockMap.count(bi.getSuccessor(1)) != 0); - const Expr* e = rep.expr(bi.getCondition()); - targets.push_back(make_pair(e, - blockMap[bi.getSuccessor(0)]->getName())); - targets.push_back(make_pair(Expr::not_(e), - blockMap[bi.getSuccessor(1)]->getName())); + targets.push_back(make_pair(e,bi.getSuccessor(0))); + targets.push_back(make_pair(Expr::not_(e),bi.getSuccessor(1))); } generatePhiAssigns(bi); generateGotoStmts(bi, targets); @@ -185,7 +193,7 @@ void SmackInstGenerator::visitSwitchInst(llvm::SwitchInst& si) { processInstruction(si); // Collect the list of tarets - vector > targets; + vector > targets; const Expr* e = rep.expr(si.getCondition()); const Expr* n = Expr::lit(true); @@ -193,37 +201,59 @@ void SmackInstGenerator::visitSwitchInst(llvm::SwitchInst& si) { for (llvm::SwitchInst::CaseIt i = si.case_begin(); i != si.case_begin(); ++i) { - assert(blockMap.count(i.getCaseSuccessor()) != 0); const Expr* v = rep.expr(i.getCaseValue()); - targets.push_back(make_pair(Expr::eq(e, v), - blockMap[i.getCaseSuccessor()]->getName())); + targets.push_back(make_pair(Expr::eq(e,v),i.getCaseSuccessor())); // Add the negation of this case to the default case n = Expr::and_(n, Expr::neq(e, v)); } // The default case - assert(blockMap.count(si.getDefaultDest()) != 0); - targets.push_back(make_pair(n, - blockMap[si.getDefaultDest()]->getName())); + targets.push_back(make_pair(n,si.getDefaultDest())); generatePhiAssigns(si); generateGotoStmts(si, targets); } +void SmackInstGenerator::visitInvokeInst(llvm::InvokeInst& ii) { + processInstruction(ii); + llvm::Function* f = ii.getCalledFunction(); + if (f) { + emit(rep.call(f, ii)); + } else { + // assert(false && "unexpected invoke instruction."); + WARN("unsoundly ignoring invoke instruction... "); + } + vector > targets; + targets.push_back(make_pair( + Expr::not_(Expr::id(Naming::EXN_VAR)), + ii.getNormalDest())); + targets.push_back(make_pair( + Expr::id(Naming::EXN_VAR), + ii.getUnwindDest())); + generateGotoStmts(ii, targets); +} + +void SmackInstGenerator::visitResumeInst(llvm::ResumeInst& ri) { + processInstruction(ri); + emit(Stmt::assign(Expr::id(Naming::EXN_VAR), Expr::lit(true))); + emit(Stmt::assign(Expr::id(Naming::EXN_VAL_VAR), rep.expr(ri.getValue()))); + emit(Stmt::return_()); +} + void SmackInstGenerator::visitUnreachableInst(llvm::UnreachableInst& ii) { processInstruction(ii); - currBlock->addStmt(Stmt::assume(Expr::lit(false))); + emit(Stmt::assume(Expr::lit(false))); } /******************************************************************************/ /* BINARY OPERATIONS */ /******************************************************************************/ -void SmackInstGenerator::visitBinaryOperator(llvm::BinaryOperator& bo) { - processInstruction(bo); - currBlock->addStmt(Stmt::assign(rep.expr(&bo), rep.op(&bo))); +void SmackInstGenerator::visitBinaryOperator(llvm::BinaryOperator& I) { + processInstruction(I); + emit(Stmt::assign(rep.expr(&I),rep.bop(&I))); } /******************************************************************************/ @@ -236,7 +266,47 @@ void SmackInstGenerator::visitBinaryOperator(llvm::BinaryOperator& bo) { /* AGGREGATE OPERATIONS */ /******************************************************************************/ -// TODO implement aggregate operations +void SmackInstGenerator::visitExtractValueInst(llvm::ExtractValueInst& evi) { + processInstruction(evi); + const Expr* e = rep.expr(evi.getAggregateOperand()); + for (unsigned i = 0; i < evi.getNumIndices(); i++) + e = Expr::fn("$extractvalue", e, Expr::lit((int)evi.getIndices()[i])); + emit(Stmt::assign(rep.expr(&evi),e)); +} + +void SmackInstGenerator::visitInsertValueInst(llvm::InsertValueInst& ivi) { + processInstruction(ivi); + const Expr* old = rep.expr(ivi.getAggregateOperand()); + const Expr* res = rep.expr(&ivi); + const llvm::Type* t = ivi.getType(); + + for (unsigned i = 0; i < ivi.getNumIndices(); i++) { + unsigned idx = ivi.getIndices()[i]; + + unsigned num_elements; + if (const llvm::StructType* st = llvm::dyn_cast(t)) { + num_elements = st->getNumElements(); + t = st->getElementType(idx); + } else if (const llvm::ArrayType* at = llvm::dyn_cast(t)) { + num_elements = at->getNumElements(); + t = at->getElementType(); + } else { + assert (false && "Unexpected aggregate type"); + } + + for (unsigned j = 0; j < num_elements; j++) { + if (j != idx) { + emit(Stmt::assume(Expr::eq( + Expr::fn("$extractvalue", res, Expr::lit((int)j)), + Expr::fn("$extractvalue", old, Expr::lit((int)j)) + ))); + } + } + res = Expr::fn("$extractvalue", res, Expr::lit((int)idx)); + old = Expr::fn("$extractvalue", old, Expr::lit((int)idx)); + } + emit(Stmt::assume(Expr::eq(res,rep.expr(ivi.getInsertedValueOperand())))); +} /******************************************************************************/ /* MEMORY ACCESS AND ADDRESSING OPERATIONS */ @@ -244,30 +314,48 @@ void SmackInstGenerator::visitBinaryOperator(llvm::BinaryOperator& bo) { void SmackInstGenerator::visitAllocaInst(llvm::AllocaInst& ai) { processInstruction(ai); - currBlock->addStmt(rep.alloca(ai)); + emit(rep.alloca(ai)); } void SmackInstGenerator::visitLoadInst(llvm::LoadInst& li) { processInstruction(li); - currBlock->addStmt(Stmt::assign(rep.expr(&li),rep.mem(li.getPointerOperand()))); + const Expr* rhs = rep.mem(li.getPointerOperand()); + + if (rep.isFloat(&li)) + rhs = Expr::fn("$si2fp", rhs); + + emit(Stmt::assign(rep.expr(&li),rhs)); if (SmackOptions::MemoryModelDebug) { - currBlock->addStmt(Stmt::call(SmackRep::REC_MEM_OP, Expr::id(SmackRep::MEM_OP_VAL))); - currBlock->addStmt(Stmt::call("boogie_si_record_int", Expr::lit(0))); - currBlock->addStmt(Stmt::call("boogie_si_record_int", rep.expr(li.getPointerOperand()))); - currBlock->addStmt(Stmt::call("boogie_si_record_int", rep.expr(&li))); + emit(Stmt::call(SmackRep::REC_MEM_OP, Expr::id(SmackRep::MEM_OP_VAL))); + emit(Stmt::call("boogie_si_record_int", Expr::lit(0))); + emit(Stmt::call("boogie_si_record_int", rep.expr(li.getPointerOperand()))); + emit(Stmt::call("boogie_si_record_int", rep.expr(&li))); } } void SmackInstGenerator::visitStoreInst(llvm::StoreInst& si) { processInstruction(si); - currBlock->addStmt(Stmt::assign(rep.mem(si.getPointerOperand()),rep.expr(si.getOperand(0)))); - + const llvm::Value* P = si.getPointerOperand(); + const llvm::Value* E = si.getOperand(0); + const Expr* rhs = rep.expr(E); + const llvm::GlobalVariable* G = llvm::dyn_cast(P); + + if (rep.isFloat(E)) + rhs = Expr::fn("$fp2si", rhs); + + emit(Stmt::assign(rep.mem(P),rhs)); + + if (SmackOptions::SourceLocSymbols && G) { + assert(G->hasName() && "Expected named global variable."); + emit(Stmt::call("boogie_si_record_int", rhs, Attr::attr("cexpr", G->getName().str()))); + } + if (SmackOptions::MemoryModelDebug) { - currBlock->addStmt(Stmt::call(SmackRep::REC_MEM_OP, Expr::id(SmackRep::MEM_OP_VAL))); - currBlock->addStmt(Stmt::call("boogie_si_record_int", Expr::lit(1))); - currBlock->addStmt(Stmt::call("boogie_si_record_int", rep.expr(si.getPointerOperand()))); - currBlock->addStmt(Stmt::call("boogie_si_record_int", rep.expr(si.getOperand(0)))); + emit(Stmt::call(SmackRep::REC_MEM_OP, Expr::id(SmackRep::MEM_OP_VAL))); + emit(Stmt::call("boogie_si_record_int", Expr::lit(1))); + emit(Stmt::call("boogie_si_record_int", rep.expr(P))); + emit(Stmt::call("boogie_si_record_int", rep.expr(E))); } } @@ -277,60 +365,22 @@ void SmackInstGenerator::visitAtomicCmpXchgInst(llvm::AtomicCmpXchgInst& i) { const Expr* ptr = rep.mem(i.getOperand(0)); const Expr* cmp = rep.expr(i.getOperand(1)); const Expr* swp = rep.expr(i.getOperand(2)); - currBlock->addStmt(Stmt::assign(res,ptr)); - currBlock->addStmt(Stmt::assign(ptr,Expr::cond(Expr::eq(ptr,cmp),swp,ptr))); + emit(Stmt::assign(res,ptr)); + emit(Stmt::assign(ptr,Expr::cond(Expr::eq(ptr,cmp),swp,ptr))); } void SmackInstGenerator::visitAtomicRMWInst(llvm::AtomicRMWInst& i) { + using llvm::AtomicRMWInst; processInstruction(i); - const Expr* res = rep.expr(&i); const Expr* mem = rep.mem(i.getPointerOperand()); const Expr* val = rep.expr(i.getValOperand()); - const Expr* op; - - switch (i.getOperation()) { - using llvm::AtomicRMWInst; - case AtomicRMWInst::Xchg: - op = val; - break; - case AtomicRMWInst::Add: - op = Expr::fn(SmackRep::ADD,mem,val); - break; - case AtomicRMWInst::Sub: - op = Expr::fn(SmackRep::SUB,mem,val); - break; - case AtomicRMWInst::And: - op = Expr::fn(SmackRep::AND,mem,val); - break; - case AtomicRMWInst::Nand: - op = Expr::fn(SmackRep::NAND,mem,val); - break; - case AtomicRMWInst::Or: - op = Expr::fn(SmackRep::OR,mem,val); - break; - case AtomicRMWInst::Xor: - op = Expr::fn(SmackRep::XOR,mem,val); - break; - case AtomicRMWInst::Max: - op = Expr::fn(SmackRep::MAX,mem,val); - break; - case AtomicRMWInst::Min: - op = Expr::fn(SmackRep::MIN,mem,val); - break; - case AtomicRMWInst::UMax: - op = Expr::fn(SmackRep::UMAX,mem,val); - break; - case AtomicRMWInst::UMin: - op = Expr::fn(SmackRep::UMIN,mem,val); - break; - default: - assert(false && "unexpected atomic operation."); - } - - currBlock->addStmt(Stmt::assign(res,mem)); - currBlock->addStmt(Stmt::assign(mem,op)); -} + emit(Stmt::assign(res,mem)); + emit(Stmt::assign(mem, + i.getOperation() == AtomicRMWInst::Xchg + ? val + : Expr::fn(rep.armwop2fn(i.getOperation()),mem,val) )); + } void SmackInstGenerator::visitGetElementPtrInst(llvm::GetElementPtrInst& gepi) { processInstruction(gepi); @@ -342,7 +392,7 @@ void SmackInstGenerator::visitGetElementPtrInst(llvm::GetElementPtrInst& gepi) { ps.push_back(gepi.getOperand(i)); ts.push_back(*typeI); } - currBlock->addStmt(Stmt::assign(rep.expr(&gepi), + emit(Stmt::assign(rep.expr(&gepi), rep.ptrArith(gepi.getPointerOperand(), ps, ts))); } @@ -350,84 +400,18 @@ void SmackInstGenerator::visitGetElementPtrInst(llvm::GetElementPtrInst& gepi) { /* CONVERSION OPERATIONS */ /******************************************************************************/ -void SmackInstGenerator::visitTruncInst(llvm::TruncInst& ti) { - processInstruction(ti); - currBlock->addStmt(Stmt::assign(rep.expr(&ti), - rep.trunc(ti.getOperand(0),ti.getType()))); -} - -void SmackInstGenerator::visitZExtInst(llvm::ZExtInst& ci) { - processInstruction(ci); - currBlock->addStmt(Stmt::assign(rep.expr(&ci), - rep.zext(ci.getOperand(0),ci.getType()))); -} - -void SmackInstGenerator::visitSExtInst(llvm::SExtInst& ci) { - processInstruction(ci); - currBlock->addStmt(Stmt::assign(rep.expr(&ci), - rep.sext(ci.getOperand(0),ci.getType()))); -} - -void SmackInstGenerator::visitFPTruncInst(llvm::FPTruncInst& i) { - processInstruction(i); - currBlock->addStmt(Stmt::assign(rep.expr(&i), - rep.fptrunc(i.getOperand(0),i.getType()))); -} - -void SmackInstGenerator::visitFPExtInst(llvm::FPExtInst& i) { - processInstruction(i); - currBlock->addStmt(Stmt::assign(rep.expr(&i), - rep.fpext(i.getOperand(0),i.getType()))); -} - -void SmackInstGenerator::visitFPToUIInst(llvm::FPToUIInst& i) { - processInstruction(i); - currBlock->addStmt(Stmt::assign(rep.expr(&i),rep.fp2ui(i.getOperand(0)))); -} - -void SmackInstGenerator::visitFPToSIInst(llvm::FPToSIInst& i) { - processInstruction(i); - currBlock->addStmt(Stmt::assign(rep.expr(&i),rep.fp2si(i.getOperand(0)))); -} - -void SmackInstGenerator::visitUIToFPInst(llvm::UIToFPInst& i) { - processInstruction(i); - currBlock->addStmt(Stmt::assign(rep.expr(&i),rep.ui2fp(i.getOperand(0)))); -} - -void SmackInstGenerator::visitSIToFPInst(llvm::SIToFPInst& i) { - processInstruction(i); - currBlock->addStmt(Stmt::assign(rep.expr(&i),rep.si2fp(i.getOperand(0)))); -} - -void SmackInstGenerator::visitPtrToIntInst(llvm::PtrToIntInst& i) { - processInstruction(i); - currBlock->addStmt(Stmt::assign(rep.expr(&i),rep.p2i(i.getOperand(0)))); -} - -void SmackInstGenerator::visitIntToPtrInst(llvm::IntToPtrInst& i) { - processInstruction(i); - currBlock->addStmt(Stmt::assign(rep.expr(&i),rep.i2p(i.getOperand(0)))); -} - -void SmackInstGenerator::visitBitCastInst(llvm::BitCastInst& ci) { - processInstruction(ci); - currBlock->addStmt(Stmt::assign(rep.expr(&ci), - rep.bitcast(ci.getOperand(0),ci.getType()))); +void SmackInstGenerator::visitCastInst(llvm::CastInst& I) { + processInstruction(I); + emit(Stmt::assign(rep.expr(&I),rep.cast(&I))); } /******************************************************************************/ /* OTHER OPERATIONS */ /******************************************************************************/ -void SmackInstGenerator::visitICmpInst(llvm::ICmpInst& ci) { - processInstruction(ci); - currBlock->addStmt(Stmt::assign(rep.expr(&ci), rep.pred(ci))); -} - -void SmackInstGenerator::visitFCmpInst(llvm::FCmpInst& ci) { - processInstruction(ci); - currBlock->addStmt(Stmt::assign(rep.expr(&ci), rep.pred(ci))); +void SmackInstGenerator::visitCmpInst(llvm::CmpInst& I) { + processInstruction(I); + emit(Stmt::assign(rep.expr(&I),rep.cmp(&I))); } void SmackInstGenerator::visitPHINode(llvm::PHINode& phi) { @@ -438,14 +422,14 @@ void SmackInstGenerator::visitPHINode(llvm::PHINode& phi) { void SmackInstGenerator::visitSelectInst(llvm::SelectInst& i) { processInstruction(i); - string x = rep.id(&i); + string x = naming.get(i); const Expr *c = rep.expr(i.getOperand(0)), *v1 = rep.expr(i.getOperand(1)), *v2 = rep.expr(i.getOperand(2)); - currBlock->addStmt(Stmt::havoc(x)); - currBlock->addStmt(Stmt::assume(Expr::and_( + emit(Stmt::havoc(x)); + emit(Stmt::assume(Expr::and_( Expr::impl(c, Expr::eq(Expr::id(x), v1)), Expr::impl(Expr::not_(c), Expr::eq(Expr::id(x), v2)) ))); @@ -455,34 +439,87 @@ void SmackInstGenerator::visitCallInst(llvm::CallInst& ci) { processInstruction(ci); llvm::Function* f = ci.getCalledFunction(); + string name = f && f->hasName() ? f->getName().str() : ""; if (ci.isInlineAsm()) { WARN("unsoundly ignoring inline asm call: " + i2s(ci)); - currBlock->addStmt(Stmt::skip()); - - } else if (f && rep.id(f).find("llvm.dbg.") != string::npos) { + emit(Stmt::skip()); + + } else if (name == "llvm.dbg.value" && SmackOptions::SourceLocSymbols) { + const llvm::MDNode* m1 = dyn_cast(ci.getArgOperand(0)); + const llvm::MDNode* m2 = dyn_cast(ci.getArgOperand(2)); + assert(m1 && "Expected metadata node in first argument to llvm.dbg.value."); + assert(m2 && "Expected metadata node in third argument to llvm.dbg.value."); + const llvm::MDString* m3 = dyn_cast(m2->getOperand(2)); + assert(m3 && "Expected metadata string in the third argument to metadata node."); + + if (const llvm::Value* V = m1->getOperand(0)) { + string recordProc; + if (rep.isBool(V)) recordProc = "boogie_si_record_bool"; + else if (rep.isFloat(V)) recordProc = "boogie_si_record_float"; + else recordProc = "boogie_si_record_int"; + emit(Stmt::call(recordProc,rep.expr(V),Attr::attr("cexpr", m3->getString().str()))); + } + + } else if (name.find("llvm.dbg.") != string::npos) { WARN("ignoring llvm.debug call."); - currBlock->addStmt(Stmt::skip()); + emit(Stmt::skip()); - } else if (f && rep.id(f) == "__SMACK_mod") { - proc.addMod(rep.code(ci)); + } else if (name.find("__SMACK_mod") != string::npos) { + addMod(rep.code(ci)); - } else if (f && rep.id(f) == "__SMACK_code") { - currBlock->addStmt(Stmt::code(rep.code(ci))); + } else if (name.find("__SMACK_code") != string::npos) { + emit(Stmt::code(rep.code(ci))); - } else if (f && rep.id(f) == "__SMACK_decl") { - proc.addDecl(Decl::code(rep.code(ci))); + } else if (name.find("__SMACK_decl") != string::npos) { + addDecl(Decl::code(rep.code(ci))); - } else if (f && rep.id(f) == "__SMACK_top_decl") { + } else if (name.find("__SMACK_top_decl") != string::npos) { string decl = rep.code(ci); - proc.getProg().addDecl(Decl::code(decl)); + addTopDecl(Decl::code(decl)); if (VAR_DECL.match(decl)) { string var = VAR_DECL.sub("\\1",decl); rep.addBplGlobal(var); } + } else if (name == "result") { + assert(ci.getNumArgOperands() == 0 && "Unexpected operands to result."); + emit(Stmt::assign(rep.expr(&ci),Expr::id(Naming::RET_VAR))); + + } else if (name == "qvar") { + assert(ci.getNumArgOperands() == 1 && "Unexpected operands to qvar."); + emit(Stmt::assign(rep.expr(&ci),Expr::id(rep.getString(ci.getArgOperand(0))))); + + } else if (name == "old") { + assert(ci.getNumArgOperands() == 1 && "Unexpected operands to old."); + llvm::LoadInst* LI = llvm::dyn_cast(ci.getArgOperand(0)); + assert(LI && "Expected value from Load."); + emit(Stmt::assign(rep.expr(&ci), + Expr::fn("old",rep.mem(LI->getPointerOperand())) )); + + } else if (name == "forall") { + assert(ci.getNumArgOperands() == 2 && "Unexpected operands to forall."); + Value* var = ci.getArgOperand(0); + Value* arg = ci.getArgOperand(1); + Slice* S = getSlice(arg); + emit(Stmt::assign(rep.expr(&ci), + Expr::forall(rep.getString(var), "int", S->getBoogieExpression(naming,rep)))); + + } else if (name == "exists") { + assert(ci.getNumArgOperands() == 2 && "Unexpected operands to forall."); + Value* var = ci.getArgOperand(0); + Value* arg = ci.getArgOperand(1); + Slice* S = getSlice(arg); + emit(Stmt::assign(rep.expr(&ci), + Expr::exists(rep.getString(var), "int", S->getBoogieExpression(naming,rep)))); + + } else if (name == "invariant") { + assert(ci.getNumArgOperands() == 1 && "Unexpected operands to invariant."); + Slice* S = getSlice(ci.getArgOperand(0)); + emit(Stmt::assert_(S->getBoogieExpression(naming,rep))); + } else if (f) { - currBlock->addStmt(rep.call(f, ci)); + emit(rep.call(f, ci)); } else { // function pointer call... @@ -497,9 +534,9 @@ void SmackInstGenerator::visitCallInst(llvm::CallInst& ci) { if (ce->isCast()) { llvm::Value* castValue = ce->getOperand(0); if (llvm::Function* castFunc = llvm::dyn_cast(castValue)) { - currBlock->addStmt(rep.call(castFunc, ci)); + emit(rep.call(castFunc, ci)); if (castFunc->isDeclaration() && rep.isExternal(&ci)) - currBlock->addStmt(Stmt::assume(Expr::fn("$isExternal",rep.expr(&ci)))); + emit(Stmt::assume(Expr::fn("$isExternal",rep.expr(&ci)))); return; } } @@ -519,7 +556,7 @@ void SmackInstGenerator::visitCallInst(llvm::CallInst& ci) { if (fs.size() == 1) { // Q: is this case really possible? - currBlock->addStmt(rep.call(fs[0], ci)); + emit(rep.call(fs[0], ci)); } else if (fs.size() > 1) { Block* tail = createBlock(); @@ -537,7 +574,7 @@ void SmackInstGenerator::visitCallInst(llvm::CallInst& ci) { } // Jump to the dispatch blocks. - currBlock->addStmt(Stmt::goto_(targets)); + emit(Stmt::goto_(targets)); // Update the current block for subsequent visits. currBlock = tail; @@ -546,12 +583,21 @@ void SmackInstGenerator::visitCallInst(llvm::CallInst& ci) { // In the worst case, we have no idea what function may have // been called... WARN("unsoundly ignoring indeterminate call: " + i2s(ci)); - currBlock->addStmt(Stmt::skip()); + emit(Stmt::skip()); } } if (f && f->isDeclaration() && rep.isExternal(&ci)) - currBlock->addStmt(Stmt::assume(Expr::fn("$isExternal",rep.expr(&ci)))); + emit(Stmt::assume(Expr::fn("$isExternal",rep.expr(&ci)))); +} + +void SmackInstGenerator::visitLandingPadInst(llvm::LandingPadInst& lpi) { + processInstruction(lpi); + // TODO what exactly!? + emit(Stmt::assign(rep.expr(&lpi),Expr::id(Naming::EXN_VAL_VAR))); + if (lpi.isCleanup()) + emit(Stmt::assign(Expr::id(Naming::EXN_VAR),Expr::lit(false))); + WARN("unsoundly ignoring landingpad clauses..."); } /******************************************************************************/ @@ -561,13 +607,13 @@ void SmackInstGenerator::visitCallInst(llvm::CallInst& ci) { void SmackInstGenerator::visitMemCpyInst(llvm::MemCpyInst& mci) { processInstruction(mci); assert (mci.getNumOperands() == 6); - currBlock->addStmt(rep.memcpy(mci)); + emit(rep.memcpy(mci)); } void SmackInstGenerator::visitMemSetInst(llvm::MemSetInst& msi) { processInstruction(msi); assert (msi.getNumOperands() == 6); - currBlock->addStmt(rep.memset(msi)); + emit(rep.memset(msi)); } } // namespace smack diff --git a/lib/smack/SmackModuleGenerator.cpp b/lib/smack/SmackModuleGenerator.cpp index ab0a11d70..8554119e8 100644 --- a/lib/smack/SmackModuleGenerator.cpp +++ b/lib/smack/SmackModuleGenerator.cpp @@ -1,90 +1,78 @@ // -// Copyright (c) 2008 Zvonimir Rakamaric (zvonimir@cs.utah.edu) // This file is distributed under the MIT License. See LICENSE for details. // +#define DEBUG_TYPE "smack-mod-gen" #include "smack/SmackModuleGenerator.h" #include "smack/SmackOptions.h" +#include "smack/Contracts.h" namespace smack { llvm::RegisterPass X("smack", "SMACK generator pass"); char SmackModuleGenerator::ID = 0; -void SmackModuleGenerator::generateProgram(llvm::Module& m, SmackRep* rep) { +void SmackModuleGenerator::generateProgram(llvm::Module& m) { - rep->setProgram( &program ); - rep->collectRegions(m); + Naming naming; + SmackRep rep(&getAnalysis(), naming, program); + rep.collectRegions(m); DEBUG(errs() << "Analyzing globals...\n"); for (llvm::Module::const_global_iterator x = m.global_begin(), e = m.global_end(); x != e; ++x) - program.addDecls(rep->globalDecl(x)); + program.addDecls(rep.globalDecl(x)); - if (rep->hasStaticInits()) - program.addDecl(rep->getStaticInit()); + if (rep.hasStaticInits()) + program.addDecl(rep.getStaticInit()); DEBUG(errs() << "Analyzing functions...\n"); for (llvm::Module::iterator func = m.begin(), e = m.end(); func != e; ++func) { - if (rep->isIgnore(func)) + if (rep.isIgnore(func)) continue; - if (rep->isMallocOrFree(func)) { - program.addDecls(rep->globalDecl(func)); + if (rep.isMallocOrFree(func)) { + program.addDecls(rep.globalDecl(func)); continue; } - if (!func->isVarArg()) - program.addDecls(rep->globalDecl(func)); + // TODO: Implement function pointers of vararg functions properly +// if (!func->isVarArg()) + program.addDecls(rep.globalDecl(func)); - ProcDecl* proc = rep->proc(func,0); + ProcDecl* proc = rep.proc(func,0); if (proc->getName() != "__SMACK_decls") program.addDecl(proc); if (!func->isDeclaration() && !func->empty() && !func->getEntryBlock().empty()) { - DEBUG(errs() << "Analyzing function: " << rep->id(func) << "\n"); + DEBUG(errs() << "Analyzing function: " << naming.get(*func) << "\n"); - map known; - stack workStack; - SmackInstGenerator igen(*rep, (ProcDecl&) *proc, known); + Slices slices; + ContractsExtractor ce(rep, *proc, naming, slices); + SmackInstGenerator igen(rep, *proc, naming, slices); + + naming.enter(); + DEBUG(errs() << "Extracting contracts for " << naming.get(*func) << " from "); + DEBUG(errs() << *func << "\n"); + ce.visit(func); + DEBUG(errs() << "\n"); + + DEBUG(errs() << "Generating body for " << naming.get(*func) << " from "); + DEBUG(errs() << *func << "\n"); + igen.visit(func); + DEBUG(errs() << "\n"); + naming.leave(); - llvm::BasicBlock& entry = func->getEntryBlock(); - workStack.push(&entry); - known[&entry] = igen.createBlock(); - // First execute static initializers, in the main procedure. - if (rep->id(func) == "main" && rep->hasStaticInits()) - known[&entry]->addStmt(Stmt::call(SmackRep::STATIC_INIT)); - - // INVARIANT: knownBlocks.CONTAINS(b) iff workStack.CONTAINS(b) - // or workStack.CONTAINED(b) at some point in time. - while (!workStack.empty()) { - llvm::BasicBlock* b = workStack.top(); - workStack.pop(); - - for (llvm::succ_iterator s = succ_begin(b), - e = succ_end(b); s != e; ++s) { - - // uncovered basic block - if (known.count(*s) == 0) { - known[*s] = igen.createBlock(); - workStack.push(*s); - } - } - - // NOTE: here we are sure that all successor blocks have - // already been created, and are mapped for the visitor. - - igen.setCurrBlock(known[b]); - igen.visit(b); - } + if (naming.get(*func) == "main" && rep.hasStaticInits()) + proc->insert(Stmt::call(SmackRep::STATIC_INIT)); - DEBUG(errs() << "Finished analyzing function: " << rep->id(func) << "\n\n"); + DEBUG(errs() << "Finished analyzing function: " << naming.get(*func) << "\n\n"); } // MODIFIES @@ -96,7 +84,7 @@ void SmackModuleGenerator::generateProgram(llvm::Module& m, SmackRep* rep) { for (unsigned i=0; ihasBody()) { - procs[i]->addMods(rep->getModifies()); + procs[i]->addMods(rep.getModifies()); } else { vector< pair > rets = procs[i]->getRets(); @@ -104,14 +92,14 @@ void SmackModuleGenerator::generateProgram(llvm::Module& m, SmackRep* rep) { r != rets.end(); ++r) { // TODO should only do this for returned POINTERS. - // procs[i]->addEnsures(rep->declareIsExternal(Expr::id(r->first))); + // procs[i]->addEnsures(rep.declareIsExternal(Expr::id(r->first))); } } } // NOTE we must do this after instruction generation, since we would not // otherwise know how many regions to declare. - program.appendPrelude(rep->getPrelude()); + program.appendPrelude(rep.getPrelude()); } } // namespace smack diff --git a/lib/smack/SmackOptions.cpp b/lib/smack/SmackOptions.cpp index 26cb9e991..021f4eeb3 100644 --- a/lib/smack/SmackOptions.cpp +++ b/lib/smack/SmackOptions.cpp @@ -1,6 +1,4 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // diff --git a/lib/smack/SmackRep.cpp b/lib/smack/SmackRep.cpp index 7450724df..68de17a17 100644 --- a/lib/smack/SmackRep.cpp +++ b/lib/smack/SmackRep.cpp @@ -1,8 +1,7 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // +#define DEBUG_TYPE "smack-rep" #include "smack/SmackRep.h" #include "smack/SmackOptions.h" @@ -10,11 +9,6 @@ namespace smack { -const string SmackRep::BLOCK_LBL = "$bb"; -const string SmackRep::RET_VAR = "$r"; -const string SmackRep::BOOL_VAR = "$b"; -const string SmackRep::FLOAT_VAR = "$f"; -const string SmackRep::PTR_VAR = "$p"; const string SmackRep::BOOL_TYPE = "bool"; const string SmackRep::FLOAT_TYPE = "float"; const string SmackRep::NULL_VAL = "$NULL"; @@ -24,78 +18,10 @@ const string SmackRep::MALLOC = "$malloc"; const string SmackRep::FREE = "$free"; const string SmackRep::MEMCPY = "$memcpy"; -const string SmackRep::PTR = "$ptr"; -const string SmackRep::OBJ = "$obj"; -const string SmackRep::OFF = "$off"; -const string SmackRep::PA = "$pa"; - -const string SmackRep::FP = "$fp"; - -const string SmackRep::TRUNC = "$trunc"; - const string SmackRep::B2P = "$b2p"; -const string SmackRep::I2P = "$i2p"; -const string SmackRep::P2I = "$p2i"; const string SmackRep::I2B = "$i2b"; const string SmackRep::B2I = "$b2i"; -const string SmackRep::FP2SI = "$fp2si"; -const string SmackRep::FP2UI = "$fp2ui"; -const string SmackRep::SI2FP = "$si2fp"; -const string SmackRep::UI2FP = "$ui2fp"; - -const string SmackRep::ADD = "$add"; -const string SmackRep::SUB = "$sub"; -const string SmackRep::MUL = "$mul"; -const string SmackRep::SDIV = "$sdiv"; -const string SmackRep::UDIV = "$udiv"; -const string SmackRep::SREM = "$srem"; -const string SmackRep::UREM = "$urem"; -const string SmackRep::AND = "$and"; -const string SmackRep::OR = "$or"; -const string SmackRep::XOR = "$xor"; -const string SmackRep::LSHR = "$lshr"; -const string SmackRep::ASHR = "$ashr"; -const string SmackRep::SHL = "$shl"; - -const string SmackRep::NAND = "$nand"; -const string SmackRep::MAX = "$max"; -const string SmackRep::MIN = "$min"; -const string SmackRep::UMAX = "$umax"; -const string SmackRep::UMIN = "$umin"; - -const string SmackRep::FADD = "$fadd"; -const string SmackRep::FSUB = "$fsub"; -const string SmackRep::FMUL = "$fmul"; -const string SmackRep::FDIV = "$fdiv"; -const string SmackRep::FREM = "$frem"; - -const string SmackRep::SGE = "$sge"; -const string SmackRep::UGE = "$uge"; -const string SmackRep::SLE = "$sle"; -const string SmackRep::ULE = "$ule"; -const string SmackRep::SLT = "$slt"; -const string SmackRep::ULT = "$ult"; -const string SmackRep::SGT = "$sgt"; -const string SmackRep::UGT = "$ugt"; - -const string SmackRep::FFALSE = "$ffalse"; -const string SmackRep::FOEQ = "$foeq"; -const string SmackRep::FOGE = "$foge"; -const string SmackRep::FOGT = "$fogt"; -const string SmackRep::FOLE = "$fole"; -const string SmackRep::FOLT = "$folt"; -const string SmackRep::FONE = "$fone"; -const string SmackRep::FORD = "$ford"; -const string SmackRep::FTRUE = "$ftrue"; -const string SmackRep::FUEQ = "$fueq"; -const string SmackRep::FUGE = "$fuge"; -const string SmackRep::FUGT = "$fugt"; -const string SmackRep::FULE = "$fule"; -const string SmackRep::FULT = "$fult"; -const string SmackRep::FUNE = "$fune"; -const string SmackRep::FUNO = "$funo"; - // used for memory model debugging const string SmackRep::MEM_OP = "$mop"; const string SmackRep::REC_MEM_OP = "boogie_si_record_mop"; @@ -107,52 +33,18 @@ const string SmackRep::STATIC_INIT = "$static_init"; const int SmackRep::width = 0; -// TODO Do the following functions belong here ? - -string EscapeString(string s) { - string Str(llvm::DOT::EscapeString(s)); - for (unsigned i = 0; i != Str.length(); ++i) - switch (Str[i]) { - case '\01': - Str[i] = '_'; - break; - case '@': - Str[i] = '.'; - break; - } - return Str; -} - -Regex BPL_KW( - "^(bool|int|false|true|old|forall|exists|requires|modifies|ensures|invariant|free" - "|unique|finite|complete|type|const|function|axiom|var|procedure" - "|implementation|where|returns|assume|assert|havoc|call|return|while" - "|break|goto|if|else|div)$"); -Regex SMACK_NAME(".*__SMACK_.*"); Regex PROC_MALLOC_FREE("^(malloc|free_)$"); Regex PROC_IGNORE("^(" "llvm\\.memcpy\\..*|llvm\\.memset\\..*|llvm\\.dbg\\..*|" "__SMACK_code|__SMACK_decl|__SMACK_top_decl" ")$"); -bool isBplKeyword(string s) { - return BPL_KW.match(s); -} - -bool SmackRep::isSmackName(string n) { - return SMACK_NAME.match(n); -} - -bool SmackRep::isSmackGeneratedName(string n) { - return n.size() > 0 && n[0] == '$'; -} - -bool SmackRep::isMallocOrFree(llvm::Function* f) { - return PROC_MALLOC_FREE.match(id(f)); +bool SmackRep::isMallocOrFree(const llvm::Function* f) { + return PROC_MALLOC_FREE.match(naming.get(*f)); } -bool SmackRep::isIgnore(llvm::Function* f) { - return PROC_IGNORE.match(id(f)); +bool SmackRep::isIgnore(const llvm::Function* f) { + return PROC_IGNORE.match(naming.get(*f)); } bool SmackRep::isInt(const llvm::Type* t) { @@ -163,7 +55,7 @@ bool SmackRep::isInt(const llvm::Value* v) { return isInt(v->getType()); } -bool SmackRep::isBool(llvm::Type* t) { +bool SmackRep::isBool(const llvm::Type* t) { return t->isIntegerTy(1); } @@ -171,15 +63,15 @@ bool SmackRep::isBool(const llvm::Value* v) { return isBool(v->getType()); } -bool SmackRep::isFloat(llvm::Type* t) { +bool SmackRep::isFloat(const llvm::Type* t) { return t->isFloatingPointTy(); } -bool SmackRep::isFloat(llvm::Value* v) { +bool SmackRep::isFloat(const llvm::Value* v) { return isFloat(v->getType()); } -string SmackRep::type(llvm::Type* t) { +string SmackRep::type(const llvm::Type* t) { if (isBool(t)) return BOOL_TYPE; else if (isFloat(t)) @@ -188,7 +80,7 @@ string SmackRep::type(llvm::Type* t) { return getPtrType(); } -string SmackRep::type(llvm::Value* v) { +string SmackRep::type(const llvm::Value* v) { return type(v->getType()); } @@ -206,101 +98,72 @@ string SmackRep::memReg(unsigned idx) { return s.str(); } +string SmackRep::memType(unsigned r) { + if (memoryRegions[r].isSingletonGlobal) + return getPtrType(); + else { + return "[int] int"; + stringstream s; + s << "[" << getPtrType() << "] " + getPtrType(); + return s.str(); + } +} + const Expr* SmackRep::mem(const llvm::Value* v) { - return mem( getRegion(v), expr(v) ); + unsigned r = getRegion(v); + if (memoryRegions[r].isSingletonGlobal) + return Expr::id(memReg(r)); + else + return Expr::sel(Expr::id(memReg(r)),expr(v)); } const Expr* SmackRep::mem(unsigned region, const Expr* addr) { - return Expr::sel( Expr::id(memReg(region)), addr ); + if (memoryRegions[region].isSingletonGlobal) + return Expr::id(memReg(region)); + else + return Expr::sel(Expr::id(memReg(region)),addr); } unsigned SmackRep::getRegion(const llvm::Value* v) { unsigned r; - + for (r=0; risNoAlias(v, memoryRegions[r].first)) + if (!aliasAnalysis->isNoAlias(v, memoryRegions[r].representative)) break; - if (r == memoryRegions.size()) - memoryRegions.push_back(make_pair(v,false)); - - memoryRegions[r].second = memoryRegions[r].second || aliasAnalysis->isAlloced(v); + if (r == memoryRegions.size()) { + llvm::Type* T = v->getType(); + while (T->isPointerTy()) T = T->getPointerElementType(); + memoryRegions.emplace_back(v,false, + aliasAnalysis->isSingletonGlobal(v) && T->isSingleValueType() + ); + } + memoryRegions[r].isAllocated = memoryRegions[r].isAllocated || aliasAnalysis->isAlloced(v); return r; } bool SmackRep::isExternal(const llvm::Value* v) { - return v->getType()->isPointerTy() && !memoryRegions[getRegion(v)].second; + return v->getType()->isPointerTy() && !memoryRegions[getRegion(v)].isAllocated; } void SmackRep::collectRegions(llvm::Module &M) { RegionCollector rc(*this); - - for (llvm::Module::iterator func = M.begin(), e = M.end(); - func != e; ++func) { - - for (llvm::Function::iterator block = func->begin(); - block != func->end(); ++block) { - - rc.visit(*block); - } - } -} - -const Expr* SmackRep::trunc(const llvm::Value* v, llvm::Type* t) { - assert(t->isIntegerTy() && "TODO: implement truncate for non-integer types."); - const Expr* e = expr(v); - - return isBool(t) - ? Expr::fn(I2B,e) - : Expr::fn(TRUNC,e,lit(t->getPrimitiveSizeInBits())); -} -const Expr* SmackRep::zext(const llvm::Value* v, llvm::Type* t) { - return isBool(v->getType()) ? b2p(v) : expr(v); -} -const Expr* SmackRep::sext(const llvm::Value* v, llvm::Type* t) { - return isBool(v->getType()) ? b2p(v) : expr(v); -} -const Expr* SmackRep::fptrunc(const llvm::Value* v, llvm::Type* t) { - return expr(v); -} -const Expr* SmackRep::fpext(const llvm::Value* v, llvm::Type* t) { - return expr(v); -} -const Expr* SmackRep::fp2ui(const llvm::Value* v) { - return Expr::fn(FP2UI, expr(v)); -} -const Expr* SmackRep::fp2si(const llvm::Value* v) { - return Expr::fn(FP2SI, expr(v)); -} -const Expr* SmackRep::ui2fp(const llvm::Value* v) { - return Expr::fn(UI2FP, expr(v)); -} -const Expr* SmackRep::si2fp(const llvm::Value* v) { - return Expr::fn(SI2FP, expr(v)); -} -const Expr* SmackRep::p2i(const llvm::Value* v) { - return Expr::fn(P2I, expr(v)); -} -const Expr* SmackRep::i2p(const llvm::Value* v) { - return Expr::fn(I2P, expr(v)); -} -const Expr* SmackRep::bitcast(const llvm::Value* v, llvm::Type* t) { - return expr(v); + rc.visit(M); } const Stmt* SmackRep::alloca(llvm::AllocaInst& i) { const Expr* size = - Expr::fn(MUL,lit(storageSize(i.getAllocatedType())),lit(i.getArraySize())); + Expr::fn("$mul",lit(storageSize(i.getAllocatedType())),lit(i.getArraySize())); - return Stmt::call(ALLOCA,size,id(&i)); + return Stmt::call(ALLOCA,size,naming.get(i)); } const Stmt* SmackRep::memcpy(const llvm::MemCpyInst& mci) { int dstRegion = getRegion(mci.getOperand(0)); int srcRegion = getRegion(mci.getOperand(1)); - program->addDecl(memcpyProc(dstRegion,srcRegion)); + program.addDecl(memcpyProc(dstRegion,srcRegion)); stringstream name; name << "$memcpy." << dstRegion << "." << srcRegion; @@ -313,7 +176,7 @@ const Stmt* SmackRep::memcpy(const llvm::MemCpyInst& mci) { const Stmt* SmackRep::memset(const llvm::MemSetInst& msi) { int region = getRegion(msi.getOperand(0)); - program->addDecl(memsetProc(region)); + program.addDecl(memsetProc(region)); stringstream name; vector args; @@ -330,7 +193,7 @@ const Expr* SmackRep::pa(const Expr* base, const Expr* index, int size) { return pa(base, index, Expr::lit(size)); } const Expr* SmackRep::pa(const Expr* base, const Expr* index, const Expr* size) { - return Expr::fn(PA, base, index, size); + return Expr::fn("$pa", base, index, size); } const Expr* SmackRep::b2p(const llvm::Value* v) { return Expr::fn(B2P, expr(v)); @@ -342,50 +205,38 @@ const Expr* SmackRep::b2i(const llvm::Value* v) { return Expr::fn(B2I, expr(v)); } -const Expr* SmackRep::undef() { - stringstream s; - s << "$u." << uniqueUndefNum++; - return Expr::id(s.str()); -} - -string SmackRep::id(const llvm::Value* v) { - string name; - - if (v->hasName()) { - name = v->getName().str(); - - } else { - assert(false && "expected named value."); - - // OLD NAME-HANDLING CODE - // llvm::raw_string_ostream ss(name); - // ss << *v; - // name = name.substr(name.find("%")); - // name = name.substr(0, name.find(" ")); - } - name = EscapeString(name); - - if (isBplKeyword(name)) - name = name + "_"; - - return name; -} - const Expr* SmackRep::lit(const llvm::Value* v) { + using namespace llvm; + if (const llvm::ConstantInt* ci = llvm::dyn_cast(v)) { if (ci->getBitWidth() == 1) return Expr::lit(!ci->isZero()); uint64_t val = ci->getLimitedValue(); if (width > 0 && ci->isNegative()) - return Expr::fn(SUB, Expr::lit(0, width), Expr::lit(-val, width)); + return Expr::fn("$sub", Expr::lit(0, width), Expr::lit(-val, width)); else return Expr::lit(val, width); - } else if (llvm::isa(v)) { - - // TODO encode floating point - return Expr::fn(FP,Expr::lit((int) uniqueFpNum++)); + } else if (const ConstantFP* CFP = dyn_cast(v)) { + const APFloat APF = CFP->getValueAPF(); + string str; + raw_string_ostream ss(str); + ss << *CFP; + istringstream iss(str); + string float_type; + int integerPart, fractionalPart, exponentPart; + char point, sign, exponent; + iss >> float_type; + iss >> integerPart; + iss >> point; + iss >> fractionalPart; + iss >> sign; + iss >> exponent; + iss >> exponentPart; + + return Expr::fn("$fp", Expr::lit(integerPart), Expr::lit(fractionalPart), + Expr::lit(exponentPart)); } else if (llvm::isa(v)) return Expr::lit(0, width); @@ -437,43 +288,38 @@ const Expr* SmackRep::expr(const llvm::Value* v) { if (const GlobalValue* g = dyn_cast(v)) { assert(g->hasName()); - return Expr::id(id(v)); + return Expr::id(naming.get(*v)); - } else if (v->hasName()) - return Expr::id(id(v)); + } else if (isa(v)) { + string name = naming.get(*v); + program.addDecl(Decl::constant(name,type(v->getType()))); + return Expr::id(name); - else if (const Constant* constant = dyn_cast(v)) { + } else if (naming.get(*v) != "") + return Expr::id(naming.get(*v)); - if (const ConstantExpr* constantExpr = dyn_cast(constant)) { + else if (const Constant* constant = dyn_cast(v)) { - if (constantExpr->getOpcode() == Instruction::GetElementPtr) { + if (const ConstantExpr* CE = dyn_cast(constant)) { - vector ps; - vector ts; - llvm::gep_type_iterator typeI = gep_type_begin(constantExpr); - for (unsigned i = 1; i < constantExpr->getNumOperands(); i++, ++typeI) { - ps.push_back(constantExpr->getOperand(i)); + if (CE->getOpcode() == Instruction::GetElementPtr) { + vector ps; + vector ts; + gep_type_iterator typeI = gep_type_begin(CE); + for (unsigned i = 1; i < CE->getNumOperands(); i++, ++typeI) { + ps.push_back(CE->getOperand(i)); ts.push_back(*typeI); } - return ptrArith(constantExpr->getOperand(0), ps, ts); - - } else if (constantExpr->getOpcode() == Instruction::BitCast) - - // TODO: currently this is a noop instruction - return expr(constantExpr->getOperand(0)); - - else if (constantExpr->getOpcode() == Instruction::IntToPtr) + return ptrArith(CE->getOperand(0), ps, ts); - // TODO test this out, formerly Expr::id("$UNDEF"); - return i2p(constantExpr->getOperand(0)); + } else if (CE->isCast()) + return cast(CE); - else if (constantExpr->getOpcode() == Instruction::PtrToInt) + else if (Instruction::isBinaryOp(CE->getOpcode())) + return bop(CE); - // TODO test this out, formerly Expr::id("$UNDEF"); - return p2i(constantExpr->getOperand(0)); - - else if (Instruction::isBinaryOp(constantExpr->getOpcode())) - return op(constantExpr); + else if (CE->isCompare()) + return cmp(CE); else { DEBUG(errs() << "VALUE : " << *v << "\n"); @@ -492,9 +338,6 @@ const Expr* SmackRep::expr(const llvm::Value* v) { } else if (constant->isNullValue()) return lit((unsigned)0); - else if (isa(constant)) - return undef(); - else { DEBUG(errs() << "VALUE : " << *v << "\n"); assert(false && "this type of constant not supported"); @@ -515,190 +358,162 @@ string SmackRep::getString(const llvm::Value* v) { return ""; } -const Expr* SmackRep::op(const llvm::User* v) { - using namespace llvm; - unsigned opcode; - string op; - - if (const BinaryOperator* bo = dyn_cast(v)) - opcode = bo->getOpcode(); - - else if (const ConstantExpr* ce = dyn_cast(v)) - opcode = ce->getOpcode(); +const Expr* SmackRep::cast(const llvm::Instruction* I) { + return cast(I->getOpcode(), I->getOperand(0), I->getType()); +} - else assert(false && "unexpected operator value."); +const Expr* SmackRep::cast(const llvm::ConstantExpr* CE) { + return cast(CE->getOpcode(), CE->getOperand(0), CE->getType()); +} +const Expr* SmackRep::cast(unsigned opcode, const llvm::Value* v, const llvm::Type* t) { + using namespace llvm; switch (opcode) { - using llvm::Instruction; + case Instruction::Trunc: + assert(t->isIntegerTy() && "TODO: implement truncate for non-integer types."); + return isBool(t) + ? Expr::fn("$i2b",expr(v)) + : Expr::fn("$trunc",expr(v),lit(t->getPrimitiveSizeInBits())); + + case Instruction::ZExt: + case Instruction::SExt: + return isBool(v->getType()) ? b2p(v) : expr(v); + + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::BitCast: + return expr(v); - // Integer operations - case Instruction::Add: - op = ADD; - break; - case Instruction::Sub: - op = SUB; - break; - case Instruction::Mul: - op = MUL; - break; - case Instruction::SDiv: - op = SDIV; - break; - case Instruction::UDiv: - op = UDIV; - break; - case Instruction::SRem: - op = SREM; - break; - case Instruction::URem: - op = UREM; - break; - case Instruction::And: - op = AND; - break; - case Instruction::Or: - op = OR; - break; - case Instruction::Xor: - op = XOR; - break; - case Instruction::LShr: - op = LSHR; - break; - case Instruction::AShr: - op = ASHR; - break; - case Instruction::Shl: - op = SHL; - break; - - // Floating point operations - case Instruction::FAdd: - op = FADD; - break; - case Instruction::FSub: - op = FSUB; - break; - case Instruction::FMul: - op = FMUL; - break; - case Instruction::FDiv: - op = FDIV; - break; - case Instruction::FRem: - op = FREM; - break; - default: - assert(false && "unexpected predicate."); + return Expr::fn(cast2fn(opcode), expr(v)); } - llvm::Value - *l = v->getOperand(0), - *r = v->getOperand(1); +} - const Expr* e = Expr::fn(op, - (isBool(l) ? b2i(l) : expr(l)), - (isBool(r) ? b2i(r) : expr(r))); +const Expr* SmackRep::bop(const llvm::ConstantExpr* CE) { + return bop(CE->getOpcode(), CE->getOperand(0), CE->getOperand(1), CE->getType()); +} - return isBool(v) ? Expr::fn("$i2b",e) : e; +const Expr* SmackRep::bop(const llvm::BinaryOperator* BO) { + return bop(BO->getOpcode(), BO->getOperand(0), BO->getOperand(1), BO->getType()); } -const Expr* SmackRep::pred(llvm::CmpInst& ci) { - const Expr* e = NULL; - string o; - const Expr - *l = expr(ci.getOperand(0)), - *r = expr(ci.getOperand(1)); +const Expr* SmackRep::bop(unsigned opcode, const llvm::Value* lhs, const llvm::Value* rhs, const llvm::Type* t) { + const Expr* e = Expr::fn(bop2fn(opcode), + (isBool(lhs) ? b2i(lhs) : expr(lhs)), + (isBool(rhs) ? b2i(rhs) : expr(rhs))); - switch (ci.getPredicate()) { - using llvm::CmpInst; + return isBool(t) ? Expr::fn("$i2b",e) : e; +} + +const Expr* SmackRep::cmp(const llvm::CmpInst* I) { + return cmp(I->getPredicate(), I->getOperand(0), I->getOperand(1)); +} - // integer comparison +const Expr* SmackRep::cmp(const llvm::ConstantExpr* CE) { + return cmp(CE->getPredicate(), CE->getOperand(0), CE->getOperand(1)); +} + +const Expr* SmackRep::cmp(unsigned predicate, const llvm::Value* lhs, const llvm::Value* rhs) { + using namespace llvm; + switch (predicate) { + using llvm::CmpInst; case CmpInst::ICMP_EQ: - e = Expr::eq(l, r); - break; + return Expr::eq(expr(lhs), expr(rhs)); case CmpInst::ICMP_NE: - e = Expr::neq(l, r); - break; - case CmpInst::ICMP_SGE: - o = SGE; - break; - case CmpInst::ICMP_UGE: - o = UGE; - break; - case CmpInst::ICMP_SLE: - o = SLE; - break; - case CmpInst::ICMP_ULE: - o = ULE; - break; - case CmpInst::ICMP_SLT: - o = SLT; - break; - case CmpInst::ICMP_ULT: - o = ULT; - break; - case CmpInst::ICMP_SGT: - o = SGT; - break; - case CmpInst::ICMP_UGT: - o = UGT; - break; - - // floating point comparison - case CmpInst::FCMP_FALSE: - o = FFALSE; - break; - case CmpInst::FCMP_OEQ: - o = FOEQ; - break; - case CmpInst::FCMP_OGE: - o = FOGE; - break; - case CmpInst::FCMP_OGT: - o = FOGT; - break; - case CmpInst::FCMP_OLE: - o = FOLE; - break; - case CmpInst::FCMP_OLT: - o = FOLT; - break; - case CmpInst::FCMP_ONE: - o = FONE; - break; - case CmpInst::FCMP_ORD: - o = FORD; - break; - case CmpInst::FCMP_TRUE: - o = FTRUE; - break; - case CmpInst::FCMP_UEQ: - o = FUEQ; - break; - case CmpInst::FCMP_UGE: - o = FUGE; - break; - case CmpInst::FCMP_UGT: - o = FUGT; - break; - case CmpInst::FCMP_ULE: - o = FULE; - break; - case CmpInst::FCMP_ULT: - o = FULT; - break; - case CmpInst::FCMP_UNE: - o = FUNE; - break; - case CmpInst::FCMP_UNO: - o = FUNO; - break; + return Expr::neq(expr(lhs), expr(rhs)); + default: + return Expr::fn(pred2fn(predicate), expr(lhs), expr(rhs)); + } +} + +string SmackRep::cast2fn(unsigned opcode) { + using llvm::Instruction; + switch (opcode) { + case Instruction::FPToUI: return "$fp2ui"; + case Instruction::FPToSI: return "$fp2si"; + case Instruction::UIToFP: return "$ui2fp"; + case Instruction::SIToFP: return "$si2fp"; + case Instruction::PtrToInt: return "$p2i"; + case Instruction::IntToPtr: return "$i2p"; + default: + assert(false && "Unexpected cast expression."); + } +} + +string SmackRep::bop2fn(unsigned opcode) { + switch (opcode) { + using llvm::Instruction; + case Instruction::Add: return "$add"; + case Instruction::Sub: return "$sub"; + case Instruction::Mul: return "$mul"; + case Instruction::SDiv: return "$sdiv"; + case Instruction::UDiv: return "$udiv"; + case Instruction::SRem: return "$srem"; + case Instruction::URem: return "$urem"; + case Instruction::And: return "$and"; + case Instruction::Or: return "$or"; + case Instruction::Xor: return "$xor"; + case Instruction::LShr: return "$lshr"; + case Instruction::AShr: return "$ashr"; + case Instruction::Shl: return "$shl"; + case Instruction::FAdd: return "$fadd"; + case Instruction::FSub: return "$fsub"; + case Instruction::FMul: return "$fmul"; + case Instruction::FDiv: return "$fdiv"; + case Instruction::FRem: return "$frem"; default: assert(false && "unexpected predicate."); } +} - return e == NULL ? Expr::fn(o, l, r) : e; +string SmackRep::pred2fn(unsigned predicate) { + switch (predicate) { + using llvm::CmpInst; + case CmpInst::ICMP_SGE: return "$sge"; + case CmpInst::ICMP_UGE: return "$uge"; + case CmpInst::ICMP_SLE: return "$sle"; + case CmpInst::ICMP_ULE: return "$ule"; + case CmpInst::ICMP_SLT: return "$slt"; + case CmpInst::ICMP_ULT: return "$ult"; + case CmpInst::ICMP_SGT: return "$sgt"; + case CmpInst::ICMP_UGT: return "$ugt"; + case CmpInst::FCMP_FALSE: return "$ffalse"; + case CmpInst::FCMP_OEQ: return "$foeq"; + case CmpInst::FCMP_OGE: return "$foge"; + case CmpInst::FCMP_OGT: return "$fogt"; + case CmpInst::FCMP_OLE: return "$fole"; + case CmpInst::FCMP_OLT: return "$folt"; + case CmpInst::FCMP_ONE: return "$fone"; + case CmpInst::FCMP_ORD: return "$ford"; + case CmpInst::FCMP_TRUE: return "$ftrue"; + case CmpInst::FCMP_UEQ: return "$fueq"; + case CmpInst::FCMP_UGE: return "$fuge"; + case CmpInst::FCMP_UGT: return "$fugt"; + case CmpInst::FCMP_ULE: return "$fule"; + case CmpInst::FCMP_ULT: return "$fult"; + case CmpInst::FCMP_UNE: return "$fune"; + case CmpInst::FCMP_UNO: return "$funo"; + default: + assert(false && "unexpected predicate."); + } +} + +string SmackRep::armwop2fn(unsigned opcode) { + using llvm::AtomicRMWInst; + switch (opcode) { + case AtomicRMWInst::Add: return "$add"; + case AtomicRMWInst::Sub: return "$sub"; + case AtomicRMWInst::And: return "$and"; + case AtomicRMWInst::Nand: return "$nand"; + case AtomicRMWInst::Or: return "$or"; + case AtomicRMWInst::Xor: return "$xor"; + case AtomicRMWInst::Max: return "$max"; + case AtomicRMWInst::Min: return "$min"; + case AtomicRMWInst::UMax: return "$umax"; + case AtomicRMWInst::UMin: return "$umin"; + default: + assert(false && "unexpected atomic operation."); + } } string indexedName(string name, int idx) { @@ -715,7 +530,7 @@ ProcDecl* SmackRep::proc(llvm::Function* f, int nargs) { arg = f->arg_begin(), e = f->arg_end(); arg != e; ++arg, ++i) { string name; if (arg->hasName()) { - name = id(arg); + name = naming.get(*arg); } else { name = indexedName("p",i); arg->setName(name); @@ -728,33 +543,40 @@ ProcDecl* SmackRep::proc(llvm::Function* f, int nargs) { args.push_back(make_pair(indexedName("p",i), getPtrType())); if (!f->getReturnType()->isVoidTy()) - rets.push_back(make_pair(RET_VAR,type(f->getReturnType()))); + rets.push_back(make_pair(Naming::RET_VAR,type(f->getReturnType()))); return (ProcDecl*) Decl::procedure( - *program, - f->isVarArg() ? indexedName(id(f),nargs) : id(f), + program, + f->isVarArg() ? indexedName(naming.get(*f),nargs) : naming.get(*f), args, rets ); } const Expr* SmackRep::arg(llvm::Function* f, unsigned pos, llvm::Value* v) { - return (f && f->isVarArg() && isFloat(v)) ? fp2si(v) : expr(v); + return (f && f->isVarArg() && isFloat(v)) ? Expr::fn("$fp2si",expr(v)) : expr(v); } -const Stmt* SmackRep::call(llvm::Function* f, llvm::CallInst& ci) { +const Stmt* SmackRep::call(llvm::Function* f, llvm::User& ci) { + using namespace llvm; assert(f && "Call encountered unresolved function."); - string name = id(f); + string name = naming.get(*f); vector args; vector rets; + + unsigned num_arg_operands = ci.getNumOperands(); + if (isa(ci)) + num_arg_operands -= 1; + else if (isa(ci)) + num_arg_operands -= 3; - for (unsigned i = 0; i < ci.getNumOperands() - 1; i++) + for (unsigned i = 0; i < num_arg_operands; i++) args.push_back(arg(f, i, ci.getOperand(i))); if (!ci.getType()->isVoidTy()) - rets.push_back(id(&ci)); + rets.push_back(naming.get(ci)); if (name == "malloc") { assert(args.size() == 1); @@ -764,10 +586,10 @@ const Stmt* SmackRep::call(llvm::Function* f, llvm::CallInst& ci) { assert(args.size() == 1); return Stmt::call(FREE, args[0]); - } else if (f->isVarArg() || (f->isDeclaration() && !isSmackName(name))) { + } else if (f->isVarArg() || (f->isDeclaration() && !Naming::isSmackName(name))) { Decl* p = proc(f,args.size()); - program->addDecl(p); + program.addDecl(p); return Stmt::call(p->getName(), args, rets); } else { @@ -790,15 +612,8 @@ string SmackRep::code(llvm::CallInst& ci) { assert(idx != string::npos && "__SMACK_code: too many arguments."); ostringstream ss; - - if (s.find("{@}") == idx-1) { - a->print(ss); - s = s.replace(idx-1,3,ss.str()); - - } else { - a->print(ss); - s = s.replace(idx,1,ss.str()); - } + a->print(ss); + s = s.replace(idx,1,ss.str()); } return s; } @@ -809,20 +624,8 @@ string SmackRep::getPrelude() { s << "// Memory region declarations"; s << ": " << memoryRegions.size() << endl; for (unsigned i=0; i 0) { - s << "// Undefined values" << endl; - s << "const "; - for (unsigned i=0; i 0 ? ", " : "") << "$u." << i; - s << ": " << getPtrType() << ";" << endl; - s << endl; - } - s << "axiom $GLOBALS_BOTTOM == " << globalsBottom << ";" << endl; return s.str(); @@ -858,7 +661,10 @@ void SmackRep::addInit(unsigned region, const Expr* addr, const llvm::Constant* if (isInt(val)) { staticInits.push_back( Stmt::assign(mem(region,addr), expr(val)) ); - + + } else if (isFloat(val)) { + staticInits.push_back( Stmt::assign(mem(region,addr), Expr::fn("$fp2si",expr(val))) ); + } else if (isa(val->getType())) { staticInits.push_back( Stmt::assign(mem(region,addr), expr(val)) ); @@ -875,6 +681,9 @@ void SmackRep::addInit(unsigned region, const Expr* addr, const llvm::Constant* addInit( region, pa(addr,fieldOffset(st,i),1), elem ); } + } else if (val->getType()->isX86_FP80Ty()) { + staticInits.push_back(Stmt::code("// ignored X86 FP80 initializer")); + } else { assert (false && "Unexpected static initializer."); } @@ -885,8 +694,8 @@ bool SmackRep::hasStaticInits() { } Decl* SmackRep::getStaticInit() { - ProcDecl* proc = (ProcDecl*) Decl::procedure(*program, STATIC_INIT); - Block* b = new Block(*proc); + ProcDecl* proc = (ProcDecl*) Decl::procedure(program, STATIC_INIT); + Block* b = new Block(); for (unsigned i=0; iaddStmt(staticInits[i]); b->addStmt(Stmt::return_()); @@ -899,7 +708,7 @@ vector SmackRep::globalDecl(const llvm::Value* v) { using namespace llvm; vector decls; vector ax; - string name = id(v); + string name = naming.get(*v); if (const GlobalVariable* g = dyn_cast(v)) { if (g->hasInitializer()) { diff --git a/lib/smack/SmackRepFlatMem.cpp b/lib/smack/SmackRepFlatMem.cpp index da9dd0f14..8a28bdd1d 100644 --- a/lib/smack/SmackRepFlatMem.cpp +++ b/lib/smack/SmackRepFlatMem.cpp @@ -1,6 +1,4 @@ // -// Copyright (c) 2013 Zvonimir Rakamaric (zvonimir@cs.utah.edu), -// Michael Emmi (michael.emmi@gmail.com) // This file is distributed under the MIT License. See LICENSE for details. // #include "smack/SmackRep.h" diff --git a/rise4fun/smack_server.py b/rise4fun/smack_server.py index 65c837578..dff848d50 100644 --- a/rise4fun/smack_server.py +++ b/rise4fun/smack_server.py @@ -1,3 +1,6 @@ +# +# This file is distributed under the MIT License. See LICENSE for details. +# import BaseHTTPServer import SimpleHTTPServer import json @@ -9,25 +12,25 @@ version = "1.4.4" rise_simple = """#include "smack.h" //__SMACK_nondet() : Is used to permit assigned memory to have unconstrained values -//__SMACK_assume(): Is used to enforce constraints on specified regions of memory -//__SMACK_assert(): Is used to prove some assertions on values in the program. Assertions may contain unconstrained values. +//assume(): Is used to enforce constraints on specified regions of memory +//assert(): Is used to prove some assertions on values in the program. Assertions may contain unconstrained values. int main() { int x = __SMACK_nondet(); int n = __SMACK_nondet(); - __SMACK_assume(n>0); - __SMACK_assert(x+n > x); + assume(n>0); + assert(x+n > x); return 0; }""" rise_simple_buggy = """#include "smack.h" //__SMACK_nondet() : Is used to permit assigned memory to have unconstrained values -//__SMACK_assume(): Is used to enforce constraints on specified regions of memory -//__SMACK_assert(): Is used to prove some assertions on values in the program. Assertions may contain unconstrained values +//assume(): Is used to enforce constraints on specified regions of memory +//assert(): Is used to prove some assertions on values in the program. Assertions may contain unconstrained values int main() { int x = __SMACK_nondet(); int n = __SMACK_nondet(); - __SMACK_assume(n>=0); - __SMACK_assert(x+n > x); + assume(n>=0); + assert(x+n > x); return 0; }""" @@ -52,7 +55,7 @@ } x = fp(x); - __SMACK_assert(x == old_x-1 || x == old_x+1); + assert(x == old_x-1 || x == old_x+1); return 0; }""" @@ -73,7 +76,7 @@ int i = __SMACK_nondet(); initDescArray(num,size); if(i >= 1 && i < 6) - __SMACK_assert(num[i] > num[i-1]); + assert(num[i] > num[i-1]); }""" @@ -114,7 +117,7 @@ int b; b = foo(__SMACK_nondet(), __SMACK_nondet()); - __SMACK_assert(b != 0); + assert(b != 0); return 0; }""" @@ -129,7 +132,7 @@ a = __SMACK_nondet(); b = __SMACK_nondet(); if(a>=0 && b>=0) - __SMACK_assert(z != (a*x+b*y)); + assert(z != (a*x+b*y)); return 0; }""" @@ -153,7 +156,7 @@ s1.a = 3; p2->x = 4; - __SMACK_assert(s1.a == 4); + assert(s1.a == 4); return 0; }""" @@ -163,9 +166,9 @@ The tool is open-source and integrates into the well-known LLVM compiler infrastructure.\r\n There are 3 types of annotations that SMACK allows the user to specify. They are the assert, assume and nondet statements.\r\n Assert: Allows the user to specify a predicate on the variables in scope. SMACK statically checks the assertion in this - program location. The predicate P can be specified in an assert in the syntax __SMACK_assert(P) \r\n + program location. The predicate P can be specified in an assert in the syntax assert(P) \r\n Assume: Assume statement allows the user to specify the assumptions of the program from the point of specification. If the - assumption is denoted by A, __SMACK_assume(A) is the syntax for specifying it. Eg: __SMACK_assume(n > 0) + assumption is denoted by A, assume(A) is the syntax for specifying it. Eg: assume(n > 0) Nondet: Allows the user to specify a "random" value. This is specified by __SMACK_nondet(). The statement returns a nondeterministic type safe value.""" metadata = { diff --git a/test/Makefile b/test/Makefile index 57ec322fc..49e39fe56 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,8 +1,10 @@ CC = clang +CPP = clang++ INC = ../include/smack CFLAGS = -c -Wall -emit-llvm -O0 -g -I$(INC) -SOURCES = simple.c simple_fail.c \ +SOURCES = hello.cc hello_fail.cc \ + simple.c simple_fail.c \ simple_pre.c simple_pre_fail.c \ simple_pre1.c simple_pre1_fail.c \ simple_pre2.c simple_pre2_fail.c \ @@ -48,15 +50,22 @@ SOURCES = simple.c simple_fail.c \ two_arrays3.c \ two_arrays4.c \ two_arrays5.c \ - two_arrays6.c two_arrays6_fail.c + two_arrays6.c two_arrays6_fail.c \ + floats_in_memory.c floats_in_memory_fail.c -BITCODE = $(SOURCES:.c=.bc) +BITCODE = $(SOURCES:.c=.bc) $(SOURCES:.cc=.bc) $(SOURCES:.cpp=.bc) all: $(BITCODE) %.bc: %.c $(CC) $(CFLAGS) $< -o $@ +%.bc: %.cc + $(CPP) $(CFLAGS) $< -o $@ + +%.bc: %.cpp + $(CPP) $(CFLAGS) $< -o $@ + clean: rm -f *.bc *.bpl diff --git a/test/array1.c b/test/array1.c index c01fff04e..cdabe9cf5 100644 --- a/test/array1.c +++ b/test/array1.c @@ -10,7 +10,7 @@ int main() { a[5] = 10; - __SMACK_assert(a[5] == 10); + assert(a[5] == 10); free(a); return 0; diff --git a/test/array1_fail.c b/test/array1_fail.c index 14ca9b7e7..198d3ca8b 100644 --- a/test/array1_fail.c +++ b/test/array1_fail.c @@ -10,7 +10,7 @@ int main() { a[5] = 10; - __SMACK_assert(a[4] == 10 || a[5] == 0); + assert(a[4] == 10 || a[5] == 0); free(a); return 0; diff --git a/test/array2.c b/test/array2.c index 93e43b034..57f7e4ace 100644 --- a/test/array2.c +++ b/test/array2.c @@ -13,7 +13,7 @@ int main() { a[i] = RESET; } - __SMACK_assert(a[5] == RESET); + assert(a[5] == RESET); free(a); return 0; diff --git a/test/array2_fail.c b/test/array2_fail.c index b16e81d55..148607dd4 100644 --- a/test/array2_fail.c +++ b/test/array2_fail.c @@ -13,7 +13,7 @@ int main() { a[i] = RESET; } - __SMACK_assert(a[5] != RESET || a[9] == RESET); + assert(a[5] != RESET || a[9] == RESET); free(a); return 0; diff --git a/test/array3.c b/test/array3.c index 2722bb68e..6f40b554e 100644 --- a/test/array3.c +++ b/test/array3.c @@ -21,7 +21,7 @@ int main() { initializeArray(array); for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(array[i] == RESET); + assert(array[i] == RESET); } free(array); diff --git a/test/array3_fail.c b/test/array3_fail.c index f63cc0e6f..767cc600d 100644 --- a/test/array3_fail.c +++ b/test/array3_fail.c @@ -23,7 +23,7 @@ int main() { initializeArray(array); for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(array[i] == RESET); + assert(array[i] == RESET); } free(array); diff --git a/test/array4.c b/test/array4.c index f8f4331cc..98630e231 100644 --- a/test/array4.c +++ b/test/array4.c @@ -26,7 +26,7 @@ int main() { initializeArray(array); for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(array[i].status == RESET); + assert(array[i].status == RESET); } free(array); diff --git a/test/array4_fail.c b/test/array4_fail.c index e9315ffc4..6db543559 100644 --- a/test/array4_fail.c +++ b/test/array4_fail.c @@ -26,7 +26,7 @@ int main() { initializeArray(array); for (i = 0; i < MAXSIZE + 1; i++) { - __SMACK_assert(array[i].status == RESET); + assert(array[i].status == RESET); } free(array); diff --git a/test/array_free.c b/test/array_free.c index 7c62f010e..ff76716bf 100644 --- a/test/array_free.c +++ b/test/array_free.c @@ -19,7 +19,7 @@ void free_array() { } for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(*(a[i].f) == 1); + assert(*(a[i].f) == 1); if (a[i].f != 0) { free(a[i].f); a[i].f = 0; diff --git a/test/array_free1.c b/test/array_free1.c index aed3dbed2..071c59d7a 100644 --- a/test/array_free1.c +++ b/test/array_free1.c @@ -21,8 +21,8 @@ void free_array() { } for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(*(a[i].f) == 1); - __SMACK_assert(a[i].x == 2); + assert(*(a[i].f) == 1); + assert(a[i].x == 2); if (a[i].f != 0) { free(a[i].f); a[i].f = 0; diff --git a/test/array_free1_fail.c b/test/array_free1_fail.c index 3217a6193..f1d863156 100644 --- a/test/array_free1_fail.c +++ b/test/array_free1_fail.c @@ -21,8 +21,8 @@ void free_array() { } for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(*(a[i].f) == 1); - __SMACK_assert(a[i].x == 2); + assert(*(a[i].f) == 1); + assert(a[i].x == 2); if (a[i].f != 0) { free(a[i].f); a[i].f = 0; diff --git a/test/array_free2.c b/test/array_free2.c index 0482f2bfa..8ccc50fd4 100644 --- a/test/array_free2.c +++ b/test/array_free2.c @@ -23,9 +23,9 @@ void free_array() { } for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(*(a[i].f) == 1); - __SMACK_assert(a[i].x == 2); - __SMACK_assert(a[i].y == 3); + assert(*(a[i].f) == 1); + assert(a[i].x == 2); + assert(a[i].y == 3); if (a[i].f != 0) { free(a[i].f); a[i].f = 0; diff --git a/test/array_free2_fail.c b/test/array_free2_fail.c index 5b6de07de..2cfe78a34 100644 --- a/test/array_free2_fail.c +++ b/test/array_free2_fail.c @@ -23,9 +23,9 @@ void free_array() { } for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(*(a[i].f) == 1); - __SMACK_assert(a[i].x == 2); - __SMACK_assert(a[i].y == 3); + assert(*(a[i].f) == 1); + assert(a[i].x == 2); + assert(a[i].y == 3); if (a[i].f != 0) { free(a[i].f); a[i].f = 0; diff --git a/test/array_free_fail.c b/test/array_free_fail.c index 445d9bfa7..edd43bbe5 100644 --- a/test/array_free_fail.c +++ b/test/array_free_fail.c @@ -19,7 +19,7 @@ void free_array() { } for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(*(a[i].f) == 1); + assert(*(a[i].f) == 1); if (a[i].f != 0) { free(a[i].f); a[i].f = 0; diff --git a/test/ase_example.c b/test/ase_example.c index 39367749b..94875b47f 100644 --- a/test/ase_example.c +++ b/test/ase_example.c @@ -26,7 +26,7 @@ void init(int size) { } for (i = 0; i < size; i++) { - __SMACK_assert(a1[i].f1 == 1); + assert(a1[i].f1 == 1); } } diff --git a/test/ase_example_fail.c b/test/ase_example_fail.c index c27effcb9..f0c9499d2 100644 --- a/test/ase_example_fail.c +++ b/test/ase_example_fail.c @@ -26,7 +26,7 @@ void init(int size) { } for (i = 0; i < size; i++) { - __SMACK_assert(a1[i].f1 == 1); + assert(a1[i].f1 == 1); } } diff --git a/test/contracts/.gitignore b/test/contracts/.gitignore new file mode 100644 index 000000000..5f36c5029 --- /dev/null +++ b/test/contracts/.gitignore @@ -0,0 +1,4 @@ +*.ll +*.bc +*.o +*.bpl diff --git a/test/contracts/and.c b/test/contracts/and.c new file mode 100644 index 000000000..9e3bde1c6 --- /dev/null +++ b/test/contracts/and.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +// @expect 1 verified, 0 errors? + +int g; + +void p() { + ensures(g == 0 && g == 0); + g = 0; +} diff --git a/test/contracts/and_fail.c b/test/contracts/and_fail.c new file mode 100644 index 000000000..8474dd85b --- /dev/null +++ b/test/contracts/and_fail.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +// @expect 0 verified, 1 errors? + +int g; + +void p() { + ensures(g == 0 && g == 1); + g = 0; +} diff --git a/test/contracts/array.c b/test/contracts/array.c new file mode 100644 index 000000000..cd25d3de0 --- /dev/null +++ b/test/contracts/array.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +// @expect 1 verified, 0 errors? + +int g[10]; + +int main(void) { + ensures(g[0] == 0); + return 0; +} \ No newline at end of file diff --git a/test/contracts/array_fail.c b/test/contracts/array_fail.c new file mode 100644 index 000000000..5bb204b26 --- /dev/null +++ b/test/contracts/array_fail.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +// @expect 0 verified, 1 errors? + +int g[10]; + +int main(void) { + ensures(g[0] == 1); + return 0; +} \ No newline at end of file diff --git a/test/contracts/array_forall.c b/test/contracts/array_forall.c new file mode 100644 index 000000000..f0c7841f1 --- /dev/null +++ b/test/contracts/array_forall.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +// @expect 1 verified, 0 errors? + +#define SIZE 10 +int g[SIZE]; + +void p() { + ensures(forall("i", qvar("i") < 0 || qvar("i") >= SIZE || g[qvar("i")] == qvar("i"))); + + for (int i=0; i= i || g[qvar("x")] == qvar("x"))); + g[i] = i; + } +} diff --git a/test/contracts/array_forall_fail.c b/test/contracts/array_forall_fail.c new file mode 100644 index 000000000..a5512b4b0 --- /dev/null +++ b/test/contracts/array_forall_fail.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +// @expect 0 verified, 1 errors? + +#define SIZE 10 +int g[SIZE]; + +void p() { + ensures(forall("i", qvar("i") < 0 || qvar("i") >= SIZE || g[qvar("i")] == qvar("i"))); + + for (int i=0; i i || g[qvar("x")] == qvar("x"))); + g[i] = i; + } +} diff --git a/test/contracts/failing/old.c b/test/contracts/failing/old.c new file mode 100644 index 000000000..5ad4f02d7 --- /dev/null +++ b/test/contracts/failing/old.c @@ -0,0 +1,17 @@ +#include +#include +#include "smack.h" + +// @expect 2 verified, 0 errors? + +int g; + +void p() { + ensures(g > old(g)); + g++; +} + +int main(void) { + p(); + return 0; +} \ No newline at end of file diff --git a/test/contracts/failing/old_fail.c b/test/contracts/failing/old_fail.c new file mode 100644 index 000000000..b81e7fd05 --- /dev/null +++ b/test/contracts/failing/old_fail.c @@ -0,0 +1,17 @@ +#include +#include +#include "smack.h" + +// @expect 1 verified, 1 errors? + +int g; + +void p() { + ensures(g == old(g)); + g++; +} + +int main(void) { + p(); + return 0; +} \ No newline at end of file diff --git a/test/contracts/failing/requires_const.c b/test/contracts/failing/requires_const.c new file mode 100644 index 000000000..7796de1ce --- /dev/null +++ b/test/contracts/failing/requires_const.c @@ -0,0 +1,9 @@ +#include +#include +#include "smack.h" + +// @expect 1 verified, 0 errors? + +void p() { + requires(true); +} diff --git a/test/contracts/forall.c b/test/contracts/forall.c new file mode 100644 index 000000000..a24f1f7b7 --- /dev/null +++ b/test/contracts/forall.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +// @expect 1 verified, 0 errors? + +int g[10]; + +int main(void) { + ensures(forall("x", g[qvar("x")] == 0 || qvar("x") < 0 || qvar("x") > 9)); + return 0; +} \ No newline at end of file diff --git a/test/contracts/forall_fail.c b/test/contracts/forall_fail.c new file mode 100644 index 000000000..b0ce7a162 --- /dev/null +++ b/test/contracts/forall_fail.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +// @expect 0 verified, 1 errors? + +int g[10]; + +int main(void) { + ensures(forall("x", g[qvar("x")] == 0 || qvar("x") < 0 || qvar("x") > 10)); + return 0; +} \ No newline at end of file diff --git a/test/contracts/invariant.c b/test/contracts/invariant.c new file mode 100644 index 000000000..b363e066b --- /dev/null +++ b/test/contracts/invariant.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +// @expect 1 verified, 0 errors? + +int g[10]; + +int main(void) { + + for (int i=0; i<4; i++) { + invariant(i <= 4); + g[i] = i; + } + + return 0; +} \ No newline at end of file diff --git a/test/contracts/invariant_fail.c b/test/contracts/invariant_fail.c new file mode 100644 index 000000000..e32666f69 --- /dev/null +++ b/test/contracts/invariant_fail.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +// @expect 0 verified, 1 errors? + +int g[10]; + +int main(void) { + + for (int i=0; i<4; i++) { + invariant(i < 4); + g[i] = i; + } + + return 0; +} \ No newline at end of file diff --git a/test/contracts/result.c b/test/contracts/result.c new file mode 100644 index 000000000..40c2ec917 --- /dev/null +++ b/test/contracts/result.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +// @expect 1 verified, 0 errors? + +int g; + +int p() { + requires(g > 0); + ensures(result() > 10); + return g + 10; +} diff --git a/test/contracts/result_fail.c b/test/contracts/result_fail.c new file mode 100644 index 000000000..0b8053839 --- /dev/null +++ b/test/contracts/result_fail.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +// @expect 0 verified, 1 errors? + +int g; + +int p() { + requires(g > 0); + ensures(result() > 11); + return g + 10; +} diff --git a/test/contracts/run.py b/test/contracts/run.py new file mode 100755 index 000000000..082711ab2 --- /dev/null +++ b/test/contracts/run.py @@ -0,0 +1,45 @@ +#! /usr/bin/env python + +import subprocess +import re +import glob +import time + +def red(text): + return '\033[0;31m' + text + '\033[0m' + +def green(text): + return '\033[0;32m' + text + '\033[0m' + +def expect(file): + for line in open(file).readlines(): + match = re.search(r'@expect (.*)',line) + if match: + return match.group(1) + print red("WARNING: @expect MISSING IN %s" % file), + return "" + +print "Running CONTRACTS regression tests..." +print + +passed = failed = 0 +for test in glob.glob("*.c"): + + print "{0:>20} :".format(test), + + # invoke SMACK + t0 = time.time() + cmd = ['smackverify.py', test, '--verifier=boogie', '--mem-mod=no-reuse'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + + # check SMACK output + if re.search(expect(test), p.communicate()[0]): + print green('PASSED') + ' [%.2fs]' % round(time.time() - t0, 2) + passed += 1 + else: + print red('FAILED') + failed += 1 + +print +print 'PASSED count: ', passed +print 'FAILED count: ', failed diff --git a/test/contracts/simple.c b/test/contracts/simple.c new file mode 100644 index 000000000..6b396e3fe --- /dev/null +++ b/test/contracts/simple.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +// @expect 2 verified, 0 errors? + +int g; + +void p() { + requires(g > 0); + ensures(g > 0); + for (int i=0; i < 10; i++) { + invariant(g > 0); + g++; + } + return; +} + +int main(void) { + g = 1; + for (int i=0; i<10; i++) { + invariant(g > 0); + p(); + } + assert(g > 0); + return 0; +} \ No newline at end of file diff --git a/test/contracts/simple_fail.c b/test/contracts/simple_fail.c new file mode 100644 index 000000000..0e6efe014 --- /dev/null +++ b/test/contracts/simple_fail.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +// @expect 1 verified, 1 errors? + +int g; + +void p() { + requires(g > 0); + ensures(g > 0); + for (int i=0; i < 10; i++) { + invariant(g >= 0); + g++; + } + return; +} + +int main(void) { + g = 1; + for (int i=0; i<10; i++) { + invariant(g > 0); + p(); + } + assert(g > 0); + return 0; +} \ No newline at end of file diff --git a/test/extern_mem.c b/test/extern_mem.c index cd779554a..be84434db 100644 --- a/test/extern_mem.c +++ b/test/extern_mem.c @@ -14,5 +14,5 @@ int main() { *x = 1; *y = 2; - __SMACK_assert(x != y); + assert(x != y); } \ No newline at end of file diff --git a/test/extern_mem_fail.c b/test/extern_mem_fail.c index c3c468a09..7439cbb58 100644 --- a/test/extern_mem_fail.c +++ b/test/extern_mem_fail.c @@ -14,5 +14,5 @@ int main() { *x = 1; *y = 2; - __SMACK_assert(x != y); + assert(x != y); } \ No newline at end of file diff --git a/test/extern_struct.c b/test/extern_struct.c index e0dc68c68..85b438750 100644 --- a/test/extern_struct.c +++ b/test/extern_struct.c @@ -4,7 +4,7 @@ extern const struct process *procinit[]; int main(void) { procinit[0] = 0; - __SMACK_assert(0); + assert(0); return 0; } diff --git a/test/floats_in_memory.c b/test/floats_in_memory.c new file mode 100644 index 000000000..17a9e4110 --- /dev/null +++ b/test/floats_in_memory.c @@ -0,0 +1,20 @@ +#include + +void ff1(float f); +void ff2(float *f1, float *f2) { + *f1 = *f2; +} + +int main() { + float f1; + float f2 = 0.0; + float f3 = 1.0; + + ff1(f1); + ff1(f2); + ff2(&f2,&f3); + + assert(f2 == f3); + + return 0; +} diff --git a/test/floats_in_memory_fail.c b/test/floats_in_memory_fail.c new file mode 100644 index 000000000..920aa80fb --- /dev/null +++ b/test/floats_in_memory_fail.c @@ -0,0 +1,20 @@ +#include + +void ff1(float f); +void ff2(float *f1, float *f2) { + *f1 = *f2 + 1; +} + +int main() { + float f1; + float f2 = 0.0; + float f3 = 1.0; + + ff1(f1); + ff1(f2); + ff2(&f2,&f3); + + assert(f2 == f3); + + return 0; +} diff --git a/test/func_ptr.c b/test/func_ptr.c index bf8e54a57..8ed7f78e7 100644 --- a/test/func_ptr.c +++ b/test/func_ptr.c @@ -19,7 +19,7 @@ int main(void) { } x = fp(x); - __SMACK_assert(x == 2); + assert(x == 2); return 0; } diff --git a/test/func_ptr1.c b/test/func_ptr1.c index e983b9b13..3d1aca628 100644 --- a/test/func_ptr1.c +++ b/test/func_ptr1.c @@ -22,7 +22,7 @@ int main(void) { } fp(x); - __SMACK_assert(*x == 2); + assert(*x == 2); return 0; } diff --git a/test/func_ptr1_fail.c b/test/func_ptr1_fail.c index c9b3ab1f5..a15b8d89f 100644 --- a/test/func_ptr1_fail.c +++ b/test/func_ptr1_fail.c @@ -22,7 +22,7 @@ int main(void) { } fp(x); - __SMACK_assert(*x == 0 || *x == 1); + assert(*x == 0 || *x == 1); return 0; } diff --git a/test/func_ptr_fail.c b/test/func_ptr_fail.c index 280578d60..54668ad81 100644 --- a/test/func_ptr_fail.c +++ b/test/func_ptr_fail.c @@ -19,7 +19,7 @@ int main(void) { } x = fp(x); - __SMACK_assert(x == 0 || x == 1); + assert(x == 0 || x == 1); return 0; } diff --git a/test/globals.c b/test/globals.c index 5456c8ea0..598bf2a62 100644 --- a/test/globals.c +++ b/test/globals.c @@ -10,6 +10,6 @@ int main(void){ g1 = 3; *x = 4; g2 = 5; - __SMACK_assert(g1 == 3 && *x == 4 && g2 == 5); + assert(g1 == 3 && *x == 4 && g2 == 5); } diff --git a/test/globals_fail.c b/test/globals_fail.c index 1583c2ab2..cc6051996 100644 --- a/test/globals_fail.c +++ b/test/globals_fail.c @@ -10,6 +10,6 @@ int main(void){ g1 = 3; *x = 4; g2 = 5; - __SMACK_assert(g1 != 3 || *x != 4 || g2 != 5); + assert(g1 != 3 || *x != 4 || g2 != 5); } diff --git a/test/hello.cc b/test/hello.cc new file mode 100644 index 000000000..29c554a50 --- /dev/null +++ b/test/hello.cc @@ -0,0 +1,9 @@ +#include +#include + +int main() +{ + std::cout << "Hello, world!" << std::endl; + assert(true); + return 0; +} diff --git a/test/hello_fail.cc b/test/hello_fail.cc new file mode 100644 index 000000000..1a54658c8 --- /dev/null +++ b/test/hello_fail.cc @@ -0,0 +1,9 @@ +#include +#include + +int main() +{ + std::cout << "Hello, world!" << std::endl; + assert(false); + return 0; +} diff --git a/test/lock.c b/test/lock.c index 187d444bd..f929713a0 100644 --- a/test/lock.c +++ b/test/lock.c @@ -14,12 +14,12 @@ lock main_lock; lock global_lock; void acquire_lock(lock *l) { - __SMACK_assert(l->locked == UNLOCKED); + assert(l->locked == UNLOCKED); l->locked = LOCKED; } void release_lock(lock *l) { - __SMACK_assert(l->locked == LOCKED); + assert(l->locked == LOCKED); l->locked = UNLOCKED; } diff --git a/test/lock_fail.c b/test/lock_fail.c index 649c3ba6a..26a2b3492 100644 --- a/test/lock_fail.c +++ b/test/lock_fail.c @@ -14,12 +14,12 @@ lock main_lock; lock global_lock; void acquire_lock(lock *l) { - __SMACK_assert(l->locked == UNLOCKED); + assert(l->locked == UNLOCKED); l->locked = LOCKED; } void release_lock(lock *l) { - __SMACK_assert(l->locked == LOCKED); + assert(l->locked == LOCKED); l->locked = UNLOCKED; } diff --git a/test/loop.c b/test/loop.c index 908206b87..d160c5aa8 100644 --- a/test/loop.c +++ b/test/loop.c @@ -14,7 +14,7 @@ int main() { for (i = 0; i < MAXSIZE; i++) { x = i; } - __SMACK_assert(x == MAXSIZE - 1); + assert(x == MAXSIZE - 1); return 0; } diff --git a/test/loop1.c b/test/loop1.c index 020a0014b..8a3948439 100644 --- a/test/loop1.c +++ b/test/loop1.c @@ -14,7 +14,7 @@ int main() { for (i = 0; i < MAXSIZE; i++) { j = i; } - __SMACK_assert(x == 1); + assert(x == 1); return 0; } diff --git a/test/loop1_fail.c b/test/loop1_fail.c index 12229a468..047d7d524 100644 --- a/test/loop1_fail.c +++ b/test/loop1_fail.c @@ -14,7 +14,7 @@ int main() { for (i = 0; i < MAXSIZE; i++) { j = i; } - __SMACK_assert(x != 1); + assert(x != 1); return 0; } diff --git a/test/loop_fail.c b/test/loop_fail.c index 0abacc4bc..43129d26c 100644 --- a/test/loop_fail.c +++ b/test/loop_fail.c @@ -14,7 +14,7 @@ int main() { for (i = 0; i < MAXSIZE; i++) { x = i; } - __SMACK_assert(x != MAXSIZE - 1); + assert(x != MAXSIZE - 1); return 0; } diff --git a/test/nested_struct.c b/test/nested_struct.c index 3bb1e2730..270602ccb 100644 --- a/test/nested_struct.c +++ b/test/nested_struct.c @@ -20,25 +20,25 @@ int main(void) { element elem; elem.count = 1; - __SMACK_assert(elem.count == 1); + assert(elem.count == 1); elem.count = 2; - __SMACK_assert(elem.count == 2); + assert(elem.count == 2); elem.point1.y = 100; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1.y == 100); + assert(elem.count == 2); + assert(elem.point1.y == 100); elem.data = 5; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1.y == 100); - __SMACK_assert(elem.data == 5); + assert(elem.count == 2); + assert(elem.point1.y == 100); + assert(elem.data == 5); elem.point2.x = 200; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1.y == 100); - __SMACK_assert(elem.data == 5); - __SMACK_assert(elem.point2.x == 200); + assert(elem.count == 2); + assert(elem.point1.y == 100); + assert(elem.data == 5); + assert(elem.point2.x == 200); return 0; } diff --git a/test/nested_struct1.c b/test/nested_struct1.c index 1de16d120..89323bb69 100644 --- a/test/nested_struct1.c +++ b/test/nested_struct1.c @@ -20,36 +20,36 @@ int main(void) { point p; elem.count = 1; - __SMACK_assert(elem.count == 1); + assert(elem.count == 1); elem.count = 2; - __SMACK_assert(elem.count == 2); + assert(elem.count == 2); elem.point1.y = 100; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1.y == 100); + assert(elem.count == 2); + assert(elem.point1.y == 100); elem.data = 5; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1.y == 100); - __SMACK_assert(elem.data == 5); + assert(elem.count == 2); + assert(elem.point1.y == 100); + assert(elem.data == 5); elem.point2.x = 200; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1.y == 100); - __SMACK_assert(elem.data == 5); - __SMACK_assert(elem.point2.x == 200); + assert(elem.count == 2); + assert(elem.point1.y == 100); + assert(elem.data == 5); + assert(elem.point2.x == 200); p.x = 1000; p.y = 2000; elem.point1 = p; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.data == 5); - __SMACK_assert(elem.point2.x == 200); - __SMACK_assert(p.x == 1000); - __SMACK_assert(p.y == 2000); - __SMACK_assert(elem.point1.x == 1000); - __SMACK_assert(elem.point1.y == 2000); + assert(elem.count == 2); + assert(elem.data == 5); + assert(elem.point2.x == 200); + assert(p.x == 1000); + assert(p.y == 2000); + assert(elem.point1.x == 1000); + assert(elem.point1.y == 2000); return 0; } diff --git a/test/nested_struct1_fail.c b/test/nested_struct1_fail.c index 58c6cf0f5..18eea5285 100644 --- a/test/nested_struct1_fail.c +++ b/test/nested_struct1_fail.c @@ -28,7 +28,7 @@ int main(void) { p.y = 2000; elem.point1 = p; - __SMACK_assert(elem.count != 2 || elem.data != 5 || elem.point2.x != 200 || p.x != 1000 || + assert(elem.count != 2 || elem.data != 5 || elem.point2.x != 200 || p.x != 1000 || p.y != 2000 || elem.point1.x != 1000 || elem.point1.y != 2000); return 0; diff --git a/test/nested_struct2.c b/test/nested_struct2.c index 577299832..a469dc8cf 100644 --- a/test/nested_struct2.c +++ b/test/nested_struct2.c @@ -20,36 +20,36 @@ int main(void) { point p; elem.count = 1; - __SMACK_assert(elem.count == 1); + assert(elem.count == 1); elem.count = 2; - __SMACK_assert(elem.count == 2); + assert(elem.count == 2); elem.point1 = &p; elem.point1->y = 100; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1->y == 100); + assert(elem.count == 2); + assert(elem.point1->y == 100); elem.data = 5; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1->y == 100); - __SMACK_assert(elem.data == 5); + assert(elem.count == 2); + assert(elem.point1->y == 100); + assert(elem.data == 5); elem.point2.x = 200; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.point1->y == 100); - __SMACK_assert(elem.data == 5); - __SMACK_assert(elem.point2.x == 200); + assert(elem.count == 2); + assert(elem.point1->y == 100); + assert(elem.data == 5); + assert(elem.point2.x == 200); p.x = 1000; p.y = 2000; - __SMACK_assert(elem.count == 2); - __SMACK_assert(elem.data == 5); - __SMACK_assert(elem.point2.x == 200); - __SMACK_assert(p.x == 1000); - __SMACK_assert(p.y == 2000); - __SMACK_assert(elem.point1->x == 1000); - __SMACK_assert(elem.point1->y == 2000); + assert(elem.count == 2); + assert(elem.data == 5); + assert(elem.point2.x == 200); + assert(p.x == 1000); + assert(p.y == 2000); + assert(elem.point1->x == 1000); + assert(elem.point1->y == 2000); return 0; } diff --git a/test/nested_struct2_fail.c b/test/nested_struct2_fail.c index a46a69990..79d526221 100644 --- a/test/nested_struct2_fail.c +++ b/test/nested_struct2_fail.c @@ -28,7 +28,7 @@ int main(void) { p.x = 1000; p.y = 2000; - __SMACK_assert(elem.count != 2 || elem.data != 5 || elem.point2.x != 200 || p.x != 1000 || + assert(elem.count != 2 || elem.data != 5 || elem.point2.x != 200 || p.x != 1000 || p.y != 2000 || elem.point1->x != 1000 || elem.point1->y != 2000); return 0; diff --git a/test/nested_struct_fail.c b/test/nested_struct_fail.c index 496d7f981..58b4febc6 100644 --- a/test/nested_struct_fail.c +++ b/test/nested_struct_fail.c @@ -25,7 +25,7 @@ int main(void) { elem.data = 5; elem.point2.x = 200; - __SMACK_assert(elem.count != 2 || elem.point1.y != 100 || elem.data != 5 || elem.point2.x != 200); + assert(elem.count != 2 || elem.point1.y != 100 || elem.data != 5 || elem.point2.x != 200); return 0; } diff --git a/test/nondet.c b/test/nondet.c index 68f6bf438..c9d863d5b 100644 --- a/test/nondet.c +++ b/test/nondet.c @@ -9,7 +9,7 @@ int main(void) { x--; } - __SMACK_assert(x == 0 || x == 2); + assert(x == 0 || x == 2); return 0; } diff --git a/test/pointers.c b/test/pointers.c index 22e3b264b..b9307d9e8 100644 --- a/test/pointers.c +++ b/test/pointers.c @@ -15,8 +15,8 @@ int main() { incr(a); incr(b); - __SMACK_assert(*a == 1); - __SMACK_assert(*b == 1); + assert(*a == 1); + assert(*b == 1); return 0; } diff --git a/test/pointers1.c b/test/pointers1.c index db61e3527..991a98697 100644 --- a/test/pointers1.c +++ b/test/pointers1.c @@ -19,8 +19,8 @@ int main() { incr(p); - __SMACK_assert(p->a == 1); - __SMACK_assert(p->b == 1); + assert(p->a == 1); + assert(p->b == 1); return 0; } diff --git a/test/pointers1_fail.c b/test/pointers1_fail.c index 9567b3fa7..ac1af5c3b 100644 --- a/test/pointers1_fail.c +++ b/test/pointers1_fail.c @@ -20,8 +20,8 @@ int main() { incr(p); - __SMACK_assert(p->a == 1); - __SMACK_assert(p->b == 1); + assert(p->a == 1); + assert(p->b == 1); return 0; } diff --git a/test/pointers2.c b/test/pointers2.c index b800d8679..50c19476d 100644 --- a/test/pointers2.c +++ b/test/pointers2.c @@ -25,8 +25,8 @@ int main() { incr(&p); decr(&p); - __SMACK_assert(p.a == 1); - __SMACK_assert(p.b == 1); + assert(p.a == 1); + assert(p.b == 1); return 0; } diff --git a/test/pointers2_fail.c b/test/pointers2_fail.c index 1fc847a82..0cc18fbb3 100644 --- a/test/pointers2_fail.c +++ b/test/pointers2_fail.c @@ -26,8 +26,8 @@ int main() { decr(&p); decr(&p); - __SMACK_assert(p.a == 1); - __SMACK_assert(p.b == 1); + assert(p.a == 1); + assert(p.b == 1); return 0; } diff --git a/test/pointers3.c b/test/pointers3.c index ba4ddcd29..923632352 100644 --- a/test/pointers3.c +++ b/test/pointers3.c @@ -26,8 +26,8 @@ void foo(void) { } void bar(void) { - __SMACK_assert(p.a == 1); - __SMACK_assert(p.b == 1); + assert(p.a == 1); + assert(p.b == 1); } int main() { diff --git a/test/pointers3_fail.c b/test/pointers3_fail.c index f6450f049..bcafc65aa 100644 --- a/test/pointers3_fail.c +++ b/test/pointers3_fail.c @@ -26,8 +26,8 @@ void foo(void) { } void bar(void) { - __SMACK_assert(p.a == 1); - __SMACK_assert(p.b == 1); + assert(p.a == 1); + assert(p.b == 1); } int main() { diff --git a/test/pointers_fail.c b/test/pointers_fail.c index 016c52792..60b0d0378 100644 --- a/test/pointers_fail.c +++ b/test/pointers_fail.c @@ -16,8 +16,8 @@ int main() { incr(b); incr(a); - __SMACK_assert(*a == 1); - __SMACK_assert(*b == 1); + assert(*a == 1); + assert(*b == 1); return 0; } diff --git a/test/regtest-corral.py b/test/regtest-corral.py deleted file mode 100755 index 9b0d9c319..000000000 --- a/test/regtest-corral.py +++ /dev/null @@ -1,130 +0,0 @@ -#! /usr/bin/env python - -import subprocess -import re -import time - -# list of regression tests with the expected outputs -tests = [ - ('simple', r'Program has no bugs', 2), - ('simple_fail', r'This assertion can fail', 2), - ('simple_pre', r'Program has no bugs', 2), - ('simple_pre_fail', r'This assertion can fail', 2), - ('simple_pre1', r'Program has no bugs', 2), - ('simple_pre1_fail', r'This assertion can fail', 2), - ('simple_pre2', r'Program has no bugs', 2), - ('simple_pre2_fail', r'This assertion can fail', 2), - ('simple_pre3', r'Program has no bugs', 2), - ('simple_pre3_fail', r'This assertion can fail', 2), -# ('simple_double_free', r'This assertion can fail', 2), - ('pointers', r'Program has no bugs', 2), - ('pointers_fail', r'This assertion can fail', 2), - ('pointers1', r'Program has no bugs', 2), - ('pointers1_fail', r'This assertion can fail', 2), - ('pointers2', r'Program has no bugs', 2), - ('pointers2_fail', r'This assertion can fail', 2), - ('pointers3', r'Program has no bugs', 2), - ('pointers3_fail', r'This assertion can fail', 2), - ('globals', r'Program has no bugs', 2), - ('globals_fail', r'This assertion can fail', 2), - ('loop', r'Program has no bugs', 11), - ('loop_fail', r'This assertion can fail', 11), - ('loop1', r'Program has no bugs', 11), - ('loop1_fail', r'This assertion can fail', 11), - ('nondet', r'Program has no bugs', 2), - ('printfs', r'Program has no bugs', 2), - ('struct_return', r'Program has no bugs', 2), - ('struct_init', r'Program has no bugs', 2), - ('struct_init_fail', r'This assertion can fail', 2), - ('extern_struct', r'This assertion can fail', 2), - ('extern_func', r'Program has no bugs', 2), - ('extern_mem', r'Program has no bugs', 2), - ('extern_mem_fail', r'This assertion can fail', 2), - ('smack_code_call', r'Program has no bugs', 2), - ('smack_code_call_fail', r'This assertion can fail', 2), - ('return_label', r'Program has no bugs', 2), - ('struct_cast', r'Program has no bugs', 2), - ('struct_cast_fail', r'This assertion can fail', 2), - ('struct_cast1', r'Program has no bugs', 2), - ('struct_cast1_fail', r'This assertion can fail', 2), - ('nested_struct', r'Program has no bugs', 2), - ('nested_struct_fail', r'This assertion can fail', 2), - ('nested_struct1', r'Program has no bugs', 2), - ('nested_struct1_fail', r'This assertion can fail', 2), - ('nested_struct2', r'Program has no bugs', 2), - ('nested_struct2_fail', r'This assertion can fail', 2), - ('struct_assign', r'Program has no bugs', 2), - ('struct_assign_fail', r'This assertion can fail', 2), - ('func_ptr', r'Program has no bugs', 2), - ('func_ptr_fail', r'This assertion can fail', 2), - ('func_ptr1', r'Program has no bugs', 2), - ('func_ptr1_fail', r'This assertion can fail', 2), - ('array', r'Program has no bugs', 2), - ('array1', r'Program has no bugs', 2), - ('array1_fail', r'This assertion can fail', 2), - ('array2', r'Program has no bugs', 11), - ('array2_fail', r'This assertion can fail', 11), - ('array3', r'Program has no bugs', 11), - ('array3_fail', r'This assertion can fail', 11), - ('array4', r'Program has no bugs', 11), - ('array4_fail', r'This assertion can fail', 11), -# ('array_free', r'Program has no bugs', 11), -# ('array_free_fail', r'This assertion can fail', 11), -# ('array_free1', r'Program has no bugs', 11), -# ('array_free1_fail', r'This assertion can fail', 11), -# ('array_free2', r'Program has no bugs', 11), -# ('array_free2_fail', r'This assertion can fail', 11), - ('lock', r'Program has no bugs', 2), - ('lock_fail', r'This assertion can fail', 2), - ('ase_example', r'Program has no bugs', 11), - ('ase_example_fail', r'This assertion can fail', 11), - ('two_arrays', r'Program has no bugs', 2), - ('two_arrays1', r'Program has no bugs', 2), - ('two_arrays2', r'Program has no bugs', 2), - ('two_arrays3', r'Program has no bugs', 2), - ('two_arrays4', r'Program has no bugs', 2), - ('two_arrays5', r'Program has no bugs', 2), - ('two_arrays6', r'Program has no bugs', 2), - ('two_arrays6_fail', r'This assertion can fail', 2) -] - -def red(text): - return '\033[0;31m' + text + '\033[0m' - -def green(text): - return '\033[0;32m' + text + '\033[0m' - -def runtests(): - passed = failed = 0 - for test in tests: - - for mem in ['no-reuse', 'no-reuse-impls', 'reuse']: - - print "{0:>20} {1:>16}:".format(test[0], "(" + mem + ")"), - - # invoke SMACK - t0 = time.time() - p = subprocess.Popen(['smackverify.py', test[0] + '.c', '--verifier=corral', - '--unroll=' + str(test[2]), '--mem-mod=' + mem, '-o', test[0] +'.bpl'], - stdout=subprocess.PIPE) - - smackOutput = p.communicate()[0] - elapsed = time.time() - t0 - - # check SMACK output - if re.search(test[1], smackOutput): - print green('PASSED') + ' [%.2fs]' % round(elapsed, 2) - passed += 1 - else: - print red('FAILED') - failed += 1 - - return passed, failed - -if __name__ == '__main__': - - passed, failed = runtests() - - print '\nPASSED count: ', passed - print 'FAILED count: ', failed - diff --git a/test/regtest.py b/test/regtest.py index 1b52b2020..bab337101 100755 --- a/test/regtest.py +++ b/test/regtest.py @@ -2,117 +2,133 @@ import subprocess import re +import argparse import time +from collections import namedtuple +import os.path + +RegTest = namedtuple('RegTest', 'name boogie corral duality unroll') # list of regression tests with the expected outputs tests = [ - ('simple', r'1 verified, 0 errors?', 2), - ('simple_fail', r'0 verified, 1 errors?', 2), - ('simple_pre', r'1 verified, 0 errors?', 2), - ('simple_pre_fail', r'0 verified, 1 errors?', 2), - ('simple_pre1', r'1 verified, 0 errors?', 2), - ('simple_pre1_fail', r'0 verified, 1 errors?', 2), - ('simple_pre2', r'1 verified, 0 errors?', 2), - ('simple_pre2_fail', r'0 verified, 1 errors?', 2), - ('simple_pre3', r'1 verified, 0 errors?', 2), - ('simple_pre3_fail', r'0 verified, 1 errors?', 2), -# ('simple_double_free', r'0 verified, 1 errors?', 2), - ('pointers', r'1 verified, 0 errors?', 2), - ('pointers_fail', r'0 verified, 1 errors?', 2), - ('pointers1', r'1 verified, 0 errors?', 2), - ('pointers1_fail', r'0 verified, 1 errors?', 2), - ('pointers2', r'1 verified, 0 errors?', 2), - ('pointers2_fail', r'0 verified, 1 errors?', 2), - ('pointers3', r'1 verified, 0 errors?', 2), - ('pointers3_fail', r'0 verified, 1 errors?', 2), - ('globals', r'1 verified, 0 errors?', 2), - ('globals_fail', r'0 verified, 1 errors?', 2), - ('loop', r'1 verified, 0 errors?', 11), - ('loop_fail', r'0 verified, 1 errors?', 11), - ('loop1', r'1 verified, 0 errors?', 11), - ('loop1_fail', r'0 verified, 1 errors?', 11), - ('nondet', r'1 verified, 0 errors?', 2), - ('printfs', r'1 verified, 0 errors?', 2), - ('struct_return', r'1 verified, 0 errors?', 2), - ('struct_init', r'1 verified, 0 errors?', 2), - ('struct_init_fail', r'0 verified, 1 errors?', 2), - ('extern_struct', r'0 verified, 1 errors?', 2), - ('extern_func', r'1 verified, 0 errors?', 2), - ('extern_mem', r'1 verified, 0 errors?', 2), - ('extern_mem_fail', r'0 verified, 1 errors?', 2), - ('smack_code_call', r'1 verified, 0 errors?', 2), - ('smack_code_call_fail', r'0 verified, 1 errors?', 2), - ('return_label', r'1 verified, 0 errors?', 2), - ('struct_cast', r'1 verified, 0 errors?', 2), - ('struct_cast_fail', r'0 verified, 1 errors?', 2), - ('struct_cast1', r'1 verified, 0 errors?', 2), - ('struct_cast1_fail', r'0 verified, 1 errors?', 2), - ('nested_struct', r'1 verified, 0 errors?', 2), - ('nested_struct_fail', r'0 verified, 1 errors?', 2), - ('nested_struct1', r'1 verified, 0 errors?', 2), - ('nested_struct1_fail', r'0 verified, 1 errors?', 2), - ('nested_struct2', r'1 verified, 0 errors?', 2), - ('nested_struct2_fail', r'0 verified, 1 errors?', 2), - ('struct_assign', r'1 verified, 0 errors?', 2), - ('struct_assign_fail', r'0 verified, 1 errors?', 2), - ('func_ptr', r'1 verified, 0 errors?', 2), - ('func_ptr_fail', r'0 verified, 1 errors?', 2), - ('func_ptr1', r'1 verified, 0 errors?', 2), - ('func_ptr1_fail', r'0 verified, 1 errors?', 2), - ('array', r'1 verified, 0 errors?', 2), - ('array1', r'1 verified, 0 errors?', 2), - ('array1_fail', r'0 verified, 1 errors?', 2), - ('array2', r'1 verified, 0 errors?', 11), - ('array2_fail', r'0 verified, 1 errors?', 11), - ('array3', r'1 verified, 0 errors?', 11), - ('array3_fail', r'0 verified, 1 errors?', 11), - ('array4', r'1 verified, 0 errors?', 11), - ('array4_fail', r'0 verified, 1 errors?', 11), -# ('array_free', r'1 verified, 0 errors?', 11), -# ('array_free_fail', r'0 verified, 3 errors?', 11), -# ('array_free1', r'1 verified, 0 errors?', 11), -# ('array_free1_fail', r'0 verified, 4 errors?', 11), -# ('array_free2', r'1 verified, 0 errors?', 11), -# ('array_free2_fail', r'0 verified, 5 errors?', 11), - ('lock', r'1 verified, 0 errors?', 2), - ('lock_fail', r'0 verified, 1 errors?', 2), - ('ase_example', r'1 verified, 0 errors?', 11), - ('ase_example_fail', r'0 verified, 1 errors?', 11), - ('two_arrays', r'1 verified, 0 errors?', 2), - ('two_arrays1', r'1 verified, 0 errors?', 2), - ('two_arrays2', r'1 verified, 0 errors?', 2), - ('two_arrays3', r'1 verified, 0 errors?', 2), - ('two_arrays4', r'1 verified, 0 errors?', 2), - ('two_arrays5', r'1 verified, 0 errors?', 2), - ('two_arrays6', r'1 verified, 0 errors?', 2), - ('two_arrays6_fail', r'0 verified, 1 errors?', 2) + RegTest('hello', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('hello_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('simple', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('simple_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('simple_pre', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('simple_pre_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('simple_pre1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('simple_pre1_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('simple_pre2', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('simple_pre2_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('simple_pre3', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('simple_pre3_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), +# RegTest('simple_double_free', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('pointers', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('pointers_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('pointers1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('pointers1_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('pointers2', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('pointers2_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('pointers3', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('pointers3_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('globals', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('globals_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('loop', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), + RegTest('loop_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 11), + RegTest('loop1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), + RegTest('loop1_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 11), + RegTest('nondet', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('printfs', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('struct_return', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('struct_init', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('struct_init_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('extern_struct', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('extern_func', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('extern_mem', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('extern_mem_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('smack_code_call', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('smack_code_call_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('return_label', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('struct_cast', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('struct_cast_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('struct_cast1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('struct_cast1_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('nested_struct', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('nested_struct_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('nested_struct1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('nested_struct1_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('nested_struct2', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('nested_struct2_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('struct_assign', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('struct_assign_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('func_ptr', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('func_ptr_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('func_ptr1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('func_ptr1_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('array', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('array1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('array1_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('array2', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), + RegTest('array2_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 11), + RegTest('array3', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), + RegTest('array3_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 11), + RegTest('array4', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), + RegTest('array4_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 11), +# RegTest('array_free', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), +# RegTest('array_free_fail', r'0 verified, 3 errors?', r'This assertion can fail', r'This assertion can fail', 11), +# RegTest('array_free1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), +# RegTest('array_free1_fail', r'0 verified, 4 errors?', r'This assertion can fail', r'This assertion can fail', 11), +# RegTest('array_free2', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), +# RegTest('array_free2_fail', r'0 verified, 5 errors?', r'This assertion can fail', r'This assertion can fail', 11), + RegTest('lock', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('lock_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('ase_example', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 11), + RegTest('ase_example_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 11), + RegTest('two_arrays', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('two_arrays1', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('two_arrays2', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('two_arrays3', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('two_arrays4', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('two_arrays5', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('two_arrays6', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('two_arrays6_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2), + RegTest('floats_in_memory', r'1 verified, 0 errors?', r'Program has no bugs', r'Program has no bugs', 2), + RegTest('floats_in_memory_fail', r'0 verified, 1 errors?', r'This assertion can fail', r'This assertion can fail', 2) ] def red(text): return '\033[0;31m' + text + '\033[0m' - + def green(text): return '\033[0;32m' + text + '\033[0m' -def runtests(): +def runtests(verifier): passed = failed = 0 for test in tests: for mem in ['no-reuse', 'no-reuse-impls', 'reuse']: - print "{0:>20} {1:>16}:".format(test[0], "(" + mem + ")"), + print "{0:>25} {1:>16}:".format(test.name, "(" + mem + ")"), + + if os.path.isfile(test.name + '.c'): + sourceFile = test.name + '.c' + elif os.path.isfile(test.name + '.cc'): + sourceFile = test.name + '.cc' + elif os.path.isfile(test[0] + '.cpp'): + sourceFile = test.name + '.cpp' # invoke SMACK t0 = time.time() - p = subprocess.Popen(['smackverify.py', test[0] + '.c', '--verifier=boogie-inline', - '--unroll=' + str(test[2]), '--mem-mod=' + mem, '-o', test[0] +'.bpl'], + p = subprocess.Popen(['smackverify.py', sourceFile, '--verifier=' + verifier, + '--unroll=' + str(test.unroll), '--mem-mod=' + mem, '-o', test.name +'.bpl'], stdout=subprocess.PIPE) smackOutput = p.communicate()[0] elapsed = time.time() - t0 # check SMACK output - if re.search(test[1], smackOutput): + if re.search(getattr(test, verifier), smackOutput): print green('PASSED') + ' [%.2fs]' % round(elapsed, 2) passed += 1 else: @@ -123,8 +139,16 @@ def runtests(): if __name__ == '__main__': - passed, failed = runtests() + # parse command line arguments + parser = argparse.ArgumentParser(description='Runs regressions in this folder.') + parser.add_argument('--verifier', dest='verifier', choices=['boogie', 'corral', 'duality'], default=['corral'], nargs='*', + help='choose verifiers to be used') + args = parser.parse_args() + + for verifier in args.verifier: + print '\nRunning regressions using', verifier + passed, failed = runtests(verifier) - print '\nPASSED count: ', passed - print 'FAILED count: ', failed + print '\nPASSED count: ', passed + print 'FAILED count: ', failed diff --git a/test/simple.c b/test/simple.c index 72a903ce8..3c1b01e5a 100644 --- a/test/simple.c +++ b/test/simple.c @@ -9,7 +9,7 @@ int main(void) { a = 1; b = 2; a = -1; - __SMACK_assert(b == 3 || a == -1 || b == 0); + assert(b == 3 || a == -1 || b == 0); return a; } diff --git a/test/simple_fail.c b/test/simple_fail.c index 0b7654bf4..3652a8f53 100644 --- a/test/simple_fail.c +++ b/test/simple_fail.c @@ -7,7 +7,7 @@ int main(void) { a = 1; a = -1; - __SMACK_assert(a != -1); + assert(a != -1); return a; } diff --git a/test/simple_pre.c b/test/simple_pre.c index 08a62e3a3..8309c2ce2 100644 --- a/test/simple_pre.c +++ b/test/simple_pre.c @@ -11,7 +11,7 @@ int main(void) { a = -1; a = returnOne(); - __SMACK_assert(a == 1); + assert(a == 1); return a; } diff --git a/test/simple_pre1.c b/test/simple_pre1.c index 691f31a9c..62289a77f 100644 --- a/test/simple_pre1.c +++ b/test/simple_pre1.c @@ -11,7 +11,7 @@ int main(void) { a = -1; a = incr(a); - __SMACK_assert(a == -1); + assert(a == -1); return a; } diff --git a/test/simple_pre1_fail.c b/test/simple_pre1_fail.c index 5bbb4b089..e6a31e8f3 100644 --- a/test/simple_pre1_fail.c +++ b/test/simple_pre1_fail.c @@ -11,7 +11,7 @@ int main(void) { a = -1; a = incr(a); - __SMACK_assert(a == -1); + assert(a == -1); return a; } diff --git a/test/simple_pre2.c b/test/simple_pre2.c index f4d05d512..f6be7c203 100644 --- a/test/simple_pre2.c +++ b/test/simple_pre2.c @@ -11,7 +11,7 @@ int main(void) { a = 1; a = incr(a); - __SMACK_assert(a == 2); + assert(a == 2); return a; } diff --git a/test/simple_pre2_fail.c b/test/simple_pre2_fail.c index 05597a96b..e428e1182 100644 --- a/test/simple_pre2_fail.c +++ b/test/simple_pre2_fail.c @@ -11,7 +11,7 @@ int main(void) { a = 1; a = incr(a); - __SMACK_assert(a == 1); + assert(a == 1); return a; } diff --git a/test/simple_pre3.c b/test/simple_pre3.c index 563a9916c..56be14006 100644 --- a/test/simple_pre3.c +++ b/test/simple_pre3.c @@ -11,7 +11,7 @@ int main(void) { a = -1; a = returnOne(); - __SMACK_assert(a == 1 || a == 2); + assert(a == 1 || a == 2); return a; } diff --git a/test/simple_pre3_fail.c b/test/simple_pre3_fail.c index c422fab81..44934c260 100644 --- a/test/simple_pre3_fail.c +++ b/test/simple_pre3_fail.c @@ -11,7 +11,7 @@ int main(void) { a = -1; a = returnOne(); - __SMACK_assert(a == -1 || a == 2); + assert(a == -1 || a == 2); return a; } diff --git a/test/simple_pre_fail.c b/test/simple_pre_fail.c index 69fc05d1c..9d0846712 100644 --- a/test/simple_pre_fail.c +++ b/test/simple_pre_fail.c @@ -11,7 +11,7 @@ int main(void) { a = -1; a = returnOne(); - __SMACK_assert(a == -1); + assert(a == -1); return a; } diff --git a/test/smack_code_call.c b/test/smack_code_call.c index 149747d59..a82b514ef 100644 --- a/test/smack_code_call.c +++ b/test/smack_code_call.c @@ -13,10 +13,10 @@ int main(void) { // using a dummy unreachable call, force DSA to analyze foo so // that __SMACK_code works properly - __SMACK_assume(tmp == 0); + assume(tmp == 0); if (tmp) foo(y); __SMACK_code("call foo(@);",y); - __SMACK_assert(*y == 20); + assert(*y == 20); } diff --git a/test/smack_code_call_fail.c b/test/smack_code_call_fail.c index 4ff890217..9c535e879 100644 --- a/test/smack_code_call_fail.c +++ b/test/smack_code_call_fail.c @@ -13,10 +13,10 @@ int main(void) { // using a dummy unreachable call, force DSA to analyze foo so // that __SMACK_code works properly - __SMACK_assume(tmp == 0); + assume(tmp == 0); if (tmp) foo(y); __SMACK_code("call foo(@);",y); - __SMACK_assert(*y == 10); + assert(*y == 10); } diff --git a/test/struct_assign.c b/test/struct_assign.c index f4f1fc8c6..927ae9ab6 100644 --- a/test/struct_assign.c +++ b/test/struct_assign.c @@ -7,7 +7,7 @@ struct a { int main(void) { struct a x = {10, 20}; - __SMACK_assert(x.j == 20); + assert(x.j == 20); return 0; } diff --git a/test/struct_assign_fail.c b/test/struct_assign_fail.c index 31c7b6af3..8609470b7 100644 --- a/test/struct_assign_fail.c +++ b/test/struct_assign_fail.c @@ -7,7 +7,7 @@ struct a { int main(void) { struct a x = {10, 20}; - __SMACK_assert(x.j == 10); + assert(x.j == 10); return 0; } diff --git a/test/struct_cast.c b/test/struct_cast.c index b1fda0afc..f38836e02 100644 --- a/test/struct_cast.c +++ b/test/struct_cast.c @@ -18,7 +18,7 @@ int main(void) { s1.a = 3; p2->x = 4; - __SMACK_assert(s1.a == 4); + assert(s1.a == 4); return 0; } diff --git a/test/struct_cast1.c b/test/struct_cast1.c index edfb21164..18d211fc1 100644 --- a/test/struct_cast1.c +++ b/test/struct_cast1.c @@ -19,7 +19,7 @@ int main(void) { s2->b = 5; s1->x = 4; - __SMACK_assert(s2->a == 4); + assert(s2->a == 4); return 0; } diff --git a/test/struct_cast1_fail.c b/test/struct_cast1_fail.c index 3bfe1e06d..3a0c4b391 100644 --- a/test/struct_cast1_fail.c +++ b/test/struct_cast1_fail.c @@ -19,7 +19,7 @@ int main(void) { s2->b = 5; s1->x = 4; - __SMACK_assert(s2->a == 3); + assert(s2->a == 3); return 0; } diff --git a/test/struct_cast_fail.c b/test/struct_cast_fail.c index 60e84c975..111696830 100644 --- a/test/struct_cast_fail.c +++ b/test/struct_cast_fail.c @@ -18,7 +18,7 @@ int main(void) { s1.a = 3; p2->x = 4; - __SMACK_assert(s1.a == 3); + assert(s1.a == 3); return 0; } diff --git a/test/struct_init.c b/test/struct_init.c index 898baebf4..53bda4cdf 100644 --- a/test/struct_init.c +++ b/test/struct_init.c @@ -7,7 +7,7 @@ struct a { int main(void) { struct a x = {0,0}; - __SMACK_assert(x.i == 0 && x.j == 0); + assert(x.i == 0 && x.j == 0); return 0; } diff --git a/test/struct_init_fail.c b/test/struct_init_fail.c index 5120a9a00..4c486eae4 100644 --- a/test/struct_init_fail.c +++ b/test/struct_init_fail.c @@ -7,7 +7,7 @@ struct a { int main(void) { struct a x = {0,0}; - __SMACK_assert(x.j == 1); + assert(x.j == 1); return 0; } diff --git a/test/struct_return.c b/test/struct_return.c index 7474c1c47..91400c308 100644 --- a/test/struct_return.c +++ b/test/struct_return.c @@ -15,7 +15,7 @@ struct a foo(struct a bar) { int main(void) { struct a x; x = foo(x); - __SMACK_assert(x.j == 20); + assert(x.j == 20); return 0; } diff --git a/test/two_arrays.c b/test/two_arrays.c index 6d332e601..afa364889 100644 --- a/test/two_arrays.c +++ b/test/two_arrays.c @@ -31,16 +31,16 @@ int main() { setArray(arrayTwo); for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(arrayOne[i] == RESET); - __SMACK_assert(arrayTwo[i] == SET); + assert(arrayOne[i] == RESET); + assert(arrayTwo[i] == SET); } setArray(arrayOne); resetArray(arrayTwo); for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(arrayOne[i] == SET); - __SMACK_assert(arrayTwo[i] == RESET); + assert(arrayOne[i] == SET); + assert(arrayTwo[i] == RESET); } free(arrayOne); diff --git a/test/two_arrays1.c b/test/two_arrays1.c index 055863bd6..c144696df 100644 --- a/test/two_arrays1.c +++ b/test/two_arrays1.c @@ -46,9 +46,9 @@ int main() { initializeCount(arrayTwo); for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(arrayOne[i].status == RESET); - __SMACK_assert(arrayTwo[i].status == SET); - __SMACK_assert(arrayTwo[i].count == 0); + assert(arrayOne[i].status == RESET); + assert(arrayTwo[i].status == SET); + assert(arrayTwo[i].count == 0); } initializeCount(arrayOne); @@ -56,9 +56,9 @@ int main() { resetArray(arrayTwo); for (i = 0; i < MAXSIZE; i++) { - __SMACK_assert(arrayOne[i].count == 0); - __SMACK_assert(arrayOne[i].status == SET); - __SMACK_assert(arrayTwo[i].status == RESET); + assert(arrayOne[i].count == 0); + assert(arrayOne[i].status == SET); + assert(arrayTwo[i].status == RESET); } free(arrayOne); diff --git a/test/two_arrays2.c b/test/two_arrays2.c index d16eac761..02fbaa147 100644 --- a/test/two_arrays2.c +++ b/test/two_arrays2.c @@ -41,7 +41,7 @@ int main() { int i = 0; arraySize = __SMACK_nondet(); - __SMACK_assume(arraySize > 0); + assume(arraySize > 0); elem *arrayOne = (elem*)malloc(arraySize * sizeof(elem)); elem *arrayTwo = (elem*)malloc(arraySize * sizeof(elem)); @@ -51,9 +51,9 @@ int main() { initializeCount(arrayTwo); for (i = 0; i < arraySize; i++) { - __SMACK_assert(arrayOne[i].status == RESET); - __SMACK_assert(arrayTwo[i].status == SET); - __SMACK_assert(arrayTwo[i].count == 0); + assert(arrayOne[i].status == RESET); + assert(arrayTwo[i].status == SET); + assert(arrayTwo[i].count == 0); } initializeCount(arrayOne); @@ -61,9 +61,9 @@ int main() { resetArray(arrayTwo); for (i = 0; i < arraySize; i++) { - __SMACK_assert(arrayOne[i].count == 0); - __SMACK_assert(arrayOne[i].status == SET); - __SMACK_assert(arrayTwo[i].status == RESET); + assert(arrayOne[i].count == 0); + assert(arrayOne[i].status == SET); + assert(arrayTwo[i].status == RESET); } free(arrayOne); diff --git a/test/two_arrays3.c b/test/two_arrays3.c index d16eac761..02fbaa147 100644 --- a/test/two_arrays3.c +++ b/test/two_arrays3.c @@ -41,7 +41,7 @@ int main() { int i = 0; arraySize = __SMACK_nondet(); - __SMACK_assume(arraySize > 0); + assume(arraySize > 0); elem *arrayOne = (elem*)malloc(arraySize * sizeof(elem)); elem *arrayTwo = (elem*)malloc(arraySize * sizeof(elem)); @@ -51,9 +51,9 @@ int main() { initializeCount(arrayTwo); for (i = 0; i < arraySize; i++) { - __SMACK_assert(arrayOne[i].status == RESET); - __SMACK_assert(arrayTwo[i].status == SET); - __SMACK_assert(arrayTwo[i].count == 0); + assert(arrayOne[i].status == RESET); + assert(arrayTwo[i].status == SET); + assert(arrayTwo[i].count == 0); } initializeCount(arrayOne); @@ -61,9 +61,9 @@ int main() { resetArray(arrayTwo); for (i = 0; i < arraySize; i++) { - __SMACK_assert(arrayOne[i].count == 0); - __SMACK_assert(arrayOne[i].status == SET); - __SMACK_assert(arrayTwo[i].status == RESET); + assert(arrayOne[i].count == 0); + assert(arrayOne[i].status == SET); + assert(arrayTwo[i].status == RESET); } free(arrayOne); diff --git a/test/two_arrays4.c b/test/two_arrays4.c index d16eac761..02fbaa147 100644 --- a/test/two_arrays4.c +++ b/test/two_arrays4.c @@ -41,7 +41,7 @@ int main() { int i = 0; arraySize = __SMACK_nondet(); - __SMACK_assume(arraySize > 0); + assume(arraySize > 0); elem *arrayOne = (elem*)malloc(arraySize * sizeof(elem)); elem *arrayTwo = (elem*)malloc(arraySize * sizeof(elem)); @@ -51,9 +51,9 @@ int main() { initializeCount(arrayTwo); for (i = 0; i < arraySize; i++) { - __SMACK_assert(arrayOne[i].status == RESET); - __SMACK_assert(arrayTwo[i].status == SET); - __SMACK_assert(arrayTwo[i].count == 0); + assert(arrayOne[i].status == RESET); + assert(arrayTwo[i].status == SET); + assert(arrayTwo[i].count == 0); } initializeCount(arrayOne); @@ -61,9 +61,9 @@ int main() { resetArray(arrayTwo); for (i = 0; i < arraySize; i++) { - __SMACK_assert(arrayOne[i].count == 0); - __SMACK_assert(arrayOne[i].status == SET); - __SMACK_assert(arrayTwo[i].status == RESET); + assert(arrayOne[i].count == 0); + assert(arrayOne[i].status == SET); + assert(arrayTwo[i].status == RESET); } free(arrayOne); diff --git a/test/two_arrays5.c b/test/two_arrays5.c index f93999c6f..e11a1d48f 100644 --- a/test/two_arrays5.c +++ b/test/two_arrays5.c @@ -39,7 +39,7 @@ void initializeCount(elem *array) { int main() { arraySize = __SMACK_nondet(); - __SMACK_assume(arraySize > 0); + assume(arraySize > 0); elem *arrayOne = (elem*)malloc(arraySize * sizeof(elem)); elem *arrayTwo = (elem*)malloc(arraySize * sizeof(elem)); diff --git a/test/two_arrays6.c b/test/two_arrays6.c index 5303ee4c2..f24a70599 100644 --- a/test/two_arrays6.c +++ b/test/two_arrays6.c @@ -43,7 +43,7 @@ int main() { elem *arrayTwo; arraySize = __SMACK_nondet(); - __SMACK_assume(arraySize > 0); + assume(arraySize > 0); arrayOne = (elem*)malloc(arraySize * sizeof(elem)); arrayTwo = (elem*)malloc(arraySize * sizeof(elem)); @@ -53,9 +53,9 @@ int main() { initializeCount(arrayTwo); for (i = 0; i < arraySize; i++) { - __SMACK_assert(arrayOne[i].status == RESET); - __SMACK_assert(arrayTwo[i].status == SET); - __SMACK_assert(arrayTwo[i].count == 0); + assert(arrayOne[i].status == RESET); + assert(arrayTwo[i].status == SET); + assert(arrayTwo[i].count == 0); } initializeCount(arrayOne); @@ -63,9 +63,9 @@ int main() { resetArray(arrayTwo); for (i = arraySize - 1; i >= 0; i--) { - __SMACK_assert(arrayOne[i].count == 0); - __SMACK_assert(arrayOne[i].status == SET); - __SMACK_assert(arrayTwo[i].status == RESET); + assert(arrayOne[i].count == 0); + assert(arrayOne[i].status == SET); + assert(arrayTwo[i].status == RESET); } free(arrayOne); diff --git a/test/two_arrays6_fail.c b/test/two_arrays6_fail.c index 00de37dba..63f39ef52 100644 --- a/test/two_arrays6_fail.c +++ b/test/two_arrays6_fail.c @@ -43,7 +43,7 @@ int main() { elem *arrayTwo; arraySize = __SMACK_nondet(); - __SMACK_assume(arraySize > 0); + assume(arraySize > 0); arrayOne = (elem*)malloc(arraySize * sizeof(elem)); arrayTwo = (elem*)malloc(arraySize * sizeof(elem)); @@ -53,9 +53,9 @@ int main() { initializeCount(arrayTwo); for (i = 0; i < arraySize; i++) { - __SMACK_assert(arrayOne[i].status == RESET); - __SMACK_assert(arrayTwo[i].status == SET); - __SMACK_assert(arrayTwo[i].count == 0); + assert(arrayOne[i].status == RESET); + assert(arrayTwo[i].status == SET); + assert(arrayTwo[i].count == 0); } initializeCount(arrayOne); @@ -63,7 +63,7 @@ int main() { resetArray(arrayTwo); for (i = arraySize - 1; i >= 0; i--) { - __SMACK_assert(arrayOne[i].count != 0 || arrayOne[i].status != SET || arrayTwo[i].status != RESET); + assert(arrayOne[i].count != 0 || arrayOne[i].status != SET || arrayTwo[i].status != RESET); } free(arrayOne); diff --git a/tools/smack/smack.cpp b/tools/smack/smack.cpp index 1e547a1b5..136ad38da 100644 --- a/tools/smack/smack.cpp +++ b/tools/smack/smack.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/raw_ostream.h" @@ -48,22 +49,22 @@ std::string getFileName(const std::string &str) { int main(int argc, char **argv) { llvm::llvm_shutdown_obj shutdown; // calls llvm_shutdown() on exit llvm::cl::ParseCommandLineOptions(argc, argv, "SMACK - LLVM bitcode to Boogie transformation\n"); - + llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram PSTP(argc, argv); llvm::EnableDebugBuffering = true; - + if (OutputFilename.empty()) { // OutputFilename = getFileName(InputFilename) + ".bpl"; OutputFilename = "a.bpl"; } - + std::string error_msg; llvm::SMDiagnostic err; llvm::LLVMContext &context = llvm::getGlobalContext(); - llvm::OwningPtr module; - llvm::OwningPtr output; - + std::unique_ptr module; + std::unique_ptr output; + module.reset(llvm::ParseIRFile(InputFilename, err, context)); if (module.get() == 0) { if (llvm::errs().has_colors()) llvm::errs().changeColor(llvm::raw_ostream::RED); @@ -71,44 +72,45 @@ int main(int argc, char **argv) { if (llvm::errs().has_colors()) llvm::errs().resetColor(); return 1; } - - output.reset(new llvm::tool_output_file(OutputFilename.c_str(), error_msg)); + + output.reset(new llvm::tool_output_file(OutputFilename.c_str(), error_msg, llvm::sys::fs::F_None)); if (!error_msg.empty()) { if (llvm::errs().has_colors()) llvm::errs().changeColor(llvm::raw_ostream::RED); llvm::errs() << "error: " << error_msg << "\n"; if (llvm::errs().has_colors()) llvm::errs().resetColor(); return 1; } - + /////////////////////////////// // initialise and run passes // /////////////////////////////// - + llvm::PassManager pass_manager; llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); llvm::initializeAnalysis(Registry); - + // add an appropriate DataLayout instance for the module - llvm::DataLayout *dl = 0; - const std::string &moduleDataLayout = module.get()->getDataLayout(); + const llvm::DataLayout *dl = 0; + const std::string &moduleDataLayout = module.get()->getDataLayoutStr(); if (!moduleDataLayout.empty()) dl = new llvm::DataLayout(moduleDataLayout); else if (!DefaultDataLayout.empty()) dl = new llvm::DataLayout(moduleDataLayout); - if (dl) pass_manager.add(dl); - + if (dl) pass_manager.add(new llvm::DataLayoutPass(*dl)); + + pass_manager.add(llvm::createLowerSwitchPass()); + pass_manager.add(llvm::createCFGSimplificationPass()); pass_manager.add(llvm::createInternalizePass()); pass_manager.add(llvm::createPromoteMemoryToRegisterPass()); - pass_manager.add(llvm::createDeadInstEliminationPass()); - pass_manager.add(llvm::createLowerSwitchPass()); pass_manager.add(new llvm::StructRet()); pass_manager.add(new llvm::SimplifyEV()); pass_manager.add(new llvm::SimplifyIV()); pass_manager.add(new smack::SmackModuleGenerator()); pass_manager.add(new smack::BplFilePrinter(output->os())); pass_manager.run(*module.get()); - + output->keep(); - + return 0; } +