2016-02-13 3 views
0

LLVM использует форму SSA (статическое одиночное присвоение) для своего IR. Это приводит к появлению новых переменных в коде на уровне IR. Однако существует ли какой-либо метод API ... для определения того, является ли переменная изначально принадлежащей программе или вставлена ​​компилятором?LLVM: откуда происходят переменные?

+0

Подумайте о внедрении прохода clang для анализа АСТ и выполните анализ, немного более связанный с исходным кодом –

ответ

3

Не существует понятия вставки новых переменных в LLVM IR. Исходный язык и LLVM IR - это просто два разных языка, и вам лучше видеть компиляцию как шаг перевода.

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

Рассмотрим, например, эту небольшую функцию C:

void test() { 
    int i; 
    i = 2; 
    i = 3; 
} 

Компиляция эту функцию LLVM IR привело бы, по меньшей мере двух переменных (если не прикладывается постоянное складывание), так как из SSA формы. Какой из них будет оригинальным, и какой из них вставлен?

Это также усложняется, когда поток управления и Фи функции участвуют:

int a = 1; 
int b = 2; 
int c = 3; 

int func() { 
    int result; 
    if (a) { 
     result = b; 
    } else { 
     result = c; 
    } 
    return result; 
} 

При переводе этой функции C для LLVM IR и применяя -mem2reg проход, мы получаем следующее:

define i32 @func() #0 { 
    %1 = load i32* @a, align 4 
    %2 = icmp ne i32 %1, 0 
    br i1 %2, label %3, label %5 

; <label>:3          ; preds = %0 
    %4 = load i32* @b, align 4 
    br label %7 

; <label>:5          ; preds = %0 
    %6 = load i32* @c, align 4 
    br label %7 

; <label>:7          ; preds = %5, %3 
    %result.0 = phi i32 [ %4, %3 ], [ %6, %5 ] 
    ret i32 %result.0 
} 

Как вы видите, имя виртуального регистра результата не отображается на этапе назначения. Это видно только в точке слияния. Здесь исходное место назначения переменной было перенесено в конец функции. Опять же, сомнительно, какие переменные вставлены, а какие - нет.

Что вы можете сделать - это скомпилировать исходную программу с помощью отладочных метаданных, а затем обработать информацию об отладке, чтобы узнать объявления переменных и т. Д. В Clang вы можете выводить информацию об отладке с флагом -g.