Создайте байт-код LLVM из классов C ++ - PullRequest
7 голосов
/ 23 июня 2011

Я пишу компилятор для языка специального назначения в 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;
}

Но это было бы много утомительной работы.Есть ли способ создать полезный байт-код из моих библиотечных источников, как они есть?Или любой другой способ сделать библиотеку доступной в моем компиляторе?

Ответы [ 2 ]

6 голосов
/ 23 июня 2011

Вы могли видеть, соблюдает ли Clang внешнюю связь для явных экземпляров шаблона.Это может относиться к не шаблонам, но в противном случае вы могли бы «заставить его работать» для шаблонов.

Простой краткий обзор:

lib1.h

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

добавитьfile 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;
}

Однако

  1. преобразование в (void *) вызывает неопределенное поведение (вы не можете скомпилировать это с -pedantic -Werror на gcc)
  2. для перегрузок, вам нужно будет указать некрасивые броски для устранения неоднозначностиих

HTH

0 голосов
/ 23 июня 2011

Альтернатива, которая работает, если нужно использовать только несколько библиотечных функций: создайте оболочку для всего, что вы используете.

// wrapper.cc
A* A_create() {
    return new A();
}

// and so on

Таким образом, вам не нужно изменять свою библиотеку, ноопределенно какая-то дополнительная печать.

...