Skip to content

Instantly share code, notes, and snippets.

@joelonsql
Created November 2, 2017 16:39
Show Gist options
  • Select an option

  • Save joelonsql/e5080a344c37b076f03abefc1778b91c to your computer and use it in GitHub Desktop.

Select an option

Save joelonsql/e5080a344c37b076f03abefc1778b91c to your computer and use it in GitHub Desktop.
Man or boy test C -> LLVM IR
/*
; ModuleID = 'man_or_boy.c'
source_filename = "man_or_boy.c"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
*/
typedef struct arg // %struct.arg = type
{ // {
int (*fn)(struct arg*); // {}*,
int *k; // i32*,
struct arg *x1, *x2, *x3, *x4, *x5; // %struct.arg*, %struct.arg*, %struct.arg*, %struct.arg*, %struct.arg*
} ARG; // }
int f_1 (ARG* _) { // define i32 @f_1(%struct.arg*) #0 {
// %2 = alloca %struct.arg*, align 8
// store %struct.arg* %0, %struct.arg** %2, align 8
return -1; // ret i32 -1
} // }
int f0 (ARG* _) { // define i32 @f0(%struct.arg*) #0 {
// %2 = alloca %struct.arg*, align 8
// store %struct.arg* %0, %struct.arg** %2, align 8
return 0; // ret i32 0
} // }
int f1 (ARG* _) { // define i32 @f1(%struct.arg*) #0 {
// %2 = alloca %struct.arg*, align 8
// store %struct.arg* %0, %struct.arg** %2, align 8
return 1; // ret i32 1
} // }
int eval(ARG* a) { // define i32 @eval(%struct.arg*) #0 {
// %2 = alloca %struct.arg*, align 8
// store %struct.arg* %0, %struct.arg** %2, align 8
// %3 = load %struct.arg*, %struct.arg** %2, align 8
// %4 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 0
// %5 = bitcast {}** %4 to i32 (%struct.arg*)**
// %6 = load i32 (%struct.arg*)*, i32 (%struct.arg*)** %5, align 8
// %7 = load %struct.arg*, %struct.arg** %2, align 8
// %8 = call i32 %6(%struct.arg* %7)
return a->fn(a); // ret i32 %8
} // }
int A(ARG*);
int B(ARG* a) { // define i32 @B(%struct.arg*) #0 {
// %2 = alloca %struct.arg*, align 8
// %3 = alloca i32, align 4
// %4 = alloca %struct.arg, align 8
int k = *a->k -= 1; // store %struct.arg* %0, %struct.arg** %2, align 8
// %5 = load %struct.arg*, %struct.arg** %2, align 8
// %6 = getelementptr inbounds %struct.arg, %struct.arg* %5, i32 0, i32 1
// %7 = load i32*, i32** %6, align 8
// %8 = load i32, i32* %7, align 4
// %9 = sub nsw i32 %8, 1
// store i32 %9, i32* %7, align 4
// store i32 %9, i32* %3, align 4
return A( //
(&(ARG){ //
B, // %10 = getelementptr inbounds %struct.arg, %struct.arg* %4, i32 0, i32 0
// %11 = bitcast {}** %10 to i32 (%struct.arg*)**
// store i32 (%struct.arg*)* @B, i32 (%struct.arg*)** %11, align 8
//
&k, // %12 = getelementptr inbounds %struct.arg, %struct.arg* %4, i32 0, i32 1
// store i32* %3, i32** %12, align 8
//
a, // %13 = getelementptr inbounds %struct.arg, %struct.arg* %4, i32 0, i32 2
// %14 = load %struct.arg*, %struct.arg** %2, align 8
// store %struct.arg* %14, %struct.arg** %13, align 8
//
a->x1, // %15 = getelementptr inbounds %struct.arg, %struct.arg* %4, i32 0, i32 3
// %16 = load %struct.arg*, %struct.arg** %2, align 8
// %17 = getelementptr inbounds %struct.arg, %struct.arg* %16, i32 0, i32 2
// %18 = load %struct.arg*, %struct.arg** %17, align 8
// store %struct.arg* %18, %struct.arg** %15, align 8
//
a->x2, // %19 = getelementptr inbounds %struct.arg, %struct.arg* %4, i32 0, i32 4
// %20 = load %struct.arg*, %struct.arg** %2, align 8
// %21 = getelementptr inbounds %struct.arg, %struct.arg* %20, i32 0, i32 3
// %22 = load %struct.arg*, %struct.arg** %21, align 8
// store %struct.arg* %22, %struct.arg** %19, align 8
//
a->x3, // %23 = getelementptr inbounds %struct.arg, %struct.arg* %4, i32 0, i32 5
// %24 = load %struct.arg*, %struct.arg** %2, align 8
// %25 = getelementptr inbounds %struct.arg, %struct.arg* %24, i32 0, i32 4
// %26 = load %struct.arg*, %struct.arg** %25, align 8
// store %struct.arg* %26, %struct.arg** %23, align 8
//
a->x4 // %27 = getelementptr inbounds %struct.arg, %struct.arg* %4, i32 0, i32 6
// %28 = load %struct.arg*, %struct.arg** %2, align 8
// %29 = getelementptr inbounds %struct.arg, %struct.arg* %28, i32 0, i32 5
// %30 = load %struct.arg*, %struct.arg** %29, align 8
// store %struct.arg* %30, %struct.arg** %27, align 8
//
}) // %31 = call i32 @A(%struct.arg* %4)
//
); // ret i32 %31
} // }
int A(ARG* a) { // define i32 @A(%struct.arg*) #0 {
// %2 = alloca %struct.arg*, align 8
//
// store %struct.arg* %0, %struct.arg** %2, align 8
// %3 = load %struct.arg*, %struct.arg** %2, align 8
// %4 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 1
// %5 = load i32*, i32** %4, align 8
return // %6 = load i32, i32* %5, align 4
*a->k <= 0 // %7 = icmp sle i32 %6, 0
//
? // br i1 %7, label %8, label %18
//
// ; <label>:8:
eval(a->x4) + eval(a->x5) // %9 = load %struct.arg*, %struct.arg** %2, align 8
// %10 = getelementptr inbounds %struct.arg, %struct.arg* %9, i32 0, i32 5
// %11 = load %struct.arg*, %struct.arg** %10, align 8
// %12 = call i32 @eval(%struct.arg* %11)
// %13 = load %struct.arg*, %struct.arg** %2, align 8
// %14 = getelementptr inbounds %struct.arg, %struct.arg* %13, i32 0, i32 6
// %15 = load %struct.arg*, %struct.arg** %14, align 8
// %16 = call i32 @eval(%struct.arg* %15)
// %17 = add nsw i32 %12, %16
// br label %21
: //
B(a) // ; <label>:18:
// %19 = load %struct.arg*, %struct.arg** %2, align 8
// %20 = call i32 @B(%struct.arg* %19)
// br label %21
//
; // ; <label>:21:
// %22 = phi i32 [ %17, %8 ], [ %20, %18 ]
// ret i32 %22
//
} // }
int main() { // define i32 @main() #0 {
// %1 = alloca i32, align 4
// %2 = alloca i32, align 4
// %3 = alloca %struct.arg, align 8
// %4 = alloca %struct.arg, align 8
// %5 = alloca %struct.arg, align 8
// %6 = alloca %struct.arg, align 8
// %7 = alloca %struct.arg, align 8
// %8 = alloca %struct.arg, align 8
//
// store i32 0, i32* %1, align 4
//
int k = 10; // store i32 10, i32* %2, align 4
//
return A( //
(&(ARG){ //
B, // %9 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 0
// %10 = bitcast {}** %9 to i32 (%struct.arg*)**
// store i32 (%struct.arg*)* @B, i32 (%struct.arg*)** %10, align 8
//
&k, // %11 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 1
// store i32* %2, i32** %11, align 8
//
(&(ARG){f1}), // %12 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 2
// %13 = bitcast %struct.arg* %4 to i8*
// call void @llvm.memset.p0i8.i64(i8* %13, i8 0, i64 56, i32 8, i1 false)
// %14 = getelementptr inbounds %struct.arg, %struct.arg* %4, i32 0, i32 0
// %15 = bitcast {}** %14 to i32 (%struct.arg*)**
// store i32 (%struct.arg*)* @f1, i32 (%struct.arg*)** %15, align 8
// store %struct.arg* %4, %struct.arg** %12, align 8
//
(&(ARG){f_1}), // %16 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 3
// %17 = bitcast %struct.arg* %5 to i8*
// call void @llvm.memset.p0i8.i64(i8* %17, i8 0, i64 56, i32 8, i1 false)
// %18 = getelementptr inbounds %struct.arg, %struct.arg* %5, i32 0, i32 0
// %19 = bitcast {}** %18 to i32 (%struct.arg*)**
// store i32 (%struct.arg*)* @f_1, i32 (%struct.arg*)** %19, align 8
// store %struct.arg* %5, %struct.arg** %16, align 8
//
(&(ARG){f_1}), // %20 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 4
// %21 = bitcast %struct.arg* %6 to i8*
// call void @llvm.memset.p0i8.i64(i8* %21, i8 0, i64 56, i32 8, i1 false)
// %22 = getelementptr inbounds %struct.arg, %struct.arg* %6, i32 0, i32 0
// %23 = bitcast {}** %22 to i32 (%struct.arg*)**
// store i32 (%struct.arg*)* @f_1, i32 (%struct.arg*)** %23, align 8
// store %struct.arg* %6, %struct.arg** %20, align 8
//
//
(&(ARG){f1}), // %24 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 5
// %25 = bitcast %struct.arg* %7 to i8*
// call void @llvm.memset.p0i8.i64(i8* %25, i8 0, i64 56, i32 8, i1 false)
// %26 = getelementptr inbounds %struct.arg, %struct.arg* %7, i32 0, i32 0
// %27 = bitcast {}** %26 to i32 (%struct.arg*)**
// store i32 (%struct.arg*)* @f1, i32 (%struct.arg*)** %27, align 8
// store %struct.arg* %7, %struct.arg** %24, align 8
//
(&(ARG){f0}) // %28 = getelementptr inbounds %struct.arg, %struct.arg* %3, i32 0, i32 6
// %29 = bitcast %struct.arg* %8 to i8*
// call void @llvm.memset.p0i8.i64(i8* %29, i8 0, i64 56, i32 8, i1 false)
// %30 = getelementptr inbounds %struct.arg, %struct.arg* %8, i32 0, i32 0
// %31 = bitcast {}** %30 to i32 (%struct.arg*)**
// store i32 (%struct.arg*)* @f0, i32 (%struct.arg*)** %31, align 8
// store %struct.arg* %8, %struct.arg** %28, align 8
//
}) // %32 = call i32 @A(%struct.arg* %3)
//
); // ret i32 %32
//
} // }
/*
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #1
attributes #0 = { noinline nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 9.0.0 (clang-900.0.38)"}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment