如何解决llvm-IR变量和汇编器符号的llvm命名策略
如我所见,llvm支持以空终止的字符串(包括任何字符(0x01至0xff))作为llvm-IR变量和汇编符号的有效名称。我认为这样的选择可能会引起一些问题。
- 当名称包含“特殊”(不可打印)字符时,很难使用文本编辑器(Vim,Kate等)在llvm-IR和汇编器中编辑程序
- LLvm和汇编程序支持使用双引号转义,例如
"A B"
是带空格字符的名称。从逻辑上讲,在特殊字符编码中期望有类似printf的样式。我的意思是"\n"
,"\t"
,"\xAB"
,但是llvm-IR和汇编器不支持这种名称样式(但是llvm支持\ KL作为初始化器)。
- 一方面
"A\n"
不会产生"A"
和newline character
,而是会在对象elf文件中使用所有3个字节进行命名
另一方面,{li>
"A\n"
和"A\\n"
为llvm产生相同的名称
(因此,似乎llvm也不以任何适当的方式支持特殊命名。)
@"A\n" = internal constant i32 1
@"A\\n" = internal constant i32 2
$ clang-9 test.ll -S
test.ll:3:1: error: redefinition of global '@A\n'
@"A\\n" = internal constant i32 2
-
关于
@GOTOFF
或@plt
的情况是什么?如何从汇编器重定位规范中区分包括@GOTOFF
在内的名称?为什么"A B@GOTOFF"
可以组装,但是"A B"@GOTOFF
不起作用? -
错误https://sourceware.org/bugzilla/show_bug.cgi?id=18581于2015年开放,但即使现在gas也不支持llvm支持的名称中的某些字符。例如
"A,B"
和"A\B"
不能用气体组装。 因此llvm会创建汇编方言,该方言不能通过gas进行汇编。
编程语言(C / C ++,Rust,Go,Python,Java等)在标识符中仅支持letters
,digits
,'_'
,'$'
个字符。前端也使用'.'
,'$'
,'#'
字符,但是它们以任何方式生成在汇编程序中有效的名称(不带双引号)。
可能只有llvm优化会生成带有特殊字符的名称。但是,这些名称仅为具有内部(C术语为静态)链接的全局变量创建。那么,为什么不对此类全局变量使用"__llvm_internal_global_Id_*"
之类的特殊模式(在所有情况下都保留某些名称)?
那么使用这种命名策略的原因是什么?使用少量但简单的有效字符进行命名可能更好吗?
解决方法
我将尝试总结中期结果。
llvm支持llvm-IR变量名称和asm符号名称,以任何字符序列组成。总的来说,这是一个很好的解决方案。
但是当前的实现有一些特殊的时刻。
-
Llvm-parser可以与llvm-IR一起使用,其中字符串初始化程序和全局变量名称都包含转义序列(使用“ \ AB”模式,其中0xAB是十六进制代码)。但是在汇编语言中,转义序列未使用或/并且不起作用(还有readelf,objdump,gdb等)。这个事实为使用文本编辑器带来了问题。
-
汇编语言在符号名称之后使用特殊的重定位修饰符,例如
@plt
,@GOTOFF
等。因此,当符号名称(用双引号引起来)包含一个像"@plt"
之类的子字符串时,这就是一次碰撞。我为汇编程序lexic-parser提出了一条简单规则
A@plt - symbol with name 'A' and plt-relocation
"A@plt" - symbol with name 'A@plt'
"A@plt"@plt - symbol with name 'A@plt' and plt-relocation
(因此,双引号中的所有字符都是名称的一部分,双引号中的所有字符或仅在符号名称的末尾都是重定位修饰符)。
- Gas声明了支持(https://sourceware.org/binutils/docs/as/Symbol-Intro.html#Symbol-Intro),但实际上不支持符号名称中的
","
或"\"
。因此,gas中的有效符号名称集要比llvm-as中的少。
我希望这些时刻能在llvm和gas中得到解决(如果这是对当前情况的正确描述)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。