/////////////////////////////////////////////////////////////////////////////// // // // DxilUtil.cpp // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Dxil helper functions. // // // /////////////////////////////////////////////////////////////////////////////// #include "llvm/IR/GlobalVariable.h" #include "dxc/HLSL/DxilTypeSystem.h" #include "dxc/HLSL/DxilUtil.h" #include "dxc/HLSL/DxilModule.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Constants.h" using namespace llvm; using namespace hlsl; namespace hlsl { namespace dxilutil { Type *GetArrayEltTy(Type *Ty) { if (isa(Ty)) Ty = Ty->getPointerElementType(); while (isa(Ty)) { Ty = Ty->getArrayElementType(); } return Ty; } bool HasDynamicIndexing(Value *V) { for (auto User : V->users()) { if (GetElementPtrInst *GEP = dyn_cast(User)) { for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) { if (!isa(Idx)) return true; } } } return false; } unsigned GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation, llvm::Type *Ty, DxilTypeSystem &typeSys) { while (isa(Ty)) { Ty = Ty->getArrayElementType(); } // Bytes. CompType compType = fieldAnnotation.GetCompType(); unsigned compSize = compType.Is64Bit() ? 8 : compType.Is16Bit() && !typeSys.UseMinPrecision() ? 2 : 4; unsigned fieldSize = compSize; if (Ty->isVectorTy()) { fieldSize *= Ty->getVectorNumElements(); } else if (StructType *ST = dyn_cast(Ty)) { DxilStructAnnotation *EltAnnotation = typeSys.GetStructAnnotation(ST); if (EltAnnotation) { fieldSize = EltAnnotation->GetCBufferSize(); } else { // Calculate size when don't have annotation. if (fieldAnnotation.HasMatrixAnnotation()) { const DxilMatrixAnnotation &matAnnotation = fieldAnnotation.GetMatrixAnnotation(); unsigned rows = matAnnotation.Rows; unsigned cols = matAnnotation.Cols; if (matAnnotation.Orientation == MatrixOrientation::ColumnMajor) { rows = cols; cols = matAnnotation.Rows; } else if (matAnnotation.Orientation != MatrixOrientation::RowMajor) { // Invalid matrix orientation. fieldSize = 0; } fieldSize = (rows - 1) * 16 + cols * 4; } else { // Cannot find struct annotation. fieldSize = 0; } } } return fieldSize; } bool IsStaticGlobal(GlobalVariable *GV) { return GV->getLinkage() == GlobalValue::LinkageTypes::InternalLinkage && GV->getType()->getPointerAddressSpace() == DXIL::kDefaultAddrSpace; } bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV) { return GV->getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace; } bool RemoveUnusedFunctions(Module &M, Function *EntryFunc, Function *PatchConstantFunc, bool IsLib) { std::vector deadList; for (auto &F : M.functions()) { if (&F == EntryFunc || &F == PatchConstantFunc) continue; if (F.isDeclaration() || !IsLib) { if (F.user_empty()) deadList.emplace_back(&F); } } bool bUpdated = deadList.size(); for (Function *F : deadList) F->eraseFromParent(); return bUpdated; } void PrintDiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context) { DiagnosticPrinter *printer = reinterpret_cast(Context); DI.print(*printer); } std::unique_ptr LoadModuleFromBitcode(llvm::MemoryBuffer *MB, llvm::LLVMContext &Ctx, std::string &DiagStr) { raw_string_ostream DiagStream(DiagStr); llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream); Ctx.setDiagnosticHandler(PrintDiagnosticHandler, &DiagPrinter, true); ErrorOr> pModule( llvm::parseBitcodeFile(MB->getMemBufferRef(), Ctx)); if (std::error_code ec = pModule.getError()) { return nullptr; } return std::unique_ptr(pModule.get().release()); } std::unique_ptr LoadModuleFromBitcode(llvm::StringRef BC, llvm::LLVMContext &Ctx, std::string &DiagStr) { std::unique_ptr pBitcodeBuf( llvm::MemoryBuffer::getMemBuffer(BC, "", false)); return LoadModuleFromBitcode(pBitcodeBuf.get(), Ctx, DiagStr); } } }