2014-07-04 16:17:05 -04:00
|
|
|
//
|
|
|
|
|
// Copyright (c) 2011 Advanced Micro Devices, Inc. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
#include "top.hpp"
|
|
|
|
|
#include "spir.hpp"
|
|
|
|
|
#include "aclTypes.h"
|
|
|
|
|
#include "bif/bifbase.hpp"
|
|
|
|
|
#include "utils/libUtils.h"
|
|
|
|
|
#include "utils/options.hpp"
|
|
|
|
|
#include "utils/target_mappings.h"
|
|
|
|
|
#include "os/os.hpp"
|
|
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <string>
|
|
|
|
|
|
2015-05-08 12:51:04 -04:00
|
|
|
#if defined(LEGACY_COMPLIB)
|
2014-07-04 16:17:05 -04:00
|
|
|
#include "llvm/DataLayout.h"
|
|
|
|
|
#include "llvm/Module.h"
|
2015-05-08 12:51:04 -04:00
|
|
|
#include "llvm/Analysis/Verifier.h"
|
|
|
|
|
#include "llvm/Assembly/PrintModulePass.h"
|
|
|
|
|
#else
|
|
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
|
#include "llvm/IR/Verifier.h"
|
|
|
|
|
#endif
|
2014-07-04 16:17:05 -04:00
|
|
|
#include "llvm/Pass.h"
|
2016-07-05 11:02:52 -04:00
|
|
|
#if defined(LEGACY_COMPLIB)
|
2014-07-04 16:17:05 -04:00
|
|
|
#include "llvm/PassManager.h"
|
2016-07-05 11:02:52 -04:00
|
|
|
#else
|
|
|
|
|
#include "llvm/IR/LegacyPassManager.h"
|
|
|
|
|
#endif
|
2014-07-04 16:17:05 -04:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
|
|
|
|
#include "llvm/Analysis/SPIRVerifier.h"
|
|
|
|
|
#include "llvm/Bitcode/ReaderWriter.h"
|
|
|
|
|
#include "llvm/Bitcode/BitstreamWriter.h"
|
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
#include "llvm/Transforms/Scalar.h"
|
|
|
|
|
|
2015-05-08 12:51:04 -04:00
|
|
|
#if defined(LEGACY_COMPLIB)
|
|
|
|
|
#define LLVMReturnStatusAction ReturnStatusAction
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-07-04 16:17:05 -04:00
|
|
|
using namespace llvm;
|
|
|
|
|
using namespace amdcl;
|
|
|
|
|
|
|
|
|
|
Module*
|
|
|
|
|
amdcl::SPIR::loadSPIR(std::string &spirBinary)
|
|
|
|
|
{
|
|
|
|
|
// Need to use the namespace here since a parent function is called Module().
|
|
|
|
|
llvm::Module *bc = NULL;
|
|
|
|
|
std::string errors;
|
|
|
|
|
source_ = spirBinary;
|
|
|
|
|
SPIRState State = {"", "", 1, 0, 1, 2};
|
|
|
|
|
bc = amdcl::LLVMCompilerStage::loadBitcode(source_);
|
|
|
|
|
if (!bc)
|
|
|
|
|
{
|
|
|
|
|
errors = "loadBitcode failed";
|
|
|
|
|
log_ += errors;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2015-05-08 12:51:04 -04:00
|
|
|
#if defined(LEGACY_COMPLIB)
|
2014-07-04 16:17:05 -04:00
|
|
|
verifyModule(*bc, ReturnStatusAction, &errors);
|
2015-05-08 12:51:04 -04:00
|
|
|
#else
|
|
|
|
|
raw_string_ostream errorsOS(errors);
|
|
|
|
|
verifyModule(*bc, &errorsOS);
|
|
|
|
|
#endif
|
2014-07-04 16:17:05 -04:00
|
|
|
if (!errors.empty()) {
|
|
|
|
|
log_ += errors;
|
|
|
|
|
errors.clear();
|
|
|
|
|
}
|
2016-07-05 11:02:52 -04:00
|
|
|
#if defined(LEGACY_COMPLIB)
|
2014-07-04 16:17:05 -04:00
|
|
|
FunctionPassManager FPM(bc);
|
2016-07-05 11:02:52 -04:00
|
|
|
#else
|
|
|
|
|
legacy::FunctionPassManager FPM(bc);
|
|
|
|
|
#endif
|
2014-07-04 16:17:05 -04:00
|
|
|
if (Options()->oVariables->verifyHWSpir) {
|
|
|
|
|
if (!isHSAILTarget(Elf()->target)) {
|
2015-05-08 12:51:04 -04:00
|
|
|
verifySPIRModule(*bc, LLVMReturnStatusAction, State, false, &errors);
|
2014-07-04 16:17:05 -04:00
|
|
|
}
|
|
|
|
|
if (!errors.empty()) {
|
|
|
|
|
log_ += errors;
|
|
|
|
|
errors.clear();
|
|
|
|
|
delete bc;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (Options()->oVariables->verifyLWSpir) {
|
|
|
|
|
if (!isHSAILTarget(Elf()->target)) {
|
2015-05-08 12:51:04 -04:00
|
|
|
verifySPIRModule(*bc, LLVMReturnStatusAction, State, true, &errors);
|
2014-07-04 16:17:05 -04:00
|
|
|
}
|
|
|
|
|
if (!errors.empty()) {
|
|
|
|
|
log_ += errors;
|
|
|
|
|
errors.clear();
|
|
|
|
|
delete bc;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return bc;
|
|
|
|
|
}
|
|
|
|
|
Module*
|
|
|
|
|
amdcl::SPIR::loadBitcode(std::string &binary)
|
|
|
|
|
{
|
|
|
|
|
llvm::Module *bc = loadSPIR(binary);
|
|
|
|
|
if (!bc) return NULL;
|
|
|
|
|
|
|
|
|
|
// FIXME: It is not clear why SPIRLoader is invoked so early here.
|
|
|
|
|
// The current view is to keep SPIRLoader as a pure pre-link pass to
|
|
|
|
|
// be called only by the linker.
|
|
|
|
|
StringRef LayoutStr = is64BitTarget(Elf()->target) ?
|
|
|
|
|
DATA_LAYOUT_64BIT : DATA_LAYOUT_32BIT;
|
|
|
|
|
bc->setDataLayout(LayoutStr);
|
|
|
|
|
bc->setTargetTriple(familySet[Elf()->target.arch_id].triple);
|
|
|
|
|
|
2015-05-08 12:51:04 -04:00
|
|
|
#if defined(LEGACY_COMPLIB)
|
2016-07-05 11:02:52 -04:00
|
|
|
llvm::PassManager SPIRPasses;
|
2014-07-04 16:17:05 -04:00
|
|
|
SPIRPasses.add(new llvm::DataLayout(bc));
|
2015-05-08 12:51:04 -04:00
|
|
|
#else
|
2016-07-05 11:02:52 -04:00
|
|
|
llvm::legacy::PassManager SPIRPasses;
|
2015-05-08 12:51:04 -04:00
|
|
|
#endif
|
2014-07-04 16:17:05 -04:00
|
|
|
SPIRPasses.add(createSPIRLoader(/*demangleBuiltin=*/ true));
|
|
|
|
|
SPIRPasses.run(*bc);
|
|
|
|
|
return bc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const void*
|
|
|
|
|
SPIR::toBinary(const void *text, size_t text_size, size_t *binary_size)
|
|
|
|
|
{
|
|
|
|
|
std::string text_buf(reinterpret_cast<const char*>(text), text_size);
|
|
|
|
|
// Need to use the namespace here since a parent function is called Module().
|
|
|
|
|
llvm::Module *mod = loadSPIR(text_buf);
|
|
|
|
|
SmallString<256> char_buf;
|
|
|
|
|
raw_svector_ostream outstream(char_buf);
|
|
|
|
|
WriteBitcodeToFile(mod, outstream);
|
|
|
|
|
std::string str_buf(char_buf.begin(), char_buf.end());
|
|
|
|
|
(*binary_size) = char_buf.size();
|
|
|
|
|
void *ptr = aclutAlloc(CL())(*binary_size);
|
|
|
|
|
std::copy(char_buf.begin(), char_buf.end(), reinterpret_cast<char*>(ptr));
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const void*
|
|
|
|
|
SPIR::toText(const void *binary, size_t binary_size, size_t *text_size)
|
|
|
|
|
{
|
|
|
|
|
std::string text_buf(reinterpret_cast<const char*>(binary), binary_size);
|
|
|
|
|
// Need to use the namespace here since a parent function is called Module().
|
|
|
|
|
llvm::Module *mod = loadSPIR(text_buf);
|
|
|
|
|
std::string errors;
|
|
|
|
|
if (!mod)
|
|
|
|
|
{
|
|
|
|
|
errors = "loadSPIR failed";
|
|
|
|
|
log_ += errors;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
std::string bin_buf;
|
|
|
|
|
raw_string_ostream buf(bin_buf);
|
|
|
|
|
mod->print(buf, NULL);
|
|
|
|
|
(*text_size) = bin_buf.size();
|
|
|
|
|
void *ptr = aclutAlloc(CL())(*text_size);
|
|
|
|
|
std::copy(bin_buf.begin(), bin_buf.end(), reinterpret_cast<char*>(ptr));
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|