brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.0 KiB · 318ef06 Raw
360 lines · cpp
1#include "MCTargetDesc/SPIRVBaseInfo.h"2#include "MCTargetDesc/SPIRVMCTargetDesc.h"3#include "SPIRV.h"4#include "SPIRVGlobalRegistry.h"5#include "SPIRVRegisterInfo.h"6#include "SPIRVTargetMachine.h"7#include "SPIRVUtils.h"8#include "llvm/ADT/SmallPtrSet.h"9#include "llvm/ADT/SmallString.h"10#include "llvm/BinaryFormat/Dwarf.h"11#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"12#include "llvm/CodeGen/MachineBasicBlock.h"13#include "llvm/CodeGen/MachineFunction.h"14#include "llvm/CodeGen/MachineFunctionPass.h"15#include "llvm/CodeGen/MachineInstr.h"16#include "llvm/CodeGen/MachineInstrBuilder.h"17#include "llvm/CodeGen/MachineModuleInfo.h"18#include "llvm/CodeGen/MachineOperand.h"19#include "llvm/CodeGen/MachineRegisterInfo.h"20#include "llvm/CodeGen/Register.h"21#include "llvm/IR/DebugInfoMetadata.h"22#include "llvm/IR/DebugProgramInstruction.h"23#include "llvm/IR/Metadata.h"24#include "llvm/Support/Casting.h"25#include "llvm/Support/Path.h"26 27#define DEBUG_TYPE "spirv-nonsemantic-debug-info"28 29using namespace llvm;30 31namespace {32struct SPIRVEmitNonSemanticDI : public MachineFunctionPass {33  static char ID;34  SPIRVTargetMachine *TM;35  SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM = nullptr)36      : MachineFunctionPass(ID), TM(TM) {}37 38  bool runOnMachineFunction(MachineFunction &MF) override;39 40private:41  bool IsGlobalDIEmitted = false;42  bool emitGlobalDI(MachineFunction &MF);43};44} // anonymous namespace45 46INITIALIZE_PASS(SPIRVEmitNonSemanticDI, DEBUG_TYPE,47                "SPIRV NonSemantic.Shader.DebugInfo.100 emitter", false, false)48 49char SPIRVEmitNonSemanticDI::ID = 0;50 51MachineFunctionPass *52llvm::createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM) {53  return new SPIRVEmitNonSemanticDI(TM);54}55 56enum BaseTypeAttributeEncoding {57  Unspecified = 0,58  Address = 1,59  Boolean = 2,60  Float = 3,61  Signed = 4,62  SignedChar = 5,63  Unsigned = 6,64  UnsignedChar = 765};66 67enum SourceLanguage {68  Unknown = 0,69  ESSL = 1,70  GLSL = 2,71  OpenCL_C = 3,72  OpenCL_CPP = 4,73  HLSL = 5,74  CPP_for_OpenCL = 6,75  SYCL = 7,76  HERO_C = 8,77  NZSL = 9,78  WGSL = 10,79  Slang = 11,80  Zig = 1281};82 83bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {84  // If this MachineFunction doesn't have any BB repeat procedure85  // for the next86  if (MF.begin() == MF.end()) {87    IsGlobalDIEmitted = false;88    return false;89  }90 91  // Required variables to get from metadata search92  LLVMContext *Context;93  SmallVector<SmallString<128>> FilePaths;94  SmallVector<int64_t> LLVMSourceLanguages;95  int64_t DwarfVersion = 0;96  int64_t DebugInfoVersion = 0;97  SmallPtrSet<DIBasicType *, 12> BasicTypes;98  SmallPtrSet<DIDerivedType *, 12> PointerDerivedTypes;99  // Searching through the Module metadata to find nescessary100  // information like DwarfVersion or SourceLanguage101  {102    const MachineModuleInfo &MMI =103        getAnalysis<MachineModuleInfoWrapperPass>().getMMI();104    const Module *M = MMI.getModule();105    Context = &M->getContext();106    const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");107    if (!DbgCu)108      return false;109    for (const auto *Op : DbgCu->operands()) {110      if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) {111        DIFile *File = CompileUnit->getFile();112        FilePaths.emplace_back();113        sys::path::append(FilePaths.back(), File->getDirectory(),114                          File->getFilename());115        LLVMSourceLanguages.push_back(116            CompileUnit->getSourceLanguage().getUnversionedName());117      }118    }119    const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");120    assert(ModuleFlags && "Expected llvm.module.flags metadata to be present");121    for (const auto *Op : ModuleFlags->operands()) {122      const MDOperand &MaybeStrOp = Op->getOperand(1);123      if (MaybeStrOp.equalsStr("Dwarf Version"))124        DwarfVersion =125            cast<ConstantInt>(126                cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())127                ->getSExtValue();128      else if (MaybeStrOp.equalsStr("Debug Info Version"))129        DebugInfoVersion =130            cast<ConstantInt>(131                cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())132                ->getSExtValue();133    }134 135    // This traversal is the only supported way to access136    // instruction related DI metadata like DIBasicType137    for (auto &F : *M) {138      for (auto &BB : F) {139        for (auto &I : BB) {140          for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {141            DILocalVariable *LocalVariable = DVR.getVariable();142            if (auto *BasicType =143                    dyn_cast<DIBasicType>(LocalVariable->getType())) {144              BasicTypes.insert(BasicType);145            } else if (auto *DerivedType =146                           dyn_cast<DIDerivedType>(LocalVariable->getType())) {147              if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {148                PointerDerivedTypes.insert(DerivedType);149                // DIBasicType can be unreachable from DbgRecord and only150                // pointed on from other DI types151                // DerivedType->getBaseType is null when pointer152                // is representing a void type153                if (auto *BT = dyn_cast_or_null<DIBasicType>(154                        DerivedType->getBaseType()))155                  BasicTypes.insert(BT);156              }157            }158          }159        }160      }161    }162  }163  // NonSemantic.Shader.DebugInfo.100 global DI instruction emitting164  {165    // Required LLVM variables for emitting logic166    const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();167    const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();168    const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();169    SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();170    MachineRegisterInfo &MRI = MF.getRegInfo();171    MachineBasicBlock &MBB = *MF.begin();172 173    // To correct placement of a OpLabel instruction during SPIRVAsmPrinter174    // emission all new instructions needs to be placed after OpFunction175    // and before first terminator176    MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());177 178    const auto EmitOpString = [&](StringRef SR) {179      const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);180      MRI.setType(StrReg, LLT::scalar(32));181      MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);182      MIB.addDef(StrReg);183      addStringImm(SR, MIB);184      return StrReg;185    };186 187    const SPIRVType *VoidTy =188        GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder,189                                 SPIRV::AccessQualifier::ReadWrite, false);190 191    const auto EmitDIInstruction =192        [&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,193            std::initializer_list<Register> Registers) {194          const Register InstReg =195              MRI.createVirtualRegister(&SPIRV::IDRegClass);196          MRI.setType(InstReg, LLT::scalar(32));197          MachineInstrBuilder MIB =198              MIRBuilder.buildInstr(SPIRV::OpExtInst)199                  .addDef(InstReg)200                  .addUse(GR->getSPIRVTypeID(VoidTy))201                  .addImm(static_cast<int64_t>(202                      SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))203                  .addImm(Inst);204          for (auto Reg : Registers) {205            MIB.addUse(Reg);206          }207          MIB.constrainAllUses(*TII, *TRI, *RBI);208          GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF);209          return InstReg;210        };211 212    const SPIRVType *I32Ty =213        GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder,214                                 SPIRV::AccessQualifier::ReadWrite, false);215 216    const Register DwarfVersionReg =217        GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false);218 219    const Register DebugInfoVersionReg =220        GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false);221 222    for (unsigned Idx = 0; Idx < LLVMSourceLanguages.size(); ++Idx) {223      const Register FilePathStrReg = EmitOpString(FilePaths[Idx]);224 225      const Register DebugSourceResIdReg = EmitDIInstruction(226          SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});227 228      SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;229      switch (LLVMSourceLanguages[Idx]) {230      case dwarf::DW_LANG_OpenCL:231        SpirvSourceLanguage = SourceLanguage::OpenCL_C;232        break;233      case dwarf::DW_LANG_OpenCL_CPP:234        SpirvSourceLanguage = SourceLanguage::OpenCL_CPP;235        break;236      case dwarf::DW_LANG_CPP_for_OpenCL:237        SpirvSourceLanguage = SourceLanguage::CPP_for_OpenCL;238        break;239      case dwarf::DW_LANG_GLSL:240        SpirvSourceLanguage = SourceLanguage::GLSL;241        break;242      case dwarf::DW_LANG_HLSL:243        SpirvSourceLanguage = SourceLanguage::HLSL;244        break;245      case dwarf::DW_LANG_SYCL:246        SpirvSourceLanguage = SourceLanguage::SYCL;247        break;248      case dwarf::DW_LANG_Zig:249        SpirvSourceLanguage = SourceLanguage::Zig;250      }251 252      const Register SourceLanguageReg =253          GR->buildConstantInt(SpirvSourceLanguage, MIRBuilder, I32Ty, false);254 255      [[maybe_unused]]256      const Register DebugCompUnitResIdReg =257          EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,258                            {DebugInfoVersionReg, DwarfVersionReg,259                             DebugSourceResIdReg, SourceLanguageReg});260    }261 262    // We aren't extracting any DebugInfoFlags now so we263    // emitting zero to use as <id>Flags argument for DebugBasicType264    const Register I32ZeroReg =265        GR->buildConstantInt(0, MIRBuilder, I32Ty, false, false);266 267    // We need to store pairs because further instructions reference268    // the DIBasicTypes and size will be always small so there isn't269    // need for any kind of map270    SmallVector<std::pair<const DIBasicType *const, const Register>, 12>271        BasicTypeRegPairs;272    for (auto *BasicType : BasicTypes) {273      const Register BasicTypeStrReg = EmitOpString(BasicType->getName());274 275      const Register ConstIntBitwidthReg = GR->buildConstantInt(276          BasicType->getSizeInBits(), MIRBuilder, I32Ty, false);277 278      uint64_t AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;279      switch (BasicType->getEncoding()) {280      case dwarf::DW_ATE_signed:281        AttributeEncoding = BaseTypeAttributeEncoding::Signed;282        break;283      case dwarf::DW_ATE_unsigned:284        AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;285        break;286      case dwarf::DW_ATE_unsigned_char:287        AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;288        break;289      case dwarf::DW_ATE_signed_char:290        AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;291        break;292      case dwarf::DW_ATE_float:293        AttributeEncoding = BaseTypeAttributeEncoding::Float;294        break;295      case dwarf::DW_ATE_boolean:296        AttributeEncoding = BaseTypeAttributeEncoding::Boolean;297        break;298      case dwarf::DW_ATE_address:299        AttributeEncoding = BaseTypeAttributeEncoding::Address;300      }301 302      const Register AttributeEncodingReg =303          GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false);304 305      const Register BasicTypeReg =306          EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic,307                            {BasicTypeStrReg, ConstIntBitwidthReg,308                             AttributeEncodingReg, I32ZeroReg});309      BasicTypeRegPairs.emplace_back(BasicType, BasicTypeReg);310    }311 312    if (PointerDerivedTypes.size()) {313      for (const auto *PointerDerivedType : PointerDerivedTypes) {314 315        assert(PointerDerivedType->getDWARFAddressSpace().has_value());316        const Register StorageClassReg = GR->buildConstantInt(317            addressSpaceToStorageClass(318                PointerDerivedType->getDWARFAddressSpace().value(),319                *TM->getSubtargetImpl()),320            MIRBuilder, I32Ty, false);321 322        // If the Pointer is representing a void type it's getBaseType323        // is a nullptr324        const auto *MaybeNestedBasicType =325            dyn_cast_or_null<DIBasicType>(PointerDerivedType->getBaseType());326        if (MaybeNestedBasicType) {327          for (const auto &BasicTypeRegPair : BasicTypeRegPairs) {328            const auto &[DefinedBasicType, BasicTypeReg] = BasicTypeRegPair;329            if (DefinedBasicType == MaybeNestedBasicType) {330              [[maybe_unused]]331              const Register DebugPointerTypeReg = EmitDIInstruction(332                  SPIRV::NonSemanticExtInst::DebugTypePointer,333                  {BasicTypeReg, StorageClassReg, I32ZeroReg});334            }335          }336        } else {337          const Register DebugInfoNoneReg =338              EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {});339          [[maybe_unused]]340          const Register DebugPointerTypeReg = EmitDIInstruction(341              SPIRV::NonSemanticExtInst::DebugTypePointer,342              {DebugInfoNoneReg, StorageClassReg, I32ZeroReg});343        }344      }345    }346  }347  return true;348}349 350bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {351  bool Res = false;352  // emitGlobalDI needs to be executed only once to avoid353  // emitting duplicates354  if (!IsGlobalDIEmitted) {355    IsGlobalDIEmitted = true;356    Res = emitGlobalDI(MF);357  }358  return Res;359}360