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

Different functions with the same name and how to call them in 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

其中在 foobar 中定义了两个不同的 b 函数。

所以foo里面的b对应的LLVM IR函数是

define void @b(%foo_type* %foo_frame) {
...

对于 bar 内的 b

define void @b.1(%bar_type* %bar_frame) {
...

问题是,当我尝试调用函数 b 时,LLVM 自动假定我正在调用 void @b,但我无法调用 void @b.1

因此,打印结果是 11 但我希望它是 12

我使用TheModule->getFunction("b");命令访问LLVM函数对象。

那么,如何调用 bar 中定义的 b 函数?

更新:

正如 AlexDenisov 指出的那样,我可以将第一个 b 命名为 main_foo_b,将第二个命名为 main_bar_b。 这样我就可以调用正确的函数 b,方法是找出我从代码的哪一部分调用 b。我将尝试通过持有所有函数名称的列表直到现在(尚未关闭)。让我们称之为 function_names_list.

所以当我调用 mainfoo 中的 b 函数时,我会调用 main_foo_b 因为 function_names_list=["main","foo"]。当我调用 mainbar 中的 b 函数时,我会调用 main_bar_b 因为 function_names_list=["main","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_fmain_gmain_h 有 1 层嵌套,main_g_f 有两层嵌套。

我需要检查嵌套级别,因为我需要更改在 h 中调用 f 的方式。我必须将其称为 main_f 而不是main_h_f。通过知道我尝试调用的 f 处于先前的嵌套级别,然后我可以按顺序使用 function_names_list (function_names_list[0:n-1]) 中除一个元素之外的所有元素获取名称 main_f.

欢迎来到 SO,Nik。

在内部,所有全局值(例如函数、变量和别名)都存在于 LLVM 模块内的类似哈希 table 的存储中,其中名称用作键。为了避免冲突,LLVM 为函数名添加了后缀。

我想在这种情况下您必须添加某种命名空间,即将第一个 b 命名为 main_foo_b,将第二个命名为 main_bar_b。这样你就可以清楚地区分'colliding'个名字。

希望对您有所帮助:)

UPD:

现在看来我有点过头了,@arnt的建议听起来更合理。您使用 function_names_list 的解决方案是正确的方向。通常,这通过所谓的 Symbol Table 来解决:一个符号 table 只是一个键值数据结构,它也有一个指向父符号 table 的指针。你的例子中的键是函数名,值是发出的 LLVM 函数。

您从一个全局符号 table(对于整个翻译单元)开始,然后每当您进入一个新范围时,您都会创建一个新符号 table 并将父级设置为“上一个”符号 table。然后,当您需要发出对函数的调用时,您会在当前符号 table 中查找命名函数,如果有 none,则您走上去查看父符号 table.递归执行直到到达全局符号 table,在这种情况下,可以将缺少的函数报告为错误。

这是您的第一个代码片段的示例:

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>

bb.1 的表是空的,所以为了简洁我跳过了它们)。

然后,根据范围(foobar),您将开始查找 foo_tablebar_table,并且应该找到正确的 b函数。