Самый простой способ работы с промежуточным форматом - PullRequest
1 голос
/ 02 февраля 2012

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

Проведя небольшое исследование gcc, я обнаружил, что формат GIMPLE легко понять, но я не уверен в сложности изменения кода GIMPLE и не знаю ни одного способа перезапускакомпиляция оттуда, за исключением использования плагинов и добавления вашего собственного прохода.Кроме того, люди предупреждали меня, что документации недостаточно, и работа становится сложной, когда вы застряли при работе с gcc.

Другой вариант - использовать байт-код LLVM.Но я никогда не работал с LLVM, поэтому не знаю, насколько сложной была бы моя задача с LLVM.Возможно, есть даже лучшие варианты, о которых я не знаю.Поэтому я просто хочу узнать лучший вариант.Мои предпочтения следующие:

  • Независимость от платформы
  • Простота в использовании
  • Хорошо задокументировано
  • Чем больше людей пользуется, тем больше справки доступно

Ответы [ 3 ]

1 голос
/ 06 февраля 2012

Согласно вашему описанию, LLVM идеально подходит для всех. Одна из его основных целей - служить гибкой библиотекой и средой для манипулирования ИК-кодом. Бесчисленные «проходы» оптимизации, преобразования и анализа служат как доказательством, так и отличным примером. IMO LLVM также очень хорошо отвечает на 4 пункта, которые вы перечислили в своем вопросе:

  • Независимость от платформы: LLVM работает на основных платформах (Linux, Mac и Windows) и знает, как генерировать код для многих типов процессоров.
  • Простота в использовании: бэкенды для IR и компилятора - сложная область для взлома, но в таких случаях LLVM - хороший кандидат, поскольку это относительно новый, хорошо документированный, с очень чистой базой кода.
  • Хорошо задокументировано: вышибись
  • Больше людей используют его: очень активное развитие и использование, причем некоторые корпорации уже вложили в него значительные средства (прежде всего Apple и Google).
1 голос
/ 02 февраля 2012

Как вы, наверное, уже знаете, MELT - это высокоуровневый язык, специфичный для предметной области, для расширения GCC. Вы можете легко работать с Gimple (и т. Д.) С ним (а также изменять внутренние представления в Gcc)

Однако расширение GCC означает некоторую работу, потому что представления Gimple (и также Tree) (с другими, например, Edges ..) являются сложными ...

0 голосов
/ 02 февраля 2012

Это может быть бесполезно, но я задумался о проходах обработки gcc. Сокращенный (в основном по сравнению с вызовами exec / fork) вывод из strace -f -o gcc.strace gcc -c tstamp.c:

7141  execve("/usr/bin/gcc", ["gcc", "-c", "tstamp.c"], [/* 52 vars */]) = 0
7141  open("/tmp/ccqzaCI4.s", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 3
7141  close(3)                          = 0
7141  vfork( <unfinished ...>
7142  execve("/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1", ["/usr/libexec/gcc/i686-redhat-lin"..., "-quiet", "tstamp.c", "-quiet", "-dumpbase", "tstamp.c", "-mtune=generic", "-march=i686", "-auxbase", "tstamp", "-o", "/tmp/ccqzaCI4.s"], [/* 55 vars */] <unfinished ...>
7141  <... vfork resumed> )             = 7142
7141  waitpid(7142,  <unfinished ...>
7142  <... execve resumed> )            = 0
7142  open("tstamp.c", O_RDONLY|O_NOCTTY|O_LARGEFILE) = 3
7142  close(3)                          = 0
7142  open("/tmp/ccqzaCI4.s", O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
7142  open("/usr/include/stdio.h", O_RDONLY|O_NOCTTY|O_LARGEFILE) = 4
... (opens and closes every include file)
7142  close(4)                          = 0
7142  close(3)                          = 0
7142  exit_group(0)                     = ?
7141  <... waitpid resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 7142
7141  vfork( <unfinished ...>
7143  execve("/usr/bin/as", ["as", "--32", "-o", "tstamp.o", "/tmp/ccqzaCI4.s"], [/* 55 vars */] <unfinished ...>
7141  <... vfork resumed> )             = 7143
7141  waitpid(7143,  <unfinished ...>
7143  <... execve resumed> )            = 0
7143  unlink("tstamp.o")                = 0
7143  open("tstamp.o", O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
7143  open("/tmp/ccqzaCI4.s", O_RDONLY|O_LARGEFILE) = 4
7143  close(4)                          = 0
7143  close(3)                          = 0
7143  exit_group(0)                     = ?
7141  <... waitpid resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 7143
7141  unlink("/tmp/ccqzaCI4.s")         = 0
7141  exit_group(0)                     = ?

cc1 имеет всю применимую логику. Я представляю, что это сложная программа, особенно после ввода:

/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1 --help

и

/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1 --help=C
...