Skip to content

Commit

Permalink
[AVR] Add the assembly instruction printer
Browse files Browse the repository at this point in the history
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
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 2 deletions.
3 changes: 2 additions & 1 deletion llvm/lib/Target/AVR/CMakeLists.txt
Expand Up @@ -17,7 +17,8 @@ add_llvm_target(AVRCodeGen

add_dependencies(LLVMAVRCodeGen intrinsics_gen)

add_subdirectory(AsmParser)
add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)
add_subdirectory(AsmParser)

172 changes: 172 additions & 0 deletions llvm/lib/Target/AVR/InstPrinter/AVRInstPrinter.cpp
@@ -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

54 changes: 54 additions & 0 deletions llvm/lib/Target/AVR/InstPrinter/AVRInstPrinter.h
@@ -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

8 changes: 8 additions & 0 deletions llvm/lib/Target/AVR/InstPrinter/CMakeLists.txt
@@ -0,0 +1,8 @@
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/..
${CMAKE_CURRENT_SOURCE_DIR}/.. )

add_llvm_library(LLVMAVRAsmPrinter
AVRInstPrinter.cpp
)

add_dependencies(LLVMAVRAsmPrinter AVRCommonTableGen)
23 changes: 23 additions & 0 deletions llvm/lib/Target/AVR/InstPrinter/LLVMBuild.txt
@@ -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
2 changes: 1 addition & 1 deletion llvm/lib/Target/AVR/LLVMBuild.txt
Expand Up @@ -22,7 +22,7 @@ subdirectories = TargetInfo
type = TargetGroup
name = AVR
parent = Target
has_asmprinter = 0
has_asmprinter = 1
has_asmparser = 1

[component_1]
Expand Down

0 comments on commit 1a7bd84

Please sign in to comment.