LLVM-如何使嵌套函数查看外部函数的变量

时间:2019-04-17 21:43:35

标签: c++ llvm

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

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中所示。 当使用此声明并尝试在嵌套函数中使用外部变量时,会弹出此错误:指令不能支配所有用途!
有办法解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

C ++不支持该功能。

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

答案 1 :(得分:0)

LLVM支持结构,对吗?这就是典型的编译器的作用。

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

例如

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)顶级函数。但是这种方法不太灵活。还是根据上下文使用两种方法,为什么不呢?

请注意,如果您的语言通过方法和/或运算符(在这种情况下称为运算符)重载来支持适当的类,那么所有这些操作都可以简化。