从C类创建LLVM字节码

前端之家收集整理的这篇文章主要介绍了从C类创建LLVM字节码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在为LLVM中的特殊用途语言编写编译器.我想为已经用C编写的库添加绑定.我的想法是将库编译为LLVM字节码(使用clang -emit-llvm -S abc.c)并在编译期间将其链接.这适用于类似的代码
// lib.c
int f() {
    return 123;
}

但是库的一部分写得像

// A.cc
class A {
    public:
        int f() { return 123; }
};

这导致空字节码文件.我知道我可以通过分离实现来解决这个问题:

// A.cc
class A {
    public:
        int f();
};

int A::f() {
    return 123;
}

但这将是一项繁琐的工作.有没有办法从我的库源创建有用的字节码呢?或者在我的编译器中使库可用的任何其他方法

解决方法

您可以看到clang是否尊重显式模板实例化的外部链接.这可能适用于非模板,但您可以“强迫它”用于模板.

简单简介:

lib1.h

template <typename T=int>
struct ATemplate { T f() { return 123; } };

添加文件lib1_instantiate.cpp

#include "lib1.h"
template struct ATemplate<int>;
template struct ATemplate<unsigned int>;
template struct ATemplate<long>; // etc.

这应该使用外部链接实例化命名模板.

如果您遇到非模板类,并且上面的技巧不适用于此,您可以像这样包装它:

instantiate.cpp:

namespace hidden_details
{
    template <class libtype> struct instantiator : public libtype 
    // derives... just do something that requires a complete type (not a forward!)
    { };
}

template struct hidden_details::instantiator<A>;

如果运气不好,你必须“使用”内联成员才能获得外部链接.一个常见的技巧是使用这些成员的地址(您不需要实现委托的东西):

instantiate.cpp:

static void force_use_A()
{
    void* unused = (void*) &A::f;
}

然而

>转换为(void *)调用未定义的行为(你无法在gcc上使用-pedantic -Werror编译它)
>对于重载,你必须指定丑陋的强制转换以消除它们的歧义

HTH

猜你在找的C&C++相关文章