32bit_me (32bit_me) wrote,
32bit_me
32bit_me

Categories:

Ещё раз про онлайновый компилятор

Немножко поигрался с онлайновым компилятором, про который я уже писал, и обнаружил немало интересного.
Во-первых, поддерживаются не только те процессоры, которые перечислены в списке, а вообще любые, которые поддерживает компилятор.
Во-вторых, можно выводить промежуточный код компилятора.
Всё это возможно благодаря тому, что мы можем сами задавать аргументы командной строки компилятора. Итак, выбираем из списка компилятор "x86-64 clang 3.9.0", и вводим в левое окно какую-нибудь функцию, например:

int foo(int x) {
    return !!x;
}



Очевидно, что функция возвращает 0, если x == 0, и 1, если x != 0.
С оптимизацией -O1 получаем:
foo(int): # @foo(int)
xor eax, eax
test edi, edi
setne al
ret


Теперь попробуем получить код для arm. Вводим параметры: -O1 -target arm
Получаем:

foo(int): @ @foo(int)
cmp r0, #0
movne r0, #1
bx lr


Можно для aarch64:

foo(int): // @foo(int)
cmp w0, #0 // =0
cset w0, ne
ret


Можно для msp430:

foo(int):
push.w r4
mov.w r1, r4
cmp.w #0, r15
mov.w r2, r12
rra.w r12
mov.w #1, r15
bic.w r12, r15
pop.w r4
ret


И так далее. Можно получить промежуточный код на ассемблере llvm. Для этого вводим: -O1 -emit-llvm

Получаем длинный текст с кучей служебной информации, но на самом деле самая суть в этом:
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: nounwind readnone uwtable
define i32 @foo(int)(i32) local_unnamed_addr #0 !dbg !6 {
tail call void @llvm.dbg.value(metadata i32 %0, i64 0, metadata !11, metadata !12), !dbg !13
%2 = icmp ne i32 %0, 0, !dbg !14
%3 = zext i1 %2 to i32, !dbg !15
ret i32 %3, !dbg !16
}


Здесь: target datalayout - информация о таргете, т.е. о процессоре, разрядность представления величин и их выравнивание, а также о big/little endian. Подробно сейчас я это расписывать не буду, но там на самом деле всё просто.
И сам ассемблер (без дебажной информации):

%2 = icmp ne i32 %0, 0,
%3 = zext i1 %2 to i32,
ret i32 %3,


Здесь стоит пояснить, что ассемблер llvm не работает с физическими регистрами, он использует именованные виртуальные регистры, которых может быть неограниченно много. Здесь это %0, %2, %3. Они имеют типы, обозначенные как i1, i32 и т.п., что (очевидно) означает целое число соответствующей разрядности. Также следует добавить, что в llvm нет знаковых или беззнаковых типов, просто каждая команда интерпретирует по-своему (в большинстве случаев, как знаковые).
В первой строке команда %2 = icmp ne i32 %0 означает: если регистр %0 не равен 0, то записать в %2 единицу, иначе записать 0.
Во второй строке %3 = zext i1 %2 to i32 написано буквально следующее: дополнить нулями %2 до 32 разрядов и записать в %3.
В третьей строке: ret i32 %3 функция возвращает значение, записанное в %3.

Вот такая интересная игрушка. Также можно заметить, что хотя промежуточный код llvm максимально абстрагируется от конкретного процессора, он всё же не является совсем аппаратно-независимым, т.к. нуждается в указании разрядности регистров. Для примера, скомпилируем то же самое для msp430 (16-разрядное ядро): -O1 -target msp430 -emit-llvm:

target datalayout = "e-m:e-p:16:16-i32:16:32-a:16-n8:16"
target triple = "msp430"

; Function Attrs: nounwind readnone
define i16 @foo(int)(i16) local_unnamed_addr #0 !dbg !6 {
tail call void @llvm.dbg.value(metadata i16 %0, i64 0, metadata !11, metadata !12), !dbg !13
%2 = icmp ne i16 %0, 0, !dbg !14
%3 = zext i1 %2 to i16, !dbg !15
ret i16 %3, !dbg !16
}


Суть та же, но регистры стали 16-разрядными. Для более сложных программ это может привести к существенным изменениям в коде.

В общем, интересная игрушка.
Tags: llvm, микроконтроллеры, программирование
Subscribe

  • RIP

  • Поздравляю

    Поздравляю всех, кто понимает, о чём я.

  • Дивный новый мир

    Если вы считаете, что для работы в софтверной компании нужны знания каких-то там алгоритмов, или, не приведи господь, языков, вы глубоко…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 9 comments