#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 object {
  int dummy;
};
struct model {
  int dummy;
};
typedef int /*<<< orphan*/ FILE;

/* Variables and functions */
int /*<<< orphan*/ debug(char *, char const *, ...);
scalar_t__ fgets(char *, int, int /*<<< orphan*/ *);
scalar_t__ isspace(char);
struct model *model_create();
int /*<<< orphan*/ model_free(struct model *);
struct object *model_object_create(struct model *, char *, int);
int /*<<< orphan*/ model_verify(struct model *);
scalar_t__ model_vertex_add(struct model *, double, double, double);
int /*<<< orphan*/ parse_face_data(char const *, unsigned int, struct model *,
                                   struct object **, char *);
int /*<<< orphan*/ strcmp(char *, char *);
double strtod(char *, char **);
int /*<<< orphan*/ warn(char *, char const *, unsigned int);
struct model *obj_load_from_file(FILE *f, const char *filename) {
  struct model *m;
  struct object *curr_grp = 0;
  char buf[1024];
  char *idx, *cmd, *tmp;
  unsigned line = 0;
  double v[3];
  unsigned i;
  m = model_create();
  while (fgets(buf, sizeof buf, f)) {
    line++;
    idx = buf;
    while (isspace(*idx))
      idx++;
    if (*idx == '#' || !*idx)
      continue;
    cmd = idx;
    while (*idx && !isspace(*idx))
      idx++;
    if (*idx) {
      *idx = 0;
      idx++;
    }
    if (!strcmp(cmd, "v")) {
      for (i = 0; i < 3; i++) {
        while (isspace(*idx))
          idx++;
        v[i] = strtod(idx, &tmp);
        if (idx == tmp)
          goto error;
        idx = tmp;
      }
      if (model_vertex_add(m, v[0], v[1], v[2]) < 0) {
        warn("%s:%u:vertex data error\n", filename, line);
        goto error;
      }
    } else if (!strcmp(cmd, "vt")) {
      for (i = 0; i < 2; i++) {
        while (isspace(*idx))
          idx++;
        v[i] = strtod(idx, &tmp);
        if (idx == tmp) {
          goto error;
        }
        idx = tmp;
      }
      debug("%s:%u:ignoring texture coord [U:%f, V:%f]\n", filename, line, v[0],
            v[1]);
    } else if (!strcmp(cmd, "vn")) {
      for (i = 0; i < 3; i++) {
        while (isspace(*idx))
          idx++;
        v[i] = strtod(idx, &tmp);
        if (idx == tmp) {
          goto error;
        }
        idx = tmp;
      }
      debug("%s:%u:ignoring normal [%f, %f, %f]\n", filename, line, v[0], v[1],
            v[2]);
    } else if (!strcmp(cmd, "p")) {
    } else if (!strcmp(cmd, "l")) {
    } else if (!strcmp(cmd, "f")) {
      if (!parse_face_data(filename, line, m, &curr_grp, idx))
        goto error;
    } else if (!strcmp(cmd, "g")) {
      tmp = idx;
      while (*idx && *idx != '\r' && *idx != '\n')
        idx++;
      if (*idx)
        *idx = 0;
      curr_grp = model_object_create(m, tmp, 1);
      debug("curr_grp=%p\n", curr_grp);
    } else if (!strcmp(cmd, "o")) {
      tmp = idx;
      while (*idx && *idx != '\r' && *idx != '\n')
        idx++;
      if (*idx)
        *idx = 0;
      debug("%s:%u:ignoring object name '%s'\n", filename, line, tmp);
    } else {
      debug("%s:%u:I don't know how to handle OBJ type '%s'!\n", filename, line,
            cmd);
    }
  }
  if (!model_verify(m)) {
    debug("%s:model verification failed\n", filename);
    goto error;
  }
  return m;
error:
  model_free(m);
  debug("%s:%u:failed!\n", filename, line);
  return 0;
}


x86 assembly (clang, -O0):
<obj_load_from_file>:
push   %rbp
mov    %rsp,%rbp
sub    $0x480,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
movq   $0x0,-0x28(%rbp)
movl   $0x0,-0x44c(%rbp)
mov    $0x0,%al
call   1070 <model_create@plt>
mov    %rax,-0x20(%rbp)
lea    -0x430(%rbp),%rdi
mov    -0x10(%rbp),%rdx
mov    $0x400,%esi
call   10a0 <fgets@plt>
cmp    $0x0,%rax
je     18bb <obj_load_from_file+0x6fb>
mov    -0x44c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x44c(%rbp)
lea    -0x430(%rbp),%rax
mov    %rax,-0x438(%rbp)
mov    -0x438(%rbp),%rax
movsbl (%rax),%edi
call   1090 <isspace@plt>
cmp    $0x0,%rax
je     125c <obj_load_from_file+0x9c>
mov    -0x438(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x438(%rbp)
jmp    122c <obj_load_from_file+0x6c>
mov    -0x438(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x23,%eax
je     127f <obj_load_from_file+0xbf>
mov    -0x438(%rbp),%rax
cmpb   $0x0,(%rax)
jne    1284 <obj_load_from_file+0xc4>
jmp    11f0 <obj_load_from_file+0x30>
mov    -0x438(%rbp),%rax
mov    %rax,-0x440(%rbp)
mov    -0x438(%rbp),%rax
movsbl (%rax),%ecx
xor    %eax,%eax
cmp    $0x0,%ecx
mov    %al,-0x475(%rbp)
je     12cb <obj_load_from_file+0x10b>
mov    -0x438(%rbp),%rax
movsbl (%rax),%edi
call   1090 <isspace@plt>
cmp    $0x0,%rax
setne  %al
xor    $0xff,%al
mov    %al,-0x475(%rbp)
mov    -0x475(%rbp),%al
test   $0x1,%al
jne    12de <obj_load_from_file+0x11e>
jmp    12f5 <obj_load_from_file+0x135>
mov    -0x438(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x438(%rbp)
jmp    1292 <obj_load_from_file+0xd2>
mov    -0x438(%rbp),%rax
cmpb   $0x0,(%rax)
je     1321 <obj_load_from_file+0x161>
mov    -0x438(%rbp),%rax
movb   $0x0,(%rax)
mov    -0x438(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x438(%rbp)
mov    -0x440(%rbp),%rdi
lea    0xcd1(%rip),%rsi
call   10b0 <strcmp@plt>
cmp    $0x0,%eax
jne    1431 <obj_load_from_file+0x271>
movl   $0x0,-0x474(%rbp)
cmpl   $0x3,-0x474(%rbp)
jae    13e6 <obj_load_from_file+0x226>
jmp    1359 <obj_load_from_file+0x199>
mov    -0x438(%rbp),%rax
movsbl (%rax),%edi
call   1090 <isspace@plt>
cmp    $0x0,%rax
je     1389 <obj_load_from_file+0x1c9>
mov    -0x438(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x438(%rbp)
jmp    1359 <obj_load_from_file+0x199>
mov    -0x438(%rbp),%rdi
lea    -0x448(%rbp),%rsi
call   1050 <strtod@plt>
mov    -0x474(%rbp),%eax
movsd  %xmm0,-0x470(%rbp,%rax,8)
ff ff
mov    -0x438(%rbp),%rax
cmp    -0x448(%rbp),%rax
jne    13c4 <obj_load_from_file+0x204>
jmp    18f1 <obj_load_from_file+0x731>
mov    -0x448(%rbp),%rax
mov    %rax,-0x438(%rbp)
mov    -0x474(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x474(%rbp)
jmp    1347 <obj_load_from_file+0x187>
mov    -0x20(%rbp),%rdi
movsd  -0x470(%rbp),%xmm0
ff
movsd  -0x468(%rbp),%xmm1
ff
movsd  -0x460(%rbp),%xmm2
ff
call   10e0 <model_vertex_add@plt>
cmp    $0x0,%rax
jge    142c <obj_load_from_file+0x26c>
mov    -0x18(%rbp),%rsi
mov    -0x44c(%rbp),%edx
lea    0xbe0(%rip),%rdi
call   1040 <warn@plt>
jmp    18f1 <obj_load_from_file+0x731>
jmp    18b6 <obj_load_from_file+0x6f6>
mov    -0x440(%rbp),%rdi
lea    0xbdc(%rip),%rsi
call   10b0 <strcmp@plt>
cmp    $0x0,%eax
jne    1523 <obj_load_from_file+0x363>
movl   $0x0,-0x474(%rbp)
cmpl   $0x2,-0x474(%rbp)
jae    14f6 <obj_load_from_file+0x336>
jmp    1469 <obj_load_from_file+0x2a9>
mov    -0x438(%rbp),%rax
movsbl (%rax),%edi
call   1090 <isspace@plt>
cmp    $0x0,%rax
je     1499 <obj_load_from_file+0x2d9>
mov    -0x438(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x438(%rbp)
jmp    1469 <obj_load_from_file+0x2a9>
mov    -0x438(%rbp),%rdi
lea    -0x448(%rbp),%rsi
call   1050 <strtod@plt>
mov    -0x474(%rbp),%eax
movsd  %xmm0,-0x470(%rbp,%rax,8)
ff ff
mov    -0x438(%rbp),%rax
cmp    -0x448(%rbp),%rax
jne    14d4 <obj_load_from_file+0x314>
jmp    18f1 <obj_load_from_file+0x731>
mov    -0x448(%rbp),%rax
mov    %rax,-0x438(%rbp)
mov    -0x474(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x474(%rbp)
jmp    1457 <obj_load_from_file+0x297>
mov    -0x18(%rbp),%rsi
mov    -0x44c(%rbp),%edx
movsd  -0x470(%rbp),%xmm0
ff
movsd  -0x468(%rbp),%xmm1
ff
lea    0xb07(%rip),%rdi
mov    $0x2,%al
call   1080 <debug@plt>
jmp    18b1 <obj_load_from_file+0x6f1>
mov    -0x440(%rbp),%rdi
lea    0xb18(%rip),%rsi
call   10b0 <strcmp@plt>
cmp    $0x0,%eax
jne    161d <obj_load_from_file+0x45d>
movl   $0x0,-0x474(%rbp)
cmpl   $0x3,-0x474(%rbp)
jae    15e8 <obj_load_from_file+0x428>
jmp    155b <obj_load_from_file+0x39b>
mov    -0x438(%rbp),%rax
movsbl (%rax),%edi
call   1090 <isspace@plt>
cmp    $0x0,%rax
je     158b <obj_load_from_file+0x3cb>
mov    -0x438(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x438(%rbp)
jmp    155b <obj_load_from_file+0x39b>
mov    -0x438(%rbp),%rdi
lea    -0x448(%rbp),%rsi
call   1050 <strtod@plt>
mov    -0x474(%rbp),%eax
movsd  %xmm0,-0x470(%rbp,%rax,8)
ff ff
mov    -0x438(%rbp),%rax
cmp    -0x448(%rbp),%rax
jne    15c6 <obj_load_from_file+0x406>
jmp    18f1 <obj_load_from_file+0x731>
mov    -0x448(%rbp),%rax
mov    %rax,-0x438(%rbp)
mov    -0x474(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x474(%rbp)
jmp    1549 <obj_load_from_file+0x389>
mov    -0x18(%rbp),%rsi
mov    -0x44c(%rbp),%edx
movsd  -0x470(%rbp),%xmm0
ff
movsd  -0x468(%rbp),%xmm1
ff
movsd  -0x460(%rbp),%xmm2
ff
lea    0xa3b(%rip),%rdi
mov    $0x3,%al
call   1080 <debug@plt>
jmp    18ac <obj_load_from_file+0x6ec>
mov    -0x440(%rbp),%rdi
lea    0xa45(%rip),%rsi
call   10b0 <strcmp@plt>
cmp    $0x0,%eax
jne    163e <obj_load_from_file+0x47e>
jmp    18a7 <obj_load_from_file+0x6e7>
mov    -0x440(%rbp),%rdi
lea    0xa26(%rip),%rsi
call   10b0 <strcmp@plt>
cmp    $0x0,%eax
jne    165f <obj_load_from_file+0x49f>
jmp    18a2 <obj_load_from_file+0x6e2>
mov    -0x440(%rbp),%rdi
lea    0xa07(%rip),%rsi
call   10b0 <strcmp@plt>
cmp    $0x0,%eax
jne    16ac <obj_load_from_file+0x4ec>
mov    -0x18(%rbp),%rdi
mov    -0x44c(%rbp),%esi
mov    -0x20(%rbp),%rdx
mov    -0x438(%rbp),%r8
lea    -0x28(%rbp),%rcx
call   10c0 <parse_face_data@plt>
cmp    $0x0,%eax
jne    16a7 <obj_load_from_file+0x4e7>
jmp    18f1 <obj_load_from_file+0x731>
jmp    189d <obj_load_from_file+0x6dd>
mov    -0x440(%rbp),%rdi
lea    0x9bc(%rip),%rsi
call   10b0 <strcmp@plt>
cmp    $0x0,%eax
jne    1796 <obj_load_from_file+0x5d6>
mov    -0x438(%rbp),%rax
mov    %rax,-0x448(%rbp)
mov    -0x438(%rbp),%rax
movsbl (%rax),%ecx
xor    %eax,%eax
cmp    $0x0,%ecx
mov    %al,-0x476(%rbp)
je     1722 <obj_load_from_file+0x562>
mov    -0x438(%rbp),%rax
movsbl (%rax),%ecx
xor    %eax,%eax
cmp    $0xd,%ecx
mov    %al,-0x476(%rbp)
je     1722 <obj_load_from_file+0x562>
mov    -0x438(%rbp),%rax
movsbl (%rax),%eax
cmp    $0xa,%eax
setne  %al
mov    %al,-0x476(%rbp)
mov    -0x476(%rbp),%al
test   $0x1,%al
jne    1735 <obj_load_from_file+0x575>
jmp    174c <obj_load_from_file+0x58c>
mov    -0x438(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x438(%rbp)
jmp    16d6 <obj_load_from_file+0x516>
mov    -0x438(%rbp),%rax
cmpb   $0x0,(%rax)
je     1766 <obj_load_from_file+0x5a6>
mov    -0x438(%rbp),%rax
movb   $0x0,(%rax)
mov    -0x20(%rbp),%rdi
mov    -0x448(%rbp),%rsi
mov    $0x1,%edx
call   1030 <model_object_create@plt>
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rsi
lea    0x8ee(%rip),%rdi
mov    $0x0,%al
call   1080 <debug@plt>
jmp    1898 <obj_load_from_file+0x6d8>
mov    -0x440(%rbp),%rdi
lea    0x8e1(%rip),%rsi
call   10b0 <strcmp@plt>
cmp    $0x0,%eax
jne    1874 <obj_load_from_file+0x6b4>
mov    -0x438(%rbp),%rax
mov    %rax,-0x448(%rbp)
mov    -0x438(%rbp),%rax
movsbl (%rax),%ecx
xor    %eax,%eax
cmp    $0x0,%ecx
mov    %al,-0x477(%rbp)
je     180c <obj_load_from_file+0x64c>
mov    -0x438(%rbp),%rax
movsbl (%rax),%ecx
xor    %eax,%eax
cmp    $0xd,%ecx
mov    %al,-0x477(%rbp)
je     180c <obj_load_from_file+0x64c>
mov    -0x438(%rbp),%rax
movsbl (%rax),%eax
cmp    $0xa,%eax
setne  %al
mov    %al,-0x477(%rbp)
mov    -0x477(%rbp),%al
test   $0x1,%al
jne    181f <obj_load_from_file+0x65f>
jmp    1836 <obj_load_from_file+0x676>
mov    -0x438(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x438(%rbp)
jmp    17c0 <obj_load_from_file+0x600>
mov    -0x438(%rbp),%rax
cmpb   $0x0,(%rax)
je     1850 <obj_load_from_file+0x690>
mov    -0x438(%rbp),%rax
movb   $0x0,(%rax)
mov    -0x18(%rbp),%rsi
mov    -0x44c(%rbp),%edx
mov    -0x448(%rbp),%rcx
lea    0x81f(%rip),%rdi
mov    $0x0,%al
call   1080 <debug@plt>
jmp    1893 <obj_load_from_file+0x6d3>
mov    -0x18(%rbp),%rsi
mov    -0x44c(%rbp),%edx
mov    -0x440(%rbp),%rcx
lea    0x81c(%rip),%rdi
mov    $0x0,%al
call   1080 <debug@plt>
jmp    1898 <obj_load_from_file+0x6d8>
jmp    189d <obj_load_from_file+0x6dd>
jmp    18a2 <obj_load_from_file+0x6e2>
jmp    18a7 <obj_load_from_file+0x6e7>
jmp    18ac <obj_load_from_file+0x6ec>
jmp    18b1 <obj_load_from_file+0x6f1>
jmp    18b6 <obj_load_from_file+0x6f6>
jmp    11f0 <obj_load_from_file+0x30>
mov    -0x20(%rbp),%rdi
call   10d0 <model_verify@plt>
cmp    $0x0,%eax
jne    18e4 <obj_load_from_file+0x724>
mov    -0x18(%rbp),%rsi
lea    0x801(%rip),%rdi
mov    $0x0,%al
call   1080 <debug@plt>
jmp    18f1 <obj_load_from_file+0x731>
mov    -0x20(%rbp),%rax
mov    %rax,-0x8(%rbp)
jmp    191a <obj_load_from_file+0x75a>
mov    -0x20(%rbp),%rdi
call   1060 <model_free@plt>
mov    -0x18(%rbp),%rsi
mov    -0x44c(%rbp),%edx
lea    0x7ec(%rip),%rdi
mov    $0x0,%al
call   1080 <debug@plt>
movq   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x480,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<obj_load_from_file>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x438,%rsp
mov    %rsi,%rbp
mov    %rdi,%r15
movq   $0x0,0x28(%rsp)
xor    %r12d,%r12d
xor    %eax,%eax
call   1070 <model_create@plt>
mov    %rax,0x8(%rsp)
lea    0x30(%rsp),%rdi
mov    $0x400,%esi
mov    %r15,%rdx
call   10a0 <fgets@plt>
test   %rax,%rax
je     16a0 <obj_load_from_file+0x4e0>
lea    0x2f(%rsp),%rbx
xor    %r12d,%r12d
jmp    125b <obj_load_from_file+0x9b>
mov    %rbp,%rdi
mov    %r12d,%esi
mov    0x8(%rsp),%rdx
lea    0x28(%rsp),%rcx
mov    %r14,%r8
call   10c0 <parse_face_data@plt>
test   %eax,%eax
je     16e5 <obj_load_from_file+0x525>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
lea    0x30(%rsp),%rdi
mov    $0x400,%esi
mov    %r15,%rdx
call   10a0 <fgets@plt>
test   %rax,%rax
je     16a0 <obj_load_from_file+0x4e0>
lea    0x31(%rsp),%rcx
mov    %rbx,%r13
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
mov    %rcx,%r14
movsbl 0x1(%r13),%edi
add    $0x1,%r13
call   1090 <isspace@plt>
lea    0x1(%r14),%rcx
test   %rax,%rax
jne    1270 <obj_load_from_file+0xb0>
add    $0x1,%r12d
mov    0x0(%r13),%al
test   %al,%al
je     1240 <obj_load_from_file+0x80>
cmp    $0x23,%al
je     1240 <obj_load_from_file+0x80>
nopw   0x0(%rax,%rax,1)
movsbl %al,%edi
call   1090 <isspace@plt>
test   %rax,%rax
jne    12bb <obj_load_from_file+0xfb>
movzbl (%r14),%eax
add    $0x1,%r14
test   %al,%al
jne    12a0 <obj_load_from_file+0xe0>
jmp    12d0 <obj_load_from_file+0x110>
cmpb   $0x0,-0x1(%r14)
je     12d0 <obj_load_from_file+0x110>
movb   $0x0,-0x1(%r14)
jmp    12d4 <obj_load_from_file+0x114>
nopl   0x0(%rax)
add    $0xffffffffffffffff,%r14
mov    %r13,%rdi
lea    0xd22(%rip),%rsi
call   10b0 <strcmp@plt>
test   %eax,%eax
je     13a1 <obj_load_from_file+0x1e1>
mov    %r13,%rdi
lea    0xd26(%rip),%rsi
call   10b0 <strcmp@plt>
test   %eax,%eax
je     1487 <obj_load_from_file+0x2c7>
mov    %r13,%rdi
lea    0xd3d(%rip),%rsi
call   10b0 <strcmp@plt>
test   %eax,%eax
je     1522 <obj_load_from_file+0x362>
mov    %r13,%rdi
lea    0xd4d(%rip),%rsi
call   10b0 <strcmp@plt>
test   %eax,%eax
je     1240 <obj_load_from_file+0x80>
mov    %r13,%rdi
lea    0xd38(%rip),%rsi
call   10b0 <strcmp@plt>
test   %eax,%eax
je     1240 <obj_load_from_file+0x80>
mov    %r13,%rdi
lea    0xd23(%rip),%rsi
call   10b0 <strcmp@plt>
test   %eax,%eax
je     1214 <obj_load_from_file+0x54>
mov    %r13,%rdi
lea    0xd0e(%rip),%rsi
call   10b0 <strcmp@plt>
test   %eax,%eax
je     1608 <obj_load_from_file+0x448>
mov    %r13,%rdi
lea    0xd06(%rip),%rsi
call   10b0 <strcmp@plt>
test   %eax,%eax
je     1627 <obj_load_from_file+0x467>
lea    0xd15(%rip),%rdi
mov    %rbp,%rsi
mov    %r12d,%edx
mov    %r13,%rcx
jmp    1694 <obj_load_from_file+0x4d4>
add    $0xffffffffffffffff,%r14
cs nopw 0x0(%rax,%rax,1)
nop
movsbl 0x1(%r14),%edi
add    $0x1,%r14
call   1090 <isspace@plt>
test   %rax,%rax
jne    13b0 <obj_load_from_file+0x1f0>
mov    %r14,%rdi
lea    0x10(%rsp),%r13
mov    %r13,%rsi
call   1050 <strtod@plt>
mov    0x10(%rsp),%rbx
cmp    %rbx,%r14
je     16e5 <obj_load_from_file+0x525>
movsd  %xmm0,0x18(%rsp)
mov    %rbp,%r14
add    $0xffffffffffffffff,%rbx
xchg   %ax,%ax
movsbl 0x1(%rbx),%edi
add    $0x1,%rbx
call   1090 <isspace@plt>
test   %rax,%rax
jne    13f0 <obj_load_from_file+0x230>
mov    %rbx,%rdi
mov    %r13,%rsi
call   1050 <strtod@plt>
mov    0x10(%rsp),%rbp
cmp    %rbp,%rbx
je     16c4 <obj_load_from_file+0x504>
movsd  %xmm0,0x20(%rsp)
add    $0xffffffffffffffff,%rbp
cs nopw 0x0(%rax,%rax,1)
nop
movsbl 0x1(%rbp),%edi
add    $0x1,%rbp
call   1090 <isspace@plt>
test   %rax,%rax
jne    1430 <obj_load_from_file+0x270>
mov    %rbp,%rdi
mov    %r13,%rsi
call   1050 <strtod@plt>
cmp    0x10(%rsp),%rbp
lea    0x2f(%rsp),%rbx
je     16c4 <obj_load_from_file+0x504>
movaps %xmm0,%xmm2
mov    0x8(%rsp),%rdi
movsd  0x18(%rsp),%xmm0
movsd  0x20(%rsp),%xmm1
call   10e0 <model_vertex_add@plt>
test   %rax,%rax
mov    %r14,%rbp
jns    1240 <obj_load_from_file+0x80>
jmp    16d3 <obj_load_from_file+0x513>
mov    %rbp,%r13
add    $0xffffffffffffffff,%r14
xchg   %ax,%ax
movsbl 0x1(%r14),%edi
add    $0x1,%r14
call   1090 <isspace@plt>
test   %rax,%rax
jne    1490 <obj_load_from_file+0x2d0>
mov    %r14,%rdi
lea    0x10(%rsp),%rbp
mov    %rbp,%rsi
call   1050 <strtod@plt>
mov    0x10(%rsp),%rbx
cmp    %rbx,%r14
je     16c9 <obj_load_from_file+0x509>
movsd  %xmm0,0x18(%rsp)
add    $0xffffffffffffffff,%rbx
nopl   0x0(%rax,%rax,1)
movsbl 0x1(%rbx),%edi
add    $0x1,%rbx
call   1090 <isspace@plt>
test   %rax,%rax
jne    14d0 <obj_load_from_file+0x310>
mov    %rbx,%rdi
mov    %rbp,%rsi
call   1050 <strtod@plt>
cmp    0x10(%rsp),%rbx
je     16c9 <obj_load_from_file+0x509>
movaps %xmm0,%xmm1
lea    0xb1c(%rip),%rdi
mov    %r13,%rbp
mov    %r13,%rsi
mov    %r12d,%edx
movsd  0x18(%rsp),%xmm0
mov    $0x2,%al
call   1080 <debug@plt>
lea    0x2f(%rsp),%rbx
jmp    1240 <obj_load_from_file+0x80>
add    $0xffffffffffffffff,%r14
cs nopw 0x0(%rax,%rax,1)
movsbl 0x1(%r14),%edi
add    $0x1,%r14
call   1090 <isspace@plt>
test   %rax,%rax
jne    1530 <obj_load_from_file+0x370>
mov    %r14,%rdi
lea    0x10(%rsp),%r13
mov    %r13,%rsi
call   1050 <strtod@plt>
mov    0x10(%rsp),%rbx
cmp    %rbx,%r14
je     16e5 <obj_load_from_file+0x525>
movsd  %xmm0,0x18(%rsp)
mov    %rbp,%r14
add    $0xffffffffffffffff,%rbx
xchg   %ax,%ax
movsbl 0x1(%rbx),%edi
add    $0x1,%rbx
call   1090 <isspace@plt>
test   %rax,%rax
jne    1570 <obj_load_from_file+0x3b0>
mov    %rbx,%rdi
mov    %r13,%rsi
call   1050 <strtod@plt>
mov    0x10(%rsp),%rbp
cmp    %rbp,%rbx
je     16c4 <obj_load_from_file+0x504>
movsd  %xmm0,0x20(%rsp)
add    $0xffffffffffffffff,%rbp
cs nopw 0x0(%rax,%rax,1)
nop
movsbl 0x1(%rbp),%edi
add    $0x1,%rbp
call   1090 <isspace@plt>
test   %rax,%rax
jne    15b0 <obj_load_from_file+0x3f0>
mov    %rbp,%rdi
mov    %r13,%rsi
call   1050 <strtod@plt>
cmp    0x10(%rsp),%rbp
lea    0x2f(%rsp),%rbx
je     16c4 <obj_load_from_file+0x504>
movaps %xmm0,%xmm2
lea    0xa65(%rip),%rdi
mov    %r14,%rbp
mov    %r14,%rsi
mov    %r12d,%edx
movsd  0x18(%rsp),%xmm0
movsd  0x20(%rsp),%xmm1
mov    $0x3,%al
call   1080 <debug@plt>
jmp    1240 <obj_load_from_file+0x80>
mov    %r14,0x10(%rsp)
mov    %r14,%rax
movzbl (%rax),%ecx
test   %cl,%cl
je     164f <obj_load_from_file+0x48f>
cmp    $0xa,%cl
je     1647 <obj_load_from_file+0x487>
cmp    $0xd,%cl
je     1647 <obj_load_from_file+0x487>
add    $0x1,%rax
jmp    1610 <obj_load_from_file+0x450>
mov    %r14,0x10(%rsp)
mov    %r14,%rax
nop
movzbl (%rax),%ecx
test   %cl,%cl
je     1684 <obj_load_from_file+0x4c4>
cmp    $0xa,%cl
je     167c <obj_load_from_file+0x4bc>
cmp    $0xd,%cl
je     167c <obj_load_from_file+0x4bc>
add    $0x1,%rax
jmp    1630 <obj_load_from_file+0x470>
movb   $0x0,(%rax)
mov    0x10(%rsp),%r14
mov    0x8(%rsp),%rdi
mov    %r14,%rsi
mov    $0x1,%edx
call   1030 <model_object_create@plt>
mov    %rax,0x28(%rsp)
lea    0xa0b(%rip),%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1080 <debug@plt>
jmp    1240 <obj_load_from_file+0x80>
movb   $0x0,(%rax)
mov    0x10(%rsp),%r14
lea    0x9fc(%rip),%rdi
mov    %rbp,%rsi
mov    %r12d,%edx
mov    %r14,%rcx
xor    %eax,%eax
call   1080 <debug@plt>
jmp    1240 <obj_load_from_file+0x80>
mov    0x8(%rsp),%rbx
mov    %rbx,%rdi
call   10d0 <model_verify@plt>
test   %eax,%eax
jne    1708 <obj_load_from_file+0x548>
lea    0xa21(%rip),%rdi
mov    %rbp,%rsi
xor    %eax,%eax
call   1080 <debug@plt>
jmp    16ea <obj_load_from_file+0x52a>
mov    %r14,%rbp
jmp    16e5 <obj_load_from_file+0x525>
mov    0x8(%rsp),%rbx
mov    %r13,%rbp
jmp    16ea <obj_load_from_file+0x52a>
lea    0x928(%rip),%rdi
mov    %rbp,%rsi
mov    %r12d,%edx
call   1040 <warn@plt>
mov    0x8(%rsp),%rbx
mov    %rbx,%rdi
call   1060 <model_free@plt>
lea    0x9fe(%rip),%rdi
xor    %ebx,%ebx
mov    %rbp,%rsi
mov    %r12d,%edx
xor    %eax,%eax
call   1080 <debug@plt>
mov    %rbx,%rax
add    $0x438,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.model = type { i32 }
%struct.object = type { i32 }
@.str = [2 x i8] c"v\00"
@.str.1 = [25 x i8] c"%s:%u:vertex data error\0A\00"
@.str.2 = [3 x i8] c"vt\00"
@.str.3 = [43 x i8] c"%s:%u:ignoring texture coord [U:%f, V:%f]\0A\00"
@.str.4 = [3 x i8] c"vn\00"
@.str.5 = [36 x i8] c"%s:%u:ignoring normal [%f, %f, %f]\0A\00"
@.str.6 = [2 x i8] c"p\00"
@.str.7 = [2 x i8] c"l\00"
@.str.8 = [2 x i8] c"f\00"
@.str.9 = [2 x i8] c"g\00"
@.str.10 = [13 x i8] c"curr_grp=%p\0A\00"
@.str.11 = [2 x i8] c"o\00"
@.str.12 = [33 x i8] c"%s:%u:ignoring object name '%s'\0A\00"
@.str.13 = [49 x i8] c"%s:%u:I don't know how to handle OBJ type '%s'!\0A\00"
@.str.14 = [30 x i8] c"%s:model verification failed\0A\00"
@.str.15 = [15 x i8] c"%s:%u:failed!\0A\00"
define %struct.model* @obj_load_from_file(i32* %0, i8* %1) {
%3 = alloca %struct.model*
%4 = alloca i32*
%5 = alloca i8*
%6 = alloca %struct.model*
%7 = alloca %struct.object*
%8 = alloca [1024 x i8]
%9 = alloca i8*
%10 = alloca i8*
%11 = alloca i8*
%12 = alloca i32
%13 = alloca [3 x double]
%14 = alloca i32
store i32* %0, i32** %4
store i8* %1, i8** %5
store %struct.object* null, %struct.object** %7
store i32 0, i32* %12
%15 = call %struct.model* (...) @model_create()
store %struct.model* %15, %struct.model** %6
br label %16
16: ; preds = %309, %42, %2
%17 = getelementptr inbounds [1024 x i8], [1024 x i8]* %8, i64 0, i64 0
%18 = load i32*, i32** %4
%19 = call i64 @fgets(i8* %17, i32 1024, i32* %18)
%20 = icmp ne i64 %19, 0
br i1 %20, label %21, label %310
21: ; preds = %16
%22 = load i32, i32* %12
%23 = add i32 %22, 1
store i32 %23, i32* %12
%24 = getelementptr inbounds [1024 x i8], [1024 x i8]* %8, i64 0, i64 0
store i8* %24, i8** %9
br label %25
25: ; preds = %30, %21
%26 = load i8*, i8** %9
%27 = load i8, i8* %26
%28 = call i64 @isspace(i8 signext %27)
%29 = icmp ne i64 %28, 0
br i1 %29, label %30, label %33
30: ; preds = %25
%31 = load i8*, i8** %9
%32 = getelementptr inbounds i8, i8* %31, i32 1
store i8* %32, i8** %9
br label %25
33: ; preds = %25
%34 = load i8*, i8** %9
%35 = load i8, i8* %34
%36 = sext i8 %35 to i32
%37 = icmp eq i32 %36, 35
br i1 %37, label %42, label %38
38: ; preds = %33
%39 = load i8*, i8** %9
%40 = load i8, i8* %39
%41 = icmp ne i8 %40, 0
br i1 %41, label %43, label %42
42: ; preds = %38, %33
br label %16
43: ; preds = %38
%44 = load i8*, i8** %9
store i8* %44, i8** %10
br label %45
45: ; preds = %58, %43
%46 = load i8*, i8** %9
%47 = load i8, i8* %46
%48 = sext i8 %47 to i32
%49 = icmp ne i32 %48, 0
br i1 %49, label %50, label %56
50: ; preds = %45
%51 = load i8*, i8** %9
%52 = load i8, i8* %51
%53 = call i64 @isspace(i8 signext %52)
%54 = icmp ne i64 %53, 0
%55 = xor i1 %54, true
br label %56
56: ; preds = %50, %45
%57 = phi i1 [ false, %45 ], [ %55, %50 ]
br i1 %57, label %58, label %61
58: ; preds = %56
%59 = load i8*, i8** %9
%60 = getelementptr inbounds i8, i8* %59, i32 1
store i8* %60, i8** %9
br label %45
61: ; preds = %56
%62 = load i8*, i8** %9
%63 = load i8, i8* %62
%64 = icmp ne i8 %63, 0
br i1 %64, label %65, label %69
65: ; preds = %61
%66 = load i8*, i8** %9
store i8 0, i8* %66
%67 = load i8*, i8** %9
%68 = getelementptr inbounds i8, i8* %67, i32 1
store i8* %68, i8** %9
br label %69
69: ; preds = %65, %61
%70 = load i8*, i8** %10
%71 = call i32 @strcmp(i8* %70, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0))
%72 = icmp ne i32 %71, 0
br i1 %72, label %116, label %73
73: ; preds = %69
store i32 0, i32* %14
br label %74
74: ; preds = %98, %73
%75 = load i32, i32* %14
%76 = icmp ult i32 %75, 3
br i1 %76, label %77, label %101
77: ; preds = %74
br label %78
78: ; preds = %83, %77
%79 = load i8*, i8** %9
%80 = load i8, i8* %79
%81 = call i64 @isspace(i8 signext %80)
%82 = icmp ne i64 %81, 0
br i1 %82, label %83, label %86
83: ; preds = %78
%84 = load i8*, i8** %9
%85 = getelementptr inbounds i8, i8* %84, i32 1
store i8* %85, i8** %9
br label %78
86: ; preds = %78
%87 = load i8*, i8** %9
%88 = call double @strtod(i8* %87, i8** %11)
%89 = load i32, i32* %14
%90 = zext i32 %89 to i64
%91 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 %90
store double %88, double* %91
%92 = load i8*, i8** %9
%93 = load i8*, i8** %11
%94 = icmp eq i8* %92, %93
br i1 %94, label %95, label %96
95: ; preds = %86
br label %319
96: ; preds = %86
%97 = load i8*, i8** %11
store i8* %97, i8** %9
br label %98
98: ; preds = %96
%99 = load i32, i32* %14
%100 = add i32 %99, 1
store i32 %100, i32* %14
br label %74
101: ; preds = %74
%102 = load %struct.model*, %struct.model** %6
%103 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%104 = load double, double* %103
%105 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%106 = load double, double* %105
%107 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 2
%108 = load double, double* %107
%109 = call i64 @model_vertex_add(%struct.model* %102, double %104, double %106, double %108)
%110 = icmp slt i64 %109, 0
br i1 %110, label %111, label %115
111: ; preds = %101
%112 = load i8*, i8** %5
%113 = load i32, i32* %12
%114 = call i32 @warn(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.1, i64 0, i64 0), i8* %112, i32 %113)
br label %319
115: ; preds = %101
br label %309
116: ; preds = %69
%117 = load i8*, i8** %10
%118 = call i32 @strcmp(i8* %117, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0))
%119 = icmp ne i32 %118, 0
br i1 %119, label %156, label %120
120: ; preds = %116
store i32 0, i32* %14
br label %121
121: ; preds = %145, %120
%122 = load i32, i32* %14
%123 = icmp ult i32 %122, 2
br i1 %123, label %124, label %148
124: ; preds = %121
br label %125
125: ; preds = %130, %124
%126 = load i8*, i8** %9
%127 = load i8, i8* %126
%128 = call i64 @isspace(i8 signext %127)
%129 = icmp ne i64 %128, 0
br i1 %129, label %130, label %133
130: ; preds = %125
%131 = load i8*, i8** %9
%132 = getelementptr inbounds i8, i8* %131, i32 1
store i8* %132, i8** %9
br label %125
133: ; preds = %125
%134 = load i8*, i8** %9
%135 = call double @strtod(i8* %134, i8** %11)
%136 = load i32, i32* %14
%137 = zext i32 %136 to i64
%138 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 %137
store double %135, double* %138
%139 = load i8*, i8** %9
%140 = load i8*, i8** %11
%141 = icmp eq i8* %139, %140
br i1 %141, label %142, label %143
142: ; preds = %133
br label %319
143: ; preds = %133
%144 = load i8*, i8** %11
store i8* %144, i8** %9
br label %145
145: ; preds = %143
%146 = load i32, i32* %14
%147 = add i32 %146, 1
store i32 %147, i32* %14
br label %121
148: ; preds = %121
%149 = load i8*, i8** %5
%150 = load i32, i32* %12
%151 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%152 = load double, double* %151
%153 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%154 = load double, double* %153
%155 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.3, i64 0, i64 0), i8* %149, i32 %150, double %152, double %154)
br label %308
156: ; preds = %116
%157 = load i8*, i8** %10
%158 = call i32 @strcmp(i8* %157, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.4, i64 0, i64 0))
%159 = icmp ne i32 %158, 0
br i1 %159, label %198, label %160
160: ; preds = %156
store i32 0, i32* %14
br label %161
161: ; preds = %185, %160
%162 = load i32, i32* %14
%163 = icmp ult i32 %162, 3
br i1 %163, label %164, label %188
164: ; preds = %161
br label %165
165: ; preds = %170, %164
%166 = load i8*, i8** %9
%167 = load i8, i8* %166
%168 = call i64 @isspace(i8 signext %167)
%169 = icmp ne i64 %168, 0
br i1 %169, label %170, label %173
170: ; preds = %165
%171 = load i8*, i8** %9
%172 = getelementptr inbounds i8, i8* %171, i32 1
store i8* %172, i8** %9
br label %165
173: ; preds = %165
%174 = load i8*, i8** %9
%175 = call double @strtod(i8* %174, i8** %11)
%176 = load i32, i32* %14
%177 = zext i32 %176 to i64
%178 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 %177
store double %175, double* %178
%179 = load i8*, i8** %9
%180 = load i8*, i8** %11
%181 = icmp eq i8* %179, %180
br i1 %181, label %182, label %183
182: ; preds = %173
br label %319
183: ; preds = %173
%184 = load i8*, i8** %11
store i8* %184, i8** %9
br label %185
185: ; preds = %183
%186 = load i32, i32* %14
%187 = add i32 %186, 1
store i32 %187, i32* %14
br label %161
188: ; preds = %161
%189 = load i8*, i8** %5
%190 = load i32, i32* %12
%191 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%192 = load double, double* %191
%193 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%194 = load double, double* %193
%195 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 2
%196 = load double, double* %195
%197 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.5, i64 0, i64 0), i8* %189, i32 %190, double %192, double %194, double %196)
br label %307
198: ; preds = %156
%199 = load i8*, i8** %10
%200 = call i32 @strcmp(i8* %199, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.6, i64 0, i64 0))
%201 = icmp ne i32 %200, 0
br i1 %201, label %203, label %202
202: ; preds = %198
br label %306
203: ; preds = %198
%204 = load i8*, i8** %10
%205 = call i32 @strcmp(i8* %204, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.7, i64 0, i64 0))
%206 = icmp ne i32 %205, 0
br i1 %206, label %208, label %207
207: ; preds = %203
br label %305
208: ; preds = %203
%209 = load i8*, i8** %10
%210 = call i32 @strcmp(i8* %209, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.8, i64 0, i64 0))
%211 = icmp ne i32 %210, 0
br i1 %211, label %221, label %212
212: ; preds = %208
%213 = load i8*, i8** %5
%214 = load i32, i32* %12
%215 = load %struct.model*, %struct.model** %6
%216 = load i8*, i8** %9
%217 = call i32 @parse_face_data(i8* %213, i32 %214, %struct.model* %215, %struct.object** %7, i8* %216)
%218 = icmp ne i32 %217, 0
br i1 %218, label %220, label %219
219: ; preds = %212
br label %319
220: ; preds = %212
br label %304
221: ; preds = %208
%222 = load i8*, i8** %10
%223 = call i32 @strcmp(i8* %222, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.9, i64 0, i64 0))
%224 = icmp ne i32 %223, 0
br i1 %224, label %260, label %225
225: ; preds = %221
%226 = load i8*, i8** %9
store i8* %226, i8** %11
br label %227
227: ; preds = %244, %225
%228 = load i8*, i8** %9
%229 = load i8, i8* %228
%230 = sext i8 %229 to i32
%231 = icmp ne i32 %230, 0
br i1 %231, label %232, label %242
232: ; preds = %227
%233 = load i8*, i8** %9
%234 = load i8, i8* %233
%235 = sext i8 %234 to i32
%236 = icmp ne i32 %235, 13
br i1 %236, label %237, label %242
237: ; preds = %232
%238 = load i8*, i8** %9
%239 = load i8, i8* %238
%240 = sext i8 %239 to i32
%241 = icmp ne i32 %240, 10
br label %242
242: ; preds = %237, %232, %227
%243 = phi i1 [ false, %232 ], [ false, %227 ], [ %241, %237 ]
br i1 %243, label %244, label %247
244: ; preds = %242
%245 = load i8*, i8** %9
%246 = getelementptr inbounds i8, i8* %245, i32 1
store i8* %246, i8** %9
br label %227
247: ; preds = %242
%248 = load i8*, i8** %9
%249 = load i8, i8* %248
%250 = icmp ne i8 %249, 0
br i1 %250, label %251, label %253
251: ; preds = %247
%252 = load i8*, i8** %9
store i8 0, i8* %252
br label %253
253: ; preds = %251, %247
%254 = load %struct.model*, %struct.model** %6
%255 = load i8*, i8** %11
%256 = call %struct.object* @model_object_create(%struct.model* %254, i8* %255, i32 1)
store %struct.object* %256, %struct.object** %7
%257 = load %struct.object*, %struct.object** %7
%258 = bitcast %struct.object* %257 to i8*
%259 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.10, i64 0, i64 0), i8* %258)
br label %303
260: ; preds = %221
%261 = load i8*, i8** %10
%262 = call i32 @strcmp(i8* %261, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.11, i64 0, i64 0))
%263 = icmp ne i32 %262, 0
br i1 %263, label %297, label %264
264: ; preds = %260
%265 = load i8*, i8** %9
store i8* %265, i8** %11
br label %266
266: ; preds = %283, %264
%267 = load i8*, i8** %9
%268 = load i8, i8* %267
%269 = sext i8 %268 to i32
%270 = icmp ne i32 %269, 0
br i1 %270, label %271, label %281
271: ; preds = %266
%272 = load i8*, i8** %9
%273 = load i8, i8* %272
%274 = sext i8 %273 to i32
%275 = icmp ne i32 %274, 13
br i1 %275, label %276, label %281
276: ; preds = %271
%277 = load i8*, i8** %9
%278 = load i8, i8* %277
%279 = sext i8 %278 to i32
%280 = icmp ne i32 %279, 10
br label %281
281: ; preds = %276, %271, %266
%282 = phi i1 [ false, %271 ], [ false, %266 ], [ %280, %276 ]
br i1 %282, label %283, label %286
283: ; preds = %281
%284 = load i8*, i8** %9
%285 = getelementptr inbounds i8, i8* %284, i32 1
store i8* %285, i8** %9
br label %266
286: ; preds = %281
%287 = load i8*, i8** %9
%288 = load i8, i8* %287
%289 = icmp ne i8 %288, 0
br i1 %289, label %290, label %292
290: ; preds = %286
%291 = load i8*, i8** %9
store i8 0, i8* %291
br label %292
292: ; preds = %290, %286
%293 = load i8*, i8** %5
%294 = load i32, i32* %12
%295 = load i8*, i8** %11
%296 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.12, i64 0, i64 0), i8* %293, i32 %294, i8* %295)
br label %302
297: ; preds = %260
%298 = load i8*, i8** %5
%299 = load i32, i32* %12
%300 = load i8*, i8** %10
%301 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([49 x i8], [49 x i8]* @.str.13, i64 0, i64 0), i8* %298, i32 %299, i8* %300)
br label %302
302: ; preds = %297, %292
br label %303
303: ; preds = %302, %253
br label %304
304: ; preds = %303, %220
br label %305
305: ; preds = %304, %207
br label %306
306: ; preds = %305, %202
br label %307
307: ; preds = %306, %188
br label %308
308: ; preds = %307, %148
br label %309
309: ; preds = %308, %115
br label %16
310: ; preds = %16
%311 = load %struct.model*, %struct.model** %6
%312 = call i32 @model_verify(%struct.model* %311)
%313 = icmp ne i32 %312, 0
br i1 %313, label %317, label %314
314: ; preds = %310
%315 = load i8*, i8** %5
%316 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.14, i64 0, i64 0), i8* %315)
br label %319
317: ; preds = %310
%318 = load %struct.model*, %struct.model** %6
store %struct.model* %318, %struct.model** %3
br label %325
319: ; preds = %314, %219, %182, %142, %111, %95
%320 = load %struct.model*, %struct.model** %6
%321 = call i32 @model_free(%struct.model* %320)
%322 = load i8*, i8** %5
%323 = load i32, i32* %12
%324 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.15, i64 0, i64 0), i8* %322, i32 %323)
store %struct.model* null, %struct.model** %3
br label %325
325: ; preds = %319, %317
%326 = load %struct.model*, %struct.model** %3
ret %struct.model* %326
}

LLVM IR (-O2):
%struct.model = type { i32 }
%struct.object = type { i32 }
@.str = [2 x i8] c"v\00"
@.str.1 = [25 x i8] c"%s:%u:vertex data error\0A\00"
@.str.2 = [3 x i8] c"vt\00"
@.str.3 = [43 x i8] c"%s:%u:ignoring texture coord [U:%f, V:%f]\0A\00"
@.str.4 = [3 x i8] c"vn\00"
@.str.5 = [36 x i8] c"%s:%u:ignoring normal [%f, %f, %f]\0A\00"
@.str.6 = [2 x i8] c"p\00"
@.str.7 = [2 x i8] c"l\00"
@.str.8 = [2 x i8] c"f\00"
@.str.9 = [2 x i8] c"g\00"
@.str.10 = [13 x i8] c"curr_grp=%p\0A\00"
@.str.11 = [2 x i8] c"o\00"
@.str.12 = [33 x i8] c"%s:%u:ignoring object name '%s'\0A\00"
@.str.13 = [49 x i8] c"%s:%u:I don't know how to handle OBJ type '%s'!\0A\00"
@.str.14 = [30 x i8] c"%s:model verification failed\0A\00"
@.str.15 = [15 x i8] c"%s:%u:failed!\0A\00"
define %struct.model* @obj_load_from_file(i32* nocapture %0, i8* %1) {
%3 = alloca %struct.object*
%4 = alloca [1024 x i8]
%5 = alloca i8*
%6 = bitcast %struct.object** %3 to i8*
store %struct.object* null, %struct.object** %3
%7 = getelementptr inbounds [1024 x i8], [1024 x i8]* %4, i64 0, i64 0
%8 = bitcast i8** %5 to i8*
%9 = tail call %struct.model* (...) @model_create()
%10 = call i64 @fgets(i8* %7, i32 1024, i32* %0)
%11 = icmp eq i64 %10, 0
br i1 %11, label %183, label %12
12: ; preds = %2, %23
%13 = phi i32 [ %21, %23 ], [ 0, %2 ]
br label %14
14: ; preds = %14, %12
%15 = phi i8* [ %7, %12 ], [ %19, %14 ]
%16 = load i8, i8* %15
%17 = call i64 @isspace(i8 signext %16)
%18 = icmp eq i64 %17, 0
%19 = getelementptr inbounds i8, i8* %15, i64 1
br i1 %18, label %20, label %14
20: ; preds = %14
%21 = add i32 %13, 1
%22 = load i8, i8* %15
switch i8 %22, label %26 [
i8 35, label %23
i8 0, label %23
]
23: ; preds = %64, %127, %142, %162, %181, %178, %148, %139, %92, %20, %20
%24 = call i64 @fgets(i8* %7, i32 1024, i32* %0)
%25 = icmp eq i64 %24, 0
br i1 %25, label %183, label %12
26: ; preds = %20, %31
%27 = phi i8* [ %32, %31 ], [ %15, %20 ]
%28 = phi i8 [ %33, %31 ], [ %22, %20 ]
%29 = call i64 @isspace(i8 signext %28)
%30 = icmp eq i64 %29, 0
br i1 %30, label %31, label %35
31: ; preds = %26
%32 = getelementptr inbounds i8, i8* %27, i64 1
%33 = load i8, i8* %32
%34 = icmp eq i8 %33, 0
br i1 %34, label %40, label %26
35: ; preds = %26
%36 = load i8, i8* %27
%37 = icmp eq i8 %36, 0
br i1 %37, label %40, label %38
38: ; preds = %35
store i8 0, i8* %27
%39 = getelementptr inbounds i8, i8* %27, i64 1
br label %40
40: ; preds = %31, %38, %35
%41 = phi i8* [ %39, %38 ], [ %27, %35 ], [ %32, %31 ]
%42 = call i32 @strcmp(i8* %15, i8* dereferenceable(2) getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0))
%43 = icmp eq i32 %42, 0
br i1 %43, label %67, label %79
44: ; preds = %73, %44
%45 = phi i8* [ %49, %44 ], [ %75, %73 ]
%46 = load i8, i8* %45
%47 = call i64 @isspace(i8 signext %46)
%48 = icmp eq i64 %47, 0
%49 = getelementptr inbounds i8, i8* %45, i64 1
br i1 %48, label %50, label %44
50: ; preds = %44
%51 = call double @strtod(i8* %45, i8** %5)
%52 = load i8*, i8** %5
%53 = icmp eq i8* %45, %52
br i1 %53, label %189, label %54
54: ; preds = %50, %54
%55 = phi i8* [ %59, %54 ], [ %52, %50 ]
%56 = load i8, i8* %55
%57 = call i64 @isspace(i8 signext %56)
%58 = icmp eq i64 %57, 0
%59 = getelementptr inbounds i8, i8* %55, i64 1
br i1 %58, label %60, label %54
60: ; preds = %54
%61 = call double @strtod(i8* %55, i8** %5)
%62 = load i8*, i8** %5
%63 = icmp eq i8* %55, %62
br i1 %63, label %189, label %64
64: ; preds = %60
%65 = call i64 @model_vertex_add(%struct.model* %9, double %74, double %51, double %61)
%66 = icmp slt i64 %65, 0
br i1 %66, label %77, label %23
67: ; preds = %40, %67
%68 = phi i8* [ %72, %67 ], [ %41, %40 ]
%69 = load i8, i8* %68
%70 = call i64 @isspace(i8 signext %69)
%71 = icmp eq i64 %70, 0
%72 = getelementptr inbounds i8, i8* %68, i64 1
br i1 %71, label %73, label %67
73: ; preds = %67
%74 = call double @strtod(i8* %68, i8** %5)
%75 = load i8*, i8** %5
%76 = icmp eq i8* %68, %75
br i1 %76, label %189, label %44
77: ; preds = %64
%78 = call i32 @warn(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.1, i64 0, i64 0), i8* %1, i32 %21)
br label %189
79: ; preds = %40
%80 = call i32 @strcmp(i8* %15, i8* dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0))
%81 = icmp eq i32 %80, 0
br i1 %81, label %94, label %104
82: ; preds = %100, %82
%83 = phi i8* [ %87, %82 ], [ %102, %100 ]
%84 = load i8, i8* %83
%85 = call i64 @isspace(i8 signext %84)
%86 = icmp eq i64 %85, 0
%87 = getelementptr inbounds i8, i8* %83, i64 1
br i1 %86, label %88, label %82
88: ; preds = %82
%89 = call double @strtod(i8* %83, i8** %5)
%90 = load i8*, i8** %5
%91 = icmp eq i8* %83, %90
br i1 %91, label %189, label %92
92: ; preds = %88
%93 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.3, i64 0, i64 0), i8* %1, i32 %21, double %101, double %89)
br label %23
94: ; preds = %79, %94
%95 = phi i8* [ %99, %94 ], [ %41, %79 ]
%96 = load i8, i8* %95
%97 = call i64 @isspace(i8 signext %96)
%98 = icmp eq i64 %97, 0
%99 = getelementptr inbounds i8, i8* %95, i64 1
br i1 %98, label %100, label %94
100: ; preds = %94
%101 = call double @strtod(i8* %95, i8** %5)
%102 = load i8*, i8** %5
%103 = icmp eq i8* %95, %102
br i1 %103, label %189, label %82
104: ; preds = %79
%105 = call i32 @strcmp(i8* %15, i8* dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @.str.4, i64 0, i64 0))
%106 = icmp eq i32 %105, 0
br i1 %106, label %129, label %139
107: ; preds = %135, %107
%108 = phi i8* [ %112, %107 ], [ %137, %135 ]
%109 = load i8, i8* %108
%110 = call i64 @isspace(i8 signext %109)
%111 = icmp eq i64 %110, 0
%112 = getelementptr inbounds i8, i8* %108, i64 1
br i1 %111, label %113, label %107
113: ; preds = %107
%114 = call double @strtod(i8* %108, i8** %5)
%115 = load i8*, i8** %5
%116 = icmp eq i8* %108, %115
br i1 %116, label %189, label %117
117: ; preds = %113, %117
%118 = phi i8* [ %122, %117 ], [ %115, %113 ]
%119 = load i8, i8* %118
%120 = call i64 @isspace(i8 signext %119)
%121 = icmp eq i64 %120, 0
%122 = getelementptr inbounds i8, i8* %118, i64 1
br i1 %121, label %123, label %117
123: ; preds = %117
%124 = call double @strtod(i8* %118, i8** %5)
%125 = load i8*, i8** %5
%126 = icmp eq i8* %118, %125
br i1 %126, label %189, label %127
127: ; preds = %123
%128 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.5, i64 0, i64 0), i8* %1, i32 %21, double %136, double %114, double %124)
br label %23
129: ; preds = %104, %129
%130 = phi i8* [ %134, %129 ], [ %41, %104 ]
%131 = load i8, i8* %130
%132 = call i64 @isspace(i8 signext %131)
%133 = icmp eq i64 %132, 0
%134 = getelementptr inbounds i8, i8* %130, i64 1
br i1 %133, label %135, label %129
135: ; preds = %129
%136 = call double @strtod(i8* %130, i8** %5)
%137 = load i8*, i8** %5
%138 = icmp eq i8* %130, %137
br i1 %138, label %189, label %107
139: ; preds = %104
%140 = call i32 @strcmp(i8* %15, i8* dereferenceable(2) getelementptr inbounds ([2 x i8], [2 x i8]* @.str.6, i64 0, i64 0))
%141 = icmp eq i32 %140, 0
br i1 %141, label %23, label %142
142: ; preds = %139
%143 = call i32 @strcmp(i8* %15, i8* dereferenceable(2) getelementptr inbounds ([2 x i8], [2 x i8]* @.str.7, i64 0, i64 0))
%144 = icmp eq i32 %143, 0
br i1 %144, label %23, label %145
145: ; preds = %142
%146 = call i32 @strcmp(i8* %15, i8* dereferenceable(2) getelementptr inbounds ([2 x i8], [2 x i8]* @.str.8, i64 0, i64 0))
%147 = icmp eq i32 %146, 0
br i1 %147, label %148, label %151
148: ; preds = %145
%149 = call i32 @parse_face_data(i8* %1, i32 %21, %struct.model* %9, %struct.object** %3, i8* %41)
%150 = icmp eq i32 %149, 0
br i1 %150, label %189, label %23
151: ; preds = %145
%152 = call i32 @strcmp(i8* %15, i8* dereferenceable(2) getelementptr inbounds ([2 x i8], [2 x i8]* @.str.9, i64 0, i64 0))
%153 = icmp eq i32 %152, 0
br i1 %153, label %154, label %167
154: ; preds = %151
store i8* %41, i8** %5
br label %155
155: ; preds = %158, %154
%156 = phi i8* [ %41, %154 ], [ %159, %158 ]
%157 = load i8, i8* %156
switch i8 %157, label %158 [
i8 0, label %162
i8 10, label %160
i8 13, label %160
]
158: ; preds = %155
%159 = getelementptr inbounds i8, i8* %156, i64 1
br label %155
160: ; preds = %155, %155
store i8 0, i8* %156
%161 = load i8*, i8** %5
br label %162
162: ; preds = %155, %160
%163 = phi i8* [ %161, %160 ], [ %41, %155 ]
%164 = call %struct.object* @model_object_create(%struct.model* %9, i8* %163, i32 1)
store %struct.object* %164, %struct.object** %3
%165 = bitcast %struct.object* %164 to i8*
%166 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.10, i64 0, i64 0), i8* %165)
br label %23
167: ; preds = %151
%168 = call i32 @strcmp(i8* %15, i8* dereferenceable(2) getelementptr inbounds ([2 x i8], [2 x i8]* @.str.11, i64 0, i64 0))
%169 = icmp eq i32 %168, 0
br i1 %169, label %170, label %181
170: ; preds = %167
store i8* %41, i8** %5
br label %171
171: ; preds = %174, %170
%172 = phi i8* [ %41, %170 ], [ %175, %174 ]
%173 = load i8, i8* %172
switch i8 %173, label %174 [
i8 0, label %178
i8 10, label %176
i8 13, label %176
]
174: ; preds = %171
%175 = getelementptr inbounds i8, i8* %172, i64 1
br label %171
176: ; preds = %171, %171
store i8 0, i8* %172
%177 = load i8*, i8** %5
br label %178
178: ; preds = %171, %176
%179 = phi i8* [ %177, %176 ], [ %41, %171 ]
%180 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.12, i64 0, i64 0), i8* %1, i32 %21, i8* %179)
br label %23
181: ; preds = %167
%182 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([49 x i8], [49 x i8]* @.str.13, i64 0, i64 0), i8* %1, i32 %21, i8* %15)
br label %23
183: ; preds = %23, %2
%184 = phi i32 [ 0, %2 ], [ %21, %23 ]
%185 = call i32 @model_verify(%struct.model* %9)
%186 = icmp eq i32 %185, 0
br i1 %186, label %187, label %193
187: ; preds = %183
%188 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.14, i64 0, i64 0), i8* %1)
br label %189
189: ; preds = %148, %135, %113, %123, %100, %88, %73, %50, %60, %187, %77
%190 = phi i32 [ %21, %77 ], [ %184, %187 ], [ %21, %60 ], [ %21, %50 ], [ %21, %73 ], [ %21, %88 ], [ %21, %100 ], [ %21, %123 ], [ %21, %113 ], [ %21, %135 ], [ %21, %148 ]
%191 = call i32 @model_free(%struct.model* %9)
%192 = call i32 (i8*, i8*, ...) @debug(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.15, i64 0, i64 0), i8* %1, i32 %190)
br label %193
193: ; preds = %183, %189
%194 = phi %struct.model* [ null, %189 ], [ %9, %183 ]
ret %struct.model* %194
}