Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[AVR] Add the assembly instruction printer
Summary: This change adds the AVR assembly instruction printer. No tests are included in this patch. I have left them downstream so we can add them once `llc` successfully runs (there's very few components left to upstream until this). Reviewers: arsenm, kparzysz Subscribers: wdng, beanz, mgorny Differential Revision: https://reviews.llvm.org/D25028 llvm-svn: 282854
- Loading branch information
Dylan McKay
committed
Sep 30, 2016
1 parent
77394f1
commit 1a7bd84
Showing
6 changed files
with
260 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
//===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This class prints an AVR MCInst to a .s file. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "AVRInstPrinter.h" | ||
|
||
#include "MCTargetDesc/AVRMCTargetDesc.h" | ||
|
||
#include "llvm/MC/MCExpr.h" | ||
#include "llvm/MC/MCInst.h" | ||
#include "llvm/MC/MCInstrDesc.h" | ||
#include "llvm/MC/MCInstrInfo.h" | ||
#include "llvm/MC/MCRegisterInfo.h" | ||
#include "llvm/Support/ErrorHandling.h" | ||
#include "llvm/Support/FormattedStream.h" | ||
|
||
#include <cstring> | ||
|
||
#define DEBUG_TYPE "asm-printer" | ||
|
||
namespace llvm { | ||
|
||
// Include the auto-generated portion of the assembly writer. | ||
#define PRINT_ALIAS_INSTR | ||
#include "AVRGenAsmWriter.inc" | ||
|
||
void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O, | ||
StringRef Annot, const MCSubtargetInfo &STI) { | ||
unsigned Opcode = MI->getOpcode(); | ||
|
||
// First handle load and store instructions with postinc or predec | ||
// of the form "ld reg, X+". | ||
// TODO: We should be able to rewrite this using TableGen data. | ||
switch (Opcode) { | ||
case AVR::LDRdPtr: | ||
case AVR::LDRdPtrPi: | ||
case AVR::LDRdPtrPd: | ||
O << "\tld\t"; | ||
printOperand(MI, 0, O); | ||
O << ", "; | ||
|
||
if (Opcode == AVR::LDRdPtrPd) | ||
O << '-'; | ||
|
||
printOperand(MI, 1, O); | ||
|
||
if (Opcode == AVR::LDRdPtrPi) | ||
O << '+'; | ||
break; | ||
case AVR::STPtrRr: | ||
O << "\tst\t"; | ||
printOperand(MI, 0, O); | ||
O << ", "; | ||
printOperand(MI, 1, O); | ||
break; | ||
case AVR::STPtrPiRr: | ||
case AVR::STPtrPdRr: | ||
O << "\tst\t"; | ||
|
||
if (Opcode == AVR::STPtrPdRr) | ||
O << '-'; | ||
|
||
printOperand(MI, 1, O); | ||
|
||
if (Opcode == AVR::STPtrPiRr) | ||
O << '+'; | ||
|
||
O << ", "; | ||
printOperand(MI, 2, O); | ||
break; | ||
default: | ||
if (!printAliasInstr(MI, O)) | ||
printInstruction(MI, O); | ||
|
||
printAnnotation(O, Annot); | ||
break; | ||
} | ||
} | ||
|
||
const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum, | ||
MCRegisterInfo const &MRI) { | ||
// GCC prints register pairs by just printing the lower register | ||
// If the register contains a subregister, print it instead | ||
if (MRI.getNumSubRegIndices() > 0) { | ||
unsigned RegLoNum = MRI.getSubReg(RegNum, AVR::sub_lo); | ||
RegNum = (RegLoNum != AVR::NoRegister) ? RegLoNum : RegNum; | ||
} | ||
|
||
return getRegisterName(RegNum); | ||
} | ||
|
||
void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, | ||
raw_ostream &O) { | ||
const MCOperand &Op = MI->getOperand(OpNo); | ||
const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo]; | ||
|
||
if (Op.isReg()) { | ||
bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) || | ||
(MOI.RegClass == AVR::PTRDISPREGSRegClassID) || | ||
(MOI.RegClass == AVR::ZREGSRegClassID); | ||
|
||
if (isPtrReg) { | ||
O << getRegisterName(Op.getReg(), AVR::ptr); | ||
} else { | ||
O << getPrettyRegisterName(Op.getReg(), MRI); | ||
} | ||
} else if (Op.isImm()) { | ||
O << Op.getImm(); | ||
} else { | ||
assert(Op.isExpr() && "Unknown operand kind in printOperand"); | ||
O << *Op.getExpr(); | ||
} | ||
} | ||
|
||
/// This is used to print an immediate value that ends up | ||
/// being encoded as a pc-relative value. | ||
void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo, | ||
raw_ostream &O) { | ||
const MCOperand &Op = MI->getOperand(OpNo); | ||
|
||
if (Op.isImm()) { | ||
int64_t Imm = Op.getImm(); | ||
O << '.'; | ||
|
||
// Print a position sign if needed. | ||
// Negative values have their sign printed automatically. | ||
if (Imm >= 0) | ||
O << '+'; | ||
|
||
O << Imm; | ||
} else { | ||
assert(Op.isExpr() && "Unknown pcrel immediate operand"); | ||
O << *Op.getExpr(); | ||
} | ||
} | ||
|
||
void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, | ||
raw_ostream &O) { | ||
const MCOperand &RegOp = MI->getOperand(OpNo); | ||
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); | ||
|
||
assert(RegOp.isReg() && "Expected a register"); | ||
|
||
// Print the register. | ||
printOperand(MI, OpNo, O); | ||
|
||
// Print the {+,-}offset. | ||
if (OffsetOp.isImm()) { | ||
int64_t Offset = OffsetOp.getImm(); | ||
|
||
if (Offset >= 0) | ||
O << '+'; | ||
|
||
O << Offset; | ||
} else if (OffsetOp.isExpr()) { | ||
O << *OffsetOp.getExpr(); | ||
} else { | ||
llvm_unreachable("unknown type for offset"); | ||
} | ||
} | ||
|
||
} // end of namespace llvm | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//===- AVRInstPrinter.h - Convert AVR MCInst to assembly syntax -*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This class prints an AVR MCInst to a .s file. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_AVR_INST_PRINTER_H | ||
#define LLVM_AVR_INST_PRINTER_H | ||
|
||
#include "llvm/MC/MCInstPrinter.h" | ||
|
||
#include "MCTargetDesc/AVRMCTargetDesc.h" | ||
|
||
namespace llvm { | ||
|
||
/// Prints AVR instructions to a textual stream. | ||
class AVRInstPrinter : public MCInstPrinter { | ||
public: | ||
AVRInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, | ||
const MCRegisterInfo &MRI) | ||
: MCInstPrinter(MAI, MII, MRI) {} | ||
|
||
static const char *getPrettyRegisterName(unsigned RegNo, | ||
MCRegisterInfo const &MRI); | ||
|
||
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, | ||
const MCSubtargetInfo &STI) override; | ||
|
||
private: | ||
static const char *getRegisterName(unsigned RegNo, | ||
unsigned AltIdx = AVR::NoRegAltName); | ||
|
||
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); | ||
void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &O); | ||
void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O); | ||
|
||
// Autogenerated by TableGen. | ||
void printInstruction(const MCInst *MI, raw_ostream &O); | ||
bool printAliasInstr(const MCInst *MI, raw_ostream &O); | ||
void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, | ||
unsigned PrintMethodIdx, raw_ostream &O); | ||
}; | ||
|
||
} // end namespace llvm | ||
|
||
#endif // LLVM_AVR_INST_PRINTER_H | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. | ||
${CMAKE_CURRENT_SOURCE_DIR}/.. ) | ||
|
||
add_llvm_library(LLVMAVRAsmPrinter | ||
AVRInstPrinter.cpp | ||
) | ||
|
||
add_dependencies(LLVMAVRAsmPrinter AVRCommonTableGen) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
;===- ./lib/Target/AVR/InstPrinter/LLVMBuild.txt ----------------*- Conf -*--===; | ||
; | ||
; The LLVM Compiler Infrastructure | ||
; | ||
; This file is distributed under the University of Illinois Open Source | ||
; License. See LICENSE.TXT for details. | ||
; | ||
;===------------------------------------------------------------------------===; | ||
; | ||
; This is an LLVMBuild description file for the components in this subdirectory. | ||
; | ||
; For more information on the LLVMBuild system, please see: | ||
; | ||
; http://llvm.org/docs/LLVMBuild.html | ||
; | ||
;===------------------------------------------------------------------------===; | ||
|
||
[component_0] | ||
type = Library | ||
name = AVRAsmPrinter | ||
parent = AVR | ||
required_libraries = MC Support | ||
add_to_library_groups = AVR |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters