Index: lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- lib/Target/AArch64/AArch64AsmPrinter.cpp +++ lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -80,10 +80,13 @@ AU.setPreservesAll(); } - bool runOnMachineFunction(MachineFunction &F) override { - AArch64FI = F.getInfo(); - STI = static_cast(&F.getSubtarget()); - return AsmPrinter::runOnMachineFunction(F); + bool runOnMachineFunction(MachineFunction &MF) override { + AArch64FI = MF.getInfo(); + STI = static_cast(&MF.getSubtarget()); + SetupMachineFunction(MF); + AArch64FI->setCurrentFnSymbol(CurrentFnSym); + EmitFunctionBody(); + return false; } private: Index: lib/Target/AArch64/AArch64ISelLowering.h =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.h +++ lib/Target/AArch64/AArch64ISelLowering.h @@ -17,6 +17,7 @@ #include "AArch64.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Instruction.h" @@ -476,6 +477,19 @@ void saveVarArgRegisters(CCState &CCInfo, SelectionDAG &DAG, const SDLoc &DL, SDValue &Chain) const; + unsigned getJumpTableEncoding() const override { + return MachineJumpTableInfo::EK_LabelDifference32; + } + SDValue getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const override; + const MCExpr *getPICJumpTableRelocBaseExpr(const MachineFunction *MF, + unsigned JTI, + MCContext &Ctx) const override; + + bool isJumpTableRelative() const override { + return true; + } + bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl &Outs, Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -2311,6 +2311,48 @@ } } +SDValue +AArch64TargetLowering::getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const { + switch (getTargetMachine().getCodeModel()) { + case CodeModel::Default: + case CodeModel::Small: + case CodeModel::Medium: + return TargetLowering::getPICJumpTableRelocBase(Table, DAG); + default: { + MachineFunction &MF = DAG.getMachineFunction(); + const Function *F = MF.getFunction(); + SDLoc DL(Table); + // Since the target is the function itself, always resolve it locally. + unsigned char OpFlags = AArch64II::MO_NO_FLAG; + auto PtrVT = getPointerTy(DAG.getDataLayout()); + SDValue Hi = DAG.getTargetGlobalAddress(F, DL, PtrVT, 0, + OpFlags | AArch64II::MO_PAGE); + unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | AArch64II::MO_NC; + SDValue Lo = DAG.getTargetGlobalAddress(F, DL, PtrVT, 0, LoFlags); + + SDValue ADRP = DAG.getNode(AArch64ISD::ADRP, DL, PtrVT, Hi); + return DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, ADRP, Lo); + } + } +} + +const MCExpr * +AArch64TargetLowering::getPICJumpTableRelocBaseExpr(const MachineFunction *MF, + unsigned JTI, + MCContext &Ctx) const { + switch (getTargetMachine().getCodeModel()) { + case CodeModel::Default: + case CodeModel::Small: + case CodeModel::Medium: + return TargetLowering::getPICJumpTableRelocBaseExpr(MF, JTI, Ctx); + default: { + auto *AArch64FI = MF->getInfo(); + return MCSymbolRefExpr::create(AArch64FI->getCurrentFnSymbol(), Ctx); + } + } +} + SDValue AArch64TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { Index: lib/Target/AArch64/AArch64MachineFunctionInfo.h =================================================================== --- lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -87,20 +87,23 @@ /// other stack allocations. bool CalleeSaveStackHasFreeSpace; + /// \brief The symbol of the current MachineFunction during emission. + MCSymbol *CurrentFnSym; + public: AArch64FunctionInfo() : BytesInStackArgArea(0), ArgumentStackToRestore(0), HasStackFrame(false), NumLocalDynamicTLSAccesses(0), VarArgsStackIndex(0), VarArgsGPRIndex(0), VarArgsGPRSize(0), VarArgsFPRIndex(0), VarArgsFPRSize(0), IsSplitCSR(false), StackRealigned(false), - CalleeSaveStackHasFreeSpace(false) {} + CalleeSaveStackHasFreeSpace(false), CurrentFnSym(nullptr) {} explicit AArch64FunctionInfo(MachineFunction &MF) : BytesInStackArgArea(0), ArgumentStackToRestore(0), HasStackFrame(false), NumLocalDynamicTLSAccesses(0), VarArgsStackIndex(0), VarArgsGPRIndex(0), VarArgsGPRSize(0), VarArgsFPRIndex(0), VarArgsFPRSize(0), IsSplitCSR(false), StackRealigned(false), - CalleeSaveStackHasFreeSpace(false) { + CalleeSaveStackHasFreeSpace(false), CurrentFnSym(nullptr) { (void)MF; } @@ -188,6 +191,9 @@ LOHRelated.insert(Args.begin(), Args.end()); } + MCSymbol *getCurrentFnSymbol() const { return CurrentFnSym; } + void setCurrentFnSymbol(MCSymbol *Value) { CurrentFnSym = Value; } + private: // Hold the lists of LOHs. MILOHContainer LOHContainerSet; Index: test/CodeGen/AArch64/jump-table.ll =================================================================== --- test/CodeGen/AArch64/jump-table.ll +++ test/CodeGen/AArch64/jump-table.ll @@ -1,6 +1,7 @@ ; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s ; RUN: llc -code-model=large -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck --check-prefix=CHECK-LARGE %s ; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs -relocation-model=pic -aarch64-enable-atomic-cfg-tidy=0 -o - %s | FileCheck --check-prefix=CHECK-PIC %s +; XXX: pic+large define i32 @test_jumptable(i32 %in) { ; CHECK: test_jumptable @@ -11,23 +12,24 @@ i32 2, label %lbl3 i32 4, label %lbl4 ] -; CHECK: adrp [[JTPAGE:x[0-9]+]], .LJTI0_0 -; CHECK: add x[[JT:[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI0_0 -; CHECK: ldr [[DEST:x[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #3] -; CHECK: br [[DEST]] - -; CHECK-LARGE: movz x[[JTADDR:[0-9]+]], #:abs_g3:.LJTI0_0 -; CHECK-LARGE: movk x[[JTADDR]], #:abs_g2_nc:.LJTI0_0 -; CHECK-LARGE: movk x[[JTADDR]], #:abs_g1_nc:.LJTI0_0 -; CHECK-LARGE: movk x[[JTADDR]], #:abs_g0_nc:.LJTI0_0 -; CHECK-LARGE: ldr [[DEST:x[0-9]+]], [x[[JTADDR]], {{x[0-9]+}}, lsl #3] -; CHECK-LARGE: br [[DEST]] - -; CHECK-PIC: adrp [[JTPAGE:x[0-9]+]], .LJTI0_0 -; CHECK-PIC: add x[[JT:[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI0_0 -; CHECK-PIC: ldrsw [[DEST:x[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #2] -; CHECK-PIC: add [[TABLE:x[0-9]+]], [[DEST]], x[[JT]] -; CHECK-PIC: br [[TABLE]] +; CHECK: adrp [[JTPAGE:x[0-9]+]], .LJTI0_0 +; CHECK: add [[JT:x[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI0_0 +; CHECK-PIC: adrp [[JTPAGE:x[0-9]+]], .LJTI0_0 +; CHECK-PIC: add [[JT:x[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI0_0 +; CHECK-LARGE: movz [[JT:x[0-9]+]], #:abs_g3:.LJTI0_0 +; CHECK-LARGE: movk [[JT]], #:abs_g2_nc:.LJTI0_0 +; CHECK-LARGE: movk [[JT]], #:abs_g1_nc:.LJTI0_0 +; CHECK-LARGE: movk [[JT]], #:abs_g0_nc:.LJTI0_0 + +; CHECK: ldrsw [[JTE:x[0-9]+]], {{\[}}[[JT]], {{x[0-9]+}}, lsl #2] +; CHECK-PIC: ldrsw [[JTE:x[0-9]+]], {{\[}}[[JT]], {{x[0-9]+}}, lsl #2] +; CHECK-LARGE: ldrsw [[JTE:x[0-9]+]], {{\[}}[[JT]], {{x[0-9]+}}, lsl #2] + +; CHECK: add [[DEST:x[0-9]+]], [[JTE]], [[JT]] +; CHECK-PIC: add [[DEST:x[0-9]+]], [[JTE]], [[JT]] +; CHECK-LARGE: adrp [[JTBASE_HI:x[0-9]+]], test_jumptable +; CHECK-LARGE: add [[JTBASE:x[0-9]+]], [[JTBASE_HI]], :lo12:test_jumptable +; CHECK-LARGE: add [[DEST:x[0-9]+]], [[JTE]], [[JTBASE]] def: ret i32 0 @@ -46,21 +48,29 @@ } -; CHECK: .rodata +; CHECK: .section .rodata +; CHECK-LABEL: .LJTI0_0: +; CHECK-NEXT: .word .LBB{{.*}}-.LJTI0_0 +; CHECK-NEXT: .word .LBB{{.*}}-.LJTI0_0 +; CHECK-NEXT: .word .LBB{{.*}}-.LJTI0_0 +; CHECK-NEXT: .word .LBB{{.*}}-.LJTI0_0 +; CHECK-NEXT: .word .LBB{{.*}}-.LJTI0_0 +; CHECK-NOT: .end_data_region -; CHECK: .LJTI0_0: -; CHECK-NEXT: .xword -; CHECK-NEXT: .xword -; CHECK-NEXT: .xword -; CHECK-NEXT: .xword -; CHECK-NEXT: .xword - -; CHECK-PIC-NOT: .data_region -; CHECK-PIC-NOT: .LJTI0_0 -; CHECK-PIC: .LJTI0_0: +; CHECK-PIC: .section .rodata +; CHECK-PIC-LABEL: .LJTI0_0: ; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0 ; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0 ; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0 ; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0 ; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0 ; CHECK-PIC-NOT: .end_data_region + +; CHECK-LARGE: .section .rodata +; CHECK-LARGE-LABEL: .LJTI0_0: +; CHECK-LARGE-NEXT: .word .LBB{{.*}}-test_jumptable +; CHECK-LARGE-NEXT: .word .LBB{{.*}}-test_jumptable +; CHECK-LARGE-NEXT: .word .LBB{{.*}}-test_jumptable +; CHECK-LARGE-NEXT: .word .LBB{{.*}}-test_jumptable +; CHECK-LARGE-NEXT: .word .LBB{{.*}}-test_jumptable +; CHECK-LARGE-NOT: .end_data_region