int main(void) {
  char hola[20] = {'h', 'o', 'l', 'a', '\0'};
  printf("Count length of \"hola\" string in a char[20]:\n  %i\n\n",
         strLength(hola));
  printf("Count length of \"Ahura Mazda\" string in a char[12]:\n  %i\n\n",
         strLength("Ahura Mazda"));
  printf("Display previous string using %%s:\n  %s\n\n", hola);
  char a[20] = "hola ";
  char b[] = "mundo";
  char c[80];
  strConcat(a, b, c);
  printf("Concatenating \"hola \" and \"mundo\"\n  \"%s\"\n\n", c);
  char d[80] = "mundo";
  printf("Check if \"mundo\" [6] and \"mundo\" [80] are equal:\n  %s\n\n",
         strEqual(b, d) ? "true" : "false");
  printf("Check if \"hola\" [5] and \"holama\" [7] are equal:\n  %s\n\n",
         strEqual("hola", "holama") ? "true" : "false");
  printf("Check if \"Jesus\" [6] and \"Muhammad\" [9] are equal:\n  %s\n\n",
         strEqual("Jesus", "Muhammad") ? "true" : "false");
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0xf0,%rsp
movl   $0x0,-0x4(%rbp)
mov    0xe97(%rip),%rax
mov    %rax,-0x20(%rbp)
mov    0xe94(%rip),%rax
mov    %rax,-0x18(%rbp)
mov    0xe92(%rip),%eax
mov    %eax,-0x10(%rbp)
lea    -0x20(%rbp),%rdi
mov    $0x0,%al
call   1070 <strLength@plt>
mov    %eax,%esi
lea    0xe9f(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    0xf00(%rip),%rdi
mov    $0x0,%al
call   1070 <strLength@plt>
mov    %eax,%esi
lea    0xeb5(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x20(%rbp),%rsi
lea    0xeea(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    0xe4d(%rip),%rax
mov    %rax,-0x40(%rbp)
mov    0xe4a(%rip),%rax
mov    %rax,-0x38(%rbp)
mov    0xe48(%rip),%eax
mov    %eax,-0x30(%rbp)
mov    0xee8(%rip),%eax
mov    %eax,-0x46(%rbp)
mov    0xee2(%rip),%ax
mov    %ax,-0x42(%rbp)
lea    -0x40(%rbp),%rdi
lea    -0x46(%rbp),%rsi
lea    -0xa0(%rbp),%rdx
mov    $0x0,%al
call   1050 <strConcat@plt>
lea    -0xa0(%rbp),%rsi
lea    0xebc(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0xf0(%rbp),%rdi
xor    %esi,%esi
mov    $0x50,%edx
call   1040 <memset@plt>
movb   $0x6d,-0xf0(%rbp)
movb   $0x75,-0xef(%rbp)
movb   $0x6e,-0xee(%rbp)
movb   $0x64,-0xed(%rbp)
movb   $0x6f,-0xec(%rbp)
lea    -0x46(%rbp),%rdi
lea    -0xf0(%rbp),%rsi
mov    $0x0,%al
call   1060 <strEqual@plt>
mov    %eax,%ecx
lea    0xecc(%rip),%rsi
lea    0xec0(%rip),%rax
cmp    $0x0,%ecx
cmovne %rax,%rsi
lea    0xe7a(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    0xee6(%rip),%rdi
lea    0xee4(%rip),%rsi
mov    $0x0,%al
call   1060 <strEqual@plt>
mov    %eax,%ecx
lea    0xe92(%rip),%rsi
lea    0xe86(%rip),%rax
cmp    $0x0,%ecx
cmovne %rax,%rsi
lea    0xe83(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    0xef2(%rip),%rdi
lea    0xef1(%rip),%rsi
mov    $0x0,%al
call   1060 <strEqual@plt>
mov    %eax,%ecx
lea    0xe58(%rip),%rsi
lea    0xe4c(%rip),%rax
cmp    $0x0,%ecx
cmovne %rax,%rsi
lea    0xe8c(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
xor    %eax,%eax
add    $0xf0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %r14
push   %rbx
sub    $0xf8,%rsp
mov    0xec0(%rip),%eax
mov    %eax,0x40(%rsp)
movaps 0xea5(%rip),%xmm0
movaps %xmm0,0x30(%rsp)
lea    0x30(%rsp),%rbx
mov    %rbx,%rdi
xor    %eax,%eax
call   1060 <strLength@plt>
lea    0xebe(%rip),%rdi
mov    %eax,%esi
xor    %eax,%eax
call   1030 <printf@plt>
lea    0xf1d(%rip),%rdi
xor    %eax,%eax
call   1060 <strLength@plt>
lea    0xed4(%rip),%rdi
mov    %eax,%esi
xor    %eax,%eax
call   1030 <printf@plt>
lea    0xf0b(%rip),%rdi
mov    %rbx,%rsi
xor    %eax,%eax
call   1030 <printf@plt>
movaps 0xe6b(%rip),%xmm0
movaps %xmm0,0x10(%rsp)
movl   $0x0,0x20(%rsp)
movw   $0x6f,0xc(%rsp)
movl   $0x646e756d,0x8(%rsp)
64
lea    0x10(%rsp),%rdi
lea    0x8(%rsp),%r14
lea    0xa0(%rsp),%rbx
mov    %r14,%rsi
mov    %rbx,%rdx
xor    %eax,%eax
call   1040 <strConcat@plt>
lea    0xee8(%rip),%rdi
mov    %rbx,%rsi
xor    %eax,%eax
call   1030 <printf@plt>
xorps  %xmm0,%xmm0
movaps %xmm0,0x50(%rsp)
movaps %xmm0,0x90(%rsp)
movaps %xmm0,0x80(%rsp)
movaps %xmm0,0x70(%rsp)
movaps %xmm0,0x60(%rsp)
movl   $0x646e756d,0x50(%rsp)
64
movb   $0x6f,0x54(%rsp)
lea    0x50(%rsp),%rsi
mov    %r14,%rdi
xor    %eax,%eax
call   1050 <strEqual@plt>
test   %eax,%eax
lea    0xeff(%rip),%r14
lea    0xef3(%rip),%rbx
mov    %rbx,%rsi
cmove  %r14,%rsi
lea    0xead(%rip),%rdi
xor    %eax,%eax
call   1030 <printf@plt>
lea    0xf19(%rip),%rdi
lea    0xf17(%rip),%rsi
xor    %eax,%eax
call   1050 <strEqual@plt>
test   %eax,%eax
mov    %rbx,%rsi
cmove  %r14,%rsi
lea    0xec4(%rip),%rdi
xor    %eax,%eax
call   1030 <printf@plt>
lea    0xf33(%rip),%rdi
lea    0xf32(%rip),%rsi
xor    %eax,%eax
call   1050 <strEqual@plt>
test   %eax,%eax
cmove  %r14,%rbx
lea    0xede(%rip),%rdi
mov    %rbx,%rsi
xor    %eax,%eax
call   1030 <printf@plt>
xor    %eax,%eax
add    $0xf8,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
@__const.main.hola = <{ i8, i8, i8, i8, [16 x i8] }> <{ i8 104, i8 111, i8 108, i8 97, [16 x i8] zeroinitializer }>
@.str = [52 x i8] c"Count length of \22hola\22 string in a char[20]:\0A %i\0A\0A\00"
@.str.1 = [59 x i8] c"Count length of \22Ahura Mazda\22 string in a char[12]:\0A %i\0A\0A\00"
@.str.2 = [12 x i8] c"Ahura Mazda\00"
@.str.3 = [42 x i8] c"Display previous string using %%s:\0A %s\0A\0A\00"
@__const.main.a = [20 x i8] c"hola \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
@__const.main.b = [6 x i8] c"mundo\00"
@.str.4 = [43 x i8] c"Concatenating \22hola \22 and \22mundo\22\0A \22%s\22\0A\0A\00"
@.str.5 = [56 x i8] c"Check if \22mundo\22 [6] and \22mundo\22 [80] are equal:\0A %s\0A\0A\00"
@.str.6 = [5 x i8] c"true\00"
@.str.7 = [6 x i8] c"false\00"
@.str.8 = [55 x i8] c"Check if \22hola\22 [5] and \22holama\22 [7] are equal:\0A %s\0A\0A\00"
@.str.9 = [5 x i8] c"hola\00"
@.str.10 = [7 x i8] c"holama\00"
@.str.11 = [58 x i8] c"Check if \22Jesus\22 [6] and \22Muhammad\22 [9] are equal:\0A %s\0A\0A\00"
@.str.12 = [6 x i8] c"Jesus\00"
@.str.13 = [9 x i8] c"Muhammad\00"
define i32 @main() {
%1 = alloca i32
%2 = alloca [20 x i8]
%3 = alloca [20 x i8]
%4 = alloca [6 x i8]
%5 = alloca [80 x i8]
%6 = alloca [80 x i8]
store i32 0, i32* %1
%7 = bitcast [20 x i8]* %2 to i8*
%8 = getelementptr inbounds [20 x i8], [20 x i8]* %2, i64 0, i64 0
%9 = call i32 (i8*, ...) bitcast (i32 (...)* @strLength to i32 (i8*, ...)*)(i8* %8)
%10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([52 x i8], [52 x i8]* @.str, i64 0, i64 0), i32 %9)
%11 = call i32 (i8*, ...) bitcast (i32 (...)* @strLength to i32 (i8*, ...)*)(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.2, i64 0, i64 0))
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([59 x i8], [59 x i8]* @.str.1, i64 0, i64 0), i32 %11)
%13 = getelementptr inbounds [20 x i8], [20 x i8]* %2, i64 0, i64 0
%14 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([42 x i8], [42 x i8]* @.str.3, i64 0, i64 0), i8* %13)
%15 = bitcast [20 x i8]* %3 to i8*
%16 = bitcast [6 x i8]* %4 to i8*
%17 = getelementptr inbounds [20 x i8], [20 x i8]* %3, i64 0, i64 0
%18 = getelementptr inbounds [6 x i8], [6 x i8]* %4, i64 0, i64 0
%19 = getelementptr inbounds [80 x i8], [80 x i8]* %5, i64 0, i64 0
%20 = call i32 (i8*, i8*, i8*, ...) bitcast (i32 (...)* @strConcat to i32 (i8*, i8*, i8*, ...)*)(i8* %17, i8* %18, i8* %19)
%21 = getelementptr inbounds [80 x i8], [80 x i8]* %5, i64 0, i64 0
%22 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.4, i64 0, i64 0), i8* %21)
%23 = bitcast [80 x i8]* %6 to i8*
%24 = bitcast i8* %23 to [80 x i8]*
%25 = getelementptr inbounds [80 x i8], [80 x i8]* %24, i32 0, i32 0
store i8 109, i8* %25
%26 = getelementptr inbounds [80 x i8], [80 x i8]* %24, i32 0, i32 1
store i8 117, i8* %26
%27 = getelementptr inbounds [80 x i8], [80 x i8]* %24, i32 0, i32 2
store i8 110, i8* %27
%28 = getelementptr inbounds [80 x i8], [80 x i8]* %24, i32 0, i32 3
store i8 100, i8* %28
%29 = getelementptr inbounds [80 x i8], [80 x i8]* %24, i32 0, i32 4
store i8 111, i8* %29
%30 = getelementptr inbounds [6 x i8], [6 x i8]* %4, i64 0, i64 0
%31 = getelementptr inbounds [80 x i8], [80 x i8]* %6, i64 0, i64 0
%32 = call i32 (i8*, i8*, ...) bitcast (i32 (...)* @strEqual to i32 (i8*, i8*, ...)*)(i8* %30, i8* %31)
%33 = icmp ne i32 %32, 0
%34 = zext i1 %33 to i64
%35 = select i1 %33, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i64 0, i64 0)
%36 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([56 x i8], [56 x i8]* @.str.5, i64 0, i64 0), i8* %35)
%37 = call i32 (i8*, i8*, ...) bitcast (i32 (...)* @strEqual to i32 (i8*, i8*, ...)*)(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.9, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.10, i64 0, i64 0))
%38 = icmp ne i32 %37, 0
%39 = zext i1 %38 to i64
%40 = select i1 %38, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i64 0, i64 0)
%41 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([55 x i8], [55 x i8]* @.str.8, i64 0, i64 0), i8* %40)
%42 = call i32 (i8*, i8*, ...) bitcast (i32 (...)* @strEqual to i32 (i8*, i8*, ...)*)(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.12, i64 0, i64 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.13, i64 0, i64 0))
%43 = icmp ne i32 %42, 0
%44 = zext i1 %43 to i64
%45 = select i1 %43, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i64 0, i64 0)
%46 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([58 x i8], [58 x i8]* @.str.11, i64 0, i64 0), i8* %45)
ret i32 0
}

LLVM IR (-O2):
@__const.main.hola = <{ i8, i8, i8, i8, [16 x i8] }> <{ i8 104, i8 111, i8 108, i8 97, [16 x i8] zeroinitializer }>
@.str = [52 x i8] c"Count length of \22hola\22 string in a char[20]:\0A %i\0A\0A\00"
@.str.1 = [59 x i8] c"Count length of \22Ahura Mazda\22 string in a char[12]:\0A %i\0A\0A\00"
@.str.2 = [12 x i8] c"Ahura Mazda\00"
@.str.3 = [42 x i8] c"Display previous string using %%s:\0A %s\0A\0A\00"
@__const.main.a = [20 x i8] c"hola \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
@__const.main.b = [6 x i8] c"mundo\00"
@.str.4 = [43 x i8] c"Concatenating \22hola \22 and \22mundo\22\0A \22%s\22\0A\0A\00"
@.str.5 = [56 x i8] c"Check if \22mundo\22 [6] and \22mundo\22 [80] are equal:\0A %s\0A\0A\00"
@.str.6 = [5 x i8] c"true\00"
@.str.7 = [6 x i8] c"false\00"
@.str.8 = [55 x i8] c"Check if \22hola\22 [5] and \22holama\22 [7] are equal:\0A %s\0A\0A\00"
@.str.9 = [5 x i8] c"hola\00"
@.str.10 = [7 x i8] c"holama\00"
@.str.11 = [58 x i8] c"Check if \22Jesus\22 [6] and \22Muhammad\22 [9] are equal:\0A %s\0A\0A\00"
@.str.12 = [6 x i8] c"Jesus\00"
@.str.13 = [9 x i8] c"Muhammad\00"
define i32 @main() {
%1 = alloca [20 x i8]
%2 = alloca [20 x i8]
%3 = alloca [6 x i8]
%4 = alloca [80 x i8]
%5 = alloca [80 x i8]
%6 = getelementptr inbounds [20 x i8], [20 x i8]* %1, i64 0, i64 0
%7 = call i32 (i8*, ...) bitcast (i32 (...)* @strLength to i32 (i8*, ...)*)(i8* %6)
%8 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([52 x i8], [52 x i8]* @.str, i64 0, i64 0), i32 %7)
%9 = call i32 (i8*, ...) bitcast (i32 (...)* @strLength to i32 (i8*, ...)*)(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.2, i64 0, i64 0))
%10 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([59 x i8], [59 x i8]* @.str.1, i64 0, i64 0), i32 %9)
%11 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([42 x i8], [42 x i8]* @.str.3, i64 0, i64 0), i8* %6)
%12 = getelementptr inbounds [20 x i8], [20 x i8]* %2, i64 0, i64 0
%13 = getelementptr inbounds [6 x i8], [6 x i8]* %3, i64 0, i64 0
%14 = getelementptr inbounds [80 x i8], [80 x i8]* %4, i64 0, i64 0
%15 = call i32 (i8*, i8*, i8*, ...) bitcast (i32 (...)* @strConcat to i32 (i8*, i8*, i8*, ...)*)(i8* %12, i8* %13, i8* %14)
%16 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([43 x i8], [43 x i8]* @.str.4, i64 0, i64 0), i8* %14)
%17 = getelementptr inbounds [80 x i8], [80 x i8]* %5, i64 0, i64 0
store i8 109, i8* %17
%18 = getelementptr inbounds [80 x i8], [80 x i8]* %5, i64 0, i64 1
store i8 117, i8* %18
%19 = getelementptr inbounds [80 x i8], [80 x i8]* %5, i64 0, i64 2
store i8 110, i8* %19
%20 = getelementptr inbounds [80 x i8], [80 x i8]* %5, i64 0, i64 3
store i8 100, i8* %20
%21 = getelementptr inbounds [80 x i8], [80 x i8]* %5, i64 0, i64 4
store i8 111, i8* %21
%22 = call i32 (i8*, i8*, ...) bitcast (i32 (...)* @strEqual to i32 (i8*, i8*, ...)*)(i8* %13, i8* %17)
%23 = icmp eq i32 %22, 0
%24 = select i1 %23, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i64 0, i64 0)
%25 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([56 x i8], [56 x i8]* @.str.5, i64 0, i64 0), i8* %24)
%26 = call i32 (i8*, i8*, ...) bitcast (i32 (...)* @strEqual to i32 (i8*, i8*, ...)*)(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.9, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.10, i64 0, i64 0))
%27 = icmp eq i32 %26, 0
%28 = select i1 %27, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i64 0, i64 0)
%29 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([55 x i8], [55 x i8]* @.str.8, i64 0, i64 0), i8* %28)
%30 = call i32 (i8*, i8*, ...) bitcast (i32 (...)* @strEqual to i32 (i8*, i8*, ...)*)(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.12, i64 0, i64 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.13, i64 0, i64 0))
%31 = icmp eq i32 %30, 0
%32 = select i1 %31, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i64 0, i64 0)
%33 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([58 x i8], [58 x i8]* @.str.11, i64 0, i64 0), i8* %32)
ret i32 0
}