Index: llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def =================================================================== --- llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def +++ llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def @@ -97,6 +97,7 @@ #undef R_PPC64_DTPREL16_HIGH #undef R_PPC64_DTPREL16_HIGHA #undef R_PPC64_REL24_NOTOC +#undef R_PPC64_PCREL_OPT #undef R_PPC64_PCREL34 #undef R_PPC64_GOT_PCREL34 #undef R_PPC64_IRELATIVE @@ -194,6 +195,7 @@ ELF_RELOC(R_PPC64_DTPREL16_HIGH, 114) ELF_RELOC(R_PPC64_DTPREL16_HIGHA, 115) ELF_RELOC(R_PPC64_REL24_NOTOC, 116) +ELF_RELOC(R_PPC64_PCREL_OPT, 123) ELF_RELOC(R_PPC64_PCREL34, 132) ELF_RELOC(R_PPC64_GOT_PCREL34, 133) ELF_RELOC(R_PPC64_IRELATIVE, 248) Index: llvm/include/llvm/MC/MCExpr.h =================================================================== --- llvm/include/llvm/MC/MCExpr.h +++ llvm/include/llvm/MC/MCExpr.h @@ -302,6 +302,7 @@ VK_PPC_TLSLD, // symbol@tlsld VK_PPC_LOCAL, // symbol@local VK_PPC_NOTOC, // symbol@notoc + VK_PPC_LINKER_OPT, // Not actually emitted as symbol@ppclinkeropt VK_COFF_IMGREL32, // symbol@imgrel (image-relative) Index: llvm/lib/MC/MCExpr.cpp =================================================================== --- llvm/lib/MC/MCExpr.cpp +++ llvm/lib/MC/MCExpr.cpp @@ -322,6 +322,8 @@ case VK_PPC_TLSLD: return "tlsld"; case VK_PPC_LOCAL: return "local"; case VK_PPC_NOTOC: return "notoc"; + case VK_PPC_LINKER_OPT: + return "ppclinkeropt"; case VK_COFF_IMGREL32: return "IMGREL"; case VK_Hexagon_LO16: return "LO16"; case VK_Hexagon_HI16: return "HI16"; @@ -437,6 +439,7 @@ .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) .Case("got@pcrel", VK_PPC_GOT_PCREL) .Case("notoc", VK_PPC_NOTOC) + .Case("ppclinkeropt", VK_PPC_LINKER_OPT) .Case("gdgot", VK_Hexagon_GD_GOT) .Case("gdplt", VK_Hexagon_GD_PLT) .Case("iegot", VK_Hexagon_IE_GOT) Index: llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp =================================================================== --- llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -126,6 +126,7 @@ bool ParseDarwinDirectiveMachine(SMLoc L); bool ParseDirectiveAbiVersion(SMLoc L); bool ParseDirectiveLocalEntry(SMLoc L); + bool ParseDirectiveReloc(SMLoc L); bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, @@ -1660,6 +1661,8 @@ ParseDirectiveAbiVersion(DirectiveID.getLoc()); else if (IDVal == ".localentry") ParseDirectiveLocalEntry(DirectiveID.getLoc()); + else if (IDVal == ".reloc") + ParseDirectiveReloc(DirectiveID.getLoc()); else return true; return false; @@ -1804,7 +1807,80 @@ return false; } +/// ParseDirectiveReloc +/// Very similar to the one in AsmParser::parseDirectiveReloc except that we +/// want to be able to parse MCExpr::Binary too. +/// Format: .reloc expression , identifier [ , expression ] +bool PPCAsmParser::ParseDirectiveReloc(SMLoc DirectiveLoc) { + const MCExpr *Offset; + const MCExpr *Expr = nullptr; + int64_t OffsetVal; + SMLoc OffsetLoc = getLexer().getTok().getLoc(); + + // Get the MCExpr that represents the first expression that immediately + // follows the .reloc. + // Note that parseExpression() returns false on success. + // So, if we fail to parse the first expression just bail. + if (getParser().parseExpression(Offset)) + return true; + + // If the expression is a negative value bail out. An absolute value needs to + // positive. + if (Offset->evaluateAsAbsolute(OffsetVal, getStreamer().getAssemblerPtr()) && + check(OffsetVal < 0, OffsetLoc, "expression is negative")) + return true; + + // The expression must be either a constant, a symbol or a binary expression. + // If it is not: exit. + if (check(Offset->getKind() != llvm::MCExpr::Constant && + Offset->getKind() != llvm::MCExpr::SymbolRef && + Offset->getKind() != llvm::MCExpr::Binary, + OffsetLoc, + "expected non-negative constant, label or a binary expression")) + return true; + + // Parse the next token. It needs to be the comma between the first expression + // and the identifier. + if (parseToken(AsmToken::Comma, "expected comma")) + return true; + + // The identifier needs to be the relocaiton name. + if(check(getTok().isNot(AsmToken::Identifier), "expected relocation name")) + return true; + + // Get the location and name of the identifier (the relocation name). + SMLoc NameLoc = getLexer().getTok().getLoc(); + StringRef Name = getLexer().getTok().getIdentifier(); + // Go to the next token. + getParser().Lex(); + + // Check for the second comma to see if the second expression is there after + // the identifier. If the next token is not a comma the Expr varaible is left + // as a null pointer. This is fine because emitRelocDirective can handle that. + if (getLexer().is(AsmToken::Comma)) { + getParser().Lex(); + SMLoc ExprLoc = getLexer().getLoc(); + if (getParser().parseExpression(Expr)) + return true; + + MCValue Value; + if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr)) + return Error(ExprLoc, "expression must be relocatable"); + } + + // Make sure that we have now reached the end of the .reloc directive. + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in .reloc directive")) + return true; + + // Now that all of the pieces are (Offset, Name, Expr) have been parsed we + // move to emit the .reloc directive. + if (getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc, + getSTI())) + return Error(NameLoc, "unknown relocation name"); + return false; +} /// Force static initialization. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmParser() { Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -33,6 +33,7 @@ case FK_Data_4: case FK_Data_8: case PPC::fixup_ppc_nofixup: + case PPC::fixup_ppc_linker_opt: return Value; case PPC::fixup_ppc_brcond14: case PPC::fixup_ppc_brcond14abs: @@ -68,6 +69,7 @@ case PPC::fixup_ppc_br24_notoc: return 4; case PPC::fixup_ppc_pcrel34: + case PPC::fixup_ppc_linker_opt: case FK_Data_8: return 8; case PPC::fixup_ppc_nofixup: @@ -100,6 +102,7 @@ { "fixup_ppc_half16", 0, 16, 0 }, { "fixup_ppc_half16ds", 0, 14, 0 }, { "fixup_ppc_pcrel34", 0, 34, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_ppc_linker_opt", 0, 64, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_ppc_nofixup", 0, 0, 0 } }; const static MCFixupKindInfo InfosLE[PPC::NumTargetFixupKinds] = { @@ -112,6 +115,7 @@ { "fixup_ppc_half16", 0, 16, 0 }, { "fixup_ppc_half16ds", 2, 14, 0 }, { "fixup_ppc_pcrel34", 0, 34, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_ppc_linker_opt", 0, 64, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_ppc_nofixup", 0, 0, 0 } }; @@ -158,6 +162,8 @@ switch ((unsigned)Kind) { default: return Kind >= FirstLiteralRelocationKind; + case PPC::fixup_ppc_linker_opt: + return true; case PPC::fixup_ppc_br24: case PPC::fixup_ppc_br24abs: case PPC::fixup_ppc_br24_notoc: Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -103,6 +103,9 @@ break; } break; + case PPC::fixup_ppc_linker_opt: + Type = ELF::R_PPC64_PCREL_OPT; + break; case PPC::fixup_ppc_brcond14: case PPC::fixup_ppc_brcond14abs: Type = ELF::R_PPC_REL14; Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h @@ -41,6 +41,11 @@ // EmitLabel updates LastLabel and LastLabelLoc when a new label is emitted. void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + // Emit a .reloc label. + bool emitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) override; + private: void emitPrefixedInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); }; Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp @@ -18,8 +18,8 @@ // //===----------------------------------------------------------------------===// - #include "PPCELFStreamer.h" +#include "PPCFixupKinds.h" #include "PPCInstrInfo.h" #include "PPCMCCodeEmitter.h" #include "llvm/BinaryFormat/ELF.h" @@ -103,6 +103,116 @@ MCELFStreamer::emitLabel(Symbol); } +// Given an MCBinary expression of the form Symbol +/- Constant find the data +// fragment and the offset into that data fragment that the expression +// represents. +// Function returns true on success and false otherwise. +static bool getOffsetFromBinaryExpr(const MCBinaryExpr &BinExpr, + uint64_t &Offset, MCDataFragment **DF) { + const MCExpr *LHS = BinExpr.getLHS(); + const MCExpr *RHS = BinExpr.getRHS(); + // At this point we only support Symbol +/- Constant. + if (LHS->getKind() != MCExpr::SymbolRef || RHS->getKind() != MCExpr::Constant) + return false; + + // If we have reached this far the LHS is a symbol and the RHS is a + // constant. + const MCSymbolRefExpr *Symbol = static_cast(LHS); + const MCConstantExpr *ConstVal = static_cast(RHS); + + // Get the Data Fragment. + // If there is no data fragment for this symbol just return false. + MCFragment *Fragment = Symbol->getSymbol().getFragment(); + if (!Fragment || Fragment->getKind() != MCFragment::FT_Data) + return false; + + // Get the offset of the symbol within the fragment. + Offset = Symbol->getSymbol().getOffset(); + switch (BinExpr.getOpcode()) { + default: + // Other opcodes are not supported. + return false; + case MCBinaryExpr::Add: + Offset += ConstVal->getValue(); + break; + case MCBinaryExpr::Sub: + Offset -= ConstVal->getValue(); + break; + } + + *DF = static_cast(Fragment); + return true; +} + +// Emit the .relc directive. This is a PPC extension of what is being done in +// the generic ELF streamer. +bool PPCELFStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) { + // If there is no MCExpr let the parent class handle it. + if (!Expr) + return MCELFStreamer::emitRelocDirective(Offset, Name, Expr, Loc, STI); + + // Get the MCFixupKind that corresponds to the string Name variable. + Optional MaybeKind = + getAssembler().getBackend().getFixupKind(Name); + if (!MaybeKind.hasValue()) + return true; + + MCFixupKind Kind = *MaybeKind; + + // Handle the Binary and Symbol cases separately. Anything else just drops + // through for default handling in the parent class. + switch (Offset.getKind()) { + case MCExpr::Binary: { + const MCBinaryExpr &BinExpr = cast(Offset); + uint64_t ComputedOffset; + MCDataFragment *DF = nullptr; + // Try to get the data fragment and offset into data fragment. + // If that fails break out and let the parent deal with it. + if (!getOffsetFromBinaryExpr(BinExpr, ComputedOffset, &DF)) + break; + + assert(DF && "Expected a valid data fragment."); + + DF->getFixups().push_back(MCFixup::create(ComputedOffset, Expr, Kind, Loc)); + return false; + } + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &SRE = cast(Offset); + const MCSymbol &Symbol = SRE.getSymbol(); + if (!Symbol.isDefined()) + break; + + // Symbols that are not variable are already handled the way we want in the + // parent. So, let the parent do it. + if (!Symbol.isVariable()) + break; + + // If the symbol expression is not a binary expression we can let the parent + // handle the issue. + const MCExpr *SymbolExpr = Symbol.getVariableValue(); + if (SymbolExpr->getKind() != MCExpr::Binary) + break; + + const MCBinaryExpr &BinExpr = cast(*SymbolExpr); + uint64_t ComputedOffset; + MCDataFragment *DF = nullptr; + // Get the offset and data fragment for the symbol's expression. + if (!getOffsetFromBinaryExpr(BinExpr, ComputedOffset, &DF)) + break; + assert(DF && "Expected a valid data fragment."); + DF->getFixups().push_back(MCFixup::create(ComputedOffset, Expr, Kind, Loc)); + return false; + } + default: + // Fall through to the parent class. + break; + } + // If the directive cannot be handled here pass it on to the parent class. + return MCELFStreamer::emitRelocDirective(Offset, Name, Expr, Loc, STI); +} + MCELFStreamer *llvm::createPPCELFStreamer( MCContext &Context, std::unique_ptr MAB, std::unique_ptr OW, Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h @@ -43,6 +43,9 @@ // A 34-bit fixup corresponding to PC-relative paddi. fixup_ppc_pcrel34, + // A linker opt fixup. + fixup_ppc_linker_opt, + /// Not a true fixup, but ties a symbol to a call to __tls_get_addr for the /// TLS general and local dynamic models, or inserts the thread-pointer /// register number. Index: llvm/test/MC/PowerPC/future-reloc-with-expr.s =================================================================== --- /dev/null +++ llvm/test/MC/PowerPC/future-reloc-with-expr.s @@ -0,0 +1,336 @@ +# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \ +# RUN: llvm-objdump -dr --mcpu=future - | FileCheck %s + + +## +# This section of tests contains the MCBinaryExpr as the first parameter of the +# .reloc relocation. +## + .text + .abiversion 2 + .globl Minimal + .p2align 4 + .type Minimal,@function +Minimal: +.LMinimal$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel1: + .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK-LABEL: Minimal +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x8 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + .globl SingleInsnBetween + .p2align 4 + .type SingleInsnBetween,@function +SingleInsnBetween: +.LSingleInsnBetween$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel2: + addi 3, 3, 42 + .reloc .Lpcrel2-8,R_PPC64_PCREL_OPT,.-(.Lpcrel2-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK_LABEL: SingleInsnBetween +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0xc +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + + .globl MultiInsnBetween # -- Begin function + .p2align 4 + .type MultiInsnBetween,@function +MultiInsnBetween: +.LMultiInsnBetween$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel3: + addi 3, 3, 42 + addi 3, 3, 42 + addi 3, 3, 42 + addi 3, 3, 42 + addi 3, 3, 42 + .reloc .Lpcrel3-8,R_PPC64_PCREL_OPT,.-(.Lpcrel3-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK_LABEL: MultiInsnBetween +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x1c +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + .globl PrefixInsnBetween # -- Begin function + .p2align 4 + .type PrefixInsnBetween,@function +PrefixInsnBetween: +.LPrefixInsnBetween$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel4: + addi 3, 3, 42 + paddi 3, 3, 42, 0 + addi 3, 3, 42 + paddi 3, 3, 42, 0 + addi 3, 3, 42 + .reloc .Lpcrel4-8,R_PPC64_PCREL_OPT,.-(.Lpcrel4-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK_LABEL: PrefixInsnBetween +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x28 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: nop +# CHECK-NEXT: paddi 3, 3, 42, 0 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: paddi 3, 3, 42, 0 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + + .globl SpaceBetween # -- Begin function + .p2align 4 + .type SpaceBetween,@function +SpaceBetween: +.LSpaceBetween$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel5: + addi 3, 3, 42 + paddi 3, 3, 42, 0 + addi 3, 3, 42 + .space 40, 0 + paddi 3, 3, 42, 0 + addi 3, 3, 42 + .reloc .Lpcrel5-8,R_PPC64_PCREL_OPT,.-(.Lpcrel5-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK_LABEL: SpaceBetween +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x50 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: nop +# CHECK-NEXT: paddi 3, 3, 42, 0 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK: paddi 3, 3, 42, 0 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + + .globl Plus + .p2align 4 + .type Plus,@function +Plus: +.LPlus$local: +# %bb.0: # %entry +.Lpcrel6: + addi 3, 3, 42 + addi 3, 3, 42 + pld 3, vec@got@pcrel(0), 1 + .reloc .Lpcrel6+8,R_PPC64_PCREL_OPT,.-(.Lpcrel6+8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK-LABEL: Plus +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x8 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + +## +# This section of tests contains the variable MCSymbol as part of the +# MCSymbolRefExpr for the first parameter of the .reloc relocation. +## + .globl VarLabelMinimal # -- Begin function + .p2align 4 + .type VarLabelMinimal,@function +VarLabelMinimal: +.LVarLabelMinimal$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel101=.-8 + .reloc .Lpcrel101,R_PPC64_PCREL_OPT,.-.Lpcrel101 + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK-LABEL: VarLabelMinimal +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x8 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + + .globl VarLabelSingleInsnBetween + .p2align 4 + .type VarLabelSingleInsnBetween,@function +VarLabelSingleInsnBetween: +.LVarLabelSingleInsnBetween$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel102: + addi 3, 3, 42 + .reloc .Lpcrel102-8,R_PPC64_PCREL_OPT,.-(.Lpcrel102-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK_LABEL: VarLabelSingleInsnBetween +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0xc +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + .globl VarLabelMultiInsnBetween # -- Begin function + .p2align 4 + .type VarLabelMultiInsnBetween,@function +VarLabelMultiInsnBetween: +.LVarLabelMultiInsnBetween$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel103: + addi 3, 3, 42 + addi 3, 3, 42 + addi 3, 3, 42 + addi 3, 3, 42 + addi 3, 3, 42 + .reloc .Lpcrel103-8,R_PPC64_PCREL_OPT,.-(.Lpcrel103-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK_LABEL: VarLabelMultiInsnBetween +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x1c +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + + .globl VarLabelPrefixInsnBetween # -- Begin function + .p2align 4 + .type VarLabelPrefixInsnBetween,@function +VarLabelPrefixInsnBetween: +.LVarLabelPrefixInsnBetween$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel104: + addi 3, 3, 42 + paddi 3, 3, 42, 0 + addi 3, 3, 42 + paddi 3, 3, 42, 0 + addi 3, 3, 42 + .reloc .Lpcrel104-8,R_PPC64_PCREL_OPT,.-(.Lpcrel104-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK_LABEL: VarLabelPrefixInsnBetween +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x24 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: paddi 3, 3, 42, 0 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: paddi 3, 3, 42, 0 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + + .globl VarLabelSpaceBetween # -- Begin function + .p2align 4 + .type VarLabelSpaceBetween,@function +VarLabelSpaceBetween: +.LVarLabelSpaceBetween$local: +# %bb.0: # %entry + pld 3, vec@got@pcrel(0), 1 +.Lpcrel105: + addi 3, 3, 42 + paddi 3, 3, 42, 0 + addi 3, 3, 42 + .space 40, 0 + paddi 3, 3, 42, 0 + addi 3, 3, 42 + .reloc .Lpcrel105-8,R_PPC64_PCREL_OPT,.-(.Lpcrel105-8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK_LABEL: VarLabelSpaceBetween +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x4c +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: paddi 3, 3, 42, 0 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK: paddi 3, 3, 42, 0 +# CHECK-NEXT: addi 3, 3, 42 +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + + .globl VarLabelPlus + .p2align 4 + .type VarLabelPlus,@function +VarLabelPlus: +.LVarLabelPlus$local: +# %bb.0: # %entry +.Lpcrel106: + addi 3, 3, 42 + addi 3, 3, 42 + pld 3, vec@got@pcrel(0), 1 + .reloc .Lpcrel106+8,R_PPC64_PCREL_OPT,.-(.Lpcrel106+8) + lwa 3, 4(3) + blr + .long 0 + .quad 0 +# CHECK-LABEL: VarLabelPlus +# CHECK: pld 3, 0(0), 1 +# CHECK-NEXT: R_PPC64_PCREL_OPT *ABS*+0x8 +# CHECK-NEXT: R_PPC64_GOT_PCREL34 vec +# CHECK-NEXT: lwa 3, 4(3) +# CHECK-NEXT: blr + + + +