Merge pull request #458 from dbabokin/dl_check
DataLayout consistency check
This commit is contained in:
23
builtins.cpp
23
builtins.cpp
@@ -640,14 +640,21 @@ AddBitcodeToModule(const unsigned char *bitcode, int length,
|
|||||||
mTriple.getVendor() == bcTriple.getVendor());
|
mTriple.getVendor() == bcTriple.getVendor());
|
||||||
bcModule->setTargetTriple(mTriple.str());
|
bcModule->setTargetTriple(mTriple.str());
|
||||||
|
|
||||||
// This is also suboptimal; LLVM issues a warning about linking
|
// We unconditionally set module DataLayout to library, but we must
|
||||||
// modules with different datalayouts, due to things like
|
// ensure that library and module DataLayouts are compatible.
|
||||||
// bulitins-c.c having the regular IA layout, but the generic
|
// If they are not, we should recompile the library for problematic
|
||||||
// targets having a layout with 16-bit alignment for 16xi1 vectors.
|
// architecture and investigate what happened.
|
||||||
// As long as builtins-c.c doesn't have any 16xi1 vector types
|
// Generally we allow library DataLayout to be subset of module
|
||||||
// (which it shouldn't!), then this override is safe.
|
// DataLayout or library DataLayout to be empty.
|
||||||
if (g->target->getISA() == Target::GENERIC)
|
if (!VerifyDataLayoutCompatibility(module->getDataLayout(),
|
||||||
bcModule->setDataLayout(module->getDataLayout());
|
bcModule->getDataLayout())) {
|
||||||
|
Error(SourcePos(), "Module DataLayout is incompatible with library DataLayout:\n"
|
||||||
|
"Module DL: %s\n"
|
||||||
|
"Library DL: %s\n",
|
||||||
|
module->getDataLayout().c_str(), bcModule->getDataLayout().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bcModule->setDataLayout(module->getDataLayout());
|
||||||
|
|
||||||
std::string(linkError);
|
std::string(linkError);
|
||||||
if (llvm::Linker::LinkModules(module, bcModule,
|
if (llvm::Linker::LinkModules(module, bcModule,
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ def run_cmds(compile_cmds, run_cmd, filename, expect_failure):
|
|||||||
if compile_failed:
|
if compile_failed:
|
||||||
sys.stdout.write("Compilation of test %s failed \n" % filename)
|
sys.stdout.write("Compilation of test %s failed \n" % filename)
|
||||||
if output != "":
|
if output != "":
|
||||||
sys.stdout.write("%s" % output)
|
sys.stdout.write("%s" % output.encode("utf-8"))
|
||||||
return (1, 0)
|
return (1, 0)
|
||||||
|
|
||||||
(return_code, output) = run_command(run_cmd)
|
(return_code, output) = run_command(run_cmd)
|
||||||
@@ -191,7 +191,7 @@ def run_cmds(compile_cmds, run_cmd, filename, expect_failure):
|
|||||||
(filename, "unexpectedly passed" if expect_failure else "failed",
|
(filename, "unexpectedly passed" if expect_failure else "failed",
|
||||||
return_code))
|
return_code))
|
||||||
if output != "":
|
if output != "":
|
||||||
sys.stdout.write("%s\n" % output)
|
sys.stdout.write("%s\n" % output.encode("utf-8"))
|
||||||
if surprise == True:
|
if surprise == True:
|
||||||
return (0, 1)
|
return (0, 1)
|
||||||
else:
|
else:
|
||||||
|
|||||||
63
util.cpp
63
util.cpp
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2010-2012, Intel Corporation
|
Copyright (c) 2010-2013, Intel Corporation
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -63,6 +63,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#endif // ISPC_IS_WINDOWS
|
#endif // ISPC_IS_WINDOWS
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
/** Returns the width of the terminal where the compiler is running.
|
/** Returns the width of the terminal where the compiler is running.
|
||||||
Finding this out may fail in a variety of reasonable situations (piping
|
Finding this out may fail in a variety of reasonable situations (piping
|
||||||
@@ -572,3 +573,63 @@ GetDirectoryAndFileName(const std::string ¤tDirectory,
|
|||||||
*directory = std::string(fp, basenameStart - fp);
|
*directory = std::string(fp, basenameStart - fp);
|
||||||
#endif // ISPC_IS_WINDOWS
|
#endif // ISPC_IS_WINDOWS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::set<std::string> lGetStringArray(const std::string &str) {
|
||||||
|
std::set<std::string> result;
|
||||||
|
|
||||||
|
Assert(str.find('-') != str.npos);
|
||||||
|
|
||||||
|
size_t pos_prev = 0, pos;
|
||||||
|
do {
|
||||||
|
pos = str.find('-', pos_prev);
|
||||||
|
std::string substr = str.substr(pos_prev, pos-pos_prev);
|
||||||
|
result.insert(substr);
|
||||||
|
pos_prev = pos;
|
||||||
|
pos_prev++;
|
||||||
|
} while (pos != str.npos);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VerifyDataLayoutCompatibility(const std::string &module_dl,
|
||||||
|
const std::string &lib_dl) {
|
||||||
|
if (lib_dl.empty()) {
|
||||||
|
// This is the case for most of library pre-compiled .ll files.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<std::string> module_dl_set = lGetStringArray(module_dl);
|
||||||
|
std::set<std::string> lib_dl_set = lGetStringArray(lib_dl);
|
||||||
|
|
||||||
|
// For each element in library data layout, find matching module element.
|
||||||
|
// If no match is found, then we are in trouble and the library can't be used.
|
||||||
|
for (std::set<std::string>::iterator it = lib_dl_set.begin();
|
||||||
|
it != lib_dl_set.end(); ++it) {
|
||||||
|
// We use the simplest possible definition of "match", which is match exactly.
|
||||||
|
// Ideally it should be relaxed and for triples [p|i|v|f|a|s]<size>:<abi>:<pref>
|
||||||
|
// we should allow <pref> part (preferred alignment) to not match.
|
||||||
|
// But this seems to have no practical value at this point.
|
||||||
|
std::set<std::string>::iterator module_match =
|
||||||
|
std::find(module_dl_set.begin(), module_dl_set.end(), *it);
|
||||||
|
if (module_match == module_dl_set.end()) {
|
||||||
|
// No match for this piece of library DataLayout was found,
|
||||||
|
// return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Remove matching piece from Module set.
|
||||||
|
module_dl_set.erase(module_match);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We allow extra types to be defined in the Module, but we should check
|
||||||
|
// that it's something that we expect. And we expect vectors and floats.
|
||||||
|
for (std::set<std::string>::iterator it = module_dl_set.begin();
|
||||||
|
it != module_dl_set.end(); ++it) {
|
||||||
|
if ((*it)[0] == 'v' || (*it)[0] == 'f') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
9
util.h
9
util.h
@@ -147,4 +147,13 @@ void GetDirectoryAndFileName(const std::string ¤tDir,
|
|||||||
const std::string &relativeName,
|
const std::string &relativeName,
|
||||||
std::string *directory, std::string *filename);
|
std::string *directory, std::string *filename);
|
||||||
|
|
||||||
|
/** Verification routine, which ensures that DataLayout of the module being
|
||||||
|
compiled is compatible with DataLayout of the library. At the moment we
|
||||||
|
allow the library DataLayout to a subset of the module DataLayout (and
|
||||||
|
extra floating point and vector types to be defined for module) or
|
||||||
|
empty library DataLayout.
|
||||||
|
*/
|
||||||
|
bool VerifyDataLayoutCompatibility(const std::string &module_dl,
|
||||||
|
const std::string &lib_dl);
|
||||||
|
|
||||||
#endif // ISPC_UTIL_H
|
#endif // ISPC_UTIL_H
|
||||||
|
|||||||
Reference in New Issue
Block a user