Skip to content

Commit

Permalink
Add separate functions for reading and translating SPIR-V
Browse files Browse the repository at this point in the history
The OpenCL runtime API requires that IL be loaded and compiled with
separate function calls:

 1. clCreateProgramWithIL(), which must check that the IL is well-formed
    and return CL_INVALID_VALUE if it is not.

 2. clBuildProgram() or clCompileProgram(), which allow build options to
    be specified.

To facilitate the above, this change adds two new API functions:

 1. readSpirvModule(), which reads an istream to produce a SPIRVModule.

 2. convertSpirvToLLVM(), which converts a SPIRVModule to LLVM IR.

The existing readSpirv() function is refactored in terms of these calls,
but is kept in the API for the convenience of tools such as llvm-spirv.
  • Loading branch information
StuartDBrady authored and svenvh committed May 16, 2019
1 parent 35666af commit 62fe6db
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 16 deletions.
10 changes: 10 additions & 0 deletions include/LLVMSPIRVLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ bool convertSpirv(std::string &Input, std::string &Out, std::string &ErrMsg,
bool isSpirvText(std::string &Img);
#endif

/// \brief Load SPIR-V from istream as a SPIRVModule.
/// \returns null on failure.
std::unique_ptr<SPIRVModule> readSpirvModule(std::istream &IS,
std::string &ErrMsg);

} // End namespace SPIRV

namespace llvm {
Expand All @@ -102,6 +107,11 @@ bool writeSpirv(Module *M, std::ostream &OS, std::string &ErrMsg);
bool readSpirv(LLVMContext &C, std::istream &IS, Module *&M,
std::string &ErrMsg);

/// \brief Convert a SPIRVModule into LLVM IR.
/// \returns null on failure.
std::unique_ptr<Module>
convertSpirvToLLVM(LLVMContext &C, SPIRV::SPIRVModule &BM, std::string &ErrMsg);

/// \brief Regularize LLVM module by removing entities not representable by
/// SPIRV.
bool regularizeLlvmForSpirv(Module *M, std::string &ErrMsg);
Expand Down
48 changes: 32 additions & 16 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2945,36 +2945,52 @@ Instruction *SPIRVToLLVM::transOCLRelational(SPIRVInstruction *I,
&Attrs)));
}

} // namespace SPIRV

bool llvm::readSpirv(LLVMContext &C, std::istream &IS, Module *&M,
std::string &ErrMsg) {
std::unique_ptr<SPIRVModule> readSpirvModule(std::istream &IS,
std::string &ErrMsg) {
std::unique_ptr<SPIRVModule> BM(SPIRVModule::createSPIRVModule());

IS >> *BM;
if (!BM->isModuleValid()) {
BM->getError(ErrMsg);
M = nullptr;
return false;
return nullptr;
}
return BM;
}

} // namespace SPIRV

std::unique_ptr<Module>
llvm::convertSpirvToLLVM(LLVMContext &C, SPIRVModule &BM, std::string &ErrMsg) {
std::unique_ptr<Module> M(new Module("", C));
SPIRVToLLVM BTL(M.get(), &BM);

M = new Module("", C);
SPIRVToLLVM BTL(M, BM.get());
bool Succeed = true;
if (!BTL.translate()) {
BM->getError(ErrMsg);
Succeed = false;
BM.getError(ErrMsg);
return nullptr;
}

llvm::legacy::PassManager PassMgr;
PassMgr.add(createSPIRVToOCL20());
PassMgr.add(createOCL20To12());
PassMgr.run(*M);

return M;
}

bool llvm::readSpirv(LLVMContext &C, std::istream &IS, Module *&M,
std::string &ErrMsg) {
std::unique_ptr<SPIRVModule> BM(readSpirvModule(IS, ErrMsg));

if (!BM)
return false;

M = convertSpirvToLLVM(C, *BM, ErrMsg).release();

if (!M)
return false;

if (DbgSaveTmpLLVM)
dumpLLVM(M, DbgTmpLLVMFileName);
if (!Succeed) {
delete M;
M = nullptr;
}
return Succeed;

return true;
}

0 comments on commit 62fe6db

Please sign in to comment.