brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 44eea81 Raw
197 lines · cpp
1//===-- MSP430AsmPrinter.cpp - MSP430 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains a printer that converts from our internal representation10// of machine-dependent LLVM code to the MSP430 assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "MCTargetDesc/MSP430InstPrinter.h"15#include "MSP430MCInstLower.h"16#include "MSP430TargetMachine.h"17#include "TargetInfo/MSP430TargetInfo.h"18#include "llvm/BinaryFormat/ELF.h"19#include "llvm/CodeGen/AsmPrinter.h"20#include "llvm/CodeGen/MachineConstantPool.h"21#include "llvm/CodeGen/MachineInstr.h"22#include "llvm/CodeGen/MachineModuleInfo.h"23#include "llvm/IR/Mangler.h"24#include "llvm/MC/MCAsmInfo.h"25#include "llvm/MC/MCInst.h"26#include "llvm/MC/MCSectionELF.h"27#include "llvm/MC/MCStreamer.h"28#include "llvm/MC/MCSymbol.h"29#include "llvm/MC/TargetRegistry.h"30#include "llvm/Support/Compiler.h"31#include "llvm/Support/raw_ostream.h"32using namespace llvm;33 34#define DEBUG_TYPE "asm-printer"35 36namespace {37  class MSP430AsmPrinter : public AsmPrinter {38  public:39    MSP430AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)40        : AsmPrinter(TM, std::move(Streamer), ID) {}41 42    StringRef getPassName() const override { return "MSP430 Assembly Printer"; }43 44    bool runOnMachineFunction(MachineFunction &MF) override;45 46    void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;47    void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,48                      bool PrefixHash = true);49    void printSrcMemOperand(const MachineInstr *MI, int OpNum,50                            raw_ostream &O);51    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,52                         const char *ExtraCode, raw_ostream &O) override;53    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,54                               const char *ExtraCode, raw_ostream &O) override;55    void emitInstruction(const MachineInstr *MI) override;56 57    void EmitInterruptVectorSection(MachineFunction &ISR);58 59    static char ID;60  };61} // end of anonymous namespace62 63void MSP430AsmPrinter::PrintSymbolOperand(const MachineOperand &MO,64                                          raw_ostream &O) {65  uint64_t Offset = MO.getOffset();66  if (Offset)67    O << '(' << Offset << '+';68 69  getSymbol(MO.getGlobal())->print(O, MAI);70 71  if (Offset)72    O << ')';73}74 75void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,76                                    raw_ostream &O, bool PrefixHash) {77  const MachineOperand &MO = MI->getOperand(OpNum);78  switch (MO.getType()) {79  default: llvm_unreachable("Not implemented yet!");80  case MachineOperand::MO_Register:81    O << MSP430InstPrinter::getRegisterName(MO.getReg());82    return;83  case MachineOperand::MO_Immediate:84    if (PrefixHash)85      O << '#';86    O << MO.getImm();87    return;88  case MachineOperand::MO_MachineBasicBlock:89    MO.getMBB()->getSymbol()->print(O, MAI);90    return;91  case MachineOperand::MO_GlobalAddress: {92    // If the global address expression is a part of displacement field with a93    // register base, we should not emit any prefix symbol here, e.g.94    //   mov.w glb(r1), r295    // Otherwise (!) msp430-as will silently miscompile the output :(96    if (PrefixHash)97      O << '#';98    PrintSymbolOperand(MO, O);99    return;100  }101  }102}103 104void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,105                                          raw_ostream &O) {106  const MachineOperand &Base = MI->getOperand(OpNum);107  const MachineOperand &Disp = MI->getOperand(OpNum+1);108 109  // Print displacement first110 111  // Imm here is in fact global address - print extra modifier.112  if (Disp.isImm() && Base.getReg() == MSP430::SR)113    O << '&';114  printOperand(MI, OpNum + 1, O, /*PrefixHash=*/false);115 116  // Print register base field117  if (Base.getReg() != MSP430::SR && Base.getReg() != MSP430::PC) {118    O << '(';119    printOperand(MI, OpNum, O);120    O << ')';121  }122}123 124/// PrintAsmOperand - Print out an operand for an inline asm expression.125///126bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,127                                       const char *ExtraCode, raw_ostream &O) {128  // Does this asm operand have a single letter operand modifier?129  if (ExtraCode && ExtraCode[0])130    return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);131 132  printOperand(MI, OpNo, O);133  return false;134}135 136bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,137                                             unsigned OpNo,138                                             const char *ExtraCode,139                                             raw_ostream &O) {140  if (ExtraCode && ExtraCode[0]) {141    return true; // Unknown modifier.142  }143  printSrcMemOperand(MI, OpNo, O);144  return false;145}146 147//===----------------------------------------------------------------------===//148void MSP430AsmPrinter::emitInstruction(const MachineInstr *MI) {149  MSP430_MC::verifyInstructionPredicates(MI->getOpcode(),150                                         getSubtargetInfo().getFeatureBits());151 152  MSP430MCInstLower MCInstLowering(OutContext, *this);153 154  MCInst TmpInst;155  MCInstLowering.Lower(MI, TmpInst);156  EmitToStreamer(*OutStreamer, TmpInst);157}158 159void MSP430AsmPrinter::EmitInterruptVectorSection(MachineFunction &ISR) {160  MCSection *Cur = OutStreamer->getCurrentSectionOnly();161  const auto *F = &ISR.getFunction();162  if (F->getCallingConv() != CallingConv::MSP430_INTR) {163    report_fatal_error("Functions with 'interrupt' attribute must have msp430_intrcc CC");164  }165  StringRef IVIdx = F->getFnAttribute("interrupt").getValueAsString();166  MCSection *IV = OutStreamer->getContext().getELFSection(167    "__interrupt_vector_" + IVIdx,168    ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_EXECINSTR);169  OutStreamer->switchSection(IV);170 171  const MCSymbol *FunctionSymbol = getSymbol(F);172  OutStreamer->emitSymbolValue(FunctionSymbol, TM.getProgramPointerSize());173  OutStreamer->switchSection(Cur);174}175 176bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {177  // Emit separate section for an interrupt vector if ISR178  if (MF.getFunction().hasFnAttribute("interrupt")) {179    EmitInterruptVectorSection(MF);180  }181 182  SetupMachineFunction(MF);183  emitFunctionBody();184  return false;185}186 187char MSP430AsmPrinter::ID = 0;188 189INITIALIZE_PASS(MSP430AsmPrinter, "msp430-asm-printer",190                "MSP430 Assembly Printer", false, false)191 192// Force static initialization.193extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void194LLVMInitializeMSP430AsmPrinter() {195  RegisterAsmPrinter<MSP430AsmPrinter> X(getTheMSP430Target());196}197