2014-01-28 3 views
14

Операнды для команды llvm::User (например, инструкция): llvm::Value s.Получение исходного имени переменной для значения LLVM

После mem2reg pass, переменные находятся в SSA form, и их имена, соответствующие исходному исходному коду, теряются. Value::getName() предназначен только для некоторых вещей; для большинства переменных, которые являются посредниками, он не установлен.

instnamer проход может быть запущен, чтобы дать все имена переменных, как tmp1 и tmp2, но это не улавливает, где они изначально пришли. Вот некоторые LLVM IR рядом исходный код C:

enter image description here

Я строй простого HTML-страницу для визуализации и отладки некоторых оптимизаций я работаю, и я хочу, чтобы показать переменный SSA, как имени вер нотация, а не только временные имена инстамеров. Это просто для того, чтобы помочь моей читаемости.

Я получаю мой LLVM IR от лязга с командной строкой, такие как:

clang -g3 -O1 -emit-llvm -o test.bc -c test.c 

Есть звонки на llvm.dbg.declare и llvm.dbg.value в ИК; как вы включаете исходные имена исходного кода и номера версий SSA?

Итак, как я могу определить исходную переменную (или имя постоянной константы) из llvm::Value? Отладчики должны быть в состоянии сделать это, так как я могу?

+1

Какой программой вы пользовались для создания такой приятной сборки кода | сравнение источников? –

+5

@JackL. Я быстро написал это сам. Это просто холст javascript. Когда кто-то зарабатывает 500 очков, давая человеко-читаемые имена ver значениям, я мог бы даже выслать подсказку подсказки;) – Will

+0

@Will Вы в конечном итоге выпустили инструмент сравнения? Подозреваю, это было бы очень полезно многим людям. – ransford

ответ

12

Это часть отладочной информации, которая прилагается к LLVM IR в виде метаданных. Документация is here. Старый пост в блоге с некоторым фоном is also available.


$ cat > z.c 
long fact(long arg, long farg, long bart) 
{ 
    long foo = farg + bart; 
    return foo * arg; 
} 

$ clang -emit-llvm -O3 -g -c z.c 
$ llvm-dis z.bc -o - 

Производит это:

define i64 @fact(i64 %arg, i64 %farg, i64 %bart) #0 { 
entry: 
    tail call void @llvm.dbg.value(metadata !{i64 %arg}, i64 0, metadata !10), !dbg !17 
    tail call void @llvm.dbg.value(metadata !{i64 %farg}, i64 0, metadata !11), !dbg !17 
    tail call void @llvm.dbg.value(metadata !{i64 %bart}, i64 0, metadata !12), !dbg !17 
    %add = add nsw i64 %bart, %farg, !dbg !18 
    tail call void @llvm.dbg.value(metadata !{i64 %add}, i64 0, metadata !13), !dbg !18 
    %mul = mul nsw i64 %add, %arg, !dbg !19 
    ret i64 %mul, !dbg !19 
} 

С -O0 вместо -O3, вы не увидите llvm.dbg.value, но вы увидите llvm.dbg.declare.

+0

Я думаю, что теория и практика расходятся :(У меня никогда не было llvm.dbg .value звонки, испущенные clang. Документация, которую я прочитал, прежде чем я спросил о SO. – Will

+1

@Will: clang не испускает 'llvm.dbg.value'. Оптимизации испускают их, когда они помещают значения в регистры (вместо более легкодоступных слоты стека). –

+0

Хорошо, тогда как вы получаете mem2reg или что-то еще, чтобы испускать их? И будут ли они секретным соусом, который позволяет мне превращать Значения в имена исходных кодов, и если да, то как? – Will

5

Учитывая Value, получать имя переменной из него может быть сделано путем обхода всех llvm.dbg.declare и llvm.dbg.value вызовы в функции ограждающей, проверяя, если какой-либо относится к этому значению, и если да, то вернуть DIVariable, связанный со значением по что внутренний вызов.

Таким образом, код должен выглядеть примерно так (грубо говоря, не испытанные или даже скомпилированный):

const Function* findEnclosingFunc(const Value* V) { 
    if (const Argument* Arg = dyn_cast<Argument>(V)) { 
    return Arg->getParent(); 
    } 
    if (const Instruction* I = dyn_cast<Instruction>(V)) { 
    return I->getParent()->getParent(); 
    } 
    return NULL; 
} 

const MDNode* findVar(const Value* V, const Function* F) { 
    for (const_inst_iterator Iter = inst_begin(F), End = inst_end(F); Iter != End; ++Iter) { 
    const Instruction* I = &*Iter; 
    if (const DbgDeclareInst* DbgDeclare = dyn_cast<DbgDeclareInst>(I)) { 
     if (DbgDeclare->getAddress() == V) return DbgDeclare->getVariable(); 
    } else if (const DbgValueInst* DbgValue = dyn_cast<DbgValueInst>(I)) { 
     if (DbgValue->getValue() == V) return DbgValue->getVariable(); 
    } 
    } 
    return NULL; 
} 

StringRef getOriginalName(const Value* V) { 
    // TODO handle globals as well 

    const Function* F = findEnclosingFunc(V); 
    if (!F) return V->getName(); 

    const MDNode* Var = findVar(V, F); 
    if (!Var) return "tmp"; 

    return DIVariable(Var).getName(); 
} 

Вы можете видеть выше, я был слишком ленив, чтобы добавить обработку глобал, но это не то, что крупные сделки на самом деле - для этого требуется итерация по всем глобальным переменным, указанным в текущей отладочной информации блока компиляции (используйте M.getNamedMetadata("llvm.dbg.cu"), чтобы получить список всех компиляционных модулей в текущем модуле), затем проверяя, что соответствует вашей переменной (методом getGlobal) и возвращает ее имя.

Однако, имейте в виду, что приведенное выше будет работать только для значений, непосредственно связанных с исходными переменными. Любое значение, которое является результатом любого вычисления, не будет надлежащим образом названо таким образом; и, в частности, значения, которые представляют собой обращения к полю, не будут называться с именем поля. Это выполнимо, но требует более сложной обработки - вам нужно будет идентифицировать номер поля из GEP, а затем выкопать информацию об отладке типа для структуры, чтобы вернуть имя поля. Отладчики делают это, да, но никакой отладчик не работает в LLVM IR land - насколько я знаю, даже LLVM LLVM работает по-разному, анализируя DWARF в объектном файле в типах Clang.

+0

Очень красивый и очень похожий на то, как я нахожу собственные имена (хотя я делаю обратную карту таблицы символов Function, чтобы немного ускорить работу). Однако большая проблема в разделе * однако *; почти все переменные в IR являются временными, хотя, как человек, вы можете следить за ними и видеть, откуда они пришли. – Will

Смежные вопросы