1 //===-- CSKYAsmPrinter.cpp - CSKY LLVM assembly writer --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains a printer that converts from our internal representation 10 // of machine-dependent LLVM code to the CSKY assembly language. 11 // 12 //===----------------------------------------------------------------------===// 13 #include "CSKYAsmPrinter.h" 14 #include "CSKY.h" 15 #include "CSKYConstantPoolValue.h" 16 #include "CSKYTargetMachine.h" 17 #include "MCTargetDesc/CSKYInstPrinter.h" 18 #include "MCTargetDesc/CSKYMCExpr.h" 19 #include "TargetInfo/CSKYTargetInfo.h" 20 #include "llvm/ADT/Statistic.h" 21 #include "llvm/CodeGen/AsmPrinter.h" 22 #include "llvm/CodeGen/MachineConstantPool.h" 23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/MC/MCAsmInfo.h" 25 #include "llvm/MC/MCContext.h" 26 #include "llvm/MC/MCInstBuilder.h" 27 #include "llvm/MC/MCStreamer.h" 28 #include "llvm/MC/TargetRegistry.h" 29 30 using namespace llvm; 31 32 #define DEBUG_TYPE "csky-asm-printer" 33 34 STATISTIC(CSKYNumInstrsCompressed, 35 "Number of C-SKY Compressed instructions emitted"); 36 37 CSKYAsmPrinter::CSKYAsmPrinter(llvm::TargetMachine &TM, 38 std::unique_ptr<llvm::MCStreamer> Streamer) 39 : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {} 40 41 bool CSKYAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 42 MCP = MF.getConstantPool(); 43 Subtarget = &MF.getSubtarget<CSKYSubtarget>(); 44 return AsmPrinter::runOnMachineFunction(MF); 45 } 46 47 #define GEN_COMPRESS_INSTR 48 #include "CSKYGenCompressInstEmitter.inc" 49 void CSKYAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { 50 MCInst CInst; 51 bool Res = compressInst(CInst, Inst, *Subtarget, OutStreamer->getContext()); 52 if (Res) 53 ++CSKYNumInstrsCompressed; 54 AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst); 55 } 56 57 // Simple pseudo-instructions have their lowering (with expansion to real 58 // instructions) auto-generated. 59 #include "CSKYGenMCPseudoLowering.inc" 60 61 void CSKYAsmPrinter::emitCustomConstantPool(const MachineInstr *MI) { 62 63 // This instruction represents a floating constant pool in the function. 64 // The first operand is the ID# for this instruction, the second is the 65 // index into the MachineConstantPool that this is, the third is the size 66 // in bytes of this constant pool entry. 67 // The required alignment is specified on the basic block holding this MI. 68 unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); 69 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); 70 71 // If this is the first entry of the pool, mark it. 72 if (!InConstantPool) { 73 OutStreamer->emitValueToAlignment(4); 74 InConstantPool = true; 75 } 76 77 OutStreamer->emitLabel(GetCPISymbol(LabelId)); 78 79 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; 80 if (MCPE.isMachineConstantPoolEntry()) 81 emitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 82 else 83 emitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal); 84 return; 85 } 86 87 void CSKYAsmPrinter::emitFunctionBodyEnd() { 88 // Make sure to terminate any constant pools that were at the end 89 // of the function. 90 if (!InConstantPool) 91 return; 92 InConstantPool = false; 93 } 94 95 void CSKYAsmPrinter::emitInstruction(const MachineInstr *MI) { 96 // Do any auto-generated pseudo lowerings. 97 if (emitPseudoExpansionLowering(*OutStreamer, MI)) 98 return; 99 100 // If we just ended a constant pool, mark it as such. 101 if (InConstantPool && MI->getOpcode() != CSKY::CONSTPOOL_ENTRY) { 102 InConstantPool = false; 103 } 104 105 if (MI->getOpcode() == CSKY::CONSTPOOL_ENTRY) 106 return emitCustomConstantPool(MI); 107 108 MCInst TmpInst; 109 MCInstLowering.Lower(MI, TmpInst); 110 EmitToStreamer(*OutStreamer, TmpInst); 111 } 112 113 // Convert a CSKY-specific constant pool modifier into the associated 114 // MCSymbolRefExpr variant kind. 115 static CSKYMCExpr::VariantKind 116 getModifierVariantKind(CSKYCP::CSKYCPModifier Modifier) { 117 switch (Modifier) { 118 case CSKYCP::NO_MOD: 119 return CSKYMCExpr::VK_CSKY_None; 120 case CSKYCP::ADDR: 121 return CSKYMCExpr::VK_CSKY_ADDR; 122 case CSKYCP::GOT: 123 return CSKYMCExpr::VK_CSKY_GOT; 124 case CSKYCP::GOTOFF: 125 return CSKYMCExpr::VK_CSKY_GOTOFF; 126 case CSKYCP::PLT: 127 return CSKYMCExpr::VK_CSKY_PLT; 128 case CSKYCP::TLSGD: 129 return CSKYMCExpr::VK_CSKY_TLSGD; 130 case CSKYCP::TLSLE: 131 return CSKYMCExpr::VK_CSKY_TLSLE; 132 case CSKYCP::TLSIE: 133 return CSKYMCExpr::VK_CSKY_TLSIE; 134 } 135 llvm_unreachable("Invalid CSKYCPModifier!"); 136 } 137 138 void CSKYAsmPrinter::emitMachineConstantPoolValue( 139 MachineConstantPoolValue *MCPV) { 140 int Size = getDataLayout().getTypeAllocSize(MCPV->getType()); 141 CSKYConstantPoolValue *CCPV = static_cast<CSKYConstantPoolValue *>(MCPV); 142 MCSymbol *MCSym; 143 144 if (CCPV->isBlockAddress()) { 145 const BlockAddress *BA = 146 cast<CSKYConstantPoolConstant>(CCPV)->getBlockAddress(); 147 MCSym = GetBlockAddressSymbol(BA); 148 } else if (CCPV->isGlobalValue()) { 149 const GlobalValue *GV = cast<CSKYConstantPoolConstant>(CCPV)->getGV(); 150 MCSym = getSymbol(GV); 151 } else if (CCPV->isMachineBasicBlock()) { 152 const MachineBasicBlock *MBB = cast<CSKYConstantPoolMBB>(CCPV)->getMBB(); 153 MCSym = MBB->getSymbol(); 154 } else if (CCPV->isJT()) { 155 signed JTI = cast<CSKYConstantPoolJT>(CCPV)->getJTI(); 156 MCSym = GetJTISymbol(JTI); 157 } else { 158 assert(CCPV->isExtSymbol() && "unrecognized constant pool value"); 159 StringRef Sym = cast<CSKYConstantPoolSymbol>(CCPV)->getSymbol(); 160 MCSym = GetExternalSymbolSymbol(Sym); 161 } 162 // Create an MCSymbol for the reference. 163 const MCExpr *Expr = 164 MCSymbolRefExpr::create(MCSym, MCSymbolRefExpr::VK_None, OutContext); 165 166 if (CCPV->getPCAdjustment()) { 167 168 MCSymbol *PCLabel = OutContext.getOrCreateSymbol( 169 Twine(MAI->getPrivateGlobalPrefix()) + "PC" + 170 Twine(getFunctionNumber()) + "_" + Twine(CCPV->getLabelID())); 171 172 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext); 173 if (CCPV->mustAddCurrentAddress()) { 174 // We want "(<expr> - .)", but MC doesn't have a concept of the '.' 175 // label, so just emit a local label end reference that instead. 176 MCSymbol *DotSym = OutContext.createTempSymbol(); 177 OutStreamer->emitLabel(DotSym); 178 const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext); 179 PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext); 180 } 181 Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext); 182 } 183 184 // Create an MCSymbol for the reference. 185 Expr = CSKYMCExpr::create(Expr, getModifierVariantKind(CCPV->getModifier()), 186 OutContext); 187 188 OutStreamer->emitValue(Expr, Size); 189 } 190 191 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmPrinter() { 192 RegisterAsmPrinter<CSKYAsmPrinter> X(getTheCSKYTarget()); 193 } 194