654 lines
26 KiB
C++
654 lines
26 KiB
C++
/*
|
|
Copyright (c) 2010-2016, Intel Corporation
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of Intel Corporation nor the names of its
|
|
contributors may be used to endorse or promote products derived from
|
|
this software without specific prior written permission.
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/** @file main.cpp
|
|
@brief main() entrypoint implementation for ispc
|
|
*/
|
|
|
|
#include "ispc.h"
|
|
#include "module.h"
|
|
#include "util.h"
|
|
#include "type.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#ifdef ISPC_IS_WINDOWS
|
|
#include <time.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif // ISPC_IS_WINDOWS
|
|
#include <llvm/Support/Signals.h>
|
|
#include <llvm/Support/TargetRegistry.h>
|
|
#include <llvm/Support/TargetSelect.h>
|
|
|
|
#ifdef ISPC_IS_WINDOWS
|
|
#define strcasecmp stricmp
|
|
#ifndef BUILD_DATE
|
|
#define BUILD_DATE __DATE__
|
|
#endif
|
|
#define BUILD_VERSION ""
|
|
#if _MSC_VER >= 1900
|
|
#define ISPC_VS_VERSION "Visual Studio 2015 and later"
|
|
#else
|
|
#define ISPC_VS_VERSION "Visual Studio 2013 and earlier"
|
|
#endif
|
|
#endif // ISPC_IS_WINDOWS
|
|
|
|
static void
|
|
lPrintVersion() {
|
|
#ifdef ISPC_IS_WINDOWS
|
|
printf("Intel(r) SPMD Program Compiler (ispc), %s (build date %s, LLVM %s)\n"
|
|
"Supported Visual Studio versions: %s.\n",
|
|
ISPC_VERSION, BUILD_DATE,
|
|
ISPC_LLVM_VERSION_STRING,
|
|
ISPC_VS_VERSION
|
|
);
|
|
#else
|
|
printf("Intel(r) SPMD Program Compiler (ispc), %s (build %s @ %s, LLVM %s)\n",
|
|
ISPC_VERSION, BUILD_VERSION, BUILD_DATE,
|
|
ISPC_LLVM_VERSION_STRING
|
|
);
|
|
#endif
|
|
}
|
|
|
|
|
|
static void
|
|
usage(int ret) {
|
|
lPrintVersion();
|
|
printf("\nusage: ispc\n");
|
|
printf(" [--addressing={32,64}]\t\tSelect 32- or 64-bit addressing. (Note that 32-bit\n");
|
|
printf(" \t\taddressing calculations are done by default, even\n");
|
|
printf(" \t\ton 64-bit target architectures.)\n");
|
|
printf(" [--arch={%s}]\t\tSelect target architecture\n",
|
|
Target::SupportedArchs());
|
|
printf(" [--c++-include-file=<name>]\t\tSpecify name of file to emit in #include statement in generated C++ code.\n");
|
|
#ifndef ISPC_IS_WINDOWS
|
|
printf(" [--colored-output]\t\tAlways use terminal colors in error/warning messages.\n");
|
|
#endif
|
|
printf(" ");
|
|
char cpuHelp[2048];
|
|
sprintf(cpuHelp, "[--cpu=<cpu>]\t\t\tSelect target CPU type\n<cpu>={%s}\n",
|
|
Target::SupportedCPUs().c_str());
|
|
PrintWithWordBreaks(cpuHelp, 16, TerminalWidth(), stdout);
|
|
printf(" [-D<foo>]\t\t\t\t#define given value when running preprocessor\n");
|
|
printf(" [--dev-stub <filename>]\t\tEmit device-side offload stub functions to file\n");
|
|
#ifdef ISPC_IS_WINDOWS
|
|
printf(" [--dllexport]\t\t\tMake non-static functions DLL exported. Windows only.\n");
|
|
#endif
|
|
#if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5
|
|
printf(" [--dwarf-version={2,3,4}]\t\tGenerate source-level debug information with given DWARF version (triggers -g)\n");
|
|
#endif
|
|
printf(" [--emit-asm]\t\t\tGenerate assembly language file as output\n");
|
|
printf(" [--emit-c++]\t\t\tEmit a C++ source file as output\n");
|
|
printf(" [--emit-llvm]\t\t\tEmit LLVM bitode file as output\n");
|
|
printf(" [--emit-obj]\t\t\tGenerate object file file as output (default)\n");
|
|
printf(" [--force-alignment=<value>]\t\tForce alignment in memory allocations routine to be <value>\n");
|
|
printf(" [-g]\t\t\t\tGenerate source-level debug information\n");
|
|
printf(" [--help]\t\t\t\tPrint help\n");
|
|
printf(" [--help-dev]\t\t\tPrint help for developer options\n");
|
|
printf(" [--host-stub <filename>]\t\tEmit host-side offload stub functions to file\n");
|
|
printf(" [-h <name>/--header-outfile=<name>]\tOutput filename for header\n");
|
|
printf(" [-I <path>]\t\t\t\tAdd <path> to #include file search path\n");
|
|
printf(" [--instrument]\t\t\tEmit instrumentation to gather performance data\n");
|
|
printf(" [--math-lib=<option>]\t\tSelect math library\n");
|
|
printf(" default\t\t\t\tUse ispc's built-in math functions\n");
|
|
printf(" fast\t\t\t\tUse high-performance but lower-accuracy math functions\n");
|
|
printf(" svml\t\t\t\tUse the Intel(r) SVML math libraries\n");
|
|
printf(" system\t\t\t\tUse the system's math library (*may be quite slow*)\n");
|
|
printf(" [-MMM <filename>\t\t\tWrite #include dependencies to given file.\n");
|
|
printf(" [--no-omit-frame-pointer]\t\tDisable frame pointer omission. It may be useful for profiling\n");
|
|
printf(" [--nostdlib]\t\t\tDon't make the ispc standard library available\n");
|
|
printf(" [--nocpp]\t\t\t\tDon't run the C preprocessor\n");
|
|
printf(" [-o <name>/--outfile=<name>]\tOutput filename (may be \"-\" for standard output)\n");
|
|
printf(" [-O0/-O(1/2/3)]\t\t\tSet optimization level (off or on). Optimizations are on by default.\n");
|
|
printf(" [--opt=<option>]\t\t\tSet optimization option\n");
|
|
printf(" disable-assertions\t\tRemove assertion statements from final code.\n");
|
|
printf(" disable-fma\t\t\tDisable 'fused multiply-add' instructions (on targets that support them)\n");
|
|
printf(" disable-loop-unroll\t\tDisable loop unrolling.\n");
|
|
printf(" fast-masked-vload\t\tFaster masked vector loads on SSE (may go past end of array)\n");
|
|
printf(" fast-math\t\t\tPerform non-IEEE-compliant optimizations of numeric expressions\n");
|
|
printf(" force-aligned-memory\t\tAlways issue \"aligned\" vector load and store instructions\n");
|
|
#ifndef ISPC_IS_WINDOWS
|
|
printf(" [--pic]\t\t\t\tGenerate position-independent code\n");
|
|
#endif // !ISPC_IS_WINDOWS
|
|
printf(" [--quiet]\t\t\t\tSuppress all output\n");
|
|
printf(" ");
|
|
char targetHelp[2048];
|
|
sprintf(targetHelp, "[--target=<t>]\t\t\tSelect target ISA and width.\n"
|
|
"<t>={%s}", Target::SupportedTargets());
|
|
PrintWithWordBreaks(targetHelp, 24, TerminalWidth(), stdout);
|
|
printf(" [--version]\t\t\t\tPrint ispc version\n");
|
|
printf(" [--werror]\t\t\t\tTreat warnings as errors\n");
|
|
printf(" [--woff]\t\t\t\tDisable warnings\n");
|
|
printf(" [--wno-perf]\t\t\tDon't issue warnings related to performance-related issues\n");
|
|
printf(" <file to compile or \"-\" for stdin>\n");
|
|
exit(ret);
|
|
}
|
|
|
|
|
|
static void
|
|
devUsage(int ret) {
|
|
lPrintVersion();
|
|
printf("\nusage (developer options): ispc\n");
|
|
printf(" [--debug]\t\t\t\tPrint information useful for debugging ispc\n");
|
|
printf(" [--print-target]\t\t\tPrint target's information\n");
|
|
printf(" [--fuzz-test]\t\t\tRandomly perturb program input to test error conditions\n");
|
|
printf(" [--fuzz-seed=<value>]\t\tSeed value for RNG for fuzz testing\n");
|
|
printf(" [--opt=<option>]\t\t\tSet optimization option\n");
|
|
printf(" disable-all-on-optimizations\t\tDisable optimizations that take advantage of \"all on\" mask\n");
|
|
printf(" disable-blended-masked-stores\t\tScalarize masked stores on SSE (vs. using vblendps)\n");
|
|
printf(" disable-blending-removal\t\tDisable eliminating blend at same scope\n");
|
|
printf(" disable-coalescing\t\t\tDisable gather coalescing\n");
|
|
printf(" disable-coherent-control-flow\t\tDisable coherent control flow optimizations\n");
|
|
printf(" disable-gather-scatter-flattening\tDisable flattening when all lanes are on\n");
|
|
printf(" disable-gather-scatter-optimizations\tDisable improvements to gather/scatter\n");
|
|
printf(" disable-handle-pseudo-memory-ops\tLeave __pseudo_* calls for gather/scatter/etc. in final IR\n");
|
|
printf(" disable-uniform-control-flow\t\tDisable uniform control flow optimizations\n");
|
|
printf(" disable-uniform-memory-optimizations\tDisable uniform-based coherent memory access\n");
|
|
printf(" [--yydebug]\t\t\t\tPrint debugging information during parsing\n");
|
|
printf(" [--debug-phase=<value>]\t\tSet optimization phases to dump. --debug-phase=first,210:220,300,305,310:last\n");
|
|
#if ISPC_LLVM_VERSION == ISPC_LLVM_3_4 || ISPC_LLVM_VERSION == ISPC_LLVM_3_5 // 3.4, 3.5
|
|
printf(" [--debug-ir=<value>]\t\tSet optimization phase to generate debugIR after it\n");
|
|
#endif
|
|
printf(" [--off-phase=<value>]\t\tSwitch off optimization phases. --off-phase=first,210:220,300,305,310:last\n");
|
|
exit(ret);
|
|
}
|
|
|
|
|
|
/** We take arguments from both the command line as well as from the
|
|
ISPC_ARGS environment variable. This function returns a new set of
|
|
arguments representing the ones from those two sources merged together.
|
|
*/
|
|
static void lGetAllArgs(int Argc, char *Argv[], int &argc, char *argv[128]) {
|
|
// Copy over the command line arguments (passed in)
|
|
for (int i = 0; i < Argc; ++i)
|
|
argv[i] = Argv[i];
|
|
argc = Argc;
|
|
|
|
// See if we have any set via the environment variable
|
|
const char *env = getenv("ISPC_ARGS");
|
|
if (!env)
|
|
return;
|
|
while (true) {
|
|
// Look for the next space in the string, which delimits the end of
|
|
// the current argument
|
|
const char *end = strchr(env, ' ');
|
|
if (end == NULL)
|
|
end = env + strlen(env);
|
|
int len = end - env;
|
|
|
|
// Copy the argument into a newly allocated memory (so we can
|
|
// NUL-terminate it).
|
|
char *ptr = new char[len+1];
|
|
strncpy(ptr, env, len);
|
|
ptr[len] = '\0';
|
|
|
|
// Add it to the args array and get out of here
|
|
argv[argc++] = ptr;
|
|
if (*end == '\0')
|
|
break;
|
|
|
|
// Advance the starting pointer of the string to the next non-space
|
|
// character
|
|
env = end+1;
|
|
while (*env == ' ')
|
|
++env;
|
|
|
|
// Hit the end of the string; get out of here
|
|
if (*env == '\0')
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
lSignal(void *) {
|
|
FATAL("Unhandled signal sent to process; terminating.");
|
|
}
|
|
|
|
|
|
static int ParsingPhaseName(char * stage) {
|
|
if (strncmp(stage, "first", 5) == 0) {
|
|
return 0;
|
|
}
|
|
else if (strncmp(stage, "last", 4) == 0) {
|
|
return LAST_OPT_NUMBER;
|
|
}
|
|
else {
|
|
int t = atoi(stage);
|
|
if (t < 0 || t > LAST_OPT_NUMBER) {
|
|
fprintf(stderr, "Phases must be from 0 to %d. %s is incorrect.\n", LAST_OPT_NUMBER, stage);
|
|
exit(0);
|
|
}
|
|
else {
|
|
return t;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static std::set<int> ParsingPhases(char * stages) {
|
|
std::set<int> phases;
|
|
int begin = ParsingPhaseName(stages);
|
|
int end = begin;
|
|
|
|
for (unsigned i = 0; i < strlen(stages); i++) {
|
|
if ((stages[i] == ',') || (i == strlen(stages) - 1)) {
|
|
for (int j = begin; j < end + 1; j++) {
|
|
phases.insert(j);
|
|
}
|
|
begin = ParsingPhaseName(stages + i + 1);
|
|
end = begin;
|
|
}
|
|
else if (stages[i] == ':') {
|
|
end = ParsingPhaseName(stages + i + 1);
|
|
}
|
|
}
|
|
return phases;
|
|
}
|
|
|
|
|
|
static void
|
|
lParseInclude(const char *path) {
|
|
#ifdef ISPC_IS_WINDOWS
|
|
char delim = ';';
|
|
#else
|
|
char delim = ':';
|
|
#endif
|
|
size_t pos = 0, pos_end;
|
|
std::string str_path(path);
|
|
do {
|
|
pos_end = str_path.find(delim, pos);
|
|
size_t len = (pos_end == std::string::npos) ?
|
|
// Not found, copy till end of the string.
|
|
std::string::npos :
|
|
// Copy [pos, pos_end).
|
|
(pos_end - pos);
|
|
std::string s = str_path.substr(pos, len);
|
|
g->includePath.push_back(s);
|
|
pos = pos_end+1;
|
|
} while (pos_end != std::string::npos);
|
|
}
|
|
|
|
|
|
int main(int Argc, char *Argv[]) {
|
|
int argc;
|
|
char *argv[128];
|
|
lGetAllArgs(Argc, Argv, argc, argv);
|
|
|
|
llvm::sys::AddSignalHandler(lSignal, NULL);
|
|
|
|
// initialize available LLVM targets
|
|
#ifndef __arm__
|
|
// FIXME: LLVM build on ARM doesn't build the x86 targets by default.
|
|
// It's not clear that anyone's going to want to generate x86 from an
|
|
// ARM host, though...
|
|
LLVMInitializeX86TargetInfo();
|
|
LLVMInitializeX86Target();
|
|
LLVMInitializeX86AsmPrinter();
|
|
LLVMInitializeX86AsmParser();
|
|
LLVMInitializeX86Disassembler();
|
|
LLVMInitializeX86TargetMC();
|
|
#endif // !__ARM__
|
|
|
|
#ifdef ISPC_ARM_ENABLED
|
|
// Generating ARM from x86 is more likely to be useful, though.
|
|
LLVMInitializeARMTargetInfo();
|
|
LLVMInitializeARMTarget();
|
|
LLVMInitializeARMAsmPrinter();
|
|
LLVMInitializeARMAsmParser();
|
|
LLVMInitializeARMDisassembler();
|
|
LLVMInitializeARMTargetMC();
|
|
#endif
|
|
|
|
#ifdef ISPC_NVPTX_ENABLED
|
|
LLVMInitializeNVPTXTargetInfo();
|
|
LLVMInitializeNVPTXTarget();
|
|
LLVMInitializeNVPTXAsmPrinter();
|
|
LLVMInitializeNVPTXTargetMC();
|
|
#endif /* ISPC_NVPTX_ENABLED */
|
|
|
|
char *file = NULL;
|
|
const char *headerFileName = NULL;
|
|
const char *outFileName = NULL;
|
|
const char *includeFileName = NULL;
|
|
const char *depsFileName = NULL;
|
|
const char *hostStubFileName = NULL;
|
|
const char *devStubFileName = NULL;
|
|
// Initiailize globals early so that we can set various option values
|
|
// as we're parsing below
|
|
g = new Globals;
|
|
|
|
Module::OutputType ot = Module::Object;
|
|
bool generatePIC = false;
|
|
const char *arch = NULL, *cpu = NULL, *target = NULL;
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
if (!strcmp(argv[i], "--help"))
|
|
usage(0);
|
|
if (!strcmp(argv[i], "--help-dev"))
|
|
devUsage(0);
|
|
else if (!strncmp(argv[i], "-D", 2))
|
|
g->cppArgs.push_back(argv[i]);
|
|
else if (!strncmp(argv[i], "--addressing=", 13)) {
|
|
if (atoi(argv[i] + 13) == 64)
|
|
// FIXME: this doesn't make sense on 32 bit platform.
|
|
g->opt.force32BitAddressing = false;
|
|
else if (atoi(argv[i] + 13) == 32)
|
|
g->opt.force32BitAddressing = true;
|
|
else {
|
|
fprintf(stderr, "Addressing width \"%s\" invalid--only 32 and "
|
|
"64 are allowed.\n", argv[i]+13);
|
|
usage(1);
|
|
}
|
|
}
|
|
else if (!strncmp(argv[i], "--arch=", 7))
|
|
arch = argv[i] + 7;
|
|
else if (!strncmp(argv[i], "--cpu=", 6))
|
|
cpu = argv[i] + 6;
|
|
else if (!strcmp(argv[i], "--fast-math")) {
|
|
fprintf(stderr, "--fast-math option has been renamed to --opt=fast-math!\n");
|
|
usage(1);
|
|
}
|
|
else if (!strcmp(argv[i], "--fast-masked-vload")) {
|
|
fprintf(stderr, "--fast-masked-vload option has been renamed to "
|
|
"--opt=fast-masked-vload!\n");
|
|
usage(1);
|
|
}
|
|
else if (!strcmp(argv[i], "--debug"))
|
|
g->debugPrint = true;
|
|
#ifdef ISPC_IS_WINDOWS
|
|
else if (!strcmp(argv[i], "--dllexport"))
|
|
g->dllExport = true;
|
|
#endif
|
|
#if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5
|
|
else if (!strncmp(argv[i], "--dwarf-version=", 16)) {
|
|
int val = atoi(argv[i] + 16);
|
|
if (2 <= val && val <=4) {
|
|
g->generateDebuggingSymbols = true;
|
|
g->generateDWARFVersion=val;
|
|
} else {
|
|
fprintf(stderr, "Invalid value for DWARF version: \"%s\" -- "
|
|
"only 2, 3 and 4 are allowed.\n", argv[i]+16);
|
|
usage(1);
|
|
}
|
|
}
|
|
#endif
|
|
else if (!strcmp(argv[i], "--print-target"))
|
|
g->printTarget = true;
|
|
else if (!strcmp(argv[i], "--no-omit-frame-pointer"))
|
|
g->NoOmitFramePointer = true;
|
|
else if (!strcmp(argv[i], "--instrument"))
|
|
g->emitInstrumentation = true;
|
|
else if (!strcmp(argv[i], "-g")) {
|
|
g->generateDebuggingSymbols = true;
|
|
}
|
|
else if (!strcmp(argv[i], "--emit-asm"))
|
|
ot = Module::Asm;
|
|
else if (!strcmp(argv[i], "--emit-c++"))
|
|
ot = Module::CXX;
|
|
else if (!strcmp(argv[i], "--emit-llvm"))
|
|
ot = Module::Bitcode;
|
|
else if (!strcmp(argv[i], "--emit-obj"))
|
|
ot = Module::Object;
|
|
else if (!strcmp(argv[i], "-I")) {
|
|
if (++i == argc) {
|
|
fprintf(stderr, "No path specified after -I option.\n");
|
|
usage(1);
|
|
}
|
|
lParseInclude(argv[i]);
|
|
}
|
|
else if (!strncmp(argv[i], "-I", 2))
|
|
lParseInclude(argv[i]+2);
|
|
else if (!strcmp(argv[i], "--fuzz-test"))
|
|
g->enableFuzzTest = true;
|
|
else if (!strncmp(argv[i], "--fuzz-seed=", 12))
|
|
g->fuzzTestSeed = atoi(argv[i] + 12);
|
|
else if (!strcmp(argv[i], "--target")) {
|
|
// FIXME: should remove this way of specifying the target...
|
|
if (++i == argc) {
|
|
fprintf(stderr, "No target specified after --target option.\n");
|
|
usage(1);
|
|
}
|
|
target = argv[i];
|
|
}
|
|
else if (!strncmp(argv[i], "--target=", 9))
|
|
target = argv[i] + 9;
|
|
else if (!strncmp(argv[i], "--math-lib=", 11)) {
|
|
const char *lib = argv[i] + 11;
|
|
if (!strcmp(lib, "default"))
|
|
g->mathLib = Globals::Math_ISPC;
|
|
else if (!strcmp(lib, "fast"))
|
|
g->mathLib = Globals::Math_ISPCFast;
|
|
else if (!strcmp(lib, "svml"))
|
|
g->mathLib = Globals::Math_SVML;
|
|
else if (!strcmp(lib, "system"))
|
|
g->mathLib = Globals::Math_System;
|
|
else {
|
|
fprintf(stderr, "Unknown --math-lib= option \"%s\".\n", lib);
|
|
usage(1);
|
|
}
|
|
}
|
|
else if (!strncmp(argv[i], "--opt=", 6)) {
|
|
const char *opt = argv[i] + 6;
|
|
if (!strcmp(opt, "fast-math"))
|
|
g->opt.fastMath = true;
|
|
else if (!strcmp(opt, "fast-masked-vload"))
|
|
g->opt.fastMaskedVload = true;
|
|
else if (!strcmp(opt, "disable-assertions"))
|
|
g->opt.disableAsserts = true;
|
|
else if (!strcmp(opt, "disable-loop-unroll"))
|
|
g->opt.unrollLoops = false;
|
|
else if (!strcmp(opt, "disable-fma"))
|
|
g->opt.disableFMA = true;
|
|
else if (!strcmp(opt, "force-aligned-memory"))
|
|
g->opt.forceAlignedMemory = true;
|
|
|
|
// These are only used for performance tests of specific
|
|
// optimizations
|
|
else if (!strcmp(opt, "disable-all-on-optimizations"))
|
|
g->opt.disableMaskAllOnOptimizations = true;
|
|
else if (!strcmp(opt, "disable-coalescing"))
|
|
g->opt.disableCoalescing = true;
|
|
else if (!strcmp(opt, "disable-handle-pseudo-memory-ops"))
|
|
g->opt.disableHandlePseudoMemoryOps = true;
|
|
else if (!strcmp(opt, "disable-blended-masked-stores"))
|
|
g->opt.disableBlendedMaskedStores = true;
|
|
else if (!strcmp(opt, "disable-coherent-control-flow"))
|
|
g->opt.disableCoherentControlFlow = true;
|
|
else if (!strcmp(opt, "disable-uniform-control-flow"))
|
|
g->opt.disableUniformControlFlow = true;
|
|
else if (!strcmp(opt, "disable-gather-scatter-optimizations"))
|
|
g->opt.disableGatherScatterOptimizations = true;
|
|
else if (!strcmp(opt, "disable-blending-removal"))
|
|
g->opt.disableMaskedStoreToStore = true;
|
|
else if (!strcmp(opt, "disable-gather-scatter-flattening"))
|
|
g->opt.disableGatherScatterFlattening = true;
|
|
else if (!strcmp(opt, "disable-uniform-memory-optimizations"))
|
|
g->opt.disableUniformMemoryOptimizations = true;
|
|
else {
|
|
fprintf(stderr, "Unknown --opt= option \"%s\".\n", opt);
|
|
usage(1);
|
|
}
|
|
}
|
|
else if (!strncmp(argv[i], "--force-alignment=", 18)) {
|
|
g->forceAlignment = atoi(argv[i] + 18);
|
|
}
|
|
else if (!strcmp(argv[i], "--woff") || !strcmp(argv[i], "-woff")) {
|
|
g->disableWarnings = true;
|
|
g->emitPerfWarnings = false;
|
|
}
|
|
else if (!strcmp(argv[i], "--werror"))
|
|
g->warningsAsErrors = true;
|
|
else if (!strcmp(argv[i], "--nowrap"))
|
|
g->disableLineWrap = true;
|
|
else if (!strcmp(argv[i], "--wno-perf") || !strcmp(argv[i], "-wno-perf"))
|
|
g->emitPerfWarnings = false;
|
|
else if (!strcmp(argv[i], "-o")) {
|
|
if (++i == argc) {
|
|
fprintf(stderr, "No output file specified after -o option.\n");
|
|
usage(1);
|
|
}
|
|
outFileName = argv[i];
|
|
}
|
|
else if (!strncmp(argv[i], "--outfile=", 10))
|
|
outFileName = argv[i] + strlen("--outfile=");
|
|
else if (!strcmp(argv[i], "-h")) {
|
|
if (++i == argc) {
|
|
fprintf(stderr, "No header file name specified after -h option.\n");
|
|
usage(1);
|
|
}
|
|
headerFileName = argv[i];
|
|
}
|
|
else if (!strncmp(argv[i], "--header-outfile=", 17)) {
|
|
headerFileName = argv[i] + strlen("--header-outfile=");
|
|
}
|
|
else if (!strncmp(argv[i], "--c++-include-file=", 19)) {
|
|
includeFileName = argv[i] + strlen("--c++-include-file=");
|
|
}
|
|
else if (!strcmp(argv[i], "-O0")) {
|
|
g->opt.level = 0;
|
|
}
|
|
else if (!strcmp(argv[i], "-O") || !strcmp(argv[i], "-O1") ||
|
|
!strcmp(argv[i], "-O2") || !strcmp(argv[i], "-O3")) {
|
|
g->opt.level = 1;
|
|
}
|
|
else if (!strcmp(argv[i], "-"))
|
|
;
|
|
else if (!strcmp(argv[i], "--nostdlib"))
|
|
g->includeStdlib = false;
|
|
else if (!strcmp(argv[i], "--nocpp"))
|
|
g->runCPP = false;
|
|
#ifndef ISPC_IS_WINDOWS
|
|
else if (!strcmp(argv[i], "--pic"))
|
|
generatePIC = true;
|
|
else if (!strcmp(argv[i], "--colored-output"))
|
|
g->forceColoredOutput = true;
|
|
#endif // !ISPC_IS_WINDOWS
|
|
else if (!strcmp(argv[i], "--quiet"))
|
|
g->quiet = true;
|
|
else if (!strcmp(argv[i], "--yydebug")) {
|
|
extern int yydebug;
|
|
yydebug = 1;
|
|
}
|
|
else if (!strcmp(argv[i], "-MMM")) {
|
|
if (++i == argc) {
|
|
fprintf(stderr, "No output file name specified after -MMM option.\n");
|
|
usage(1);
|
|
}
|
|
depsFileName = argv[i];
|
|
}
|
|
else if (!strcmp(argv[i], "--dev-stub")) {
|
|
if (++i == argc) {
|
|
fprintf(stderr, "No output file name specified after --dev-stub option.\n");
|
|
usage(1);
|
|
}
|
|
devStubFileName = argv[i];
|
|
}
|
|
else if (!strcmp(argv[i], "--host-stub")) {
|
|
if (++i == argc) {
|
|
fprintf(stderr, "No output file name specified after --host-stub option.\n");
|
|
usage(1);
|
|
}
|
|
hostStubFileName = argv[i];
|
|
}
|
|
else if (strncmp(argv[i], "--debug-phase=", 14) == 0) {
|
|
fprintf(stderr, "WARNING: Adding debug phases may change the way PassManager"
|
|
"handles the phases and it may possibly make some bugs go"
|
|
"away or introduce the new ones.\n");
|
|
g->debug_stages = ParsingPhases(argv[i] + strlen("--debug-phase="));
|
|
}
|
|
|
|
#if ISPC_LLVM_VERSION == ISPC_LLVM_3_4 || ISPC_LLVM_VERSION == ISPC_LLVM_3_5 // 3.4, 3.5
|
|
else if (strncmp(argv[i], "--debug-ir=", 11) == 0) {
|
|
g->debugIR = ParsingPhaseName(argv[i] + strlen("--debug-ir="));
|
|
}
|
|
#endif
|
|
else if (strncmp(argv[i], "--off-phase=", 12) == 0) {
|
|
g->off_stages = ParsingPhases(argv[i] + strlen("--off-phase="));
|
|
}
|
|
else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
|
|
lPrintVersion();
|
|
return 0;
|
|
}
|
|
else if (argv[i][0] == '-') {
|
|
fprintf(stderr, "Unknown option \"%s\".\n", argv[i]);
|
|
usage(1);
|
|
}
|
|
else {
|
|
if (file != NULL) {
|
|
fprintf(stderr, "Multiple input files specified on command "
|
|
"line: \"%s\" and \"%s\".\n", file, argv[i]);
|
|
usage(1);
|
|
}
|
|
else
|
|
file = argv[i];
|
|
}
|
|
}
|
|
|
|
if (g->enableFuzzTest) {
|
|
if (g->fuzzTestSeed == -1) {
|
|
#ifdef ISPC_IS_WINDOWS
|
|
int seed = (unsigned)time(NULL);
|
|
#else
|
|
int seed = getpid();
|
|
#endif
|
|
g->fuzzTestSeed = seed;
|
|
Warning(SourcePos(), "Using seed %d for fuzz testing",
|
|
g->fuzzTestSeed);
|
|
}
|
|
#ifdef ISPC_IS_WINDOWS
|
|
srand(g->fuzzTestSeed);
|
|
#else
|
|
srand48(g->fuzzTestSeed);
|
|
#endif
|
|
}
|
|
|
|
if (outFileName == NULL &&
|
|
headerFileName == NULL &&
|
|
depsFileName == NULL &&
|
|
hostStubFileName == NULL &&
|
|
devStubFileName == NULL)
|
|
Warning(SourcePos(), "No output file or header file name specified. "
|
|
"Program will be compiled and warnings/errors will "
|
|
"be issued, but no output will be generated.");
|
|
|
|
return Module::CompileAndOutput(file, arch, cpu, target, generatePIC,
|
|
ot,
|
|
outFileName,
|
|
headerFileName,
|
|
includeFileName,
|
|
depsFileName,
|
|
hostStubFileName,
|
|
devStubFileName);
|
|
}
|