2016-11-20 11 views
1

В функции я хочу знать, как параметры передаются в тело функции, чтобы отслеживать поток параметров. Я попробовал простой код и обнаружил, что для каждого параметра есть шаблон alloc - store, интересно, правда ли это или нет?Как Clang генерирует код для параметров функции?

Демонстрационный код

int add(int x, int y){ 
    return x+y; 
} 

LLVM л он генерируемый:

; Function Attrs: nounwind uwtable 
define i32 @add(i32 %x, i32 %y) #0 { 
    %1 = alloca i32, align 4 
    %2 = alloca i32, align 4 
    store i32 %x, i32* %1, align 4 
    store i32 %y, i32* %2, align 4 
    %3 = load i32, i32* %1, align 4 
    %4 = load i32, i32* %2, align 4 
    %5 = add nsw i32 %3, %4 
    ret i32 %5 
} 

В примере мы можем видеть, что,

  1. Для каждого параметра, лязг используйте команду alloc для определения локальной переменной

  2. В соответствии с инструкцией alloc, инструкции store используются для присвоить значения?

Мои вопросы:

  1. ли генерируются все функции LLVM IR в этом alloc и store узорами? Или что именно LLVM делает с параметрами?
  2. Порядок parameters определяется используемым условным обозначением?
+0

незначительный комментарий: вы, кажется, спрашиваете, как clang генерирует LLVM IR, а не как LLVM генерирует код. –

+0

@ IsmailBadawi Спасибо за ваш комментарий, я отредактировал этот вопрос. – Qoros

ответ

1

Я думаю, что этот шаблон имеет место для кода, который не имеет оптимизаций во время компиляции; Однако, если вы вместо того, чтобы скомпилировать код с -O3 (или что-нибудь, что применяется оптимизация mem2reg), эта картина оптимизированными:

(лязг -emit-LLVM -S -O0 add.c)

define i32 @add(i32 %x, i32 %y) #0 { 
    %1 = alloca i32, align 4 
    %2 = alloca i32, align 4 
    store i32 %x, i32* %1, align 4 
    store i32 %y, i32* %2, align 4 
    %3 = load i32, i32* %1, align 4 
    %4 = load i32, i32* %2, align 4 
    %5 = add nsw i32 %3, %4 
    ret i32 %5 
} 

(неавтоматического -mem2reg add.ll -o add_m.ll)

define i32 @add(i32 %x, i32 %y) #0 { 
    %1 = add nsw i32 %y, %x 
    ret i32 %1 
} 

Так что, если вы контролируете весь код, который вы анализируете, то вы можете рассчитывать на этой модели. Вместо этого я рекомендую вам использовать LLVM API для получения аргументов функции. Следующий код выполняет итерацию с помощью аргументов функции F и печатает их после внесения значений.

for (auto AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) 
{ 
    Value* v = &*AI; 
    errs() << *v << "\n"; 
} 

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

+0

Спасибо, Брайан. Я попробовал, как вы указали, но печатает как 'i32% x'. Мне интересно, как проверить, равны ли два значения, например, в двоичном файле, каждый указатель сохраняет адрес, на который указывает. – Qoros

+0

Это другой вопрос. Получив значение * для каждого аргумента функции, вы затем сможете использовать его для дальнейшего анализа. Это может быть статичным, поскольку оно было первоначально помечено, и в этом случае вам может понадобиться построить граф потока управления и использование переменных через каждую функцию.Динамически вы можете проверить равенство, добавив дополнительный IR, который проверяет значения на входе, либо путем построения сравнения на месте, либо передачи значений для разделения подпрограмм поддержки. Мой пример должен был показать простой способ первоначального доступа к значениям и сделать что-то с ними. – Brian

+0

Спасибо за хорошее руководство. – Qoros