步骤1 创建测试C代码
首先编写一个测试用的C代码example.c,内容如下:
#include<stdio.h>
void test() {
printf("hello\n");
}
int main(int argc, char ** argv) {
int a = 2;
int b = 1;
int c = 0;
test();
c = a + b;
printf("c is %d\n", c);
}
步骤2 使用clang编译代码
clang -S -O0 -emit-llvm example.c
编译成功后会生成example.ll文件,可以直接用文本编辑器打开查看。
步骤3 使用opt调用pass
网上的材料大多是linux下或是mac下的,Windows下略微不同,调用的命令如下:
opt -mypass example.ll
输出信息:
test
main
说明我们的pass被调用啦~
附:
步骤2的example.ll文件内容:
; ModuleID = 'C:\Users\sing\Desktop\example.c'
source_filename = "C:\5CUsers\sing\5CDesktop\5Cexample.c"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.12.25831"
$"\01??_C@_06BGKFAKIK@hello?6?$AA@" = comdat any
$"\01??_C@_08PFOKLJEB@c?5is?5?$CFd?6?$AA@" = comdat any
@"\01??_C@_06BGKFAKIK@hello?6?$AA@" = linkonce_odr unnamed_addr constant [7 x i8] c"hello\0A\00", comdat, align 1
@"\01??_C@_08PFOKLJEB@c?5is?5?$CFd?6?$AA@" = linkonce_odr unnamed_addr constant [9 x i8] c"c is %d\0A\00", comdat, align 1
; Function Attrs: noinline nounwind optnone uwtable
define void @test() #0 {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01??_C@_06BGKFAKIK@hello?6?$AA@", i32 0, i32 0))
ret void
}
declare i32 @printf(i8*, ...) #1
; Function Attrs: noinline nounwind optnone uwtable
define i32 @main(i32 %argc, i8** %argv) #0 {
entry:
%argv.addr = alloca i8**, align 8
%argc.addr = alloca i32, align 4
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
store i8** %argv, i8*** %argv.addr, align 8
store i32 %argc, i32* %argc.addr, align 4
store i32 2, i32* %a, align 4
store i32 1, i32* %b, align 4
store i32 0, i32* %c, align 4
call void @test()
%0 = load i32, i32* %a, align 4
%1 = load i32, i32* %b, align 4
%add = add nsw i32 %0, %1
store i32 %add, i32* %c, align 4
%2 = load i32, i32* %c, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08PFOKLJEB@c?5is?5?$CFd?6?$AA@", i32 0, i32 0), i32 %2)
ret i32 0
}
attributes #0 = { noinline nounwind optnone 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" }
attributes #1 = { "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-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, !1}
!llvm.ident = !{!2}
!0 = !{i32 1, !"wchar_size", i32 2}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{!"clang version 6.0.0 (tags/RELEASE_600/final)"}
是因为使用了-O0优化开关,如果不使用这个开关,使用:
clang -S -emit-llvm example.c
生成的example.ll文件比较大:
; ModuleID = 'example.c'
source_filename = "example.c"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.12.25831"
%struct.__crt_locale_pointers = type { %struct.__crt_locale_data*, %struct.__crt_multibyte_data* }
%struct.__crt_locale_data = type opaque
%struct.__crt_multibyte_data = type opaque
%struct._iobuf = type { i8* }
$sprintf = comdat any
$vsprintf = comdat any
$_snprintf = comdat any
$_vsnprintf = comdat any
$printf = comdat any
$_vsprintf_l = comdat any
$_vsnprintf_l = comdat any
$__local_stdio_printf_options = comdat any
$_vfprintf_l = comdat any
$"\01??_C@_07NNOMJDJG@hello2?6?$AA@" = comdat any
$"\01??_C@_08PFOKLJEB@c?5is?5?$CFd?6?$AA@" = comdat any
@"\01??_C@_07NNOMJDJG@hello2?6?$AA@" = linkonce_odr unnamed_addr constant [8 x i8] c"hello2\0A\00", comdat, align 1
@"\01??_C@_08PFOKLJEB@c?5is?5?$CFd?6?$AA@" = linkonce_odr unnamed_addr constant [9 x i8] c"c is %d\0A\00", comdat, align 1
@__local_stdio_printf_options._OptionsStorage = internal global i64 0, align 8
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @sprintf(i8*, i8*, ...) #0 comdat {
%3 = alloca i8*, align 8
%4 = alloca i8*, align 8
%5 = alloca i32, align 4
%6 = alloca i8*, align 8
store i8* %1, i8** %3, align 8
store i8* %0, i8** %4, align 8
%7 = bitcast i8** %6 to i8*
call void @llvm.va_start(i8* %7)
%8 = load i8*, i8** %6, align 8
%9 = load i8*, i8** %3, align 8
%10 = load i8*, i8** %4, align 8
%11 = call i32 @_vsprintf_l(i8* %10, i8* %9, %struct.__crt_locale_pointers* null, i8* %8)
store i32 %11, i32* %5, align 4
%12 = bitcast i8** %6 to i8*
call void @llvm.va_end(i8* %12)
%13 = load i32, i32* %5, align 4
ret i32 %13
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @vsprintf(i8*, i8*, i8*) #0 comdat {
%4 = alloca i8*, align 8
%5 = alloca i8*, align 8
%6 = alloca i8*, align 8
store i8* %2, i8** %4, align 8
store i8* %1, i8** %5, align 8
store i8* %0, i8** %6, align 8
%7 = load i8*, i8** %4, align 8
%8 = load i8*, i8** %5, align 8
%9 = load i8*, i8** %6, align 8
%10 = call i32 @_vsnprintf_l(i8* %9, i64 -1, i8* %8, %struct.__crt_locale_pointers* null, i8* %7)
ret i32 %10
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @_snprintf(i8*, i64, i8*, ...) #0 comdat {
%4 = alloca i8*, align 8
%5 = alloca i64, align 8
%6 = alloca i8*, align 8
%7 = alloca i32, align 4
%8 = alloca i8*, align 8
store i8* %2, i8** %4, align 8
store i64 %1, i64* %5, align 8
store i8* %0, i8** %6, align 8
%9 = bitcast i8** %8 to i8*
call void @llvm.va_start(i8* %9)
%10 = load i8*, i8** %8, align 8
%11 = load i8*, i8** %4, align 8
%12 = load i64, i64* %5, align 8
%13 = load i8*, i8** %6, align 8
%14 = call i32 @_vsnprintf(i8* %13, i64 %12, i8* %11, i8* %10)
store i32 %14, i32* %7, align 4
%15 = bitcast i8** %8 to i8*
call void @llvm.va_end(i8* %15)
%16 = load i32, i32* %7, align 4
ret i32 %16
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @_vsnprintf(i8*, i64, i8*, i8*) #0 comdat {
%5 = alloca i8*, align 8
%6 = alloca i8*, align 8
%7 = alloca i64, align 8
%8 = alloca i8*, align 8
store i8* %3, i8** %5, align 8
store i8* %2, i8** %6, align 8
store i64 %1, i64* %7, align 8
store i8* %0, i8** %8, align 8
%9 = load i8*, i8** %5, align 8
%10 = load i8*, i8** %6, align 8
%11 = load i64, i64* %7, align 8
%12 = load i8*, i8** %8, align 8
%13 = call i32 @_vsnprintf_l(i8* %12, i64 %11, i8* %10, %struct.__crt_locale_pointers* null, i8* %9)
ret i32 %13
}
; Function Attrs: noinline nounwind optnone uwtable
define void @test() #0 {
%1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @"\01??_C@_07NNOMJDJG@hello2?6?$AA@", i32 0, i32 0))
ret void
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @printf(i8*, ...) #0 comdat {
%2 = alloca i8*, align 8
%3 = alloca i32, align 4
%4 = alloca i8*, align 8
store i8* %0, i8** %2, align 8
%5 = bitcast i8** %4 to i8*
call void @llvm.va_start(i8* %5)
%6 = load i8*, i8** %4, align 8
%7 = load i8*, i8** %2, align 8
%8 = call %struct._iobuf* @__acrt_iob_func(i32 1)
%9 = call i32 @_vfprintf_l(%struct._iobuf* %8, i8* %7, %struct.__crt_locale_pointers* null, i8* %6)
store i32 %9, i32* %3, align 4
%10 = bitcast i8** %4 to i8*
call void @llvm.va_end(i8* %10)
%11 = load i32, i32* %3, align 4
ret i32 %11
}
; Function Attrs: noinline nounwind optnone uwtable
define i32 @main(i32, i8**) #0 {
%3 = alloca i8**, align 8
%4 = alloca i32, align 4
%5 = alloca i32, align 4
%6 = alloca i32, align 4
%7 = alloca i32, align 4
store i8** %1, i8*** %3, align 8
store i32 %0, i32* %4, align 4
store i32 2, i32* %5, align 4
store i32 1, i32* %6, align 4
store i32 0, i32* %7, align 4
call void @test()
%8 = load i32, i32* %5, align 4
%9 = load i32, i32* %6, align 4
%10 = add nsw i32 %8, %9
store i32 %10, i32* %7, align 4
%11 = load i32, i32* %7, align 4
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08PFOKLJEB@c?5is?5?$CFd?6?$AA@", i32 0, i32 0), i32 %11)
ret i32 0
}
; Function Attrs: nounwind
declare void @llvm.va_start(i8*) #1
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @_vsprintf_l(i8*, i8*, %struct.__crt_locale_pointers*, i8*) #0 comdat {
%5 = alloca i8*, align 8
%6 = alloca %struct.__crt_locale_pointers*, align 8
%7 = alloca i8*, align 8
%8 = alloca i8*, align 8
store i8* %3, i8** %5, align 8
store %struct.__crt_locale_pointers* %2, %struct.__crt_locale_pointers** %6, align 8
store i8* %1, i8** %7, align 8
store i8* %0, i8** %8, align 8
%9 = load i8*, i8** %5, align 8
%10 = load %struct.__crt_locale_pointers*, %struct.__crt_locale_pointers** %6, align 8
%11 = load i8*, i8** %7, align 8
%12 = load i8*, i8** %8, align 8
%13 = call i32 @_vsnprintf_l(i8* %12, i64 -1, i8* %11, %struct.__crt_locale_pointers* %10, i8* %9)
ret i32 %13
}
; Function Attrs: nounwind
declare void @llvm.va_end(i8*) #1
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @_vsnprintf_l(i8*, i64, i8*, %struct.__crt_locale_pointers*, i8*) #0 comdat {
%6 = alloca i8*, align 8
%7 = alloca %struct.__crt_locale_pointers*, align 8
%8 = alloca i8*, align 8
%9 = alloca i64, align 8
%10 = alloca i8*, align 8
%11 = alloca i32, align 4
store i8* %4, i8** %6, align 8
store %struct.__crt_locale_pointers* %3, %struct.__crt_locale_pointers** %7, align 8
store i8* %2, i8** %8, align 8
store i64 %1, i64* %9, align 8
store i8* %0, i8** %10, align 8
%12 = load i8*, i8** %6, align 8
%13 = load %struct.__crt_locale_pointers*, %struct.__crt_locale_pointers** %7, align 8
%14 = load i8*, i8** %8, align 8
%15 = load i64, i64* %9, align 8
%16 = load i8*, i8** %10, align 8
%17 = call i64* @__local_stdio_printf_options()
%18 = load i64, i64* %17, align 8
%19 = or i64 %18, 1
%20 = call i32 @__stdio_common_vsprintf(i64 %19, i8* %16, i64 %15, i8* %14, %struct.__crt_locale_pointers* %13, i8* %12)
store i32 %20, i32* %11, align 4
%21 = load i32, i32* %11, align 4
%22 = icmp slt i32 %21, 0
br i1 %22, label %23, label %24
; <label>:23: ; preds = %5
br label %26
; <label>:24: ; preds = %5
%25 = load i32, i32* %11, align 4
br label %26
; <label>:26: ; preds = %24, %23
%27 = phi i32 [ -1, %23 ], [ %25, %24 ]
ret i32 %27
}
declare i32 @__stdio_common_vsprintf(i64, i8*, i64, i8*, %struct.__crt_locale_pointers*, i8*) #2
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i64* @__local_stdio_printf_options() #0 comdat {
ret i64* @__local_stdio_printf_options._OptionsStorage
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @_vfprintf_l(%struct._iobuf*, i8*, %struct.__crt_locale_pointers*, i8*) #0 comdat {
%5 = alloca i8*, align 8
%6 = alloca %struct.__crt_locale_pointers*, align 8
%7 = alloca i8*, align 8
%8 = alloca %struct._iobuf*, align 8
store i8* %3, i8** %5, align 8
store %struct.__crt_locale_pointers* %2, %struct.__crt_locale_pointers** %6, align 8
store i8* %1, i8** %7, align 8
store %struct._iobuf* %0, %struct._iobuf** %8, align 8
%9 = load i8*, i8** %5, align 8
%10 = load %struct.__crt_locale_pointers*, %struct.__crt_locale_pointers** %6, align 8
%11 = load i8*, i8** %7, align 8
%12 = load %struct._iobuf*, %struct._iobuf** %8, align 8
%13 = call i64* @__local_stdio_printf_options()
%14 = load i64, i64* %13, align 8
%15 = call i32 @__stdio_common_vfprintf(i64 %14, %struct._iobuf* %12, i8* %11, %struct.__crt_locale_pointers* %10, i8* %9)
ret i32 %15
}
declare %struct._iobuf* @__acrt_iob_func(i32) #2
declare i32 @__stdio_common_vfprintf(i64, %struct._iobuf*, i8*, %struct.__crt_locale_pointers*, i8*) #2
attributes #0 = { noinline nounwind optnone 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" }
attributes #1 = { nounwind }
attributes #2 = { "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-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, !1}
!llvm.ident = !{!2}
!0 = !{i32 1, !"wchar_size", i32 2}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{!"clang version 6.0.0 (tags/RELEASE_600/final)"}
使用opt -mypass example.ll输出:
sprintf
vsprintf
_snprintf
_vsnprintf
test
printf
main
_vsprintf_l
_vsnprintf_l
__local_stdio_printf_options
_vfprintf_l
使用clang时开启该pass:
clang.exe -mllvm -mypass example.c -o example.exe
文档信息
- 本文作者:zhupite
- 本文链接:https://zhupite.com/llvm/windows-llvm-use-custom-pass.html
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)