Index: include/llvm/BinaryFormat/ELFRelocs/AVR.def =================================================================== --- include/llvm/BinaryFormat/ELFRelocs/AVR.def +++ include/llvm/BinaryFormat/ELFRelocs/AVR.def @@ -33,8 +33,9 @@ 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) Index: include/llvm/MC/MCExpr.h =================================================================== --- include/llvm/MC/MCExpr.h +++ include/llvm/MC/MCExpr.h @@ -206,6 +206,14 @@ 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 Index: lib/MC/MCExpr.cpp =================================================================== --- lib/MC/MCExpr.cpp +++ lib/MC/MCExpr.cpp @@ -224,6 +224,13 @@ 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 @@ .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) Index: lib/Target/AVR/AsmParser/AVRAsmParser.cpp =================================================================== --- lib/Target/AVR/AsmParser/AVRAsmParser.cpp +++ lib/Target/AVR/AsmParser/AVRAsmParser.cpp @@ -11,6 +11,7 @@ #include "AVRRegisterInfo.h" #include "MCTargetDesc/AVRMCExpr.h" #include "MCTargetDesc/AVRMCTargetDesc.h" +#include "MCTargetDesc/AVRMCELFStreamer.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/StringSwitch.h" @@ -40,6 +41,7 @@ const MCSubtargetInfo &STI; MCAsmParser &Parser; const MCRegisterInfo *MRI; + const std::string GENERATE_STUBS = "gs"; #define GET_ASSEMBLER_HEADER #include "AVRGenAsmMatcher.inc" @@ -54,7 +56,11 @@ bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; - bool ParseDirective(AsmToken directiveID) override; + bool ParseDirective(AsmToken DirectiveID +#ifdef REFACTORY_PARSEDIRECTIVE + , OperandVector &Operands +#endif + ) override; OperandMatchResultTy parseMemriOperand(OperandVector &Operands); @@ -80,6 +86,12 @@ uint64_t const &ErrorInfo); bool missingFeature(SMLoc const &Loc, uint64_t const &ErrorInfo); + bool parseLiteralValues(unsigned SizeInBytes, SMLoc L +#ifdef REFACTORY_PARSEDIRECTIVE + , OperandVector &Operands +#endif + ); + public: AVRAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, const MCInstrInfo &MII, const MCTargetOptions &Options) @@ -404,11 +416,14 @@ 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 +431,8 @@ } // Eat the sign - Parser.Lex(); + if (CurTok == AsmToken::Minus || CurTok == AsmToken::Plus) + Parser.Lex(); } } @@ -432,14 +448,34 @@ 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 +616,90 @@ return false; } -bool AVRAsmParser::ParseDirective(llvm::AsmToken DirectiveID) { return true; } +bool AVRAsmParser::ParseDirective(llvm::AsmToken DirectiveID +#ifdef REFACTORY_PARSEDIRECTIVE + , OperandVector &Operands +#endif + ) { + StringRef IDVal = DirectiveID.getIdentifier(); + if (IDVal.lower() == ".long") { + parseLiteralValues(SIZE_LONG, DirectiveID.getLoc() +#ifdef REFACTORY_PARSEDIRECTIVE + , Operands +#endif + ); + } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") { + parseLiteralValues(SIZE_WORD, DirectiveID.getLoc() +#ifdef REFACTORY_PARSEDIRECTIVE + , Operands +#endif + ); + } else if (IDVal.lower() == ".byte") { + parseLiteralValues(1, DirectiveID.getLoc() +#ifdef REFACTORY_PARSEDIRECTIVE + , Operands +#endif + ); + } + return true; +} + +bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L +#ifdef REFACTORY_PARSEDIRECTIVE + , OperandVector &Operands +#endif + ) { + MCAsmParser &Parser = getParser(); + 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) { + AVRMCELFStreamer &AVRStreamer = + static_cast(Parser.getStreamer()); + MCSymbol *Symbol = getContext().getOrCreateSymbol(".text"); + AVRStreamer.EmitValue(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()); +#ifdef REFACTORY_PARSEDIRECTIVE + const MCExpr *InnerExpression; + if (Parser.parseExpression(InnerExpression)) + return true; + MCExpr const *Expression = AVRMCExpr::create(ModifierKind, InnerExpression, + false, getContext()); + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(AVROperand::CreateImm(Expression, S, E)); +#endif + AVRMCELFStreamer &AVRStreamer = + static_cast(Parser.getStreamer()); + AVRStreamer.EmitValue(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()); Index: lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h +++ lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h @@ -38,7 +38,8 @@ void adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t &Value, MCContext *Ctx = nullptr) const; - MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override; + std::unique_ptr + createObjectWriter(raw_pwrite_stream &OS) const override; void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, Index: lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp +++ lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp @@ -266,13 +266,17 @@ break; case AVR::fixup_lo8_ldi: case AVR::fixup_lo8_ldi_pm: - if (Kind == AVR::fixup_lo8_ldi_pm) adjust::pm(Value); + case AVR::fixup_lo8_ldi_gs: + if (Kind == AVR::fixup_lo8_ldi_pm || Kind == AVR::fixup_lo8_ldi_gs) + adjust::pm(Value); adjust::ldi::lo8(Size, Fixup, Value, Ctx); break; case AVR::fixup_hi8_ldi: case AVR::fixup_hi8_ldi_pm: - if (Kind == AVR::fixup_hi8_ldi_pm) adjust::pm(Value); + case AVR::fixup_hi8_ldi_gs: + if (Kind == AVR::fixup_hi8_ldi_pm || Kind == AVR::fixup_hi8_ldi_gs) + adjust::pm(Value); adjust::ldi::hi8(Size, Fixup, Value, Ctx); break; @@ -340,7 +344,8 @@ } } -MCObjectWriter *AVRAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { +std::unique_ptr +AVRAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { return createAVRELFObjectWriter(OS, MCELFObjectTargetWriter::getOSABI(OSType)); } @@ -421,8 +426,9 @@ {"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}, Index: lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp +++ lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp @@ -15,6 +15,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCValue.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -39,12 +40,43 @@ 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: @@ -103,10 +135,12 @@ 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: @@ -118,9 +152,10 @@ } } -MCObjectWriter *createAVRELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI) { - MCELFObjectTargetWriter *MOTW = new AVRELFObjectWriter(OSABI); - return createELFObjectWriter(MOTW, OS, true); +std::unique_ptr +createAVRELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI) { + return createELFObjectWriter(llvm::make_unique(OSABI), + OS, true); } } // end of namespace llvm Index: lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h +++ lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h @@ -117,8 +117,9 @@ /// 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, Index: lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h +++ 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/AVRMCTargetDesc.h" +#include "MCTargetDesc/AVRMCExpr.h" +#include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCCodeEmitter.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 EmitValue(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 Index: lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp +++ lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp @@ -0,0 +1,52 @@ +//===--------- 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::EmitValue(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 Index: lib/Target/AVR/MCTargetDesc/AVRMCExpr.h =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRMCExpr.h +++ lib/Target/AVR/MCTargetDesc/AVRMCExpr.h @@ -30,7 +30,11 @@ 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: Index: lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp +++ lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp @@ -29,6 +29,9 @@ {"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 @@ -118,11 +121,20 @@ case AVRMCExpr::VK_AVR_PM_HH8: Value >>= 17; break; + case AVRMCExpr::VK_AVR_LO8_GS: + Value >>= 1; + break; + case AVRMCExpr::VK_AVR_HI8_GS: + Value >>= 9; + break; + case AVRMCExpr::VK_AVR_GS: + Value >>= 1; + break; case AVRMCExpr::VK_AVR_None: llvm_unreachable("Uninitialized expression."); } - return static_cast(Value) & 0xff; + return static_cast(Value) & 0xffff; } AVR::Fixups AVRMCExpr::getFixupKind() const { @@ -151,6 +163,12 @@ 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"); Index: lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h +++ lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h @@ -15,6 +15,7 @@ #define LLVM_AVR_MCTARGET_DESC_H #include "llvm/Support/DataTypes.h" +#include namespace llvm { @@ -32,6 +33,8 @@ Target &getTheAVRTarget(); +MCInstrInfo *createAVRMCInstrInfo(); + /// Creates a machine code emitter for AVR. MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, @@ -43,7 +46,8 @@ const llvm::MCTargetOptions &TO); /// Creates an ELF object writer for AVR. -MCObjectWriter *createAVRELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI); +std::unique_ptr + createAVRELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI); } // end namespace llvm Index: lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp =================================================================== --- lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp +++ lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp @@ -15,12 +15,15 @@ #include "AVRELFStreamer.h" #include "AVRMCAsmInfo.h" #include "AVRTargetStreamer.h" +#include "AVRMCELFStreamer.h" #include "InstPrinter/AVRInstPrinter.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCCodeEmitter.h" #include "llvm/Support/TargetRegistry.h" #define GET_INSTRINFO_MC_DESC @@ -34,7 +37,7 @@ using namespace llvm; -static MCInstrInfo *createAVRMCInstrInfo() { +MCInstrInfo *llvm::createAVRMCInstrInfo() { MCInstrInfo *X = new MCInstrInfo(); InitAVRMCInstrInfo(X); @@ -66,9 +69,12 @@ } static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, - MCAsmBackend &MAB, raw_pwrite_stream &OS, - MCCodeEmitter *Emitter, bool RelaxAll) { - return createELFStreamer(Context, MAB, OS, Emitter, RelaxAll); + std::unique_ptr &&MAB, + raw_pwrite_stream &OS, + std::unique_ptr &&Emitter, + bool RelaxAll) { + return createAVRELFStreamer(T, Context, std::move(MAB), OS, + std::move(Emitter)); } static MCTargetStreamer * @@ -104,7 +110,7 @@ // 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. Index: lib/Target/AVR/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/AVR/MCTargetDesc/CMakeLists.txt +++ lib/Target/AVR/MCTargetDesc/CMakeLists.txt @@ -7,6 +7,7 @@ AVRMCExpr.cpp AVRMCTargetDesc.cpp AVRTargetStreamer.cpp + AVRMCELFStreamer.cpp ) add_dependencies(LLVMAVRDesc AVRCommonTableGen) Index: test/MC/AVR/relocations.s =================================================================== --- test/MC/AVR/relocations.s +++ 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 @@ ; 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