【问题标题】:LLVM - How to make a nested function see an outside function's variablesLLVM - 如何让嵌套函数看到外部函数的变量
【发布时间】:2019-04-17 21:43:34
【问题描述】:

我正在尝试为支持嵌套函数的语言编写编译器,例如:

func a()
   int x;
   func b()
      int y;
      {
       // code of func b - both x and y are visible here
      }
   {
    // code of func a - only x is visible here
   }

我在 C++ 中使用 LLVM API 来编译代码。我的问题是我不知道如何使变量 x 在函数 b 中可见,因为据我所知 llvm 不支持嵌套函数。我现在声明变量的方式是这个函数:

static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName, Type *T) {
    IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin());
    return TmpB.CreateAlloca(T, 0, VarName.c_str());
}

如llvm教程https://llvm.org/docs/tutorial/LangImpl07.html#adjusting-existing-variables-for-mutation所示。 当使用此声明并尝试在嵌套函数中使用外部变量时,会弹出此错误:指令不支配所有使用!
有没有办法解决这个问题?

【问题讨论】:

  • c++ 除了 lambda 函数定义外,不支持嵌套函数定义。目前还不清楚你在追求什么。
  • 这不是受支持的 C++ 编程实践。如果要访问父函数中的变量,请传递对它的引用。
  • 我正在尝试将示例中的代码(带有函数 a 和 b)编译为 llvm 代码(不确定这是否是所谓的),以使用 llc 编译。但是因为 llvm 是一种类似 c 的语言并且不支持嵌套函数,所以我需要另一种方法来使变量 x 在函数 b 中可见和可访问。全局变量是一种方法,但我认为使用它们并不可行。
  • @JohnFikioris 所以这就是实际的编译器所做的:他们将这样的嵌套函数转换为具有构造函数和方法的类(作为实际的函数体)。构造函数获取外部变量的引用(或值,依赖)并将其存储在对象中。然后将代码转化为“创建对象”和“调用方法”指令。这就是你需要实现的。
  • @freakish 你有什么建议吗?

标签: c++ llvm


【解决方案1】:

LLVM 确实支持结构,对吗?这就是典型的编译器所做的。

您需要创建一个匿名结构,其中包含从您引用的每个 外部变量生成的字段。然后创建一个对应于b() 的匿名函数,该函数将该结构作为参数并对其进行操作。基本上你把b() 变成了一个普通的顶级函数。最后,您转换a() 代码,以便它创建结构实例并调用匿名函数。在这一点上,进一步的优化是可能的。做好准备:这并不容易,可能是一个非常高级的代码转换主题。

例如

func a()
   int x = 1;
   func b() {
      return x+1;
   }
   return b() + 2;
}

变成

struct tmp {
    int tmpx;  // reference or value?
}
func tmp_b(tmp& instance) {
    instance.tmpx += 1;
    return instance.tmpx;
}
func a() {
    int x = 1;
    tmp instance(tmpx = x);  // should it go by reference or value?
    return tmp_b(instance) + 2;
}

作为替代方案,您可以将b() 转换为b(int x) 顶级函数。但这种方法不太灵活 IMO。或者根据上下文使用这两种方法,为什么不呢。

请注意,如果您的语言支持具有方法和/或运算符(在本例中为调用运算符)重载的适当类,则所有这些都可以简化。

【讨论】:

    【解决方案2】:

    这不是 C++ 中支持的功能。

    如果您希望以这种方式从嵌套函数或任何其他函数中访问变量,请传递对它的引用。 :)

    【讨论】:

    • 我试图编译的代码不是 C++。我正在使用 LLVM API 创建已编译的可执行文件。我要编译的语言支持嵌套函数。
    • 啊...您已将此标记为 C++ 问题。我误读了你的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 2017-05-07
    • 2018-05-27
    • 2011-09-06
    相关资源
    最近更新 更多