Целью данной работы является получение кода, сгенерированного бэк-эндом компилятора LLVM MSP430
Введение
CLANG — это просто фронт-энд компилятора С для LLVM. LLVM — это фреймворк для разработки фронт-эндов, бэк-эндов компиляторов для разных целевых платформ. Этот фреймворк облегчает анализ путем приведения всех фронт-эндов к промежуточному представлению (IR). Все бэк-энды оперируют с этим общим представлением.
Одна из целевых платформ, которая меня интересует, это MSP430 — популярный встраиваемый микроконтроллер, используемый во многих микропотребляющих приложениях.
Текущая поддержка MSP430 весьма ограничена. Я надеюсь, что смогу помочь кому-нибудь, упорно фейс-палмя, чтобы сохранить их лицо.
Поехали
Текущая поддержка данной платформы предельно ограничена. Надеюсь, я смогу восполнить этот пробел. Ниже приведена упрощенная диаграмма того, как должна происходить сборка:
[Source Code (.cpp)] -> [clang] --.ll --> [llc] --.s --> [msp430-gcc] --> elf
Clang берет ваш исходный код и компилирует его, основываясь на предоставленных параметрах. По умолчанию он скрывает много чего под своей оболочкой. Все это не что иное, как попытка сделать процесс более приятным для разработчика. Другими словами, обычно вы никогда не заглянете в промежуточное представление IR, ассемблер или линковку.
Что упущено в документации по целевой платформе MSP430, так это факт, что clang + llvm на самом деле не будет генерировать для вас бинарник elf. Кодогенератор просто производит ассемблерный код для вашей платформы. Это ваша личная обязанность произвести линковку и генерацию файла elf.
Технически, вам не нужен весь msp430-gcc. Вам всего лишь нужны libc, скрипты линкера и binutils. С другой стороны, msp430-gcc делает полезное дело, позволяя вам не вспоминать все ссылки и зависимости, необходимые для генерации финального elf (vector tables, crt0,...etc). Так что воспользуемся им.
Рабочее окружение и первоначальное исследование
Машина, которая используется для работы — это macbook pro под управлением OSX 10.9.2. Дополнительно используется LLVM и msp430-gcc.
До msp430-gcc я использовал патченную версию gcc, выложенную на sourceforge.net. В поисках более свежей версии я обнаружил, что она больше не поддерживается, потому что Texas Instruments и RHEL берут это на себя.
Здорово, подумал я, TI собирается работать с RHEL, чтобы взять на себя разработку, больше не нужны будут проприетарные компиляторы под windows.
FACEPALM 1
TI не рекомендует к использованию собственное решение, используйте на свой страх и риск (see TI's compiler download). Oке-ей… Так на что я надеюсь?
FACEPALM 2
Хорошо, я могу согласиться, что они не доверяют собственному продукту, что и я чувствую большую часть времени. Пытаясь собрать это, я быстро обнаружил, что TI не поддерживает сборку на OS X. Это следствие использования xgcc и того факта, что некоторые флаги не поддерживаются OS X.
Следует заметить, что работа идет, нужно лишь убрать лишние параметры и добавить некоторые хаки. Я ленив, и допиливание существующей системы сборки наводило тоску. Что ж, давайте посмотрим другие варианты, раз уж сказали, чтобы не доверять данному решению.
Что я сделал
Технически мне не нужен фронт-энд, мне всего лишь нужен линкер/ассемблер. Я предполагал, что есть brew/fink/ports путь. Я хотел использовать окружение gcc4.7 и использовать brew, но ничего не нашел.
Так что я создал свой собственный форк (основанный на sampsyo/homebrew-mspgcc). Он включает gcc, libc, gdb, mcu, binutils и mspdebug:
brew tap wbennett/homebrew-mspgcc
brew install wbennett/mspgcc/msp430-binutils
brew install wbennett/mspgcc/msp430-gcc
brew install wbennett/mspgcc/msp430-libc
brew install wbennett/mspgcc/msp430-mcu
brew install wbennett/mspgcc/msp430-gdb
brew install mspdebug
Вах… Теперь у нас есть gcc.
Мое лицо горит
Все становится жертвой цифрового распада, но особенное страдание доставляет open source софт. В частности, многочисленные хинты, представленные в тредах помощи и степень релевантности вашим запросам, по отношению к периоду полураспада информации, в них предоставленной.
Если вы ищете в интернетах информацию, как собрать в clang для платформы msp430, напрямую вы ничего не найдете. Вы найдете немного обнадеживающие наборы параметров, непотребные объемы документации и возможно, предложения использовать некоторые опции, о которых вы не думали:
$>clang -ccc-host-triple msp430-elf
clang-3.5: error: unsupported option '-ccc-host-triple'
clang-3.5: error: no such file or directory: 'msp430-elf'
clang-3.5: error: no input files
Отлично, это не работает.
Я могу только предположить, что это из-за старой версии LLVM. Может быть, я должен был использовать llc после того, как clang превратил его в LLVM байткод?.. Хорошо, посмотрим, какие варианты ещё остались.
Попробуем тестовое приложение:
#include "msp430.h"
#include "stdlib.h"
int main(void)
{
//disable watchdog
WDCTL = WDTPW + WDTHOLD;
//do something silly
auto i = 1;
auto result = i+1;
//avoid warnings
if(result == 2)
return 2;
//loop forever
while(true){}
//never reach this
return 0;
}
#compile application to llvm assembler
~/local/bin/clang++ -I/usr/local/Cellar/msp430-libc/20120716/msp430/include/
-D__MSP430F5438__ -g -S -emit-llvm -std=c++11 -Wall -c src/simpleadd.cpp -o src/simpleadd.ll
Отлично! Выглядит, как нормальный LL
; ModuleID = 'src/simpleadd.cpp'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9.0"
@"