代码之家  ›  专栏  ›  技术社区  ›  Indiana Kernick Michael Durrant

按值传递结构,同时符合LLVM IR中的C调用约定

  •  0
  • Indiana Kernick Michael Durrant  · 技术社区  · 7 年前

    我想通过C++和JIT LLVM程序之间的值传递结构。我看过很多关于这个的讨论,甚至还有一些问题。我已经读过,如果我想让我的程序真正传递值,我需要做一个叫做“参数强制”的事情。使用 byval sret 看起来像是简单的跨平台解决方案。它仍然有点痛苦,C++代码必须记住传递指针而不是值(虽然调用代码是C++的,所以我可以做一些模板魔术)。

    有没有一张通行证可以强制我辩论?访问每个函数声明和每个函数调用并转换所有结构以使它们与平台的C ABI兼容的pass?我觉得这是所有前端都会用到的东西,如果它存在,克朗不使用它,所以也许这是不可能的。为什么这不是一个可行的解决方案?如果通行证可以处理这个问题,那么我希望它是LLVM的一部分。

    我不明白为什么每个前端都要做论点强制。我甚至不知道如何进行论点强制。我见过一些例子,人们使用Clang代码生成代码,并分解出执行参数强制的部分。不幸的是,如果我想要真正的C ABI兼容性,这似乎是最好的解决方案。甚至可以将另一个前端的一部分重新用于完全不同的语言,这一事实让我继续怀疑为什么必须在前端这样做?

    必须为此做点什么!我们不能只在每个前端编写相同的C ABI兼容代码。太可笑了!也许我就是不明白。

    有人能帮我把这个弄清楚吗?我在考虑用 拜瓦尔 和 sret公司 只是因为它比修改clang代码生成器更容易。有更简单的方法吗?

    1 回复  |  直到 7 年前
        1
  •  0
  •   Indiana Kernick Michael Durrant    7 年前

    当在LLVM IR中按值传递结构时,必须制定自己的规则。我选择了最简单的一套规则。

    假设我有一个这样的程序:

    struct MyStruct {
      int a;
      char b, c, d, e;
    };
    
    MyStruct identityImpl(MyStruct s) {
      return s;
    }
    
    MyStruct identity(MyStruct s) {
      return identityImpl(s);
    }
    

    此程序的LLVM IR等效于:

    void identityImpl(MyStruct *ret, const MyStruct *s) {
      MyStruct localS = *s;
      *ret = localS;
    }
    
    void identity(MyStruct *ret, const MyStruct *s) {
      MyStruct localS = *s;
      MyStruct localRet;
      identityImpl(&localRet, &localS);
      *ret = localRet;
    }
    

    这不是传递结构的最有效方法,因为 MyStruct 可以放入64位寄存器。但是,优化器可以删除 localS 使用 s 当地人 从未写信给。这两个函数都优化为一次调用 memcpy .

    只花了半天时间。走叮当声路线可能至少要一个星期。我仍然认为我不得不这样做是很不幸的,但我现在明白了这个问题。结构的传递不是由平台的C ABI指定的。

    推荐文章