#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
struct dirent {
  int d_type;
  char *d_name;
};
typedef int /*<<< orphan*/ DIR;

/* Variables and functions */
#define DT_BLK 134
#define DT_CHR 133
#define DT_DIR 132
#define DT_FIFO 131
#define DT_LNK 130
#define DT_REG 129
#define DT_SOCK 128
int /*<<< orphan*/ closedir(int /*<<< orphan*/ *);
int /*<<< orphan*/ *opendir(char *);
int /*<<< orphan*/ perror(char *);
int /*<<< orphan*/ printf(char *, char *);
struct dirent *readdir(int /*<<< orphan*/ *);
int main(void) {
  DIR *dp;
  struct dirent *ep;
  dp = opendir("./");
  if (dp != NULL) {
    for (; (ep = readdir(dp));) {
      switch (ep->d_type) {
      case DT_BLK:
        printf("%s is a block device.\n", ep->d_name);
        break;
      case DT_CHR:
        printf("%s is a character device.\n", ep->d_name);
        break;
      case DT_DIR:
        printf("%s is a directory.\n", ep->d_name);
        break;
      case DT_FIFO:
        printf("%s is a named pipe (FIFO).\n", ep->d_name);
        break;
      case DT_LNK:
        printf("%s is a symbolic link.\n", ep->d_name);
        break;
      case DT_REG:
        printf("%s is a regular file.\n", ep->d_name);
        break;
      case DT_SOCK:
        printf("%s is a UNIX domain socket.\n", ep->d_name);
        break;
      default:
        printf("The %s's type could not be determined.\n", ep->d_name);
        break;
      }
    }
    (void)closedir(dp);
  } else {
    perror("Couldn't open the directory");
  }
  return (0);
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
movl   $0x0,-0x4(%rbp)
lea    0xeb6(%rip),%rdi
call   1030 <opendir@plt>
mov    %rax,-0x10(%rbp)
cmpq   $0x0,-0x10(%rbp)
je     1298 <main+0x148>
jmp    117f <main+0x2f>
mov    -0x10(%rbp),%rdi
call   1060 <readdir@plt>
mov    %rax,-0x18(%rbp)
cmp    $0x0,%rax
je     128a <main+0x13a>
mov    -0x18(%rbp),%rax
mov    (%rax),%eax
add    $0xffffff80,%eax
mov    %eax,%ecx
mov    %rcx,-0x20(%rbp)
sub    $0x6,%eax
ja     1271 <main+0x121>
mov    -0x20(%rbp),%rax
lea    0xe47(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rsi
lea    0xe4e(%rip),%rdi
call   1040 <printf@plt>
jmp    1285 <main+0x135>
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rsi
lea    0xe4c(%rip),%rdi
call   1040 <printf@plt>
jmp    1285 <main+0x135>
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rsi
lea    0xe4e(%rip),%rdi
call   1040 <printf@plt>
jmp    1285 <main+0x135>
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rsi
lea    0xe49(%rip),%rdi
call   1040 <printf@plt>
jmp    1285 <main+0x135>
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rsi
lea    0xe4c(%rip),%rdi
call   1040 <printf@plt>
jmp    1285 <main+0x135>
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rsi
lea    0xe4b(%rip),%rdi
call   1040 <printf@plt>
jmp    1285 <main+0x135>
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rsi
lea    0xe49(%rip),%rdi
call   1040 <printf@plt>
jmp    1285 <main+0x135>
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rsi
lea    0xe4d(%rip),%rdi
call   1040 <printf@plt>
jmp    117f <main+0x2f>
mov    -0x10(%rbp),%rdi
call   1050 <closedir@plt>
jmp    12a4 <main+0x154>
lea    0xe56(%rip),%rdi
call   1070 <perror@plt>
xor    %eax,%eax
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %r15
push   %r14
push   %rbx
lea    0xea4(%rip),%rdi
call   1030 <opendir@plt>
test   %rax,%rax
je     11cf <main+0x7f>
mov    %rax,%rbx
mov    %rax,%rdi
call   1060 <readdir@plt>
test   %rax,%rax
je     11bf <main+0x6f>
lea    0xf34(%rip),%r14
lea    0xf74(%rip),%r15
jmp    11a6 <main+0x56>
cs nopw 0x0(%rax,%rax,1)
mov    0x8(%rax),%rsi
call   1040 <printf@plt>
mov    %rbx,%rdi
call   1060 <readdir@plt>
test   %rax,%rax
je     11bf <main+0x6f>
mov    (%rax),%ecx
add    $0xffffff80,%ecx
mov    %r14,%rdi
cmp    $0x6,%ecx
ja     1190 <main+0x40>
movslq %ecx,%rcx
movslq (%r15,%rcx,4),%rdi
add    %r15,%rdi
jmp    1190 <main+0x40>
mov    %rbx,%rdi
call   1050 <closedir@plt>
xor    %eax,%eax
pop    %rbx
pop    %r14
pop    %r15
ret
lea    0xf03(%rip),%rdi
call   1070 <perror@plt>
jmp    11c7 <main+0x77>

LLVM IR (-O0):
%struct.dirent = type { i32, i8* }
@.str = [3 x i8] c"./\00"
@.str.1 = [23 x i8] c"%s is a block device.\0A\00"
@.str.2 = [27 x i8] c"%s is a character device.\0A\00"
@.str.3 = [20 x i8] c"%s is a directory.\0A\00"
@.str.4 = [28 x i8] c"%s is a named pipe (FIFO).\0A\00"
@.str.5 = [24 x i8] c"%s is a symbolic link.\0A\00"
@.str.6 = [23 x i8] c"%s is a regular file.\0A\00"
@.str.7 = [29 x i8] c"%s is a UNIX domain socket.\0A\00"
@.str.8 = [40 x i8] c"The %s's type could not be determined.\0A\00"
@.str.9 = [28 x i8] c"Couldn't open the directory\00"
define i32 @main() {
%1 = alloca i32
%2 = alloca i32*
%3 = alloca %struct.dirent*
store i32 0, i32* %1
%4 = call i32* @opendir(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0))
store i32* %4, i32** %2
%5 = load i32*, i32** %2
%6 = icmp ne i32* %5, null
br i1 %6, label %7, label %60
7: ; preds = %0
br label %8
8: ; preds = %56, %7
%9 = load i32*, i32** %2
%10 = call %struct.dirent* @readdir(i32* %9)
store %struct.dirent* %10, %struct.dirent** %3
%11 = icmp ne %struct.dirent* %10, null
br i1 %11, label %12, label %57
12: ; preds = %8
%13 = load %struct.dirent*, %struct.dirent** %3
%14 = getelementptr inbounds %struct.dirent, %struct.dirent* %13, i32 0, i32 0
%15 = load i32, i32* %14
switch i32 %15, label %51 [
i32 134, label %16
i32 133, label %21
i32 132, label %26
i32 131, label %31
i32 130, label %36
i32 129, label %41
i32 128, label %46
]
16: ; preds = %12
%17 = load %struct.dirent*, %struct.dirent** %3
%18 = getelementptr inbounds %struct.dirent, %struct.dirent* %17, i32 0, i32 1
%19 = load i8*, i8** %18
%20 = call i32 @printf(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.1, i64 0, i64 0), i8* %19)
br label %56
21: ; preds = %12
%22 = load %struct.dirent*, %struct.dirent** %3
%23 = getelementptr inbounds %struct.dirent, %struct.dirent* %22, i32 0, i32 1
%24 = load i8*, i8** %23
%25 = call i32 @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.2, i64 0, i64 0), i8* %24)
br label %56
26: ; preds = %12
%27 = load %struct.dirent*, %struct.dirent** %3
%28 = getelementptr inbounds %struct.dirent, %struct.dirent* %27, i32 0, i32 1
%29 = load i8*, i8** %28
%30 = call i32 @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.3, i64 0, i64 0), i8* %29)
br label %56
31: ; preds = %12
%32 = load %struct.dirent*, %struct.dirent** %3
%33 = getelementptr inbounds %struct.dirent, %struct.dirent* %32, i32 0, i32 1
%34 = load i8*, i8** %33
%35 = call i32 @printf(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.4, i64 0, i64 0), i8* %34)
br label %56
36: ; preds = %12
%37 = load %struct.dirent*, %struct.dirent** %3
%38 = getelementptr inbounds %struct.dirent, %struct.dirent* %37, i32 0, i32 1
%39 = load i8*, i8** %38
%40 = call i32 @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.5, i64 0, i64 0), i8* %39)
br label %56
41: ; preds = %12
%42 = load %struct.dirent*, %struct.dirent** %3
%43 = getelementptr inbounds %struct.dirent, %struct.dirent* %42, i32 0, i32 1
%44 = load i8*, i8** %43
%45 = call i32 @printf(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.6, i64 0, i64 0), i8* %44)
br label %56
46: ; preds = %12
%47 = load %struct.dirent*, %struct.dirent** %3
%48 = getelementptr inbounds %struct.dirent, %struct.dirent* %47, i32 0, i32 1
%49 = load i8*, i8** %48
%50 = call i32 @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.7, i64 0, i64 0), i8* %49)
br label %56
51: ; preds = %12
%52 = load %struct.dirent*, %struct.dirent** %3
%53 = getelementptr inbounds %struct.dirent, %struct.dirent* %52, i32 0, i32 1
%54 = load i8*, i8** %53
%55 = call i32 @printf(i8* getelementptr inbounds ([40 x i8], [40 x i8]* @.str.8, i64 0, i64 0), i8* %54)
br label %56
56: ; preds = %51, %46, %41, %36, %31, %26, %21, %16
br label %8
57: ; preds = %8
%58 = load i32*, i32** %2
%59 = call i32 @closedir(i32* %58)
br label %62
60: ; preds = %0
%61 = call i32 @perror(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.9, i64 0, i64 0))
br label %62
62: ; preds = %60, %57
ret i32 0
}

LLVM IR (-O2):
%struct.dirent = type { i32, i8* }
@.str = [3 x i8] c"./\00"
@.str.1 = [23 x i8] c"%s is a block device.\0A\00"
@.str.2 = [27 x i8] c"%s is a character device.\0A\00"
@.str.3 = [20 x i8] c"%s is a directory.\0A\00"
@.str.4 = [28 x i8] c"%s is a named pipe (FIFO).\0A\00"
@.str.5 = [24 x i8] c"%s is a symbolic link.\0A\00"
@.str.6 = [23 x i8] c"%s is a regular file.\0A\00"
@.str.7 = [29 x i8] c"%s is a UNIX domain socket.\0A\00"
@.str.8 = [40 x i8] c"The %s's type could not be determined.\0A\00"
@.str.9 = [28 x i8] c"Couldn't open the directory\00"
@reltable.main = [7 x i32] [i32 trunc (i64 sub (i64 ptrtoint ([29 x i8]* @.str.7 to i64), i64 ptrtoint ([7 x i32]* @reltable.main to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([23 x i8]* @.str.6 to i64), i64 ptrtoint ([7 x i32]* @reltable.main to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([24 x i8]* @.str.5 to i64), i64 ptrtoint ([7 x i32]* @reltable.main to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([28 x i8]* @.str.4 to i64), i64 ptrtoint ([7 x i32]* @reltable.main to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([20 x i8]* @.str.3 to i64), i64 ptrtoint ([7 x i32]* @reltable.main to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([27 x i8]* @.str.2 to i64), i64 ptrtoint ([7 x i32]* @reltable.main to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([23 x i8]* @.str.1 to i64), i64 ptrtoint ([7 x i32]* @reltable.main to i64)) to i32)]
define i32 @main() {
%1 = tail call i32* @opendir(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0))
%2 = icmp eq i32* %1, null
br i1 %2, label %25, label %3
3: ; preds = %0
%4 = tail call %struct.dirent* @readdir(i32* %1)
%5 = icmp eq %struct.dirent* %4, null
br i1 %5, label %23, label %6
6: ; preds = %3, %16
%7 = phi %struct.dirent* [ %21, %16 ], [ %4, %3 ]
%8 = getelementptr inbounds %struct.dirent, %struct.dirent* %7, i64 0, i32 0
%9 = load i32, i32* %8
%10 = add i32 %9, -128
%11 = icmp ult i32 %10, 7
br i1 %11, label %12, label %16
12: ; preds = %6
%13 = sext i32 %10 to i64
%14 = shl i64 %13, 2
%15 = call i8* @llvm.load.relative.i64(i8* bitcast ([7 x i32]* @reltable.main to i8*), i64 %14)
br label %16
16: ; preds = %6, %12
%17 = phi i8* [ %15, %12 ], [ getelementptr inbounds ([40 x i8], [40 x i8]* @.str.8, i64 0, i64 0), %6 ]
%18 = getelementptr inbounds %struct.dirent, %struct.dirent* %7, i64 0, i32 1
%19 = load i8*, i8** %18
%20 = tail call i32 @printf(i8* %17, i8* %19)
%21 = tail call %struct.dirent* @readdir(i32* %1)
%22 = icmp eq %struct.dirent* %21, null
br i1 %22, label %23, label %6
23: ; preds = %16, %3
%24 = tail call i32 @closedir(i32* %1)
br label %27
25: ; preds = %0
%26 = tail call i32 @perror(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.9, i64 0, i64 0))
br label %27
27: ; preds = %25, %23
ret i32 0
}