Compiler construction 具有相同名称的不同函数以及如何在LLVM IR中调用它们
我正在为类似pascal的语言编写一个玩具编译器。 假设我有一个伪代码,如下所示:Compiler construction 具有相同名称的不同函数以及如何在LLVM IR中调用它们,compiler-construction,llvm,llvm-ir,Compiler Construction,Llvm,Llvm Ir,我正在为类似pascal的语言编写一个玩具编译器。 假设我有一个伪代码,如下所示: define main define foo define b writeInteger: 1 call b define bar define b writeInteger: 2 call b call foo call bar define main define f wri
define main
define foo
define b
writeInteger: 1
call b
define bar
define b
writeInteger: 2
call b
call foo
call bar
define main
define f
writeInteger: 1
define g
define f
writeInteger: 2
call f
define h
call f
call g # prints 2
call f # prints 1
call h # prints 1
其中,在foo
和bar
中定义了两个不同的b
函数
因此foo
内部的b
对应的LLVM IR函数为
define void @b(%foo_type* %foo_frame) {
...
define void @b.1(%bar_type* %bar_frame) {
...
对于b
而言,条的内部是
define void @b(%foo_type* %foo_frame) {
...
define void @b.1(%bar_type* %bar_frame) {
...
问题是,当我尝试调用函数b
时,LLVM自动假定我正在调用void@b
,但我无法调用void@b.1
因此,打印的结果是11
,但我希望它是12
我使用module->getFunction(“b”)代码>访问LLVM函数对象的命令
那么,如何调用bar
中定义的b
函数呢
更新:
正如阿列克谢尼索夫指出的,我可以将第一个b命名为main\u foo\u b
,第二个命名为main\u bar\u b
。
这样我就可以调用正确的函数b
,通过找出调用b的代码部分。我将通过保存一个到目前为止(尚未关闭)的所有函数名的列表来尝试这一点。让我们称它为函数\u名称\u列表
因此,当我调用main
和foo
中的b
函数时,我会调用main\u foo\u b
,因为function\u names\u list=[“main”,“foo”]
。当我调用main
和bar
中的b
函数时,我会调用main\u bar\u b
,因为function\u names\u list=[“main”,“bar”]
。
这可能会解决当前示例的问题
但在如下示例中:
define main
define foo
define b
writeInteger: 1
call b
define bar
define b
writeInteger: 2
call b
call foo
call bar
define main
define f
writeInteger: 1
define g
define f
writeInteger: 2
call f
define h
call f
call g # prints 2
call f # prints 1
call h # prints 1
我还需要检查函数的嵌套级别。我所说的嵌套级别是指我目前拥有多少个封闭函数main
有零嵌套级别,main\u f
,main\u g
和main\u h
有一个嵌套级别,main\u f
有两个嵌套级别
我需要检查嵌套级别,因为我需要更改在h
内部调用f
的方式。我必须将其称为main\u f
,而不是main\u f
。通过知道我试图调用的f
处于先前的嵌套级别,然后,我可以使用函数名称列表中的所有元素,但只有一个元素(函数名称列表[0:n-1]
),以获得名称主元素欢迎来到SO,Nik
在内部,所有全局值(如函数、变量和别名)都位于LLVM模块内部的类似哈希表的存储中,其中名称用作键。为了避免冲突,LLVM在函数名中添加后缀
我想在这种情况下,您必须添加某种名称空间,即将第一个b
命名为main\u foo\u b
,将第二个命名为main\u bar\u b
。这样,您可以清楚地区分“冲突”名称
我希望这有帮助:)
UPD:
现在看来我走得太远了,@arnt的建议听起来更合理。您使用函数\u名称\u列表
的解决方案是正确的方向。通常,这可以通过一个所谓的方法来解决:符号表只是一个键值数据结构,它也有一个指向父符号表的指针。本例中的键是函数名,值是由LLVM函数发出的
从全局符号表(用于整个翻译单元)开始,然后无论何时输入新范围,都会创建一个新符号表,并将父符号表设置为“上一个”符号表。然后,当需要发出对函数的调用时,在当前符号表中查找命名函数,如果没有,则向上查看父符号表。递归地执行此操作,直到到达全局符号表,在这种情况下,丢失的函数可以作为错误报告
以下是第一个代码段的示例:
global_table:
scope = <whole translation unit>
parent = null
"main" = <main function>
main_table:
scope = <main function>
parent = global_table
"foo" = <foo function>
"bar" = <bar function>
foo_table:
scope = <foo function>
parent = main_table
"b" = <b function>
bar_table:
scope = <bar function>
parent = main_table
"b" = <b.1 function>
global\u表:
范围=
父项=null
“主要”=
主表:
范围=
父表=全局表
“福”=
“酒吧”=
富奥表:
范围=
父表=主表
“b”=
吧台:
范围=
父表=主表
“b”=
(用于b
和b.1
的表格是空的,因此为了简洁起见,我跳过了它们)
然后,根据范围(foo
或bar
),您将开始查找foo\u表
或bar\u表
,并应找到正确的b
函数。如果您在LLVM中将其定义为@b.1
,您还必须使用b.1
名称访问它,不是b
模块->获取函数(“b.1”)代码>?谢谢您的回答。将其用作module->getFunction(“b.1”)的问题代码>是指我不知道何时调用哪个b
。函数调用module->getFunction(name)
名称将是一个字符串“b”
,因为解析器将读取该字符串。有没有其他方法可以得到正确的“b”函数,意思是“b.1”?谢谢你的回答。我认为您的解决方案可能适用于当前的示例。我需要保留函数的名称,然后像你说的那样调用b。但在一个例子中,我还需要在main内部调用一个调用f
函数的h
函数,我还需要检查函数的嵌套级别,因为在h
内部我需要调用main\u f
而不是main\u f
对不起,如果没有格式,我看不到代码:)我建议您将此代码段添加到问题的末尾(只需编辑问题)。非常感谢您的回答和指导。我会尝试这个解决方案,看看这是否有助于我解决这个问题。通常情况下,你会有一个cl