解决LLVM单元测试globalvariable-attributes.ll报错

解决LLVM单元测试globalvariable-attributes.ll报错

由于修改了LLVM代码,LLVM单元测试globalvariable-attributes.ll报错。下面记下我调试的过程

问题定位

单元测试的报错信息如下:

FAIL: LLVM :: Assembler/globalvariable-attributes.ll (4858 of 32600)
******************** TEST 'LLVM :: Assembler/globalvariable-attributes.ll' FAILED ********************   Script:
--
: 'RUN: at line 1';   /home/cmp/work_dir/source_code/WMarsh_shadow_build/bin/llvm-as < /home/cmp/work_dir/source_code/WMarsh_shadow/llvm/test/Assembler/globalvariable-attributes.ll | /home/cmp/work_dir/source_code/WMarsh_shadow_build/bin/llvm-dis | /home/cmp/work_dir/source_code/WMarsh_shadow_build/bin/llvm-as | /home/cmp/work_dir/source_code/WMarsh_shadow_build/bin/llvm-dis | /home/cmp/work_dir/source_code/WMarsh_shadow_build/bin/FileCheck /home/cmp/work_dir/source_code/WMarsh_shadow/llvm/test/Assembler/globalvariable-attributes.ll
--
Exit Code: 1

为了找到问题的原因我试着,在输入同一个文件/home/cmp/work_dir/source_code/WMarsh_shadow/llvm/test/Assembler/globalvariable-attributes.ll下,用原llvm-as和修改后的llvm-as1对比输出结果:

/home/cmp/work_dir/source_code/WMarsh_shadow_build/bin/llvm-as -f /home/cmp/work_dir/source_code/WMarsh_shadow/llvm/test/Assembler/globalvariable-attributes.ll -o ./WMarsh_tmp.bc
/home/cmp/work_dir/source_code/llvm-project-9.0/bin/llvm-as -f /home/cmp/work_dir/source_code/WMarsh_shadow/llvm/test/Assembler/globalvariable-attributes.ll -o ./llvm90_tmp.bc

使用原llvm-as将IR转为字节码文件,生成llvm90_tmp.bc

使用llvm-as1将IR转为字节码文件,生成WMarsh_tmp.bc

然后使用原llvm-dis分别处理llvm90_tmp.bc结果如下:

; ModuleID = 'llvm90_tmp.bc'
source_filename = "/home/cmp/work_dir/source_code/WMarsh_shadow/llvm/test/Assembler/globalvariable-attributes.ll"

@g1 = global i32 7 #0
@g2 = global i32 2, align 4 #1
@g3 = global i32 2 #2
@g4 = global i32 2, align 4 #3

attributes #0 = { "key"="value" "key2"="value2" }
attributes #1 = { "key3"="value3" }
attributes #2 = { nobuiltin norecurse "string"="value" }
attributes #3 = { nobuiltin norecurse "key5"="value5" "string"="value" }

然后使用原llvm-dis分别处理WMarsh_tmp.bc结果如下:

; ModuleID = 'WMarsh_tmp.bc'
source_filename = "/home/cmp/work_dir/source_code/WMarsh_shadow/llvm/test/Assembler/globalvariable-attributes.ll"

@g1 = dso_local global i32 7, partition "g1"
@g2 = global i32 2, partition "g1", align 4
@g3 = global i32 2, partition "g1"
@g4 = global i32 2, partition "g1", align 4

从上面结果可以看出是我修改的代码影响了llvm-as工具,导致产生的字节码文件有问题。

进一步精确定位问题

由于llvm-as工具产生的是llvm二进制字节码文件,直接对比阅读llvm-as的输出文件是不可行的。

首先我的想法是利用llvm-dis工具分别读入llvm90_tmp.bc和WMarsh_tmp.bc文件,然后通过调试观察@g全局变量的输入是由什么原因引起的。如下图所示:

PrintDSOLocation函数会根据GV中的信息,输入dso_local

hasPartition函数会判断GV中是否有partition,然后通过getPartition函数获取,最后printEscapedString输出

从上面基本上我们可以看出差异,并可以通过PrintDSOLocation、hasPartition、getPartition和printEscapedString所用到的GV中的相关变量来反向锁定llvm字节码文件中存在的问题,然后在通过发现的问题,反过来定位llvm-dis或者llvm-as在输出字节码过程中存在的bug。

调试

调试中发现:1.输出的dso_local和BitcodeReader在读取GV时,取的Record的第14个元素;2.输出的partition和BitcodeReader在读取GV时,取的Record的第16个元素。如下图所示:

对比llvm-as工具在输出llvm字节码时,WMarsh_tmp.bc相比于llvm90_tmp.bc多在Record中输出了isNoCrossCheck的元素,该元素插入Record中,位于Record中第11位。增加isNoCrossCheck到Record中的代码如下图所示:

调试对比BitcodeReader在读取正确的GV Record和错误和GV Record时,Record中各个元素的值信息,如下图所示:

可以看出WMarsh_tmp.bc相比于llvm90_tmp.bc,Record多了一个元素。继续走读BitcodeReader::parseGlobalVarRecord函数会发现:由于在Record中增加了第11位的isNoCrossCheck,我在修改代码的时候,忘记在原来的基础上对Record后面的元素读取做对应修改了,都应该在读取时为元素的位置+1。修改方案如下图所示:

结束语

首次对编译器进行定制修改和调试,很多陌生的地方;以及编译器涉及的字节码和指令码都比较底层,和硬件架构相关等等,感觉十分困难。

比较庆幸的是,在足够耐心,多次慢慢啃问题终于把之前单元测试7K多FAILED,解决到现在只有40个FAILED。

耐心,信心,细心,决心,相信自己一定能在最快时间把编译器开发调试的目标完成。

猜你喜欢

转载自blog.csdn.net/weixin_46222091/article/details/105038223