diff --git a/Makefile b/Makefile index 4ce1dbdb..ec541339 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,17 @@ # ispc Makefile # -ARCH = $(shell uname) +ARCH_OS = $(shell uname) +ARCH_TYPE = $(shell arch) CLANG=clang +CLANG_LIBS = -lclangFrontendTool -lclangFrontend -lclangDriver \ + -lclangSerialization -lclangCodeGen -lclangParse -lclangSema \ + -lclangStaticAnalyzerFrontend -lclangStaticAnalyzerCheckers \ + -lclangStaticAnalyzerCore \ + -lclangAnalysis -lclangIndex -lclangRewrite \ + -lclangAST -lclangLex -lclangBasic + LLVM_LIBS=$(shell llvm-config --ldflags --libs) -lpthread -ldl LLVM_CXXFLAGS=$(shell llvm-config --cppflags) LLVM_VERSION_DEF=-DLLVM_$(shell llvm-config --version | sed s/\\./_/) @@ -18,10 +26,14 @@ CXXFLAGS=-g3 $(LLVM_CXXFLAGS) -I. -Iobjs/ -Wall $(LLVM_VERSION_DEF) \ -DBUILD_DATE="\"$(BUILD_DATE)\"" -DBUILD_VERSION="\"$(BUILD_VERSION)\"" LDFLAGS= -ifeq ($(ARCH),Linux) +ifeq ($(ARCH_OS),Linux) # try to link everything statically under Linux (including libstdc++) so # that the binaries we generate will be portable across distributions... - LDFLAGS=-static -L/usr/lib/gcc/x86_64-linux-gnu/4.4 + ifeq ($(ARCH_TYPE),x86_64) + LDFLAGS=-static -L/usr/lib/gcc/x86_64-linux-gnu/4.4 + else + LDFLAGS=-L/usr/lib/gcc/i686-redhat-linux/4.6.0 + endif endif LEX=flex @@ -68,7 +80,7 @@ doxygen: ispc: print_llvm_src dirs $(OBJS) @echo Creating ispc executable - @$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LLVM_LIBS) + @$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(CLANG_LIBS) $(LLVM_LIBS) ispc_test: dirs ispc_test.cpp @echo Creating ispc_test executable diff --git a/module.cpp b/module.cpp index 0403b81e..1c66cb52 100644 --- a/module.cpp +++ b/module.cpp @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,9 @@ #include #include #include +#include +#include +#include #ifndef LLVM_2_8 #include #include @@ -133,8 +137,9 @@ extern FILE *yyin; extern int yyparse(); typedef struct yy_buffer_state *YY_BUFFER_STATE; extern void yy_switch_to_buffer(YY_BUFFER_STATE); +extern YY_BUFFER_STATE yy_scan_string(const char *); extern YY_BUFFER_STATE yy_create_buffer(FILE *, int); - +extern void yy_delete_buffer(YY_BUFFER_STATE); int Module::CompileFile() { @@ -146,63 +151,17 @@ Module::CompileFile() { bool runPreprocessor = g->runCPP; - // We currently require that the user run the preprocessor by hand on - // windows and pipe the result to ispc. - // FIXME: It'd be nice to run cl.exe for them to do this, if it's available - // in the PATH... -#ifdef ISPC_IS_WINDOWS - runPreprocessor = false; -#endif // ISPC_IS_WINDOWS - - // The FILE handle that we'll point the parser at. This may end up - // being stdin, an opened file on disk, or the piped output from the - // preprocessor. - FILE *f; - if (runPreprocessor) { - // Before we run the preprocessor, make sure that file exists and - // we can read it since otherwise we get a pretty obscure/unhelpful - // error message from cpp - if (filename) { - f = fopen(filename, "r"); - if (f == NULL) { - perror(filename); - return 1; - } - fclose(f); - } - - // Go ahead and construct a command string to run the preprocessor. - // First, concatentate all of the -D statements from the original - // ispc command line so that we can pass them along to cpp. - std::string cppDefs; - for (unsigned int i = 0; i < g->cppArgs.size(); ++i) { - cppDefs += g->cppArgs[i]; - cppDefs += ' '; - } - -#ifdef ISPC_IS_WINDOWS - // For now, this code should never be reached - FATAL("Need to implement code to run the preprocessor for windows"); -#else // ISPC_IS_WINDOWS - char *cmd = NULL; - if (asprintf(&cmd, "/usr/bin/cpp -DISPC=1 -DPI=3.1415926536 %s %s", - cppDefs.c_str(), filename ? filename : "-") == -1) { - fprintf(stderr, "Unable to allocate memory in asprintf()?!\n"); - exit(1); - } - - f = popen(cmd, "r"); - free(cmd); - - if (f == NULL) { - perror(filename ? filename : ""); - return 1; - } -#endif // ISPC_IS_WINDOWS + std::string buffer; + llvm::raw_string_ostream os(buffer); + execPreprocessor(filename, &os); + YY_BUFFER_STATE strbuf = yy_scan_string(os.str().c_str()); + yyparse(); + yy_delete_buffer(strbuf); } else { // No preprocessor, just open up the file if it's not stdin.. + FILE* f = NULL; if (filename == NULL) f = stdin; else { @@ -212,24 +171,11 @@ Module::CompileFile() { return 1; } } - } - - // Here is where the magic happens: parse the file, build the AST, etc. - // This in turn will lead to calls back to Module::AddFunction(), - // etc... - yyin = f; - yy_switch_to_buffer(yy_create_buffer(yyin, 4096)); - yyparse(); - - if (runPreprocessor) { -#ifdef ISPC_IS_WINDOWS - FATAL("need to implement this for windows as well"); -#else - pclose(f); -#endif // ISPC_IS_WINDOWS - } - else + yyin = f; + yy_switch_to_buffer(yy_create_buffer(yyin, 4096)); + yyparse(); fclose(f); + } if (errorCount == 0) Optimize(module, g->opt.level); @@ -1430,3 +1376,44 @@ Module::writeHeader(const char *fn) { fclose(f); return true; } + +void +Module::execPreprocessor(const char* infilename, llvm::raw_string_ostream* ostream) const +{ + clang::CompilerInstance inst; + std::string error; + + inst.createFileManager(); + inst.createDiagnostics(0, NULL); + clang::TargetOptions& options = inst.getTargetOpts(); + + llvm::Triple triple(module->getTargetTriple()); + if (triple.getTriple().empty()) + triple.setTriple(llvm::sys::getHostTriple()); + + options.Triple = triple.getTriple(); + + clang::TargetInfo* target + = clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), options); + + inst.setTarget(target); + inst.createSourceManager(inst.getFileManager()); + inst.InitializeSourceManager(infilename); + + clang::PreprocessorOptions& opts = inst.getPreprocessorOpts(); + + //Add defs for ISPC and PI + opts.addMacroDef("ISPC"); + opts.addMacroDef("PI=3.1415926535"); + + for (unsigned int i = 0; i < g->cppArgs.size(); ++i) { + //Sanity Check, should really begin with -D + if (g->cppArgs[i].substr(0,2) == "-D") { + opts.addMacroDef(g->cppArgs[i].substr(2)); + } + } + inst.createPreprocessor(); + clang::DoPrintPreprocessedInput(inst.getPreprocessor(), + ostream, inst.getPreprocessorOutputOpts()); +} + diff --git a/module.h b/module.h index 403f5d05..85b74adb 100644 --- a/module.h +++ b/module.h @@ -41,6 +41,11 @@ #include "ispc.h" +namespace llvm +{ +class raw_string_ostream; +} + class Module { public: /** The name of the source file being compiled should be passed as the @@ -108,6 +113,8 @@ private: bool writeHeader(const char *filename); bool writeObjectFileOrAssembly(OutputType outputType, const char *filename); + void execPreprocessor(const char *infilename, llvm::raw_string_ostream* ostream) const; + }; #endif // ISPC_MODULE_H