Crystal-lang: почему LLVM "hello.bc" не совпадает, если генерируется Crystal или clang? - PullRequest
0 голосов
/ 18 октября 2018

это мой первый вопрос о Stackoverflow: -)

Мой опыт:

  • 2 года опыта работы с Python
  • 2 месяца опыта работы с Crystal Lang (веб-сайты работают сЯнтарный каркас)
  • 1 месяц на C, C ++, сборка

Факты: - crystal-lang компилируется и работает без проблем - работает на x86_64

Пожалуйстабудьте добры, так как у меня пока недостаточно глубокие знания языка.

Насколько я понимаю, когда мы компилируем и запускаем базовый файл hello.c с использованием LLVM, он выглядит следующим образом:

hello.c:

#include
int main() {
  printf("hello world\n");
  return 0;
}

shell:

$ clang -O3 -emit-llvm hello.c -c -o hello.bc
$ llc hello.bc -o hello.s
$ gcc hello.s -o hello.native
$ ./hello.native

это происходит из примеров LLVM)

Я хочу сказать, что мы можем сделать довольно короткий приветФайл .bc (128 строк), который можно запустить медленнее, используя:

$ lli hello.bc

, но когда я попытался сгенерировать аналогичный файл hello.bc из файла hello.cr и запустить его, как я делал сфайл hello.c:

hello.cr:

puts "hello world"

shell:

$ crystal build hello.cr --emit llvm-bc --release
$ llc hello.bc -o hello.s

что я заметил:

  • Этот файл hello.bc намного больше, чем файл, сгенерированный из файла c (43'624 строки)
  • Этот hello.bc нельзя запустить с помощью"lli", поскольку он генерирует:

    "ОШИБКА LLVM: Программа использовала внешнюю функцию 'pcre_malloc', которая не может быть разрешена!

  • Я не могу даже скомпилировать из hello.s в hello.native

  • Та же проблема, если я пытаюсь использовать generate и hello.llfile

Как я понял, LLVM является переносимым, и что все языки интерфейса будут создавать промежуточный * .bc, который затем может быть скомпилирован для любой архитектуры.

Мои вопросы:

  • Почему hello.bc не похожи в обоих случаях?
  • Что-то не так в процедуре кристалла?

Спасибо!

1 Ответ

0 голосов
/ 18 октября 2018

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

Пример C практически не содержит ничего, кроме системного вызова printf.Вот почему скомпилированный ASM также очень крошечный.

Простой вызов Crystal puts гораздо больше стоит за этим.Он основан на библиотеках для обработки асинхронного ввода-вывода, параллелизма, обработки сигналов, сбора мусора и многого другого.Некоторые из этих библиотек полностью реализованы в стандартной библиотеке Crystal, некоторые используют другие библиотеки, которые либо непосредственно встроены в двоичный файл (libgc), либо для которых по-прежнему требуются динамические библиотеки из системы (libpcre, libpthread).

По умолчанию любая программа Crystal поставляется с этой библиотекой времени выполнения.Даже пустая программа.Обычно это остается совершенно незамеченным, поскольку в любом случае этим программам в конечном итоге понадобятся более крупные программы, а размер скомпилированного двоичного файла библиотеки времени выполнения составляет менее 500 КБ (в режиме выпуска).Такая маленькая программа, как ваша, на самом деле не нуждается в этом всего лишь для печати строки.Но эти библиотеки необходимы для среды выполнения Crystal.

ПРИМЕЧАНИЕ. Вы можете скомпилировать программу Crystal без этих библиотек по умолчанию.Но это означает, что вы не можете использовать что-нибудь из stdlib Crystal, и вам необходимо написать код C с синтаксисом Crystal (или реализовать свой собственный stdlib):

require "lib_c"
require "c/stdio"

LibC.printf pointerof("hello world".@c)

скомпилирован с опцией --prelude=empty, и он сгенерирует существенно меньший ASM, примерно такой же, как в примере с Си.

...