Учебник LLVM по калейдоскопу не работает на локальном компьютере - PullRequest
0 голосов
/ 05 января 2019

Я работаю над учебным пособием по калейдоскопу LLVM . Все работает нормально, кроме локальных внешних (в отличие от таких вещей, как математические функции).

[c34n10 kaleidoscope] ./toy
ready> extern sin(x); sin(1);
ready> Read extern:
declare double @sin(double)

ready> ready> Evaluated to 0.841471
ready> extern putchard(x); putchard(120);
ready> Read extern:
declare double @putchard(double)

ready> ready> Failure value returned from cantFail wrapped call
UNREACHABLE executed at /gpfs/loomis/project/fas/manohar/emb99/llvm/include/llvm/Support/Error.h:732!
Aborted (core dumped)

putchard объявлено в моем коде, согласно учебнику, как

/// putchard - putchar that takes a double and returns 0.
extern "C" DLLEXPORT double putchard(double X) {
  fputc((char)X, stderr);
  return 0;
}

Другие посты онлайн предполагают, что эта проблема может быть вызвана не компиляцией с -rdynamic, но я.

Фактическая ошибка происходит со следующим кодом

auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
assert(ExprSymbol && "Function not found");

// cast to double-returning function
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());

и некоторые исследования с GDB показывают, что флаг hasError для ExprSymbol.getAddress() является истинным, поэтому cantFail терпит неудачу. Что касается того, почему этот флаг установлен, я в растерянности.

Кажется, это не проблема самой функции: из GDB я могу успешно запустить call putchard(120), поэтому символ определенно существует в исполняемом файле.

Наконец, мой make-файл выглядит как

LIBS=core orcjit native analysis executionengine instcombine object runtimedyld scalaropts support
FLAGS=`llvm-config --cxxflags --ldflags --system-libs --libs $(LIBS)`

%: %.cpp
        clang++ -v -g3 -O0 $^ -o $@ $(FLAGS) -rdynamic

1 Ответ

0 голосов
/ 03 июля 2019

Я столкнулся с точно такой же проблемой в LLVM 8.

Проблема в том, что распознаватель символов не пытается найти запрошенный символ в адресе локального процесса, а Expected<T> требует обязательной проверки на наличие ошибок.

Я немного изменил KaleidoscopeJIT.h, чтобы справиться с этим.

Замените конструктор KaleidoscopeJIT следующим:

KaleidoscopeJIT()
      : Resolver(createLegacyLookupResolver(
            ES,
            [this](const std::string &Name) {
              auto symbol = ObjectLayer.findSymbol(Name, true);
              if (!symbol)
              {
                if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
                  return JITSymbol(SymAddr, JITSymbolFlags::Exported);
              }
              return symbol;
            },
            [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })),
        TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
        ObjectLayer(ES,
                    [this](VModuleKey) {
                      return ObjLayerT::Resources{
                          std::make_shared<SectionMemoryManager>(), Resolver};
                    }),
        CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
    llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
  }

Единственное изменение: если после вызова ObjectLayer.findSymbol() символ не найден, он найдет RTDyldMemoryManager::getSymbolAddressInProcess() для поиска и создания объекта JITSymbol.

...