| /////////////////////////////////////////////////////////////////////////////// |
| // // |
| // 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<PointerType>(Ty)) |
| Ty = Ty->getPointerElementType(); |
| while (isa<ArrayType>(Ty)) { |
| Ty = Ty->getArrayElementType(); |
| } |
| return Ty; |
| } |
| |
| bool HasDynamicIndexing(Value *V) { |
| for (auto User : V->users()) { |
| if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) { |
| for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) { |
| if (!isa<ConstantInt>(Idx)) |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| unsigned |
| GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation, |
| llvm::Type *Ty, |
| DxilTypeSystem &typeSys) { |
| |
| while (isa<ArrayType>(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<StructType>(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<Function *> 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<DiagnosticPrinter *>(Context); |
| DI.print(*printer); |
| } |
| |
| std::unique_ptr<llvm::Module> 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<std::unique_ptr<llvm::Module>> pModule( |
| llvm::parseBitcodeFile(MB->getMemBufferRef(), Ctx)); |
| if (std::error_code ec = pModule.getError()) { |
| return nullptr; |
| } |
| return std::unique_ptr<llvm::Module>(pModule.get().release()); |
| } |
| |
| std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::StringRef BC, |
| llvm::LLVMContext &Ctx, |
| std::string &DiagStr) { |
| std::unique_ptr<llvm::MemoryBuffer> pBitcodeBuf( |
| llvm::MemoryBuffer::getMemBuffer(BC, "", false)); |
| return LoadModuleFromBitcode(pBitcodeBuf.get(), Ctx, DiagStr); |
| } |
| |
| } |
| } |