处理的语句

case

术语约定或备忘

case起止范围: 从冒号到下一个’case’开头, 简称有: case内 、case内容

Ast: Abstract syntax tree: 抽象语法树

没插入花括号的case

若case内, 以下任一条成立,则 跳过该case 即 不会对该case内容用花括号包裹.

有#define、

有#include、

有直属变量声明、

空case、

有宏调用

详述

预处理回调收集#include指令、宏定义

CollectIncMacro_PPCb:Collect Inlucde Macro PPCallbacks : 收集Inlucde和Macro的预处理回调

收集 #include、 #define , 以判断case起止范围内 有无 #include、 #define

遍历switch内某case起止范围内每条语句

RangeHasMacroAstVst: Range Has Macro Call Ast Vistor: 给定范围有无宏调用Ast遍历器

名义上遍历整个switch下的Stmt,实际遍历 给定范围内( 即 case起止范围 内) 的语句,进行以下计算:

1. hasMacro: case起止范围 有无宏调用,

从而帮助过滤掉 有宏调用 的case

2. caseKSubStmtCnt: case起止范围 语句个数(即 case子语句个数),

从而帮助 过滤掉 空case

3. VarDeclDirectlyInCaseKCnt: 直接写在'case'内的变量声明语句个数,

即 直属变量声明个数

从而 帮助过滤掉 有直属变量声明 的case。

直接写在'case'内的变量声明语句个数,包括以下两种情况:

3.1. 直接写在'case'内,其父亲是case语句的

3.2. 直接写在'case'内, 但是其父亲是switch块的.

即 存在 在case内的语句 但却不属于该case 而是直接属于switch, 此现象,直接导致 case的子语句 是伪命题,

才使得 RangeHasMacroAstVst 不可能 实现无遗漏地 遍历 case下的子语句 ,

只能扩大遍历范围到整个switch 并只关注case起止范围内的语句 才能 实现无遗漏地、精准地 遍历 case下的子语句。

实际运行花括号插件

到此 加花括号插件完工了,在llvm-project上正常运行:

sudo docker exec -it ubuntu2204_clang15Compile bash

弹出docker实例ubuntu2204_clang15Compile的bash命令行,以下命令都在此命令行下执行

cd /pubx/

git clone https://gitcode.net/pubz/llvm-project/-/commits/brc-dev-no_tick

#即 https://gitcode.net/pubz/llvm-project/-/commit/bee38a325d0957a28b4d06cb4be3c251d143cdf0

#克隆仓库llvm-project后目录结构如下: /pubx/llvm-project/.git/config

步骤1: 对每个被直接编译的源文件中单语句加花括号

对llvm-project的每个源文件的编译过程应用插件libBrcPlugin.so 以 对 该源文件中单语句加花括号

source /pubx/llvm-project/doc_clang15_build/brc_build1_plugin.sh

brc_build1_plugin.sh

步骤2: 对加了花括号后的llvm-project再次做正常的普通编译

source /pubx/llvm-project/doc_clang15_build/brc_build2_directly.sh

brc_build2_directly.sh

步骤3: 验证

//编写c语言源文件 hello.c,内容如下:

#include

int main(int argc, char** argv){

int a,b;

printf("a,b:");

scanf("%d,%d",&a,&b);

int sum=a+b, diff=a-b, div=a/b, mod=a%b;

printf("sum=%d,diff=%d,div=%d,mod=%d\n",sum,diff,div,mod);

return 0;

}

/pubx/build-llvm15/bin/clang-15 hello.c -o hello.app

./hello.app

a,b:45,21

sum=66,diff=24,div=2,mod=3

加完花括号的llvm-project源码编译出的编译器clang-15 对 hello.c 实施编译, 编译出二进制文件 hello.app,

而该二进制文件 hello.app 正常运行

由此说明 ,花括号加的位置基本正确。

#统计

find /pubx/llvm-project/ -not -path '*/.git/*' -type f \( -name "*.cpp" -or -name "*.c" \) | xargs -I% grep -Hn BrcXxx % > /pubx/BrcXxx.log

#把上一条bash命令抽成bash函数

findBrcCommentThenSave() {

set -x #bash启用显示执行的命令

keyword=$1

find /pubx/llvm-project/ -not -path '*/.git/*' -type f \( -name "*.cpp" -or -name "*.c" \) | xargs -I% grep -Hn "$keyword" % |tee /pubx/"${keyword}.log"

set +x #bash禁止显示执行的命令

}

findBrcCommentThenSave BrcThen

findBrcCommentThenSave BrcSw

findBrcCommentThenSave BrcElse

findBrcCommentThenSave BrcFor

findBrcCommentThenSave BrcForRange

findBrcCommentThenSave BrcWhl

findBrcCommentThenSave BrcSw

各种语句分别加了多少花括号

ls -S /pubx/Brc* | xargs -I% sh -c 'wc -l %; '

'''

93201 /pubx/BrcThen.log

29832 /pubx/BrcSw.log

5539 /pubx/BrcElse.log

3603 /pubx/BrcFor.log

2187 /pubx/BrcForRange.log

663 /pubx/BrcWhl.log

'''

各种语句加了花括号的,有多少含有return

这些单语句return,由于没有被花括号包裹,才没有被t_clock_tick插入栈变量释放语句。 而tick插件栈变量分配、释放不平衡,具体为 栈变量共24万、最终残留2万没释放。 此不平衡是 由于 这些大约5万个单return语句没释放栈变量 导致的吗? 如下所示,被BrcPlugin插入花括号的语句中 大约5万个含有return.

ls -S /pubx/Brc* | xargs -I% sh -c 'echo -n "% "; grep return % |wc -l '

'''

/pubx/BrcThen.log 50438

/pubx/BrcSw.log 2681

/pubx/BrcElse.log 815

/pubx/BrcFor.log 6

/pubx/BrcForRange.log 4

/pubx/BrcWhl.log 2

'''

实现

CMakeLists.txt

cmake_minimum_required(VERSION 3.13.4)

set(LIBFMT_DIR "/pubx/fmt/")

#set(LIBFMT_STATIC /pubx/fmt/include)

set(LIBFMT_INCLUDE "${LIBFMT_DIR}/include/")

#set(LIBFMT_STATIC /pubx/fmt/build/libfmt.a)

set(LIBFMT_STATIC "${LIBFMT_DIR}/build/libfmt.a")

include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/include")

include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/base_home/include/")

if (NOT EXISTS "${LIBFMT_STATIC}")

MESSAGE(FATAL_ERROR "libfmt静态库${LIBFMT_STATIC} 不存在,请参照 build-libfmt.sh 构建libfmt静态库")

endif()

if (NOT EXISTS "${LIBFMT_INCLUDE}")

MESSAGE(FATAL_ERROR "libfmt头文件目录${LIBFMT_INCLUDE} 不存在,请参照 build-libfmt.sh 构建libfmt静态库")

endif()

#===============================================================================

# 0. GET CLANG INSTALLATION DIR

#修改默认编译器

set(CT_Clang_INSTALL_DIR "/llvm_release_home/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4")

set(CMAKE_VERBOSE_MAKEFILE ON)

set(CURSES_LIBRARY "/lib64/libncurses.so.6")

set(CURSES_INCLUDE_PATH "/usr/include/")

set(CMAKE_EXPORT_COMPILE_COMMANDS True)

#编译器还是使用自带的gcc, 否则 调试时 没有 libstdc++ 的调试信息,导致std::string在gdb中不显示,参考:https://stackoverflow.com/questions/58356385/python-exception-class-gdb-error-there-is-no-member-named-m-dataplus-whe/58356946#58356946

# gdb显示std::string时报错: There is no member named _M_dataplus。 因此gdb不显示std::string的值.

#set(CMAKE_C_COMPILER "/llvm_release_home/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4/bin/clang")

#set(CMAKE_CXX_COMPILER "/llvm_release_home/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4/bin/clang++")

set(LLVM_DIR "/llvm_release_home/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4")

#set(xxx "")

project(clang-brc)

#project放到默认编译器定义之后,否则cmake会死循环

set(CT_LLVM_INCLUDE_DIR "${CT_Clang_INSTALL_DIR}/include/llvm")

set(CT_LLVM_CMAKE_FILE "${CT_Clang_INSTALL_DIR}/lib/cmake/clang/ClangConfig.cmake")

# http://llvm.org/docs/CMake.html#embedding-llvm-in-your-project

list(APPEND CMAKE_PREFIX_PATH "${CT_Clang_INSTALL_DIR}/lib/cmake/clang/")

find_package(Clang REQUIRED CONFIG)

# Sanity check. As Clang does not expose e.g. `CLANG_VERSION_MAJOR` through

# AddClang.cmake, we have to use LLVM_VERSION_MAJOR instead.

# TODO: Revisit when next version is released.

if(NOT "15" VERSION_EQUAL "${LLVM_VERSION_MAJOR}")

message(FATAL_ERROR "Found LLVM ${LLVM_VERSION_MAJOR}, but need LLVM 15")

endif()

message(STATUS "Found Clang ${LLVM_PACKAGE_VERSION}")

message(STATUS "Using ClangConfig.cmake in: ${CT_Clang_INSTALL_DIR}")

message("CLANG STATUS:

Includes (clang) ${

CLANG_INCLUDE_DIRS}

Includes (llvm) ${

LLVM_INCLUDE_DIRS}"

)

# Set the LLVM and Clang header and library paths

include_directories(SYSTEM "${LLVM_INCLUDE_DIRS};${CLANG_INCLUDE_DIRS}")

#===============================================================================

# 3. CLANG-brc BUILD CONFIGURATION

#===============================================================================

# Use the same C++ standard as LLVM does

set(CMAKE_CXX_STANDARD 17 CACHE STRING "")

# Build type

if(NOT CMAKE_BUILD_TYPE)

set(CMAKE_BUILD_TYPE Debug CACHE

STRING "Build type (default Debug):" FORCE)

endif()

# Compiler flags

set(CMAKE_CXX_FLAGS "${

CMAKE_CXX_FLAGS} -Wall\

-fdiagnostics-color=always")

# LLVM/Clang is normally built without RTTI. Be consistent with that.

if(NOT LLVM_ENABLE_RTTI)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")

endif()

# -fvisibility-inlines-hidden is set when building LLVM and on Darwin warnings

# are triggered if llvm-tutor is built without this flag (though otherwise it

# builds fine). For consistency, add it here too.

include(CheckCXXCompilerFlag)

check_cxx_compiler_flag("-fvisibility-inlines-hidden"

SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: