From 04c93043d64e74a05f55dfaeb05cbab84be2e66a Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Mon, 15 Aug 2011 16:03:50 +0100 Subject: [PATCH] Target handling fixes. Set the Module's target appropriately when it's first created. Compile separate 32 and 64 bit versions of the builtins-c bitcocde and load the appropriate one based on the target we're compiling for. --- Makefile | 19 ++++++++---- builtins.cpp | 33 +++++++++++++++++++-- ispc.cpp | 1 + ispc.h | 3 ++ ispc.vcxproj | 7 +++-- main.cpp | 7 ++++- module.cpp | 82 ++++++++++++++++++++++++++-------------------------- 7 files changed, 99 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index 0966c8c2..023a63b4 100644 --- a/Makefile +++ b/Makefile @@ -48,8 +48,9 @@ BUILTINS_SRC=builtins-avx.ll builtins-sse2.ll builtins-sse4.ll builtins-sse4x2.l BISON_SRC=parse.yy FLEX_SRC=lex.ll -OBJS=$(addprefix objs/, $(CXX_SRC:.cpp=.o) $(BUILTINS_SRC:.ll=.o) builtins-c.o stdlib_ispc.o \ - $(BISON_SRC:.yy=.o) $(FLEX_SRC:.ll=.o)) +OBJS=$(addprefix objs/, $(CXX_SRC:.cpp=.o) $(BUILTINS_SRC:.ll=.o) \ + builtins-c-32.o builtins-c-64.o stdlib_ispc.o $(BISON_SRC:.yy=.o) \ + $(FLEX_SRC:.ll=.o)) default: ispc ispc_test @@ -112,11 +113,19 @@ objs/builtins-%.o: objs/builtins-%.cpp @echo Compiling $< @$(CXX) $(CXXFLAGS) -o $@ -c $< -objs/builtins-c.cpp: builtins-c.c +objs/builtins-c-32.cpp: builtins-c.c @echo Creating C++ source from builtins definition file $< - @$(CLANG) -I /opt/l1om/usr/include/ -emit-llvm -c $< -o - | llvm-dis - | ./bitcode2cpp.py $< > $@ + @$(CLANG) -m32 -emit-llvm -c $< -o - | llvm-dis - | ./bitcode2cpp.py builtins-c-32.c > $@ -objs/builtins-c.o: objs/builtins-c.cpp +objs/builtins-c-32.o: objs/builtins-c-32.cpp + @echo Compiling $< + @$(CXX) $(CXXFLAGS) -o $@ -c $< + +objs/builtins-c-64.cpp: builtins-c.c + @echo Creating C++ source from builtins definition file $< + @$(CLANG) -m64 -emit-llvm -c $< -o - | llvm-dis - | ./bitcode2cpp.py builtins-c-64.c > $@ + +objs/builtins-c-64.o: objs/builtins-c-64.cpp @echo Compiling $< @$(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/builtins.cpp b/builtins.cpp index 5b4f4d2e..7fc3781d 100644 --- a/builtins.cpp +++ b/builtins.cpp @@ -54,6 +54,8 @@ #include #include #include +#include +#include #include #include @@ -344,6 +346,22 @@ lAddBitcode(const unsigned char *bitcode, int length, if (!bcModule) Error(SourcePos(), "Error parsing stdlib bitcode: %s", bcErr.c_str()); else { + // FIXME: this feels like a bad idea, but the issue is that when we + // set the llvm::Module's target triple in the ispc Module::Module + // constructor, we start by calling llvm::sys::getHostTriple() (and + // then change the arch if needed). Somehow that ends up giving us + // strings like 'x86_64-apple-darwin11.0.0', while the stuff we + // compile to bitcode with clang has module triples like + // 'i386-apple-macosx10.7.0'. And then LLVM issues a warning about + // linking together modules with incompatible target triples.. + llvm::Triple mTriple(m->module->getTargetTriple()); + llvm::Triple bcTriple(bcModule->getTargetTriple()); + assert(bcTriple.getArch() == llvm::Triple::UnknownArch || + mTriple.getArch() == bcTriple.getArch()); + assert(bcTriple.getVendor() == llvm::Triple::UnknownVendor || + mTriple.getVendor() == bcTriple.getVendor()); + bcModule->setTargetTriple(mTriple.str()); + std::string(linkError); if (llvm::Linker::LinkModules(module, bcModule, &linkError)) Error(SourcePos(), "Error linking stdlib bitcode: %s", linkError.c_str()); @@ -395,9 +413,18 @@ void DefineStdlib(SymbolTable *symbolTable, llvm::LLVMContext *ctx, llvm::Module *module, bool includeStdlibISPC) { // Add the definitions from the compiled builtins-c.c file - extern unsigned char builtins_bitcode_c[]; - extern int builtins_bitcode_c_length; - lAddBitcode(builtins_bitcode_c, builtins_bitcode_c_length, module, symbolTable); + if (g->target.is32bit) { + extern unsigned char builtins_bitcode_c_32[]; + extern int builtins_bitcode_c_32_length; + lAddBitcode(builtins_bitcode_c_32, builtins_bitcode_c_32_length, + module, symbolTable); + } + else { + extern unsigned char builtins_bitcode_c_64[]; + extern int builtins_bitcode_c_64_length; + lAddBitcode(builtins_bitcode_c_64, builtins_bitcode_c_64_length, + module, symbolTable); + } // Next, add the target's custom implementations of the various needed // builtin functions (e.g. __masked_store_32(), etc). diff --git a/ispc.cpp b/ispc.cpp index 669ce267..2b7d30ce 100644 --- a/ispc.cpp +++ b/ispc.cpp @@ -60,6 +60,7 @@ Module *m; Target::Target() { arch = "x86-64"; cpu = "nehalem"; + is32bit = false; isa = SSE4; nativeVectorWidth = 4; vectorWidth = 4; diff --git a/ispc.h b/ispc.h index 6d3f7acc..409adb4a 100644 --- a/ispc.h +++ b/ispc.h @@ -168,6 +168,9 @@ struct Target { /** Target system architecture. (e.g. "x86-64", "x86"). */ std::string arch; + /** Is the target architecture 32 or 64 bit */ + bool is32bit; + /** Target CPU. (e.g. "corei7", "corei7-avx", ..) */ std::string cpu; diff --git a/ispc.vcxproj b/ispc.vcxproj index fea47cb5..a2f641ba 100755 --- a/ispc.vcxproj +++ b/ispc.vcxproj @@ -16,7 +16,8 @@ - + + @@ -29,9 +30,9 @@ - %LLVM_INSTALL_DIR%\bin\clang -emit-llvm builtins-c.c -c -o - | %LLVM_INSTALL_DIR%\bin\llvm-dis - | python bitcode2cpp.py builtins-c.c > gen-bitcode-c.cpp + %LLVM_INSTALL_DIR%\bin\clang -m32 -emit-llvm builtins-c.c -c -o - | %LLVM_INSTALL_DIR%\bin\llvm-dis - | python bitcode2cpp.py builtins-c-32.c > gen-bitcode-c-32.cpp clang builtins-c.c - %LLVM_INSTALL_DIR%\bin\clang -emit-llvm builtins-c.c -c -o - | %LLVM_INSTALL_DIR%\bin\llvm-dis - | python bitcode2cpp.py builtins-c.c > gen-bitcode-c.cpp + %LLVM_INSTALL_DIR%\bin\clang -m32 -emit-llvm builtins-c.c -c -o - | %LLVM_INSTALL_DIR%\bin\llvm-dis - | python bitcode2cpp.py builtins-c-32.c > gen-bitcode-c-32.cpp clang builtins-c.c gen-bitcode-c.cpp gen-bitcode-c.cpp diff --git a/main.cpp b/main.cpp index a581ea77..86e7cad4 100644 --- a/main.cpp +++ b/main.cpp @@ -209,8 +209,13 @@ int main(int Argc, char *Argv[]) { g->cppArgs.push_back(argv[i]); } #endif // !ISPC_IS_WINDOWS - else if (!strncmp(argv[i], "--arch=", 7)) + else if (!strncmp(argv[i], "--arch=", 7)) { g->target.arch = argv[i] + 7; + if (g->target.arch == "x86") + g->target.is32bit = true; + else if (g->target.arch == "x86-64") + g->target.is32bit = false; + } else if (!strncmp(argv[i], "--cpu=", 6)) g->target.cpu = argv[i] + 6; else if (!strcmp(argv[i], "--fast-math")) diff --git a/module.cpp b/module.cpp index d184ce6f..78da0f95 100644 --- a/module.cpp +++ b/module.cpp @@ -107,6 +107,43 @@ Module::Module(const char *fn) { symbolTable = new SymbolTable; module = new llvm::Module(filename ? filename : "", *g->ctx); + // initialize target in module + llvm::InitializeAllTargets(); + + llvm::Triple triple; + // Start with the host triple as the default + triple.setTriple(llvm::sys::getHostTriple()); + if (g->target.arch != "") { + // If the user specified a target architecture, see if it's a known + // one; print an error with the valid ones otherwise. + const llvm::Target *target = NULL; + for (llvm::TargetRegistry::iterator iter = llvm::TargetRegistry::begin(); + iter != llvm::TargetRegistry::end(); ++iter) { + if (g->target.arch == iter->getName()) { + target = &*iter; + break; + } + } + if (!target) { + fprintf(stderr, "Invalid target \"%s\"\nOptions: ", + g->target.arch.c_str()); + llvm::TargetRegistry::iterator iter; + for (iter = llvm::TargetRegistry::begin(); + iter != llvm::TargetRegistry::end(); ++iter) + fprintf(stderr, "%s ", iter->getName()); + fprintf(stderr, "\n"); + exit(1); + } + + // And override the arch in the host triple + llvm::Triple::ArchType archType = + llvm::Triple::getArchTypeForLLVMName(g->target.arch); + if (archType != llvm::Triple::UnknownArch) + triple.setArch(archType); + } + module->setTargetTriple(triple.str()); + + #ifndef LLVM_2_8 if (g->generateDebuggingSymbols) diBuilder = new llvm::DIBuilder(*module); @@ -923,7 +960,6 @@ Module::WriteOutput(OutputType outputType, const char *outFileName) { bool Module::writeObjectFileOrAssembly(OutputType outputType, const char *outFileName) { - llvm::InitializeAllTargets(); #if defined(LLVM_3_0) || defined(LLVM_3_0svn) llvm::InitializeAllTargetMCs(); #endif @@ -931,47 +967,12 @@ Module::writeObjectFileOrAssembly(OutputType outputType, const char *outFileName llvm::InitializeAllAsmParsers(); llvm::Triple triple(module->getTargetTriple()); - if (triple.getTriple().empty()) - triple.setTriple(llvm::sys::getHostTriple()); + assert(triple.getTriple().empty() == false); const llvm::Target *target = NULL; - if (g->target.arch != "") { - // If the user specified a target architecture, see if it's a known - // one; print an error with the valid ones otherwise. - for (llvm::TargetRegistry::iterator iter = llvm::TargetRegistry::begin(); - iter != llvm::TargetRegistry::end(); ++iter) { - if (g->target.arch == iter->getName()) { - target = &*iter; - break; - } - } - if (!target) { - fprintf(stderr, "Invalid target \"%s\"\nOptions: ", - g->target.arch.c_str()); - llvm::TargetRegistry::iterator iter; - for (iter = llvm::TargetRegistry::begin(); - iter != llvm::TargetRegistry::end(); ++iter) - fprintf(stderr, "%s ", iter->getName()); - fprintf(stderr, "\n"); - return false; - } - - llvm::Triple::ArchType archType = - llvm::Triple::getArchTypeForLLVMName(g->target.arch); - if (archType != llvm::Triple::UnknownArch) - triple.setArch(archType); - } - else { - // Otherwise get the target either based on the host or the - // module's target, if it has been set there. - std::string error; - target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), error); - if (!target) { - fprintf(stderr, "Unable to select target for module: %s\n", - error.c_str()); - return false; - } - } + std::string error; + target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), error); + assert(target != NULL); std::string featuresString; llvm::TargetMachine *targetMachine = NULL; @@ -1004,7 +1005,6 @@ Module::writeObjectFileOrAssembly(OutputType outputType, const char *outFileName bool binary = (fileType == llvm::TargetMachine::CGFT_ObjectFile); unsigned int flags = binary ? llvm::raw_fd_ostream::F_Binary : 0; - std::string error; llvm::tool_output_file *of = new llvm::tool_output_file(outFileName, error, flags); if (error.size()) { fprintf(stderr, "Error opening output file \"%s\".\n", outFileName);