================ @@ -0,0 +1,934 @@ +//===-- PISAAsmPrinter.cpp - PISA LLVM assembly writer --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/PISAInstPrinter.h" +#include "MCTargetDesc/PISARegEncoder.h" +#include "MCTargetDesc/PISATargetStreamer.h" +#include "PISA.h" +#include "PISAInstrInfo.h" +#include "PISAMCInstLower.h" +#include "PISAMachineFunctionInfo.h" +#include "PISARegManager.h" +#include "PISASubtarget.h" +#include "PISATargetMachine.h" +#include "PISAUtils.h" +#include "TargetInfo/PISATargetInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/PISAAddrSpace.h" +#include "llvm/Support/Regex.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/PISATargetParser.h" +#include <llvm/IR/DiagnosticInfo.h> + +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +namespace { +class PISAAsmPrinter : public AsmPrinter { + +public: + PISATargetStreamer &getTargetStreamer() const { + return static_cast<PISATargetStreamer &>(*OutStreamer->getTargetStreamer()); + } + +private: + void collectRegDcls(PISA::RegDcls &); + void collectLocalVariableDcls(PISA::LocalVariableDcls &); + void updateFuncParamIdxs(PISA::DataTypes &DTs); + + void outputInstruction(const MachineInstr *MI); + void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); + + std::string getVirtualRegisterName(Register R) const; + + void collectFunctionDeclaration(PISA::FunctionDeclaration &, + const Function &F); + void collectFunctionSignature(PISA::FunctionSignature &); + void collectFunctionParameters(PISA::FunctionSignature &); + void collectKernelParameters(PISA::FunctionSignature &); + void collectFunctionDirectiveAndName(PISA::FunctionDirectiveAndName &DN, + const Function &F); + PISA::LinkageTy collectLinkage(const GlobalValue &V); + void collectGlobalVariable(PISA::GlobalVariableDcl &PGV, + const GlobalVariable &GV); + + void emitGlobalsAndFuncDecls(Module &M); + + const PISASubtarget *ST = nullptr; + const PISAInstrInfo *TII = nullptr; + const PISARegisterInfo *TRI = nullptr; + PISA::RegManager *RegMgr = nullptr; + PISA::DataTypes *DTs = nullptr; + bool GlobalsEmitted = false; + + class FlattenGlobal { + public: + FlattenGlobal(const Constant *C, PISA::VariableInit &VI, + const DataLayout &DL, AsmPrinter &AP) + : DL(DL), VI(VI), AP(AP) { + process(C); + dischargeZeros(); + assert(computeSize(C) == DL.getTypeAllocSize(C->getType()) && + "size mismatch?"); + } + + private: + bool isZero(const Constant *C) const { + if (isa<ConstantPointerNull>(C)) + return false; + + return C->isNullValue() || isa<UndefValue>(C); + } + void pad(const Constant *C, unsigned NumElts = 0) { + unsigned Size = DL.getTypeAllocSize(C->getType()); + if (NumElts == 0) { + ZeroCnt += Size; + return; + } + unsigned EmittedSize = + DL.getTypeAllocSize(C->getType()->getContainedType(0)) * NumElts; + assert(EmittedSize <= Size && "Size cannot be less than EmittedSize!"); + if (unsigned Padding = Size - EmittedSize) + ZeroCnt += Padding; + } + void pad(uint64_t NumBytes) { ZeroCnt += NumBytes; } + void dischargeZeros() { + if (ZeroCnt == 0) + return; + // Insert dummy slot + VI.Initializer.push_back({LLT{}, 0}); + uint64_t Idx = VI.Initializer.size() - 1; + VI.Exprs.insert({Idx, PISA::VariableInit::Zeros{ZeroCnt}}); + ZeroCnt = 0; + } + void addVal(LLT Ty, uint64_t Val) { + dischargeZeros(); + VI.Initializer.push_back({Ty, Val}); + } + void addGlobal(LLT Ty, const PISA::VariableInit::GlobalExpr &GE) { + // Insert dummy slot + addVal(Ty, 0); + uint64_t Idx = VI.Initializer.size() - 1; + VI.Exprs.insert({Idx, GE}); + } + void lowerConstant(const Constant *C) { + auto *Expr = AP.lowerConstant(C); + MCValue Res; + if (!Expr->evaluateAsRelocatable(Res, nullptr)) + llvm_unreachable("unhandled expression!"); + LLT Ty = getLLTForType(*C->getType(), DL); + if (!Res.getAddSym() && !Res.getSubSym()) { + if (Res.getConstant() == 0) + pad(C); + else + addVal(Ty, static_cast<uint64_t>(Res.getConstant())); + return; + } + assert(!Res.getSubSym() && "unhandled expression!"); + std::string Name = Res.getAddSym()->getName().str(); + PISA::VariableInit::GlobalExpr E{std::move(Name), Res.getConstant()}; + addGlobal(Ty, E); + } + uint64_t computeSize(const Constant *C) const { + uint64_t Total = 0; + for (auto [i, Elt] : llvm::enumerate(VI.Initializer)) { + if (auto Iter = VI.Exprs.find(i); Iter != VI.Exprs.end()) { + auto &Entry = Iter->second; + if (auto *Z = std::get_if<PISA::VariableInit::Zeros>(&Entry)) { + Total += Z->N; + continue; + } + } + Total += Elt.Type.getSizeInBytes(); + } + return Total; + } + void emitGlobalConstantLargeInt(const ConstantInt *CI) { + unsigned BitWidth = CI->getBitWidth(); + + // Copy the value as we may massage the layout for constants whose bit + // width is not a multiple of 64-bits. + APInt Realigned(CI->getValue()); + uint64_t ExtraBits = 0; + unsigned ExtraBitsSize = BitWidth & 63; + + if (ExtraBitsSize) { + // The bit width of the data is not a multiple of 64-bits. + // The extra bits are expected to be at the end of the chunk of the + // memory. Little endian: + // * Nothing to be done, just record the extra bits to emit. + ExtraBits = Realigned.getRawData()[BitWidth / 64]; + } + + // We don't expect assemblers to support integer data directives + // for more than 64 bits, so we emit the data in at most 64-bit + // quantities at a time. + const uint64_t *RawData = Realigned.getRawData(); + for (unsigned I = 0, E = BitWidth / 64; I != E; ++I) + addVal(LLT::integer(64), RawData[I]); + + if (ExtraBitsSize) { + // Emit the extra bits after the 64-bits chunks. + // Emit a directive that fills the expected size. + uint64_t Size = DL.getTypeStoreSize(CI->getType()); + Size -= (BitWidth / 64) * 8; + assert(Size && Size * 8 >= ExtraBitsSize && + (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) == + ExtraBits && + "Directive too small for extra bits."); + addVal(LLT::integer(Size * 8), ExtraBits); + } + } + const DataLayout &DL; + PISA::VariableInit &VI; + AsmPrinter &AP; + void process(const Constant *C); + unsigned ZeroCnt = 0; + }; + +protected: + bool doInitialization(Module &M) override; + bool doFinalization(Module &M) override; + +public: + explicit PISAAsmPrinter(TargetMachine &TM, + std::unique_ptr<MCStreamer> Streamer) + : AsmPrinter(TM, std::move(Streamer)) {} + + StringRef getPassName() const override { return "PISA Assembly Printer"; } + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + const char *ExtraCode, raw_ostream &O) override; + + void emitInstruction(const MachineInstr *MI) override; + void emitFunctionHeader() override; + void emitFunctionBodyStart() override; + void emitFunctionBodyEnd() override; + void emitEndOfAsmFile(Module &) override; + + void emitFunctionEntryLabel() override {} + void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {} + void emitGlobalVariable(const GlobalVariable *GV) override {} + + bool runOnMachineFunction(MachineFunction &MF) override; +}; +} // namespace + +void PISAAsmPrinter::FlattenGlobal::process(const Constant *C) { ---------------- arsenm wrote:
I'm not sure why you need this, the generic asm printer already has the code to write out a constant aggregate? https://github.com/llvm/llvm-project/pull/214647 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
