Index: llvm/lib/MC/MCObjectFileInfo.cpp =================================================================== --- llvm/lib/MC/MCObjectFileInfo.cpp +++ llvm/lib/MC/MCObjectFileInfo.cpp @@ -326,6 +326,9 @@ FDECFIEncoding = PositionIndependent ? dwarf::DW_EH_PE_pcrel : dwarf::DW_EH_PE_absptr; break; + case Triple::xtensa: + FDECFIEncoding = dwarf::DW_EH_PE_sdata4; + break; default: FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; break; Index: llvm/lib/Target/Xtensa/CMakeLists.txt =================================================================== --- llvm/lib/Target/Xtensa/CMakeLists.txt +++ llvm/lib/Target/Xtensa/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_TARGET_DEFINITIONS Xtensa.td) tablegen(LLVM XtensaGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM XtensaGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM XtensaGenRegisterInfo.inc -gen-register-info) add_public_tablegen_target(XtensaCommonTableGen) Index: llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt =================================================================== --- llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt +++ llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt @@ -1,3 +1,7 @@ add_llvm_component_library(LLVMXtensaDesc + XtensaAsmBackend.cpp + XtensaELFObjectWriter.cpp + XtensaMCAsmInfo.cpp + XtensaMCCodeEmitter.cpp XtensaMCTargetDesc.cpp ) Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp @@ -0,0 +1,118 @@ +//===-- XtensaMCAsmBackend.cpp - Xtensa assembler backend ---------------===// +// +// The LLVM Compiler Infrastructure +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--------------------------------------------------------------------===// + +#include "MCTargetDesc/XtensaMCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace llvm { +class MCObjectTargetWriter; +class XtensaMCAsmBackend : public MCAsmBackend { + uint8_t OSABI; + bool IsLittleEndian; + +public: + XtensaMCAsmBackend(uint8_t osABI, bool isLE) + : MCAsmBackend(support::little), OSABI(osABI), IsLittleEndian(isLE) {} + + unsigned getNumFixupKinds() const override { return 1; } + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef Data, + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override; + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *Fragment, + const MCAsmLayout &Layout) const override; + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + + std::unique_ptr createObjectTargetWriter() const { + return createXtensaObjectWriter(OSABI, IsLittleEndian); + } +}; +} // namespace llvm + +const MCFixupKindInfo & +XtensaMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { + return MCAsmBackend::getFixupKindInfo(MCFixupKind::FK_NONE); +} +void XtensaMCAsmBackend::applyFixup(const MCAssembler &Asm, + const MCFixup &Fixup, const MCValue &Target, + MutableArrayRef Data, uint64_t Value, + bool IsResolved, + const MCSubtargetInfo *STI) const {} + +bool XtensaMCAsmBackend::mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const { + return false; +} + +bool XtensaMCAsmBackend::fixupNeedsRelaxation( + const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *Fragment, + const MCAsmLayout &Layout) const { + return false; +} + +void XtensaMCAsmBackend::relaxInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI, + MCInst &Res) const {} + +bool XtensaMCAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { + uint64_t NumNops24b = Count / 3; + + for (uint64_t i = 0; i != NumNops24b; ++i) { + // Currently just little-endian machine supported, + // but probably big-endian will be also implemented in future + if (IsLittleEndian) { + OS.write("\xf0", 1); + OS.write("\x20", 1); + OS.write("\0x00", 1); + } else { + llvm_unreachable("Big-endian mode currently is not supported!"); + } + Count -= 3; + } + + // TODO maybe function should return error if (Count > 0) + switch (Count) { + default: + break; + case 1: + OS.write("\0", 1); + break; + case 2: + OS.write("\0\0", 2); + break; + } + + return true; +} + +MCAsmBackend *llvm::createXtensaMCAsmBackend(const Target &T, + const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options) { + uint8_t OSABI = + MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS()); + return new llvm::XtensaMCAsmBackend(OSABI, true); +} Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp @@ -0,0 +1,60 @@ +//===-- XtensaMCObjectWriter.cpp - Xtensa ELF writer ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/XtensaMCTargetDesc.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include + +using namespace llvm; + +namespace { +class XtensaObjectWriter : public MCELFObjectTargetWriter { +public: + XtensaObjectWriter(uint8_t OSABI); + + virtual ~XtensaObjectWriter(); + +protected: + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; + bool needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const override; +}; +} // namespace + +XtensaObjectWriter::XtensaObjectWriter(uint8_t OSABI) + : MCELFObjectTargetWriter(false, OSABI, ELF::EM_XTENSA, + /*HasRelocationAddend=*/true) {} + +XtensaObjectWriter::~XtensaObjectWriter() {} + +unsigned XtensaObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + report_fatal_error("invalid fixup kind!"); +} + +std::unique_ptr +llvm::createXtensaObjectWriter(uint8_t OSABI, bool IsLittleEndian) { + return std::make_unique(OSABI); +} + +bool XtensaObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const { + return false; +} Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.h =================================================================== --- /dev/null +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.h @@ -0,0 +1,30 @@ +//===-- XtensaMCAsmInfo.h - Xtensa Asm Info --------------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the XtensaMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSATARGETASMINFO_H +#define LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSATARGETASMINFO_H + +#include "llvm/MC/MCAsmInfoELF.h" + +namespace llvm { +class Triple; + +class XtensaMCAsmInfo : public MCAsmInfoELF { +public: + explicit XtensaMCAsmInfo(const Triple &TT); +}; + +} // namespace llvm + +#endif /* LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSATARGETASMINFO_H */ Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.cpp @@ -0,0 +1,32 @@ +//===-- XtensaMCAsmInfo.cpp - Xtensa Asm Properties -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the XtensaMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "XtensaMCAsmInfo.h" +#include "llvm/ADT/Triple.h" + +using namespace llvm; + +XtensaMCAsmInfo::XtensaMCAsmInfo(const Triple &TT) { + CodePointerSize = 4; + CalleeSaveStackSlotSize = 4; + PrivateGlobalPrefix = ".L"; + CommentString = "#"; + ZeroDirective = "\t.space\t"; + Data64bitsDirective = "\t.quad\t"; + GlobalDirective = "\t.global\t"; + UsesELFSectionDirectiveForBSS = true; + SupportsDebugInformation = true; + ExceptionsType = ExceptionHandling::DwarfCFI; + AlignmentIsInBytes = false; +} Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp @@ -0,0 +1,129 @@ +//===-- XtensaMCCodeEmitter.cpp - Convert Xtensa Code to Machine Code -----===// +// +// The LLVM Compiler Infrastructure +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the XtensaMCCodeEmitter class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mccodeemitter" +#include "MCTargetDesc/XtensaMCTargetDesc.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" + +using namespace llvm; + +namespace { +class XtensaMCCodeEmitter : public MCCodeEmitter { + const MCInstrInfo &MCII; + MCContext &Ctx; + bool IsLittleEndian; + +public: + XtensaMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLE) + : MCII(mcii), Ctx(ctx), IsLittleEndian(isLE) {} + + ~XtensaMCCodeEmitter() {} + + // OVerride MCCodeEmitter. + void encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override; + +private: + // Automatically generated by TableGen. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // Called by the TableGen code to get the binary encoding of operand + // MO in MI. Fixups is the list of fixups against MI. + uint32_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + uint32_t getImm8OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + uint32_t getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; +}; +} // namespace + +MCCodeEmitter *llvm::createXtensaMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new XtensaMCCodeEmitter(MCII, Ctx, true); +} + +void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); + unsigned Size = MCII.get(MI.getOpcode()).getSize(); + + if (IsLittleEndian) { + // Little-endian insertion of Size bytes. + unsigned ShiftValue = 0; + for (unsigned I = 0; I != Size; ++I) { + OS << uint8_t(Bits >> ShiftValue); + ShiftValue += 8; + } + } else { + // TODO Big-endian insertion of Size bytes. + llvm_unreachable("Big-endian mode currently is not supported!"); + } +} + +uint32_t +XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + if (MO.isReg()) + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + if (MO.isImm()) { + uint32_t res = static_cast(MO.getImm()); + return res; + } + + llvm_unreachable("Unhandled expression!"); + return 0; +} + +uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + int32_t Res = MO.getImm(); + + assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!"); + + return (Res & 0xff); +} + +uint32_t +XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + int32_t Res = MO.getImm(); + + assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) && + "Unexpected operand value!"); + + return (Res & 0xffff); +} + +#include "XtensaGenMCCodeEmitter.inc" Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h =================================================================== --- llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h @@ -14,5 +14,44 @@ #ifndef LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCTARGETDESC_H #define LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCTARGETDESC_H +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/TargetRegistry.h" + +namespace llvm { + +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectTargetWriter; +class MCObjectWriter; +class MCRegisterInfo; +class MCSubtargetInfo; +class StringRef; +class Target; +class raw_ostream; + +extern Target TheXtensaTarget; + +MCCodeEmitter *createXtensaMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx); + +MCAsmBackend *createXtensaMCAsmBackend(const Target &T, + const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options); +std::unique_ptr +createXtensaObjectWriter(uint8_t OSABI, bool IsLittleEndian); +} // end namespace llvm + +// Defines symbolic names for Xtensa registers. +// This defines a mapping from register name to register number. +#define GET_REGINFO_ENUM +#include "XtensaGenRegisterInfo.inc" + +// Defines symbolic names for the Xtensa instructions. +#define GET_INSTRINFO_ENUM +#include "XtensaGenInstrInfo.inc" #endif /* LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAMCTARGETDESC_H */ Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp @@ -8,6 +8,59 @@ // //===----------------------------------------------------------------------===// #include "XtensaMCTargetDesc.h" +#include "XtensaMCAsmInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" -// We need to define this function for linking succeed -extern "C" void LLVMInitializeXtensaTargetMC() {} +#define GET_INSTRINFO_MC_DESC +#include "XtensaGenInstrInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "XtensaGenRegisterInfo.inc" + +using namespace llvm; + +static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT, + const MCTargetOptions &Options) { + MCAsmInfo *MAI = new XtensaMCAsmInfo(TT); + return MAI; +} + +static MCInstrInfo *createXtensaMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitXtensaMCInstrInfo(X); + return X; +} + +static MCRegisterInfo *createXtensaMCRegisterInfo(const Triple &TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitXtensaMCRegisterInfo(X, Xtensa::SP); + return X; +} + +extern "C" void LLVMInitializeXtensaTargetMC() { + // Register the MCAsmInfo. + TargetRegistry::RegisterMCAsmInfo(TheXtensaTarget, createXtensaMCAsmInfo); + + // Register the MCCodeEmitter. + TargetRegistry::RegisterMCCodeEmitter(TheXtensaTarget, + createXtensaMCCodeEmitter); + + // Register the MCInstrInfo. + TargetRegistry::RegisterMCInstrInfo(TheXtensaTarget, createXtensaMCInstrInfo); + + // Register the MCRegisterInfo. + TargetRegistry::RegisterMCRegInfo(TheXtensaTarget, + createXtensaMCRegisterInfo); + + // Register the MCAsmBackend. + TargetRegistry::RegisterMCAsmBackend(TheXtensaTarget, + createXtensaMCAsmBackend); +} Index: llvm/lib/Target/Xtensa/XtensaOperands.td =================================================================== --- llvm/lib/Target/Xtensa/XtensaOperands.td +++ llvm/lib/Target/Xtensa/XtensaOperands.td @@ -26,11 +26,13 @@ // imm8 predicate - Immediate in the range [-128,127] def Imm8_AsmOperand: ImmAsmOperand<"Imm8">; def imm8: Immediate= -128 && Imm <= 127; }], "Imm8_AsmOperand"> { + let EncoderMethod = "getImm8OpValue"; } // imm8_sh8 predicate - Immediate in the range [-32768,32512] with (bits[7-0] == 0) // imm8 value left shifted by 8 bits def Imm8_sh8_AsmOperand: ImmAsmOperand<"Imm8_sh8">; def imm8_sh8: Immediate= -32768 && Imm <= 32512 && ((Imm & 0xFF) == 0); }], "Imm8_sh8_AsmOperand"> { - + let EncoderMethod = "getImm8_sh8OpValue"; } +