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.
This commit is contained in:
Matt Pharr
2011-08-15 16:03:50 +01:00
parent 46037c7a11
commit 04c93043d6
7 changed files with 99 additions and 53 deletions

View File

@@ -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 $<

View File

@@ -54,6 +54,8 @@
#include <llvm/Instructions.h>
#include <llvm/Intrinsics.h>
#include <llvm/Linker.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/SubtargetFeature.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Bitcode/ReaderWriter.h>
@@ -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).

View File

@@ -60,6 +60,7 @@ Module *m;
Target::Target() {
arch = "x86-64";
cpu = "nehalem";
is32bit = false;
isa = SSE4;
nativeVectorWidth = 4;
vectorWidth = 4;

3
ispc.h
View File

@@ -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;

View File

@@ -16,7 +16,8 @@
<ClCompile Include="decl.cpp" />
<ClCompile Include="expr.cpp" />
<ClCompile Include="gen-bitcode-avx.cpp" />
<ClCompile Include="gen-bitcode-c.cpp" />
<ClCompile Include="gen-bitcode-c-32.cpp" />
<ClCompile Include="gen-bitcode-c-64.cpp" />
<ClCompile Include="gen-bitcode-sse2.cpp" />
<ClCompile Include="gen-bitcode-sse4.cpp" />
<ClCompile Include="gen-bitcode-sse4x2.cpp" />
@@ -29,9 +30,9 @@
<ClCompile Include="opt.cpp" />
<ClCompile Include="parse.cc" />
<CustomBuild Include="builtins-c.c">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%LLVM_INSTALL_DIR%\bin\clang -emit-llvm builtins-c.c -c -o - | %LLVM_INSTALL_DIR%\bin\llvm-dis - | python bitcode2cpp.py builtins-c.c &gt; gen-bitcode-c.cpp</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%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 &gt; gen-bitcode-c-32.cpp</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">clang builtins-c.c</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%LLVM_INSTALL_DIR%\bin\clang -emit-llvm builtins-c.c -c -o - | %LLVM_INSTALL_DIR%\bin\llvm-dis - | python bitcode2cpp.py builtins-c.c &gt; gen-bitcode-c.cpp</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%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 &gt; gen-bitcode-c-32.cpp</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">clang builtins-c.c</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">gen-bitcode-c.cpp</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">gen-bitcode-c.cpp</Outputs>

View File

@@ -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"))

View File

@@ -107,6 +107,43 @@ Module::Module(const char *fn) {
symbolTable = new SymbolTable;
module = new llvm::Module(filename ? filename : "<stdin>", *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;
}
}
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);