+static void free_temp_files(void)
+{
+ if (temp_files == NULL)
+ return;
+
+ size_t n_temp_files = ARR_LEN(temp_files);
+ size_t i;
+ for (i = 0; i < n_temp_files; ++i) {
+ char *file = temp_files[i];
+ unlink(file);
+ }
+ DEL_ARR_F(temp_files);
+ temp_files = NULL;
+}
+
+typedef enum compile_mode_t {
+ BenchmarkParser,
+ PreprocessOnly,
+ ParseOnly,
+ Compile,
+ CompileDump,
+ CompileExportIR,
+ CompileAssemble,
+ CompileAssembleLink,
+ PrintAst,
+ PrintFluffy,
+ PrintJna,
+ PrintCompoundSizes,
+} compile_mode_t;
+
+static void usage(const char *argv0)
+{
+ fprintf(stderr, "Usage %s [options] input [-o output]\n", argv0);
+}
+
+static void print_cparser_version(void)
+{
+ printf("cparser (%s) using libFirm (%u.%u",
+ cparser_REVISION, ir_get_version_major(),
+ ir_get_version_minor());
+
+ const char *revision = ir_get_version_revision();
+ if (revision[0] != 0) {
+ putchar('-');
+ fputs(revision, stdout);
+ }
+
+ const char *build = ir_get_version_build();
+ if (build[0] != 0) {
+ putchar(' ');
+ fputs(build, stdout);
+ }
+ puts(")");
+ puts("This is free software; see the source for copying conditions. There is NO\n"
+ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+}
+
+static void print_cparser_version_short(void)
+{
+ puts(cparser_REVISION);
+}
+
+static void print_help_basic(const char *argv0)
+{
+ usage(argv0);
+ puts("");
+ put_help("--help", "Display this information");
+ put_help("--version", "Display compiler version");
+ put_help("--help-parser", "Display information about parser options");
+ put_help("--help-warnings", "Display information about warning options");
+ put_help("--help-codegen", "Display information about code-generation options");
+ put_help("--help-optimization", "Display information about optimization options");
+ put_help("--help-linker", "Display information about linker options");
+ put_help("--help-language-tools", "Display information about language tools options");
+ put_help("--help-debug", "Display information about compiler debugging options");
+ put_help("--help-firm", "Display information about direct firm options");
+ put_help("--help-all", "Display information about all options");
+ put_help("-c", "Compile and assemble but do not link");
+ put_help("-E", "Preprocess only");
+ put_help("-S", "Compile but do not assembler or link");
+ put_help("-o", "Specify output file");
+ put_help("-v", "Verbose output (show invocation of sub-processes)");
+ put_help("-x", "Force input language:");
+ put_choice("c", "C");
+ put_choice("c++", "C++");
+ put_choice("assembler", "Assembler (no preprocessing)");
+ put_choice("assembler-with-cpp", "Assembler with preprocessing");
+ put_choice("none", "Autodetection");
+ put_help("-pipe", "Ignored (gcc compatibility)");
+}
+
+static void print_help_preprocessor(void)
+{
+ put_help("-nostdinc", "Do not search standard system include directories");
+ put_help("-trigraphs", "Support ISO C trigraphs");
+ put_help("-isystem", "");
+ put_help("-include", "");
+ put_help("-I PATH", "");
+ put_help("-D SYMBOL[=value]", "");
+ put_help("-U SYMBOL", "");
+ put_help("-Wp,OPTION", "Pass option directly to preprocessor");
+ put_help("-M", "");
+ put_help("-MD", "");
+ put_help("-MMD", "");
+ put_help("-MM", "");
+ put_help("-MP", "");
+ put_help("-MT", "");
+ put_help("-MQ", "");
+ put_help("-MF", "");
+}
+
+static void print_help_parser(void)
+{
+ put_help("-finput-charset=CHARSET", "Select encoding of input files");
+ put_help("-fmessage-length=LEN", "Ignored (gcc compatibility)");
+ put_help("-fshort-wchar", "Type \"wchar_t\" is unsigned short instead of int");
+ put_help("-fshow-column", "Show the column number in diagnostic messages");
+ put_help("-fsigned-char", "Type \"char\" is a signed type");
+ put_help("-funsigned-char", "Type \"char\" is an unsigned type");
+ put_help("--ms", "Enable msvc extensions");
+ put_help("--no-ms", "Disable msvc extensions");
+ put_help("--gcc", "Enable gcc extensions");
+ put_help("--no-gcc", "Disable gcc extensions");
+ put_help("-std=STANDARD", "Specify language standard:");
+ put_choice("c99", "ISO C99 standard");
+ put_choice("c89", "ISO C89 standard");
+ put_choice("c90", "Same as -std=c89");
+ put_choice("c11", "ISO C11 standard");
+ put_choice("c9x", "Deprecated");
+ put_choice("c++", "ISO C++ 98");
+ put_choice("c++98", "ISO C++ 98");
+ put_choice("gnu99", "ISO C99 + GNU extensions (default)");
+ put_choice("gnu89", "ISO C89 + GNU extensions");
+ put_choice("gnu11", "ISO C11 + GNU extensions");
+ put_choice("gnu9x", "Deprecated");
+ put_choice("iso9899:1990", "ISO C89");
+ put_choice("iso9899:199409", "ISO C90");
+ put_choice("iso9899:1999", "ISO C99");
+ put_choice("iso9899:199x", "Deprecated");
+ put_help("-pedantic", "Ignored (gcc compatibility)");
+ put_help("-ansi", "-std=c90 (for C) or -std=c++98 (for C++)");
+ put_help("--strict", "Enable strict conformance checking");
+}
+
+static void print_help_warnings(void)
+{
+ put_help("-f[no-]diagnostics-show-option", "Show the switch, which controls a warning, after each warning");
+ put_help("-w", "Disable all warnings");
+ put_help("-Wno-trigraphs", "Warn if input contains trigraphs");
+ put_help("-Wundef", "Warn if an undefined macro is used in an #if");
+ put_help("-Wmissing-include-dirs", "Warn about missing user-specified include directories");
+ put_help("-Wendif-labels", "Warn about stray text after #elif and #endif");
+ put_help("-Winit-self", "Ignored (gcc compatibility)");
+ put_help("-Wformat-y2k", "Ignored (gcc compatibility)");
+ put_help("-Wformat-security", "Ignored (gcc compatibility)");
+ put_help("-Wold-style-declaration", "Ignored (gcc compatibility)");
+ put_help("-Wtype-limits", "Ignored (gcc compatibility)");
+ print_warning_opt_help();
+}
+
+static void print_help_optimization(void)
+{
+ put_help("-O LEVEL", "Select optimization level (0-4)");
+ firm_option_help(put_help);
+ put_help("-fexpensive-optimizations","Ignored (gcc compatibility)");
+}
+
+static void print_help_codegeneration(void)
+{
+ put_help("-g", "Generate debug information");
+ put_help("-pg", "Instrument code for gnu gprof");
+ put_help("-fomit-frame-pointer", "Produce code without frame pointer where possible");
+ put_help("-ffreestanding", "Compile in freestanding mode (see ISO C standard)");
+ put_help("-fhosted", "Compile in hosted (not freestanding) mode");
+ put_help("-fprofile-generate", "Generate instrumented code to collect profile information");
+ put_help("-fprofile-use", "Use profile information generated by instrumented binaries");
+ put_help("-ffp-precise", "Precise floating point model");
+ put_help("-ffp-fast", "Imprecise floating point model");
+ put_help("-ffp-strict", "Strict floating point model");
+ put_help("-pthread", "Use pthread threading library");
+ put_help("-mtarget=TARGET", "Specify target architecture as CPU-manufacturer-OS triple");
+ put_help("-mtriple=TARGET", "Alias for -mtarget (clang compatibility)");
+ put_help("-march=ARCH", "");
+ put_help("-mtune=ARCH", "");
+ put_help("-mcpu=CPU", "");
+ put_help("-mfpmath=", "");
+ put_help("-mpreferred-stack-boundary=", "");
+ put_help("-mrtd", "");
+ put_help("-mregparm=", "Not supported yet");
+ put_help("-msoft-float", "Not supported yet");
+ put_help("-m32", "Generate 32bit code");
+ put_help("-m64", "Generate 64bit code");
+ put_help("-fverbose-asm", "Ignored (gcc compatibility)");
+ put_help("-fjump-tables", "Ignored (gcc compatibility)");
+ put_help("-fcommon", "Ignored (gcc compatibility)");
+ put_help("-foptimize-sibling-calls", "Ignored (gcc compatibility)");
+ put_help("-falign-loops", "Ignored (gcc compatibility)");
+ put_help("-falign-jumps", "Ignored (gcc compatibility)");
+ put_help("-falign-functions", "Ignored (gcc compatibility)");
+ put_help("-fPIC", "Ignored (gcc compatibility)");
+ put_help("-ffast-math", "Same as -ffp-fast (gcc compatibility)");
+ puts("");
+ puts("\tMost of these options can be used with a no- prefix to disable them");
+ puts("\te.g. -fno-omit-frame-pointer");
+}
+
+static void print_help_linker(void)
+{
+ put_help("-l LIBRARY", "");
+ put_help("-L PATH", "");
+ put_help("-s", "Do not produce symbol table and relocation information");
+ put_help("-shared", "Produce a shared library");
+ put_help("-static", "Produce statically linked binary");
+ put_help("-Wl,OPTION", "Pass option directly to linker");
+}
+
+static void print_help_debug(void)
+{
+ put_help("--print-ast", "Preprocess, parse and print AST");
+ put_help("--print-implicit-cast", "");
+ put_help("--print-parenthesis", "");
+ put_help("--benchmark", "Preprocess and parse, produces no output");
+ put_help("--time", "Measure time of compiler passes");
+ put_help("--statev", "Produce statev output");
+ put_help("--filtev=filter", "Set statev filter regex");
+ put_help("--dump-function func", "Preprocess, parse and output vcg graph of func");
+ put_help("--export-ir", "Preprocess, parse and output compiler intermediate representation");
+}
+
+static void print_help_language_tools(void)
+{
+ put_help("--print-fluffy", "Preprocess, parse and generate declarations for the fluffy language");
+ put_help("--print-jna", "Preprocess, parse and generate declarations for JNA");
+ put_help("--jna-limit filename", "");
+ put_help("--jna-libname name", "");
+}
+
+static void print_help_firm(void)
+{
+ put_help("-bOPTION", "Directly pass option to libFirm backend");
+ int res = be_parse_arg("help");
+ (void) res;
+ assert(res);
+}
+
+typedef enum {
+ HELP_NONE = 0,
+ HELP_BASIC = 1 << 0,
+ HELP_PREPROCESSOR = 1 << 1,
+ HELP_PARSER = 1 << 2,
+ HELP_WARNINGS = 1 << 3,
+ HELP_OPTIMIZATION = 1 << 4,
+ HELP_CODEGEN = 1 << 5,
+ HELP_LINKER = 1 << 6,
+ HELP_LANGUAGETOOLS = 1 << 7,
+ HELP_DEBUG = 1 << 8,
+ HELP_FIRM = 1 << 9,
+
+ HELP_ALL = -1
+} help_sections_t;
+
+static void print_help(const char *argv0, help_sections_t sections)
+{
+ if (sections & HELP_BASIC) print_help_basic(argv0);
+ if (sections & HELP_PREPROCESSOR) print_help_preprocessor();
+ if (sections & HELP_PARSER) print_help_parser();
+ if (sections & HELP_WARNINGS) print_help_warnings();
+ if (sections & HELP_OPTIMIZATION) print_help_optimization();
+ if (sections & HELP_CODEGEN) print_help_codegeneration();
+ if (sections & HELP_LINKER) print_help_linker();
+ if (sections & HELP_LANGUAGETOOLS) print_help_language_tools();
+ if (sections & HELP_DEBUG) print_help_debug();
+ if (sections & HELP_FIRM) print_help_firm();
+}
+
+static void set_be_option(const char *arg)
+{
+ int res = be_parse_arg(arg);
+ (void) res;
+ assert(res);
+}
+
+static compilation_unit_type_t get_unit_type_from_string(const char *string)
+{
+ if (streq(string, "c") || streq(string, "c-header"))
+ return COMPILATION_UNIT_C;
+ if (streq(string, "c++") || streq(string, "c++-header"))
+ return COMPILATION_UNIT_CXX;
+ if (streq(string, "assembler"))
+ return COMPILATION_UNIT_PREPROCESSED_ASSEMBLER;
+ if (streq(string, "assembler-with-cpp"))
+ return COMPILATION_UNIT_ASSEMBLER;
+ if (streq(string, "none"))
+ return COMPILATION_UNIT_AUTODETECT;
+
+ return COMPILATION_UNIT_UNKNOWN;
+}
+
+static bool init_os_support(void)
+{
+ wchar_atomic_kind = ATOMIC_TYPE_INT;
+ enable_main_collect2_hack = false;
+ define_intmax_types = false;
+
+ if (firm_is_unixish_os(target_machine)) {
+ set_create_ld_ident(create_name_linux_elf);
+ } else if (firm_is_darwin_os(target_machine)) {
+ set_create_ld_ident(create_name_macho);
+ define_intmax_types = true;
+ } else if (firm_is_windows_os(target_machine)) {
+ wchar_atomic_kind = ATOMIC_TYPE_USHORT;
+ enable_main_collect2_hack = true;
+ set_create_ld_ident(create_name_win32);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+static bool parse_target_triple(const char *arg)
+{
+ machine_triple_t *triple = firm_parse_machine_triple(arg);
+ if (triple == NULL) {
+ fprintf(stderr, "Target-triple is not in the form 'cpu_type-manufacturer-operating_system'\n");
+ return false;
+ }
+ target_machine = triple;
+ return true;
+}
+
+static unsigned decide_modulo_shift(unsigned type_size)
+{
+ if (architecture_modulo_shift == 0)
+ return 0;
+ if (type_size < architecture_modulo_shift)
+ return architecture_modulo_shift;
+ return type_size;
+}
+
+static bool is_ia32_cpu(const char *architecture)
+{
+ return streq(architecture, "i386")
+ || streq(architecture, "i486")
+ || streq(architecture, "i586")
+ || streq(architecture, "i686")
+ || streq(architecture, "i786");
+}
+
+static const char *setup_isa_from_tripel(const machine_triple_t *machine)
+{
+ const char *cpu = machine->cpu_type;
+
+ if (is_ia32_cpu(cpu)) {
+ return "ia32";
+ } else if (streq(cpu, "x86_64")) {
+ return "amd64";
+ } else if (streq(cpu, "sparc")) {
+ return "sparc";
+ } else if (streq(cpu, "arm")) {
+ return "arm";
+ } else {
+ fprintf(stderr, "Unknown cpu '%s' in target-triple\n", cpu);
+ return NULL;
+ }
+}
+
+static const char *setup_target_machine(void)
+{
+ if (!setup_firm_for_machine(target_machine))
+ exit(1);
+
+ const char *isa = setup_isa_from_tripel(target_machine);
+
+ if (isa == NULL)
+ exit(1);
+
+ init_os_support();
+
+ return isa;
+}
+