diff --git a/include/llvm/BinaryFormat/ELFRelocs/AVR.def b/include/llvm/BinaryFormat/ELFRelocs/AVR.def index 5692d6cb9aa..696fc60b0f5 100644 --- a/include/llvm/BinaryFormat/ELFRelocs/AVR.def +++ b/include/llvm/BinaryFormat/ELFRelocs/AVR.def @@ -33,8 +33,9 @@ ELF_RELOC(R_AVR_8, 26) ELF_RELOC(R_AVR_8_LO8, 27) ELF_RELOC(R_AVR_8_HI8, 28) ELF_RELOC(R_AVR_8_HLO8, 29) -ELF_RELOC(R_AVR_SYM_DIFF, 30) -ELF_RELOC(R_AVR_16_LDST, 31) +ELF_RELOC(R_AVR_DIFF8, 30) +ELF_RELOC(R_AVR_DIFF16, 31) +ELF_RELOC(R_AVR_DIFF32, 32) ELF_RELOC(R_AVR_LDS_STS_16, 33) ELF_RELOC(R_AVR_PORT6, 34) ELF_RELOC(R_AVR_PORT5, 35) diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index a91a31414bd..fcbbe650d26 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -206,6 +206,14 @@ public: VK_ARM_TLSLDO, // symbol(tlsldo) VK_ARM_TLSDESCSEQ, + VK_AVR_NONE, + VK_AVR_LO8, + VK_AVR_HI8, + VK_AVR_HLO8, + VK_AVR_DIFF8, + VK_AVR_DIFF16, + VK_AVR_DIFF32, + VK_PPC_LO, // symbol@l VK_PPC_HI, // symbol@h VK_PPC_HA, // symbol@ha diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 38a8af49c19..f8fff4414f4 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -224,6 +224,13 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_ARM_SBREL: return "sbrel"; case VK_ARM_TLSLDO: return "tlsldo"; case VK_ARM_TLSDESCSEQ: return "tlsdescseq"; + case VK_AVR_NONE: return "none"; + case VK_AVR_LO8: return "lo8"; + case VK_AVR_HI8: return "hi8"; + case VK_AVR_HLO8: return "hlo8"; + case VK_AVR_DIFF8: return "diff8"; + case VK_AVR_DIFF16: return "diff16"; + case VK_AVR_DIFF32: return "diff32"; case VK_PPC_LO: return "l"; case VK_PPC_HI: return "h"; case VK_PPC_HA: return "ha"; @@ -389,6 +396,9 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("prel31", VK_ARM_PREL31) .Case("sbrel", VK_ARM_SBREL) .Case("tlsldo", VK_ARM_TLSLDO) + .Case("lo8", VK_AVR_LO8) + .Case("hi8", VK_AVR_HI8) + .Case("hlo8", VK_AVR_HLO8) .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI) .Case("rel32@lo", VK_AMDGPU_REL32_LO) diff --git a/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/lib/Target/AVR/AsmParser/AVRAsmParser.cpp index 2e1adcc6a4f..b527ad3e0b1 100644 --- a/lib/Target/AVR/AsmParser/AVRAsmParser.cpp +++ b/lib/Target/AVR/AsmParser/AVRAsmParser.cpp @@ -9,6 +9,7 @@ #include "AVR.h" #include "AVRRegisterInfo.h" +#include "MCTargetDesc/AVRMCELFStreamer.h" #include "MCTargetDesc/AVRMCExpr.h" #include "MCTargetDesc/AVRMCTargetDesc.h" @@ -40,6 +41,7 @@ class AVRAsmParser : public MCTargetAsmParser { const MCSubtargetInfo &STI; MCAsmParser &Parser; const MCRegisterInfo *MRI; + const std::string GENERATE_STUBS = "gs"; #define GET_ASSEMBLER_HEADER #include "AVRGenAsmMatcher.inc" @@ -54,7 +56,7 @@ class AVRAsmParser : public MCTargetAsmParser { bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; - bool ParseDirective(AsmToken directiveID) override; + bool ParseDirective(AsmToken DirectiveID) override; OperandMatchResultTy parseMemriOperand(OperandVector &Operands); @@ -80,6 +82,8 @@ class AVRAsmParser : public MCTargetAsmParser { uint64_t const &ErrorInfo); bool missingFeature(SMLoc const &Loc, uint64_t const &ErrorInfo); + bool parseLiteralValues(unsigned SizeInBytes, SMLoc L); + public: AVRAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, const MCInstrInfo &MII, const MCTargetOptions &Options) @@ -404,11 +408,14 @@ bool AVRAsmParser::tryParseRelocExpression(OperandVector &Operands) { size_t ReadCount = Parser.getLexer().peekTokens(tokens); if (ReadCount == 2) { - if (tokens[0].getKind() == AsmToken::Identifier && - tokens[1].getKind() == AsmToken::LParen) { + if ((tokens[0].getKind() == AsmToken::Identifier && + tokens[1].getKind() == AsmToken::LParen) || + (tokens[0].getKind() == AsmToken::LParen && + tokens[1].getKind() == AsmToken::Minus)) { AsmToken::TokenKind CurTok = Parser.getLexer().getKind(); - if (CurTok == AsmToken::Minus) { + if (CurTok == AsmToken::Minus || + tokens[1].getKind() == AsmToken::Minus) { isNegated = true; } else { assert(CurTok == AsmToken::Plus); @@ -416,7 +423,8 @@ bool AVRAsmParser::tryParseRelocExpression(OperandVector &Operands) { } // Eat the sign - Parser.Lex(); + if (CurTok == AsmToken::Minus || CurTok == AsmToken::Plus) + Parser.Lex(); } } @@ -432,14 +440,34 @@ bool AVRAsmParser::tryParseRelocExpression(OperandVector &Operands) { if (ModifierKind != AVRMCExpr::VK_AVR_None) { Parser.Lex(); Parser.Lex(); // Eat modifier name and parenthesis + if (Parser.getTok().getString() == GENERATE_STUBS && + Parser.getTok().getKind() == AsmToken::Identifier) { + std::string GSModName = ModifierName.str() + "_" + GENERATE_STUBS; + ModifierKind = AVRMCExpr::getKindByName(GSModName.c_str()); + if (ModifierKind != AVRMCExpr::VK_AVR_None) + Parser.Lex(); // Eat gs modifier name + } } else { return Error(Parser.getTok().getLoc(), "unknown modifier"); } + if (tokens[1].getKind() == AsmToken::Minus || + tokens[1].getKind() == AsmToken::Plus) { + Parser.Lex(); + assert(Parser.getTok().getKind() == AsmToken::LParen); + Parser.Lex(); // Eat the sign and parenthesis + } + MCExpr const *InnerExpression; if (getParser().parseExpression(InnerExpression)) return true; + if (tokens[1].getKind() == AsmToken::Minus || + tokens[1].getKind() == AsmToken::Plus) { + assert(Parser.getTok().getKind() == AsmToken::RParen); + Parser.Lex(); // Eat closing parenthesis + } + // If we have a modifier wrap the inner expression assert(Parser.getTok().getKind() == AsmToken::RParen); Parser.Lex(); // Eat closing parenthesis @@ -580,7 +608,59 @@ bool AVRAsmParser::ParseInstruction(ParseInstructionInfo &Info, return false; } -bool AVRAsmParser::ParseDirective(llvm::AsmToken DirectiveID) { return true; } +bool AVRAsmParser::ParseDirective(llvm::AsmToken DirectiveID) { + StringRef IDVal = DirectiveID.getIdentifier(); + if (IDVal.lower() == ".long") { + parseLiteralValues(SIZE_LONG, DirectiveID.getLoc()); + } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") { + parseLiteralValues(SIZE_WORD, DirectiveID.getLoc()); + } else if (IDVal.lower() == ".byte") { + parseLiteralValues(1, DirectiveID.getLoc()); + } + return true; +} + +bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) { + MCAsmParser &Parser = getParser(); + AVRMCELFStreamer &AVRStreamer = + static_cast(Parser.getStreamer()); + AsmToken Tokens[2]; + size_t ReadCount = Parser.getLexer().peekTokens(Tokens); + if (ReadCount == 2 && Parser.getTok().getKind() == AsmToken::Identifier && + Tokens[0].getKind() == AsmToken::Minus && + Tokens[1].getKind() == AsmToken::Identifier) { + MCSymbol *Symbol = getContext().getOrCreateSymbol(".text"); + AVRStreamer.EmitValueForModiferKind(Symbol, SizeInBytes, L, + AVRMCExpr::VK_AVR_None); + return false; + } + + if (Parser.getTok().getKind() == AsmToken::Identifier && + Parser.getLexer().peekTok().getKind() == AsmToken::LParen) { + StringRef ModifierName = Parser.getTok().getString(); + AVRMCExpr::VariantKind ModifierKind = + AVRMCExpr::getKindByName(ModifierName.str().c_str()); + if (ModifierKind != AVRMCExpr::VK_AVR_None) { + Parser.Lex(); + Parser.Lex(); // Eat the modifier and parenthesis + } else { + return Error(Parser.getTok().getLoc(), "unknown modifier"); + } + MCSymbol *Symbol = + getContext().getOrCreateSymbol(Parser.getTok().getString()); + AVRStreamer.EmitValueForModiferKind(Symbol, SizeInBytes, L, ModifierKind); + return false; + } + + auto parseOne = [&]() -> bool { + const MCExpr *Value; + if (Parser.parseExpression(Value)) + return true; + Parser.getStreamer().EmitValue(Value, SizeInBytes, L); + return false; + }; + return (parseMany(parseOne)); +} extern "C" void LLVMInitializeAVRAsmParser() { RegisterMCAsmParser X(getTheAVRTarget()); diff --git a/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp b/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp index 01a09610118..4016773e9b4 100644 --- a/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp +++ b/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp @@ -422,8 +422,9 @@ MCFixupKindInfo const &AVRAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { {"fixup_8_hi8", 0, 8, 0}, {"fixup_8_hlo8", 0, 8, 0}, - {"fixup_sym_diff", 0, 32, 0}, - {"fixup_16_ldst", 0, 16, 0}, + {"fixup_diff8", 0, 8, 0}, + {"fixup_diff16", 0, 16, 0}, + {"fixup_diff32", 0, 32, 0}, {"fixup_lds_sts_16", 0, 16, 0}, diff --git a/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp b/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp index 25da75e63fe..412f66fbcf2 100644 --- a/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp +++ b/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp @@ -40,12 +40,43 @@ unsigned AVRELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { + MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); switch ((unsigned) Fixup.getKind()) { case FK_Data_1: + switch (Modifier) { + default: + llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_None: + return ELF::R_AVR_8; + case MCSymbolRefExpr::VK_AVR_DIFF8: + return ELF::R_AVR_DIFF8; + case MCSymbolRefExpr::VK_AVR_LO8: + return ELF::R_AVR_8_LO8; + case MCSymbolRefExpr::VK_AVR_HI8: + return ELF::R_AVR_8_HI8; + case MCSymbolRefExpr::VK_AVR_HLO8: + return ELF::R_AVR_8_HLO8; + } case FK_Data_4: - llvm_unreachable("unsupported relocation type"); + switch (Modifier) { + default: + llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_None: + return ELF::R_AVR_32; + case MCSymbolRefExpr::VK_AVR_DIFF32: + return ELF::R_AVR_DIFF32; + } case FK_Data_2: - return ELF::R_AVR_16_PM; + switch (Modifier) { + default: + llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_None: + return ELF::R_AVR_16; + case MCSymbolRefExpr::VK_AVR_NONE: + return ELF::R_AVR_16_PM; + case MCSymbolRefExpr::VK_AVR_DIFF16: + return ELF::R_AVR_DIFF16; + } case AVR::fixup_32: return ELF::R_AVR_32; case AVR::fixup_7_pcrel: @@ -104,10 +135,12 @@ unsigned AVRELFObjectWriter::getRelocType(MCContext &Ctx, return ELF::R_AVR_8_HI8; case AVR::fixup_8_hlo8: return ELF::R_AVR_8_HLO8; - case AVR::fixup_sym_diff: - return ELF::R_AVR_SYM_DIFF; - case AVR::fixup_16_ldst: - return ELF::R_AVR_16_LDST; + case AVR::fixup_diff8: + return ELF::R_AVR_DIFF8; + case AVR::fixup_diff16: + return ELF::R_AVR_DIFF16; + case AVR::fixup_diff32: + return ELF::R_AVR_DIFF32; case AVR::fixup_lds_sts_16: return ELF::R_AVR_LDS_STS_16; case AVR::fixup_port6: diff --git a/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h b/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h index d3bd52d343f..cdb0b215bc6 100644 --- a/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h +++ b/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h @@ -115,10 +115,9 @@ enum Fixups { fixup_8_hi8, fixup_8_hlo8, - /// Fixup to calculate the difference between two symbols. - /// Is the only stateful fixup. We do not support it yet. - fixup_sym_diff, - fixup_16_ldst, + fixup_diff8, + fixup_diff16, + fixup_diff32, fixup_lds_sts_16, diff --git a/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp b/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp new file mode 100644 index 00000000000..c60ea7a92e6 --- /dev/null +++ b/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp @@ -0,0 +1,51 @@ +//===--------- AVRMCELFStreamer.cpp - AVR subclass of MCELFStreamer -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a stub that parses a MCInst bundle and passes the +// instructions on to the real streamer. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "avrmcelfstreamer" + +#include "MCTargetDesc/AVRMCELFStreamer.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" + +using namespace llvm; + +void AVRMCELFStreamer::EmitValueForModiferKind( + const MCSymbol *Sym, unsigned SizeInBytes, SMLoc Loc, + AVRMCExpr::VariantKind ModifierKind) { + MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_AVR_NONE; + if (ModifierKind == AVRMCExpr::VK_AVR_None) { + Kind = MCSymbolRefExpr::VK_AVR_DIFF8; + if (SizeInBytes == SIZE_LONG) + Kind = MCSymbolRefExpr::VK_AVR_DIFF32; + else if (SizeInBytes == SIZE_WORD) + Kind = MCSymbolRefExpr::VK_AVR_DIFF16; + } else if (ModifierKind == AVRMCExpr::VK_AVR_LO8) + Kind = MCSymbolRefExpr::VK_AVR_LO8; + else if (ModifierKind == AVRMCExpr::VK_AVR_HI8) + Kind = MCSymbolRefExpr::VK_AVR_HI8; + else if (ModifierKind == AVRMCExpr::VK_AVR_HH8) + Kind = MCSymbolRefExpr::VK_AVR_HLO8; + MCELFStreamer::EmitValue(MCSymbolRefExpr::create(Sym, Kind, getContext()), + SizeInBytes, Loc); +} + +namespace llvm { +MCStreamer *createAVRELFStreamer(Triple const &TT, MCContext &Context, + std::unique_ptr MAB, + raw_pwrite_stream &OS, + std::unique_ptr CE) { + return new AVRMCELFStreamer(Context, std::move(MAB), OS, std::move(CE)); +} + +} // end namespace llvm diff --git a/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h b/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h new file mode 100644 index 00000000000..398b409f458 --- /dev/null +++ b/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h @@ -0,0 +1,54 @@ +//===--------- AVRMCELFStreamer.h - AVR subclass of MCELFStreamer ---------===// +// +// 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_AVR_MCTARGETDESC_AVRMCELFSTREAMER_H +#define LLVM_LIB_TARGET_AVR_MCTARGETDESC_AVRMCELFSTREAMER_H + +#include "MCTargetDesc/AVRMCExpr.h" +#include "MCTargetDesc/AVRMCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCInstrInfo.h" + +namespace llvm { + +const int SIZE_LONG = 4; +const int SIZE_WORD = 2; + +class AVRMCELFStreamer : public MCELFStreamer { + std::unique_ptr MCII; + +public: + AVRMCELFStreamer(MCContext &Context, std::unique_ptr TAB, + raw_pwrite_stream &OS, + std::unique_ptr Emitter) + : MCELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)), + MCII(createAVRMCInstrInfo()) {} + + AVRMCELFStreamer(MCContext &Context, std::unique_ptr TAB, + raw_pwrite_stream &OS, + std::unique_ptr Emitter, + MCAssembler *Assembler) + : MCELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)), + MCII(createAVRMCInstrInfo()) {} + + void EmitValueForModiferKind( + const MCSymbol *Sym, unsigned SizeInBytes, SMLoc Loc = SMLoc(), + AVRMCExpr::VariantKind ModifierKind = AVRMCExpr::VK_AVR_None); +}; + +MCStreamer *createAVRELFStreamer(Triple const &TT, MCContext &Context, + std::unique_ptr MAB, + raw_pwrite_stream &OS, + std::unique_ptr CE); + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_AVR_MCTARGETDESC_AVRMCELFSTREAMER_H diff --git a/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp b/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp index 085afd23a83..fdd43dd5ee1 100644 --- a/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp +++ b/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp @@ -29,6 +29,9 @@ const struct ModifierEntry { {"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8}, {"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8}, {"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8}, + + {"lo8_gs", AVRMCExpr::VK_AVR_LO8_GS}, {"hi8_gs", AVRMCExpr::VK_AVR_HI8_GS}, + {"gs", AVRMCExpr::VK_AVR_GS}, }; } // end of anonymous namespace @@ -101,23 +104,40 @@ int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const { case AVRMCExpr::VK_AVR_LO8: break; case AVRMCExpr::VK_AVR_HI8: + Value &= 0xff00; Value >>= 8; break; case AVRMCExpr::VK_AVR_HH8: + Value &= 0xff0000; Value >>= 16; break; case AVRMCExpr::VK_AVR_HHI8: + Value &= 0xff000000; Value >>= 24; break; case AVRMCExpr::VK_AVR_PM_LO8: + Value &= 0xff; Value >>= 1; break; case AVRMCExpr::VK_AVR_PM_HI8: + Value &= 0xff00; Value >>= 9; break; case AVRMCExpr::VK_AVR_PM_HH8: + Value &= 0xff0000; Value >>= 17; break; + case AVRMCExpr::VK_AVR_LO8_GS: + Value &= 0xff; + Value >>= 1; + break; + case AVRMCExpr::VK_AVR_HI8_GS: + Value &= 0xff00; + Value >>= 9; + break; + case AVRMCExpr::VK_AVR_GS: + Value >>= 1; + break; case AVRMCExpr::VK_AVR_None: llvm_unreachable("Uninitialized expression."); @@ -151,6 +171,12 @@ AVR::Fixups AVRMCExpr::getFixupKind() const { case VK_AVR_PM_HH8: Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm; break; + case VK_AVR_LO8_GS: + Kind = AVR::fixup_lo8_ldi_gs; + break; + case VK_AVR_HI8_GS: + Kind = AVR::fixup_hi8_ldi_gs; + break; case VK_AVR_None: llvm_unreachable("Uninitialized expression"); diff --git a/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h b/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h index be565a8be34..a166b094674 100644 --- a/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h +++ b/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h @@ -30,7 +30,11 @@ public: VK_AVR_PM_LO8, ///< Corresponds to `pm_lo8()`. VK_AVR_PM_HI8, ///< Corresponds to `pm_hi8()`. - VK_AVR_PM_HH8 ///< Corresponds to `pm_hh8()`. + VK_AVR_PM_HH8, ///< Corresponds to `pm_hh8()`. + + VK_AVR_LO8_GS, ///< Corresponds to `lo8(gs())`. + VK_AVR_HI8_GS, ///< Corresponds to `hi8(gs())`. + VK_AVR_GS, ///< Corresponds to `gs()`. }; public: diff --git a/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp b/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp index bccce5d307e..dd65a431207 100644 --- a/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp +++ b/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp @@ -11,12 +11,14 @@ // //===----------------------------------------------------------------------===// -#include "AVRMCTargetDesc.h" #include "AVRELFStreamer.h" #include "AVRMCAsmInfo.h" +#include "AVRMCELFStreamer.h" +#include "AVRMCTargetDesc.h" #include "AVRTargetStreamer.h" #include "InstPrinter/AVRInstPrinter.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCInstrInfo.h" @@ -35,7 +37,7 @@ using namespace llvm; -static MCInstrInfo *createAVRMCInstrInfo() { +MCInstrInfo *llvm::createAVRMCInstrInfo() { MCInstrInfo *X = new MCInstrInfo(); InitAVRMCInstrInfo(X); @@ -108,7 +110,7 @@ extern "C" void LLVMInitializeAVRTargetMC() { // Register the MC Code Emitter TargetRegistry::RegisterMCCodeEmitter(getTheAVRTarget(), createAVRMCCodeEmitter); - // Register the ELF streamer + // Register the obj streamer TargetRegistry::RegisterELFStreamer(getTheAVRTarget(), createMCStreamer); // Register the obj target streamer. diff --git a/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h b/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h index 8053b8d389f..5615fd72e45 100644 --- a/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h +++ b/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h @@ -34,6 +34,8 @@ class raw_pwrite_stream; Target &getTheAVRTarget(); +MCInstrInfo *createAVRMCInstrInfo(); + /// Creates a machine code emitter for AVR. MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, diff --git a/lib/Target/AVR/MCTargetDesc/CMakeLists.txt b/lib/Target/AVR/MCTargetDesc/CMakeLists.txt index 5bad6494c8a..eb7fe956cf3 100644 --- a/lib/Target/AVR/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/AVR/MCTargetDesc/CMakeLists.txt @@ -4,6 +4,7 @@ add_llvm_library(LLVMAVRDesc AVRELFStreamer.cpp AVRMCAsmInfo.cpp AVRMCCodeEmitter.cpp + AVRMCELFStreamer.cpp AVRMCExpr.cpp AVRMCTargetDesc.cpp AVRTargetStreamer.cpp diff --git a/test/MC/AVR/relocations.s b/test/MC/AVR/relocations.s index 398d5d3c5a1..da9925dcdbb 100644 --- a/test/MC/AVR/relocations.s +++ b/test/MC/AVR/relocations.s @@ -2,6 +2,10 @@ ; CHECK: RELOCATION RECORDS FOR +; CHECK: RELOCATION RECORDS BAR +bar: + jmp bar + ; CHECK-NEXT: R_AVR_LDI SYMBOL+3 ldi r21, SYMBOL+3 @@ -28,48 +32,105 @@ brcs foo+2 ; CHECK-NEXT: R_AVR_LO8_LDI bar+3 ldi r24, lo8(bar+3) +ldi r16, +lo8(abc) +ldi r16, lo8(+(abc)) ; CHECK-NEXT: R_AVR_HI8_LDI abc ldi r30, hi8(abc) +ldi r16, +hi8(abc) +ldi r16, hi8(+(abc)) ; CHECK-NEXT: R_AVR_LO8_LDI_NEG abc ldi r16, -lo8(abc) +ldi r16, lo8(-(abc)) ; CHECK-NEXT: R_AVR_HI8_LDI_NEG abc ldi r16, -hi8(abc) +ldi r16, hi8(-(abc)) ; CHECK-NEXT: R_AVR_HH8_LDI foo ldi r16, hh8(foo) +ldi r16, +hh8(foo) +ldi r16, hh8(+(foo)) ; CHECK-NEXT: R_AVR_HH8_LDI_NEG foo ldi r16, -hh8(foo) +ldi r16, hh8(-(foo)) ; CHECK-NEXT: R_AVR_HH8_LDI foo ldi r24, hlo8(foo) +ldi r24, +hlo8(foo) +ldi r24, hlo8(+(foo)) ; CHECK-NEXT: R_AVR_HH8_LDI_NEG foo ldi r24, -hlo8(foo) +ldi r24, hlo8(-(foo)) ; CHECK-NEXT: R_AVR_MS8_LDI bar ldi r24, hhi8(bar) +ldi r24, +hhi8(bar) +ldi r24, hhi8(+(bar)) ; CHECK-NEXT: R_AVR_MS8_LDI_NEG bar ldi r24, -hhi8(bar) +ldi r24, hhi8(-(bar)) ; CHECK-NEXT: R_AVR_LO8_LDI_PM foo ldi r17, pm_lo8(foo) +ldi r25, +pm_lo8(foo) +ldi r25, pm_lo8(+(foo)) ; CHECK-NEXT: R_AVR_HI8_LDI_PM bar ldi r22, pm_hi8(bar) +ldi r25, +pm_hi8(foo) +ldi r25, pm_hi8(+(foo)) ; CHECK-NEXT: R_AVR_HH8_LDI_PM baz ldi r25, pm_hh8(baz) +ldi r25, +pm_hh8(foo) +ldi r25, pm_hh8(+(foo)) ; CHECK-NEXT: R_AVR_LO8_LDI_PM_NEG ldi r25, -pm_lo8(foo) +ldi r25, pm_lo8(-(foo)) ; CHECK-NEXT: R_AVR_HI8_LDI_PM_NEG ldi r25, -pm_hi8(foo) +ldi r25, pm_hi8(-(foo)) ; CHECK-NEXT: R_AVR_HH8_LDI_PM_NEG ldi r25, -pm_hh8(foo) +ldi r25, pm_hh8(-(foo)) + +; CHECK-NEXT: R_AVR_LO8_LDI_GS +ldi r17, lo8(gs(foo)) + +; CHECK-NEXT: R_AVR_HI8_LDI_GS +ldi r18, hi8(gs(foo)) + +; CHECK-NEXT: R_AVR_16 +.short foo + +; CHECK-NEXT: R_AVR_16_PM +.short gs(foo) + +; CHECK-NEXT: R_AVR_8 +.byte foo + +; CHECK-NEXT: R_AVR_8_LO8 +.byte lo8(foo) + +; CHECK-NEXT: R_AVR_8_HI8 +.byte hi8(foo) + +; CHECK-NEXT: R_AVR_8_HLO8 +.byte hlo8(foo) + +; CHECK-NEXT: R_AVR_DIFF8 +.byte foo - bar + +; CHECK-NEXT: R_AVR_DIFF16 +.short foo - bar + +; CHECK-NEXT: R_AVR_DIFF32 +.long foo - bar