Compiler construction 具有相同名称的不同函数以及如何在LLVM IR中调用它们

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

我正在为类似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

      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