#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 */
typedef int /*<<< orphan*/ FILE;

/* Variables and functions */
int /*<<< orphan*/ fprintf(int /*<<< orphan*/ *, char *, int, int, int);
int /*<<< orphan*/ fputs(char *, int /*<<< orphan*/ *);
void print_code_header(FILE *fp) {
  fputs("#include <assert.h>\n"
        "#include <setjmp.h>\n"
        "#include <stdio.h>\n"
        "#include <stdlib.h>\n\n",
        fp);
  fputs("#ifndef __cplusplus\n"
        "#  if defined(_MSC_VER)\n"
        "#    define inline      __inline\n"
        "#    define __inline__  __inline\n"
        "#  elif !defined(__GNUC__) && (!defined(__STDC_VERSION__) || "
        "__STDC_VERSION__ < 199901L)\n"
        "#    define inline\n"
        "#    define __inline\n"
        "#  endif\n"
        "#endif\n\n",
        fp);
  fprintf(fp,
          "#define STACK_SIZE %d\n"
          "#define HEAP_SIZE %d\n"
          "#define CALL_STACK_SIZE %d\n\n"
          "#define LENGTHOF(array) (sizeof(array) / sizeof((array)[0]))\n"
          "#define SWAP(type, a, b) \\\n"
          "  "
          "do { \\\n"
          "  "
          "  "
          "type __tmp_swap_var__ = *(a); \\\n"
          "  "
          "  "
          "*(a) = *(b); \\\n"
          "  "
          "  "
          "*(b) = __tmp_swap_var__; \\\n"
          "  "
          "} while (0)\n\n",
          65536, 65536, 65536);
  fputs("inline static int  pop(void);\n"
        "inline static void push(int e);\n"
        "inline static void dup_n(size_t n);\n"
        "inline static void slide(size_t n);\n"
        "inline static void swap(void);\n",
        fp);
  fputs("inline static void arith_add(void);\n"
        "inline static void arith_sub(void);\n"
        "inline static void arith_mul(void);\n"
        "inline static void arith_div(void);\n"
        "inline static void arith_mod(void);\n",
        fp);
  fputs("inline static void heap_store(void);\n"
        "inline static void heap_read(void);\n\n",
        fp);
  fputs("static int stack[STACK_SIZE];\n"
        "static int heap[HEAP_SIZE];\n"
        "static jmp_buf call_stack[CALL_STACK_SIZE];\n"
        "static size_t stack_idx = 0;\n"
        "static size_t call_stack_idx = 0;\n\n\n",
        fp);
  fputs("int main(void)\n"
        "{\n",
        fp);
}


x86 assembly (clang, -O0):
<print_code_header>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rsi
lea    0xec9(%rip),%rdi
call   1030 <fputs@plt>
mov    -0x8(%rbp),%rsi
lea    0xf0a(%rip),%rdi
call   1030 <fputs@plt>
mov    -0x8(%rbp),%rdi
lea    0xffb(%rip),%rsi
mov    $0x10000,%r8d
mov    %r8d,%edx
mov    %r8d,%ecx
call   1040 <fprintf@plt>
mov    -0x8(%rbp),%rsi
lea    0x10ed(%rip),%rdi
call   1030 <fputs@plt>
mov    -0x8(%rbp),%rsi
lea    0x1183(%rip),%rdi
call   1030 <fputs@plt>
mov    -0x8(%rbp),%rsi
lea    0x1228(%rip),%rdi
call   1030 <fputs@plt>
mov    -0x8(%rbp),%rsi
lea    0x1263(%rip),%rdi
call   1030 <fputs@plt>
mov    -0x8(%rbp),%rsi
lea    0x12fb(%rip),%rdi
call   1030 <fputs@plt>
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<print_code_header>:
push   %rbx
mov    %rdi,%rbx
lea    0xed5(%rip),%rdi
mov    $0x50,%esi
mov    $0x1,%edx
mov    %rbx,%rcx
call   1040 <fwrite@plt>
lea    0xf0d(%rip),%rdi
mov    $0x100,%esi
mov    $0x1,%edx
mov    %rbx,%rcx
call   1040 <fwrite@plt>
lea    0xff5(%rip),%rsi
mov    %rbx,%rdi
mov    $0x10000,%edx
mov    $0x10000,%ecx
mov    $0x10000,%r8d
call   1030 <fprintf@plt>
lea    0x10e4(%rip),%rdi
mov    $0xa5,%esi
mov    $0x1,%edx
mov    %rbx,%rcx
call   1040 <fwrite@plt>
lea    0x1171(%rip),%rdi
mov    $0xb4,%esi
mov    $0x1,%edx
mov    %rbx,%rcx
call   1040 <fwrite@plt>
lea    0x120d(%rip),%rdi
mov    $0x4a,%esi
mov    $0x1,%edx
mov    %rbx,%rcx
call   1040 <fwrite@plt>
lea    0x123f(%rip),%rdi
mov    $0xa7,%esi
mov    $0x1,%edx
mov    %rbx,%rcx
call   1040 <fwrite@plt>
lea    0x12ce(%rip),%rdi
mov    $0x11,%esi
mov    $0x1,%edx
mov    %rbx,%rcx
pop    %rbx
jmp    1040 <fwrite@plt>

LLVM IR (-O0):
@.str = [81 x i8] c"#include <assert.h>\0A#include <setjmp.h>\0A#include <stdio.h>\0A#include <stdlib.h>\0A\0A\00"
@.str.1 = [257 x i8] c"#ifndef __cplusplus\0A# if defined(_MSC_VER)\0A# define inline __inline\0A# define __inline__ __inline\0A# elif !defined(__GNUC__) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)\0A# define inline\0A# define __inline\0A# endif\0A#endif\0A\0A\00"
@.str.2 = [270 x i8] c"#define STACK_SIZE %d\0A#define HEAP_SIZE %d\0A#define CALL_STACK_SIZE %d\0A\0A#define LENGTHOF(array) (sizeof(array) / sizeof((array)[0]))\0A#define SWAP(type, a, b) \\\0A do { \\\0A type __tmp_swap_var__ = *(a); \\\0A *(a) = *(b); \\\0A *(b) = __tmp_swap_var__; \\\0A } while (0)\0A\0A\00"
@.str.3 = [166 x i8] c"inline static int pop(void);\0Ainline static void push(int e);\0Ainline static void dup_n(size_t n);\0Ainline static void slide(size_t n);\0Ainline static void swap(void);\0A\00"
@.str.4 = [181 x i8] c"inline static void arith_add(void);\0Ainline static void arith_sub(void);\0Ainline static void arith_mul(void);\0Ainline static void arith_div(void);\0Ainline static void arith_mod(void);\0A\00"
@.str.5 = [75 x i8] c"inline static void heap_store(void);\0Ainline static void heap_read(void);\0A\0A\00"
@.str.6 = [168 x i8] c"static int stack[STACK_SIZE];\0Astatic int heap[HEAP_SIZE];\0Astatic jmp_buf call_stack[CALL_STACK_SIZE];\0Astatic size_t stack_idx = 0;\0Astatic size_t call_stack_idx = 0;\0A\0A\0A\00"
@.str.7 = [18 x i8] c"int main(void)\0A{\0A\00"
define void @print_code_header(i32* %0) {
%2 = alloca i32*
store i32* %0, i32** %2
%3 = load i32*, i32** %2
%4 = call i32 @fputs(i8* getelementptr inbounds ([81 x i8], [81 x i8]* @.str, i64 0, i64 0), i32* %3)
%5 = load i32*, i32** %2
%6 = call i32 @fputs(i8* getelementptr inbounds ([257 x i8], [257 x i8]* @.str.1, i64 0, i64 0), i32* %5)
%7 = load i32*, i32** %2
%8 = call i32 @fprintf(i32* %7, i8* getelementptr inbounds ([270 x i8], [270 x i8]* @.str.2, i64 0, i64 0), i32 65536, i32 65536, i32 65536)
%9 = load i32*, i32** %2
%10 = call i32 @fputs(i8* getelementptr inbounds ([166 x i8], [166 x i8]* @.str.3, i64 0, i64 0), i32* %9)
%11 = load i32*, i32** %2
%12 = call i32 @fputs(i8* getelementptr inbounds ([181 x i8], [181 x i8]* @.str.4, i64 0, i64 0), i32* %11)
%13 = load i32*, i32** %2
%14 = call i32 @fputs(i8* getelementptr inbounds ([75 x i8], [75 x i8]* @.str.5, i64 0, i64 0), i32* %13)
%15 = load i32*, i32** %2
%16 = call i32 @fputs(i8* getelementptr inbounds ([168 x i8], [168 x i8]* @.str.6, i64 0, i64 0), i32* %15)
%17 = load i32*, i32** %2
%18 = call i32 @fputs(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.7, i64 0, i64 0), i32* %17)
ret void
}

LLVM IR (-O2):
@.str = [81 x i8] c"#include <assert.h>\0A#include <setjmp.h>\0A#include <stdio.h>\0A#include <stdlib.h>\0A\0A\00"
@.str.1 = [257 x i8] c"#ifndef __cplusplus\0A# if defined(_MSC_VER)\0A# define inline __inline\0A# define __inline__ __inline\0A# elif !defined(__GNUC__) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)\0A# define inline\0A# define __inline\0A# endif\0A#endif\0A\0A\00"
@.str.2 = [270 x i8] c"#define STACK_SIZE %d\0A#define HEAP_SIZE %d\0A#define CALL_STACK_SIZE %d\0A\0A#define LENGTHOF(array) (sizeof(array) / sizeof((array)[0]))\0A#define SWAP(type, a, b) \\\0A do { \\\0A type __tmp_swap_var__ = *(a); \\\0A *(a) = *(b); \\\0A *(b) = __tmp_swap_var__; \\\0A } while (0)\0A\0A\00"
@.str.3 = [166 x i8] c"inline static int pop(void);\0Ainline static void push(int e);\0Ainline static void dup_n(size_t n);\0Ainline static void slide(size_t n);\0Ainline static void swap(void);\0A\00"
@.str.4 = [181 x i8] c"inline static void arith_add(void);\0Ainline static void arith_sub(void);\0Ainline static void arith_mul(void);\0Ainline static void arith_div(void);\0Ainline static void arith_mod(void);\0A\00"
@.str.5 = [75 x i8] c"inline static void heap_store(void);\0Ainline static void heap_read(void);\0A\0A\00"
@.str.6 = [168 x i8] c"static int stack[STACK_SIZE];\0Astatic int heap[HEAP_SIZE];\0Astatic jmp_buf call_stack[CALL_STACK_SIZE];\0Astatic size_t stack_idx = 0;\0Astatic size_t call_stack_idx = 0;\0A\0A\0A\00"
@.str.7 = [18 x i8] c"int main(void)\0A{\0A\00"
define void @print_code_header(i32* nocapture %0) {
%2 = tail call i64 @fwrite(i8* getelementptr inbounds ([81 x i8], [81 x i8]* @.str, i64 0, i64 0), i64 80, i64 1, i32* %0)
%3 = tail call i64 @fwrite(i8* getelementptr inbounds ([257 x i8], [257 x i8]* @.str.1, i64 0, i64 0), i64 256, i64 1, i32* %0)
%4 = tail call i32 @fprintf(i32* %0, i8* getelementptr inbounds ([270 x i8], [270 x i8]* @.str.2, i64 0, i64 0), i32 65536, i32 65536, i32 65536)
%5 = tail call i64 @fwrite(i8* getelementptr inbounds ([166 x i8], [166 x i8]* @.str.3, i64 0, i64 0), i64 165, i64 1, i32* %0)
%6 = tail call i64 @fwrite(i8* getelementptr inbounds ([181 x i8], [181 x i8]* @.str.4, i64 0, i64 0), i64 180, i64 1, i32* %0)
%7 = tail call i64 @fwrite(i8* getelementptr inbounds ([75 x i8], [75 x i8]* @.str.5, i64 0, i64 0), i64 74, i64 1, i32* %0)
%8 = tail call i64 @fwrite(i8* getelementptr inbounds ([168 x i8], [168 x i8]* @.str.6, i64 0, i64 0), i64 167, i64 1, i32* %0)
%9 = tail call i64 @fwrite(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.7, i64 0, i64 0), i64 17, i64 1, i32* %0)
ret void
}