diff --git a/builtins.cpp b/builtins.cpp index 53047c94..53cab1f6 100644 --- a/builtins.cpp +++ b/builtins.cpp @@ -640,14 +640,21 @@ AddBitcodeToModule(const unsigned char *bitcode, int length, mTriple.getVendor() == bcTriple.getVendor()); bcModule->setTargetTriple(mTriple.str()); - // This is also suboptimal; LLVM issues a warning about linking - // modules with different datalayouts, due to things like - // bulitins-c.c having the regular IA layout, but the generic - // targets having a layout with 16-bit alignment for 16xi1 vectors. - // As long as builtins-c.c doesn't have any 16xi1 vector types - // (which it shouldn't!), then this override is safe. - if (g->target->getISA() == Target::GENERIC) - bcModule->setDataLayout(module->getDataLayout()); + // We unconditionally set module DataLayout to library, but we must + // ensure that library and module DataLayouts are compatible. + // If they are not, we should recompile the library for problematic + // architecture and investigate what happened. + // Generally we allow library DataLayout to be subset of module + // DataLayout or library DataLayout to be empty. + if (!VerifyDataLayoutCompatibility(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); if (llvm::Linker::LinkModules(module, bcModule, diff --git a/util.cpp b/util.cpp index ee5b8d55..73fb5b5f 100644 --- a/util.cpp +++ b/util.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2010-2012, Intel Corporation + Copyright (c) 2010-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -63,6 +63,7 @@ #include #endif // ISPC_IS_WINDOWS #include +#include /** Returns the width of the terminal where the compiler is running. 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); #endif // ISPC_IS_WINDOWS } + +static std::set lGetStringArray(const std::string &str) { + std::set 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 module_dl_set = lGetStringArray(module_dl); + std::set 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::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]:: + // we should allow part (preferred alignment) to not match. + // But this seems to have no practical value at this point. + std::set::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::iterator it = module_dl_set.begin(); + it != module_dl_set.end(); ++it) { + if ((*it)[0] == 'v' || (*it)[0] == 'f') { + continue; + } + return false; + } + + return true; +} + diff --git a/util.h b/util.h index 4880182a..b247b8bd 100644 --- a/util.h +++ b/util.h @@ -147,4 +147,13 @@ void GetDirectoryAndFileName(const std::string ¤tDir, const std::string &relativeName, 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