Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
АСНИ.doc
Скачиваний:
47
Добавлен:
26.11.2019
Размер:
6.35 Mб
Скачать

Производные типы

Указатели

тип*

i32* — указатель на 32-битное целое

Массивы

[число элементов x тип]

  • [10 x i32]

  • [8 x double]

Структуры

{ i32, i32, double }

Вектор — специальный тип для упрощения SIMD-операций. Вектор состоит из 2n значений примитивного типа — целого или с плавающей точкой.

< число элементов x тип >

< 4 x float > — вектор XMM

Функции

  • i32 (i32, i32)

  • float ({ float, float }, { float, float })

Система типов рекурсивна, то есть можно использовать многомерные массивы, массивы структур, указатели на структуры и функции и т. д.

Операции

Большинство инструкций в LLVM принимают два аргумента (операнда) и возвращают одно значение (трёхадресный код). Значения определяются текстовым идентификатором. Локальные значения обозначаются префиксом %, а глобальные — @. Локальные значения также называют регистрами, а LLVM — виртуальной машиной с бесконечным числом регистров. Пример:

%sum = add i32 %n, 5

%diff = sub double %a, %b

%z = add <4 x float> %v1, %v2 ; поэлементное сложение

%cond = icmp eq %x, %y ; Сравнение целых чисел. Результат имеет тип i1.

%success = call i32 @puts(i8* %str)

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

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

LLVM IR строго типизирован, поэтому существуют операции приведения типов, которые явно кодируются специальными инструкциями. Набор из 9 инструкций покрывает всевозможные приведения между различными числовыми типами: целыми и с плавающей точкой, со знаком и без, различной разрядности и пр. Кроме этого есть инструкции преобразования между целыми и указателями, а также инструкция bitcast, которая приведёт всё ко всему, но за результат вы отвечаете сами.

Память

Помимо значений-регистров, в LLVM есть и работа с памятью. Значения в памяти адресуются типизированными указателями. Обратиться к памяти можно с помощью двух инструкций: load и store. Например:

%x = load i32* %x.ptr ; загрузить значение типа i32 по указателю %x.ptr

%tmp = add i32 %x, 5 ; прибавить 5

store i32 %tmp, i32* %x.ptr ; и положить обратно

Инструкция malloc транслируется в вызов одноименной системной функции и выделяет память накуче, возвращая значение — указатель определенного типа. В паре с ней идёт инструкция free.

%struct.ptr = malloc { double, double }

%string = malloc i8, i32 %length

%array = malloc [16 x i32]

free i8* %string

Инструкция alloca выделяет память на стеке.

%x.ptr = alloca double ; %x.ptr имеет тип double*

%array = alloca float, i32 8 ; %array имеет тип float*, а не [8 x float]!

Память, выделенная alloca, автоматически освобождается при выходе из функции при помощи инструкций ret или unwind.