如何将函数下的多个相同类型的循环映射到LLVM IR中生成的基本块?

问题描述 投票:1回答:1

如果循环属于不同类型,那么我可以使用名称轻松识别它们,但如果有多个相同的类型循环(比如5个while循环),我如何识别LLVM IR中的哪个基本块对应于源中的哪个循环码?

当我们按顺序访问代码和LLVM IR时,手动很容易识别,但我正在寻找如何以编程方式识别相同的内容。

例如,我在C中有以下源代码:

int main()
{
   int count=1;
   while (count <= 4)
   {
        count++;
   }
   while (count > 4)
   {
        count--;
   }
   return 0;
}

当我执行命令qazxsw poi时,我得到了fileName.ll创建以下内容:

clang -S -emit-llvm fileName.c

现在为给定的源文件创建了两个基本块,如; ModuleID = 'abc.c' source_filename = "abc.c" target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc19.0.23026" ; Function Attrs: noinline nounwind uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 %count = alloca i32, align 4 store i32 0, i32* %retval, align 4 store i32 1, i32* %count, align 4 br label %while.cond while.cond: ; preds = %while.body, %entry %0 = load i32, i32* %count, align 4 %cmp = icmp sle i32 %0, 4 br i1 %cmp, label %while.body, label %while.end while.body: ; preds = %while.cond %1 = load i32, i32* %count, align 4 %inc = add nsw i32 %1, 1 store i32 %inc, i32* %count, align 4 br label %while.cond while.end: ; preds = %while.cond br label %while.cond1 while.cond1: ; preds = %while.body3, %while.end %2 = load i32, i32* %count, align 4 %cmp2 = icmp sgt i32 %2, 4 br i1 %cmp2, label %while.body3, label %while.end4 while.body3: ; preds = %while.cond1 %3 = load i32, i32* %count, align 4 %dec = add nsw i32 %3, -1 store i32 %dec, i32* %count, align 4 br label %while.cond1 while.end4: ; preds = %while.cond1 ret i32 0 } attributes #0 = { noinline nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0} !llvm.ident = !{!1} !0 = !{i32 1, !"PIC Level", i32 2} !1 = !{!"clang version 4.0.0 (tags/RELEASE_400/final)"} while.cond,如何识别哪个基本块是源代码中的while循环?

c llvm llvm-ir llvm-c++-api
1个回答
2
投票

在我尝试回答之前,我只想注意,根据所选的优化级别或while.cond1手动选择的传递,信息可能不存在或者可能不那么准确(例如因为内联,克隆等)。

现在,在低级表示和源代码之间关联的方式是使用调试信息(例如,使用opt格式)。要生成调试信息,您需要在编译期间使用DWARF命令行标志。

对于LLVM IR,如果你看看-g API有相关的调用,如Loop。所以你可以做这样的事情(例如在getStartLoc传递的runOn方法内):

llvm::Function

此外,对于llvm::SmallVector<llvm::Loop *> workList; auto &LI = getAnalysis<llvm::LoopInfoWrapperPass>(CurFunc).getLoopInfo(); std::for_each(LI.begin(), LI.end(), [&workList](llvm::Loop *e) { workList.push_back(e); }); for(auto *e : workList) { auto line = e->getStartLoc().getLine(); auto *scope = llvm::dyn_cast<llvm::DIScope>(e->getStartLoc().getScope()); auto filename = scope->getFilename(); // do stuff here } ,您还可以使用BasicBlock中的调试相关方法(例如Instruction)并将其与对其他getDebugLoc方法(如Loop等)的调用相结合。

另外,请注意,有一个getHeader方法为每个循环使用内部唯一ID,但这并不总是存在,并且它受到我在开始时提到的潜在缺陷的影响。无论如何,如果你需要操作它,请按照getLoopID方法(例如在setLoopID中)查看LLVM源代码中的示例。

© www.soinside.com 2019 - 2024. All rights reserved.