Index: lib/Target/NDS32/CMakeLists.txt =================================================================== --- lib/Target/NDS32/CMakeLists.txt +++ lib/Target/NDS32/CMakeLists.txt @@ -5,6 +5,7 @@ tablegen(LLVM NDS32GenCallingConv.inc -gen-callingconv) tablegen(LLVM NDS32GenSubtargetInfo.inc -gen-subtarget) tablegen(LLVM NDS32GenDAGISel.inc -gen-dag-isel) +tablegen(LLVM NDS32GenAsmWriter.inc -gen-asm-writer) add_public_tablegen_target(NDS32CommonTableGen) @@ -18,8 +19,11 @@ NDS32RegisterInfo.cpp NDS32FrameLowering.cpp NDS32SelectionDAGInfo.cpp + NDS32MCInstLower.cpp + NDS32AsmPrinter.cpp NDS32TargetMachine.cpp ) add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) +add_subdirectory(InstPrinter) Index: lib/Target/NDS32/InstPrinter/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/NDS32/InstPrinter/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMNDS32AsmPrinter + NDS32InstPrinter.cpp + ) Index: lib/Target/NDS32/InstPrinter/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/NDS32/InstPrinter/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/NDS32/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 = NDS32AsmPrinter +parent = NDS32 +required_libraries = MC Support +add_to_library_groups = NDS32 Index: lib/Target/NDS32/InstPrinter/NDS32InstPrinter.h =================================================================== --- /dev/null +++ lib/Target/NDS32/InstPrinter/NDS32InstPrinter.h @@ -0,0 +1,52 @@ +//==- NDS32InstPrinter.h - Convert NDS32 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 a NDS32 MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NDS32_INSTPRINTER_NDS32INSTPRINTER_H +#define LLVM_LIB_TARGET_NDS32_INSTPRINTER_NDS32INSTPRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { + class NDS32InstPrinter : public MCInstPrinter { + public: + NDS32InstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, + const MCSubtargetInfo &STI) override; + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = nullptr); + + void printRegName(raw_ostream &OS, unsigned RegNo) const override; + + void printAddrImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printSPImplyAddrImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printAddrRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAddrOffsetOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printAddrRegOffsetOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + + void printRegisterList(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printRegShiftOp(const MCInst *MI, unsigned OpNum, raw_ostream &O); + }; +} + +#endif Index: lib/Target/NDS32/InstPrinter/NDS32InstPrinter.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/InstPrinter/NDS32InstPrinter.cpp @@ -0,0 +1,181 @@ +//===-- NDS32InstPrinter.cpp - Convert NDS32 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 NDS32 MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#include "NDS32InstPrinter.h" +#include "NDS32.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +// Include the auto-generated portion of the assembly writer. +#include "NDS32GenAsmWriter.inc" + +void NDS32InstPrinter::printInst(const MCInst *MI, raw_ostream &O, + StringRef Annot, const MCSubtargetInfo &STI) { + printInstruction(MI, O); + printAnnotation(O, Annot); +} + +void NDS32InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, const char *Modifier) { + assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported"); + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + O << '$' << getRegisterName(Op.getReg()); + } else if (Op.isImm()) { + O << Op.getImm(); + } else { + assert(Op.isExpr() && "unknown operand kind in printOperand"); + Op.getExpr()->print(O, &MAI); + } +} + +void NDS32InstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { + OS << markup(""); +} + +// print [Reg + Imm] addressing mode +void NDS32InstPrinter::printAddrImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum + 1); + + O << markup("") << "]" << markup(">"); +} + +// print sp base imply [+ Imm] addressing mode +void NDS32InstPrinter::printSPImplyAddrImmOperand(const MCInst *MI, + unsigned OpNum, + raw_ostream &O) { + const MCOperand &MO2 = MI->getOperand(OpNum + 1); + + O << markup("") << "]" << markup(">"); +} + +// print [Reg + Reg << Imm] addressing mode +void NDS32InstPrinter::printRegShiftOp(const MCInst *MI, unsigned Op, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(Op); + const MCOperand &MO2 = MI->getOperand(Op + 1); + const MCOperand &MO3 = MI->getOperand(Op + 2); + + O << markup(""); +} + +// print [Reg] operand in ([Reg], Offset) addressing mode +void NDS32InstPrinter::printAddrRegOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(OpNum); + O << markup(""); +} + +// print Offset operand in ([Reg], Offset) addressing mode +void NDS32InstPrinter::printAddrOffsetOperand(const MCInst *MI, + unsigned OpNum, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(OpNum); + + O << markup(""); +} + +// print RegA operand in ([Reg], RegA) addressing mode +void NDS32InstPrinter::printAddrRegOffsetOperand(const MCInst *MI, + unsigned OpNum, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(OpNum); + + O << '$'; + printRegName(O, MO1.getReg()); +} + +// print Re, Enable4 in (Rb ,[Ra], Re, Enable4) addressing mode +void NDS32InstPrinter::printRegisterList(const MCInst *MI, + unsigned OpNum, + raw_ostream &O) { + unsigned Rb = NDS32::SP; + unsigned Re = NDS32::SP; + unsigned Ra; + unsigned Enable4 = 0; + unsigned i; + unsigned e = MI->getNumOperands(); + + // First operand will be base register [Ra] + Ra = MI->getOperand(OpNum).getReg(); + + for (i = OpNum + 1; i != e; ++i) { + unsigned Reg = MI->getOperand(i).getReg(); + switch (Reg) { + case NDS32::SP: + Enable4 += 1; + break; + case NDS32::LP: + Enable4 += 2; + break; + case NDS32::GP: + Enable4 += 4; + break; + case NDS32::FP: + Enable4 += 8; + break; + default: + if (Rb == NDS32::SP) + Rb = Reg; + Re = Reg; + break; + } + } + O << '$'; + printRegName(O, Rb); + O << ", [$"; + printRegName(O, Ra); + O << "], $"; + printRegName(O, Re); + O << ", " << Enable4; +} Index: lib/Target/NDS32/LLVMBuild.txt =================================================================== --- lib/Target/NDS32/LLVMBuild.txt +++ lib/Target/NDS32/LLVMBuild.txt @@ -16,16 +16,17 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = TargetInfo MCTargetDesc +subdirectories = TargetInfo MCTargetDesc InstPrinter [component_0] type = TargetGroup name = NDS32 parent = Target +has_asmprinter = 1 [component_1] type = Library name = NDS32CodeGen parent = NDS32 -required_libraries = CodeGen Core SelectionDAG NDS32Info NDS32Desc Support Target +required_libraries = MC AsmPrinter NDS32AsmPrinter CodeGen Core SelectionDAG NDS32Info NDS32Desc Support Target add_to_library_groups = NDS32 Index: lib/Target/NDS32/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/NDS32/MCTargetDesc/CMakeLists.txt +++ lib/Target/NDS32/MCTargetDesc/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMNDS32Desc NDS32MCTargetDesc.cpp NDS32MCAsmInfo.cpp + NDS32MCExpr.cpp ) Index: lib/Target/NDS32/MCTargetDesc/LLVMBuild.txt =================================================================== --- lib/Target/NDS32/MCTargetDesc/LLVMBuild.txt +++ lib/Target/NDS32/MCTargetDesc/LLVMBuild.txt @@ -19,5 +19,5 @@ type = Library name = NDS32Desc parent = NDS32 -required_libraries = MC NDS32Info Support +required_libraries = MC NDS32AsmPrinter NDS32Info Support add_to_library_groups = NDS32 Index: lib/Target/NDS32/MCTargetDesc/NDS32MCExpr.h =================================================================== --- /dev/null +++ lib/Target/NDS32/MCTargetDesc/NDS32MCExpr.h @@ -0,0 +1,58 @@ +//===-- NDS32MCExpr.h - NDS32 specific MC expression classes ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NDS32_MCTARGETDESC_NDS32MCEXPR_H +#define LLVM_LIB_TARGET_NDS32_MCTARGETDESC_NDS32MCEXPR_H + +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCValue.h" + +namespace llvm { + +class NDS32MCExpr : public MCTargetExpr { +public: + enum NDS32ExprKind { + MEK_None, + MEK_HI, + MEK_LO, + MEK_Special, + }; + +private: + const NDS32ExprKind Kind; + const MCExpr *Expr; + + explicit NDS32MCExpr(NDS32ExprKind Kind, const MCExpr *Expr) + : Kind(Kind), Expr(Expr) {} + +public: + static const NDS32MCExpr *create(NDS32ExprKind Kind, const MCExpr *Expr, + MCContext &Ctx); + + /// Get the kind of this expression. + NDS32ExprKind getKind() const { return Kind; } + + /// Get the child of this expression. + const MCExpr *getSubExpr() const { return Expr; } + + void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; + + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const override; + void visitUsedExpr(MCStreamer &Streamer) const override; + // There are no TLS NDS32MCExprs at the moment. + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {} + MCFragment *findAssociatedFragment() const override { + return getSubExpr()->findAssociatedFragment(); + } +}; +} // end namespace llvm + +#endif Index: lib/Target/NDS32/MCTargetDesc/NDS32MCExpr.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/MCTargetDesc/NDS32MCExpr.cpp @@ -0,0 +1,94 @@ +//===-- NDS32MCExpr.cpp - NDS32 specific MC expression classes ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NDS32MCExpr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/Support/ELF.h" + +using namespace llvm; + +#define DEBUG_TYPE "nds32mcexpr" + +const NDS32MCExpr *NDS32MCExpr::create(NDS32MCExpr::NDS32ExprKind Kind, + const MCExpr *Expr, MCContext &Ctx) { + return new (Ctx) NDS32MCExpr(Kind, Expr); +} + +void NDS32MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { + int64_t AbsVal; + + switch (Kind) { + case MEK_None: + case MEK_Special: + break; + case MEK_HI: + OS << "hi20("; + break; + case MEK_LO: + OS << "lo12("; + break; + default: + break; + } + + if (Expr->evaluateAsAbsolute(AbsVal)) + OS << AbsVal; + else + Expr->print(OS, MAI, true); + + switch (Kind) { + case MEK_HI: + case MEK_LO: + OS << ")"; + break; + default: + break; + } +} + +bool +NDS32MCExpr::evaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout, + const MCFixup *Fixup) const { + if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) + return false; + + if (Res.getRefKind() != MCSymbolRefExpr::VK_None) + return false; + + if (Res.isAbsolute() && Fixup == nullptr) { + int64_t AbsVal = Res.getConstant(); + switch (Kind) { + case MEK_None: + case MEK_Special: + llvm_unreachable("MEK_None and MEK_Special are invalid"); + case MEK_HI: + AbsVal = SignExtend64<20>(AbsVal >> 12); + break; + case MEK_LO: + AbsVal = SignExtend64<12>(AbsVal & 0xfff); + break; + Res = MCValue::get(AbsVal); + return true; + } + } + + Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), + getKind()); + + return true; +} + +void NDS32MCExpr::visitUsedExpr(MCStreamer &Streamer) const { + Streamer.visitUsedExpr(*getSubExpr()); +} Index: lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.cpp =================================================================== --- lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.cpp +++ lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.cpp @@ -13,6 +13,7 @@ #include "NDS32MCTargetDesc.h" #include "NDS32MCAsmInfo.h" +#include "InstPrinter/NDS32InstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -57,6 +58,16 @@ return createNDS32MCSubtargetInfoImpl(TT, CPU, FS); } +static MCInstPrinter *createNDS32MCInstPrinter(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + if (SyntaxVariant == 0) + return new NDS32InstPrinter(MAI, MII, MRI); + return nullptr; +} + extern "C" void LLVMInitializeNDS32TargetMC() { // Register the MC asm info. RegisterMCAsmInfoFn X(TheNDS32Target, createNDS32MCAsmInfo); @@ -71,4 +82,8 @@ // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(TheNDS32Target, createNDS32MCSubtargetInfo); + + // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(TheNDS32Target, + createNDS32MCInstPrinter); } Index: lib/Target/NDS32/NDS32AsmPrinter.h =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32AsmPrinter.h @@ -0,0 +1,40 @@ +//===-- NDS32AsmPrinter.h - NDS32 LLVM Assembly Printer --------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// NDS32 Assembly printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NDS32_NDS32ASMPRINTER_H +#define LLVM_LIB_TARGET_NDS32_NDS32ASMPRINTER_H + +#include "NDS32Subtarget.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class LLVM_LIBRARY_VISIBILITY NDS32AsmPrinter : public AsmPrinter { + public: + explicit NDS32AsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer); + + StringRef getPassName() const override { return "NDS32 Assembly Printer"; } + bool isBlockOnlyReachableByFallthrough( + const MachineBasicBlock* MBB) const override; + void printOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char* Modifier = nullptr); + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) override; + void EmitInstruction(const MachineInstr *MI) override; + }; +} + +#endif Index: lib/Target/NDS32/NDS32AsmPrinter.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32AsmPrinter.cpp @@ -0,0 +1,139 @@ +//===-- NDS32AsmPrinter.cpp - NDS32 LLVM assembly writer ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to the NDS32 assembly language. +// +//===----------------------------------------------------------------------===// + +#include "NDS32.h" +#include "InstPrinter/NDS32InstPrinter.h" +#include "NDS32InstrInfo.h" +#include "NDS32MCInstLower.h" +#include "NDS32TargetMachine.h" +#include "NDS32AsmPrinter.h" +#include "MCTargetDesc/NDS32BaseInfo.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Mangler.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/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +NDS32AsmPrinter::NDS32AsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)) {} + +void NDS32AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char *Modifier) { + const MachineOperand &MO = MI->getOperand(OpNum); + + switch(MO.getTargetFlags()) { + case NDS32II::MO_HI20: O << "hi20("; break; + case NDS32II::MO_LO12: O << "lo12("; break; + default: break; + } + + switch (MO.getType()) { + default: llvm_unreachable("Not implemented yet!"); + case MachineOperand::MO_Register: + O << NDS32InstPrinter::getRegisterName(MO.getReg()); + return; + case MachineOperand::MO_Immediate: + O << MO.getImm(); + return; + case MachineOperand::MO_MachineBasicBlock: + MO.getMBB()->getSymbol()->print(O, MAI); + return; + case MachineOperand::MO_GlobalAddress: { + uint64_t Offset = MO.getOffset(); + + if (Offset) + O << '(' << Offset << '+'; + + getSymbol(MO.getGlobal())->print(O, MAI); + + if (Offset) + O << ')'; + + return; + } + } +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool NDS32AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: + // See if this is a generic print operand + return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); + case 'c': + if (!MI->getOperand(OpNo).isImm()) + return true; + O << MI->getOperand(OpNo).getImm(); + return false; + } + } + + printOperand(MI, OpNo, O); + return false; +} + +/// isBlockOnlyReachableByFallthough - Return true if the basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +bool NDS32AsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* + MBB) const { + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *MBB->pred_begin(); + + // If the predecessor is a switch statement, assume a jump table + // implementation, so it is not a fall through. + // To avoid AsmPrinter::EmitBasicBlockStart() not emit entry label + // for jump table. + if (const BasicBlock *bb = Pred->getBasicBlock()) + if (isa(bb->getTerminator())) + return false; + + return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); +} + + +//===----------------------------------------------------------------------===// +void NDS32AsmPrinter::EmitInstruction(const MachineInstr *MI) { + NDS32MCInstLower MCInstLowering(OutContext, *this); + + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); + EmitToStreamer(*OutStreamer, TmpInst); +} + +// Force static initialization. +extern "C" void LLVMInitializeNDS32AsmPrinter() { + RegisterAsmPrinter X(TheNDS32Target); +} Index: lib/Target/NDS32/NDS32MCInstLower.h =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32MCInstLower.h @@ -0,0 +1,44 @@ +//===-- NDS32MCInstLower.h - Lower MachineInstr to MCInst ------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NDS32_NDS32MCINSTLOWER_H +#define LLVM_LIB_TARGET_NDS32_NDS32MCINSTLOWER_H +#include "MCTargetDesc/NDS32MCExpr.h" +#include "llvm/Support/Compiler.h" +#include "llvm/CodeGen/MachineOperand.h" + +namespace llvm { + class NDS32AsmPrinter; + class MCContext; + class MCInst; + class MCOperand; + class MCSymbol; + class MachineInstr; + class MachineModuleInfoMachO; + class MachineOperand; + + /// NDS32MCInstLower - This class is used to lower an MachineInstr + /// into an MCInst. +class LLVM_LIBRARY_VISIBILITY NDS32MCInstLower { + typedef MachineOperand::MachineOperandType MachineOperandType; + MCContext &Ctx; + + NDS32AsmPrinter &Printer; +public: + NDS32MCInstLower(MCContext &ctx, NDS32AsmPrinter &printer) + : Ctx(ctx), Printer(printer) {} + void Lower(const MachineInstr *MI, MCInst &OutMI) const; + + MCOperand LowerSymbolOperand(const MachineOperand &MO, + MachineOperandType MOTy, unsigned Offset) const; +}; + +} + +#endif Index: lib/Target/NDS32/NDS32MCInstLower.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32MCInstLower.cpp @@ -0,0 +1,143 @@ +//===-- NDS32MCInstLower.cpp - Convert NDS32 MachineInstr to an MCInst ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower NDS32 MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "NDS32MCInstLower.h" +#include "NDS32AsmPrinter.h" +#include "MCTargetDesc/NDS32BaseInfo.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + + +MCOperand NDS32MCInstLower:: +LowerSymbolOperand(const MachineOperand &MO, MachineOperandType MOTy, + unsigned Offset) const { + + NDS32MCExpr::NDS32ExprKind TargetKind = NDS32MCExpr::MEK_None; + const MCSymbol *Symbol; + + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + case NDS32II::MO_HI20: + TargetKind = NDS32MCExpr::MEK_HI; + break; + case NDS32II::MO_LO12: + TargetKind = NDS32MCExpr::MEK_LO; + break; + + case 0: break; + } + + switch (MOTy) { + case MachineOperand::MO_MachineBasicBlock: + Symbol = MO.getMBB()->getSymbol(); + break; + + case MachineOperand::MO_GlobalAddress: + Symbol = Printer.getSymbol(MO.getGlobal()); + Offset += MO.getOffset(); + break; + + case MachineOperand::MO_BlockAddress: + Symbol = Printer.GetBlockAddressSymbol(MO.getBlockAddress()); + Offset += MO.getOffset(); + break; + + case MachineOperand::MO_ExternalSymbol: + Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName()); + Offset += MO.getOffset(); + break; + + case MachineOperand::MO_MCSymbol: + Symbol = MO.getMCSymbol(); + Offset += MO.getOffset(); + break; + + case MachineOperand::MO_JumpTableIndex: + Symbol = Printer.GetJTISymbol(MO.getIndex()); + break; + + case MachineOperand::MO_ConstantPoolIndex: + Symbol = Printer.GetCPISymbol(MO.getIndex()); + Offset += MO.getOffset(); + break; + + default: + llvm_unreachable(""); + } + + + const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Ctx); + + if (Offset) { + // Assume offset is never negative. + assert(Offset > 0); + + Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, Ctx), + Ctx); + } + + if (TargetKind != NDS32MCExpr::MEK_None) + Expr = NDS32MCExpr::create(TargetKind, Expr, Ctx); + + return MCOperand::createExpr(Expr); +} + +void NDS32MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + unsigned offset = 0; + + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + MCOperand MCOp; + switch (MO.getType()) { + default: + MI->dump(); + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) continue; + MCOp = MCOperand::createReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::createImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_BlockAddress: + MCOp = LowerSymbolOperand(MO, MO.getType(), offset); + break; + case MachineOperand::MO_RegisterMask: + continue; + } + + OutMI.addOperand(MCOp); + } +}