Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 2e76b3d

Browse files
committed
Merge pull request #9 from linux-on-ibm-z/swift-3.0-s390x
Support Linux on z in Swift 3.0
2 parents 1d0a2ff + a549f69 commit 2e76b3d

19 files changed

+899
-6
lines changed

lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,11 @@ void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section,
10471047
case ELF::R_390_64:
10481048
writeInt64BE(LocalAddress, Value + Addend);
10491049
break;
1050+
case ELF::R_390_PC64: {
1051+
int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset);
1052+
writeInt64BE(LocalAddress, Delta);
1053+
break;
1054+
}
10501055
}
10511056
}
10521057

lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,11 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
260260
.addImm(15).addReg(SystemZ::R0D);
261261
break;
262262

263+
// Emit nothing here but a comment if we can.
264+
case SystemZ::MemBarrier:
265+
OutStreamer->emitRawComment("MEMBARRIER");
266+
return;
267+
263268
default:
264269
Lower.lower(MI, LoweredMI);
265270
break;

lib/Target/SystemZ/SystemZCallingConv.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ def RetCC_SystemZ : CallingConv<[
3333
// Promote i32 to i64 if it has an explicit extension type.
3434
CCIfType<[i32], CCIfExtend<CCPromoteToType<i64>>>,
3535

36+
// A SwiftError is returned in R9.
37+
CCIfSwiftError<CCIfType<[i64], CCAssignToReg<[R9D]>>>,
38+
3639
// ABI-compliant code returns 64-bit integers in R2. Make the other
3740
// call-clobbered argument registers available for code that doesn't
3841
// care about the ABI. (R6 is an argument register too, but is
@@ -65,6 +68,12 @@ def CC_SystemZ : CallingConv<[
6568
// are smaller than 64 bits shouldn't.
6669
CCIfType<[i32], CCIfExtend<CCPromoteToType<i64>>>,
6770

71+
// A SwiftSelf is passed in callee-saved R10.
72+
CCIfSwiftSelf<CCIfType<[i64], CCAssignToReg<[R10D]>>>,
73+
74+
// A SwiftError is passed in callee-saved R9.
75+
CCIfSwiftError<CCIfType<[i64], CCAssignToReg<[R9D]>>>,
76+
6877
// Force long double values to the stack and pass i64 pointers to them.
6978
CCIfType<[f128], CCPassIndirect<i64>>,
7079

@@ -105,3 +114,6 @@ def CC_SystemZ : CallingConv<[
105114
//===----------------------------------------------------------------------===//
106115
def CSR_SystemZ : CalleeSavedRegs<(add (sequence "R%dD", 6, 15),
107116
(sequence "F%dD", 8, 15))>;
117+
118+
// R9 is used to return SwiftError; remove it from CSR.
119+
def CSR_SystemZ_SwiftError : CalleeSavedRegs<(sub CSR_SystemZ, R9D)>;

lib/Target/SystemZ/SystemZISelLowering.cpp

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
216216
setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Custom);
217217
setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Custom);
218218

219+
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
220+
219221
// z10 has instructions for signed but not unsigned FP conversion.
220222
// Handle unsigned 32-bit types as signed 64-bit types.
221223
if (!Subtarget.hasFPExtension()) {
@@ -987,9 +989,11 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
987989
}
988990

989991
static bool canUseSiblingCall(const CCState &ArgCCInfo,
990-
SmallVectorImpl<CCValAssign> &ArgLocs) {
992+
SmallVectorImpl<CCValAssign> &ArgLocs,
993+
SmallVectorImpl<ISD::OutputArg> &Outs) {
991994
// Punt if there are any indirect or stack arguments, or if the call
992-
// needs the call-saved argument register R6.
995+
// needs the callee-saved argument register R6, or if the call uses
996+
// the callee-saved register arguments SwiftSelf and SwiftError.
993997
for (unsigned I = 0, E = ArgLocs.size(); I != E; ++I) {
994998
CCValAssign &VA = ArgLocs[I];
995999
if (VA.getLocInfo() == CCValAssign::Indirect)
@@ -999,6 +1003,8 @@ static bool canUseSiblingCall(const CCState &ArgCCInfo,
9991003
unsigned Reg = VA.getLocReg();
10001004
if (Reg == SystemZ::R6H || Reg == SystemZ::R6L || Reg == SystemZ::R6D)
10011005
return false;
1006+
if (Outs[I].Flags.isSwiftSelf() || Outs[I].Flags.isSwiftError())
1007+
return false;
10021008
}
10031009
return true;
10041010
}
@@ -1032,7 +1038,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
10321038

10331039
// We don't support GuaranteedTailCallOpt, only automatically-detected
10341040
// sibling calls.
1035-
if (IsTailCall && !canUseSiblingCall(ArgCCInfo, ArgLocs))
1041+
if (IsTailCall && !canUseSiblingCall(ArgCCInfo, ArgLocs, Outs))
10361042
IsTailCall = false;
10371043

10381044
// Get a count of how many bytes are to be pushed on the stack.
@@ -1849,7 +1855,7 @@ static unsigned getTestUnderMaskCond(unsigned BitSize, unsigned CCMask,
18491855
if (CCMask == SystemZ::CCMASK_CMP_NE)
18501856
return SystemZ::CCMASK_TM_SOME_1;
18511857
}
1852-
if (EffectivelyUnsigned && CmpVal <= Low) {
1858+
if (EffectivelyUnsigned && CmpVal > 0 && CmpVal <= Low) {
18531859
if (CCMask == SystemZ::CCMASK_CMP_LT)
18541860
return SystemZ::CCMASK_TM_ALL_0;
18551861
if (CCMask == SystemZ::CCMASK_CMP_GE)
@@ -2640,6 +2646,57 @@ SDValue SystemZTargetLowering::lowerConstantPool(ConstantPoolSDNode *CP,
26402646
return DAG.getNode(SystemZISD::PCREL_WRAPPER, DL, PtrVT, Result);
26412647
}
26422648

2649+
SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op,
2650+
SelectionDAG &DAG) const {
2651+
MachineFunction &MF = DAG.getMachineFunction();
2652+
MachineFrameInfo *MFI = MF.getFrameInfo();
2653+
MFI->setFrameAddressIsTaken(true);
2654+
2655+
SDLoc DL(Op);
2656+
unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
2657+
EVT PtrVT = getPointerTy(DAG.getDataLayout());
2658+
2659+
// If the back chain frame index has not been allocated yet, do so.
2660+
SystemZMachineFunctionInfo *FI = MF.getInfo<SystemZMachineFunctionInfo>();
2661+
int BackChainIdx = FI->getFramePointerSaveIndex();
2662+
if (!BackChainIdx) {
2663+
// By definition, the frame address is the address of the back chain.
2664+
BackChainIdx = MFI->CreateFixedObject(8, -SystemZMC::CallFrameSize, false);
2665+
FI->setFramePointerSaveIndex(BackChainIdx);
2666+
}
2667+
SDValue BackChain = DAG.getFrameIndex(BackChainIdx, PtrVT);
2668+
2669+
// FIXME The frontend should detect this case.
2670+
if (Depth > 0) {
2671+
report_fatal_error("Unsupported stack frame traversal count");
2672+
}
2673+
2674+
return BackChain;
2675+
}
2676+
2677+
SDValue SystemZTargetLowering::lowerRETURNADDR(SDValue Op,
2678+
SelectionDAG &DAG) const {
2679+
MachineFunction &MF = DAG.getMachineFunction();
2680+
MachineFrameInfo *MFI = MF.getFrameInfo();
2681+
MFI->setReturnAddressIsTaken(true);
2682+
2683+
if (verifyReturnAddressArgumentIsConstant(Op, DAG))
2684+
return SDValue();
2685+
2686+
SDLoc DL(Op);
2687+
unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
2688+
EVT PtrVT = getPointerTy(DAG.getDataLayout());
2689+
2690+
// FIXME The frontend should detect this case.
2691+
if (Depth > 0) {
2692+
report_fatal_error("Unsupported stack frame traversal count");
2693+
}
2694+
2695+
// Return R14D, which has the return address. Mark it an implicit live-in.
2696+
unsigned LinkReg = MF.addLiveIn(SystemZ::R14D, &SystemZ::GR64BitRegClass);
2697+
return DAG.getCopyFromReg(DAG.getEntryNode(), DL, LinkReg, PtrVT);
2698+
}
2699+
26432700
SDValue SystemZTargetLowering::lowerBITCAST(SDValue Op,
26442701
SelectionDAG &DAG) const {
26452702
SDLoc DL(Op);
@@ -3031,6 +3088,25 @@ SDValue SystemZTargetLowering::lowerCTPOP(SDValue Op,
30313088
return Op;
30323089
}
30333090

3091+
SDValue SystemZTargetLowering::lowerATOMIC_FENCE(SDValue Op,
3092+
SelectionDAG &DAG) const {
3093+
SDLoc DL(Op);
3094+
AtomicOrdering FenceOrdering = static_cast<AtomicOrdering>(
3095+
cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue());
3096+
SynchronizationScope FenceScope = static_cast<SynchronizationScope>(
3097+
cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue());
3098+
3099+
// The only fence that needs an instruction is a sequentially-consistent
3100+
// cross-thread fence.
3101+
if (FenceOrdering == SequentiallyConsistent && FenceScope == CrossThread) {
3102+
return SDValue(DAG.getMachineNode(SystemZ::Serialize, DL, MVT::Other,
3103+
Op.getOperand(0)), 0);
3104+
}
3105+
3106+
// MEMBARRIER is a compiler barrier; it codegens to a no-op.
3107+
return DAG.getNode(SystemZISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));
3108+
}
3109+
30343110
// Op is an atomic load. Lower it into a normal volatile load.
30353111
SDValue SystemZTargetLowering::lowerATOMIC_LOAD(SDValue Op,
30363112
SelectionDAG &DAG) const {
@@ -4312,6 +4388,10 @@ SDValue SystemZTargetLowering::lowerShift(SDValue Op, SelectionDAG &DAG,
43124388
SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
43134389
SelectionDAG &DAG) const {
43144390
switch (Op.getOpcode()) {
4391+
case ISD::FRAMEADDR:
4392+
return lowerFRAMEADDR(Op, DAG);
4393+
case ISD::RETURNADDR:
4394+
return lowerRETURNADDR(Op, DAG);
43154395
case ISD::BR_CC:
43164396
return lowerBR_CC(Op, DAG);
43174397
case ISD::SELECT_CC:
@@ -4354,6 +4434,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
43544434
case ISD::CTTZ_ZERO_UNDEF:
43554435
return DAG.getNode(ISD::CTTZ, SDLoc(Op),
43564436
Op.getValueType(), Op.getOperand(0));
4437+
case ISD::ATOMIC_FENCE:
4438+
return lowerATOMIC_FENCE(Op, DAG);
43574439
case ISD::ATOMIC_SWAP:
43584440
return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_SWAPW);
43594441
case ISD::ATOMIC_STORE:
@@ -4457,6 +4539,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
44574539
OPCODE(SEARCH_STRING);
44584540
OPCODE(IPM);
44594541
OPCODE(SERIALIZE);
4542+
OPCODE(MEMBARRIER);
44604543
OPCODE(TBEGIN);
44614544
OPCODE(TBEGIN_NOFLOAT);
44624545
OPCODE(TEND);
@@ -5218,6 +5301,7 @@ SystemZTargetLowering::emitAtomicLoadMinMax(MachineInstr *MI,
52185301
MachineBasicBlock *
52195302
SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr *MI,
52205303
MachineBasicBlock *MBB) const {
5304+
52215305
MachineFunction &MF = *MBB->getParent();
52225306
const SystemZInstrInfo *TII =
52235307
static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo());

lib/Target/SystemZ/SystemZISelLowering.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ enum NodeType : unsigned {
146146
// Perform a serialization operation. (BCR 15,0 or BCR 14,0.)
147147
SERIALIZE,
148148

149+
// Compiler barrier only; generate a no-op.
150+
MEMBARRIER,
151+
149152
// Transaction begin. The first operand is the chain, the second
150153
// the TDB pointer, and the third the immediate control field.
151154
// Returns chain and glue.
@@ -449,6 +452,10 @@ class SystemZTargetLowering : public TargetLowering {
449452
SelectionDAG &DAG) const override;
450453
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
451454

455+
bool supportSwiftError() const override {
456+
return true;
457+
}
458+
452459
private:
453460
const SystemZSubtarget &Subtarget;
454461

@@ -467,6 +474,8 @@ class SystemZTargetLowering : public TargetLowering {
467474
SelectionDAG &DAG) const;
468475
SDValue lowerJumpTable(JumpTableSDNode *JT, SelectionDAG &DAG) const;
469476
SDValue lowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;
477+
SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
478+
SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
470479
SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
471480
SDValue lowerVACOPY(SDValue Op, SelectionDAG &DAG) const;
472481
SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
@@ -477,6 +486,7 @@ class SystemZTargetLowering : public TargetLowering {
477486
SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
478487
SDValue lowerOR(SDValue Op, SelectionDAG &DAG) const;
479488
SDValue lowerCTPOP(SDValue Op, SelectionDAG &DAG) const;
489+
SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
480490
SDValue lowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const;
481491
SDValue lowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const;
482492
SDValue lowerATOMIC_LOAD_OP(SDValue Op, SelectionDAG &DAG,

lib/Target/SystemZ/SystemZInstrInfo.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,10 @@ def PFDRL : PrefetchRILPC<"pfdrl", 0xC62, z_prefetch>;
12241224
let hasSideEffects = 1 in
12251225
def Serialize : Alias<2, (outs), (ins), [(z_serialize)]>;
12261226

1227+
// A pseudo instruction that serves as a compiler barrier.
1228+
let hasSideEffects = 1 in
1229+
def MemBarrier : Pseudo<(outs), (ins), [(z_membarrier)]>;
1230+
12271231
let Predicates = [FeatureInterlockedAccess1], Defs = [CC] in {
12281232
def LAA : LoadAndOpRSY<"laa", 0xEBF8, atomic_load_add_32, GR32>;
12291233
def LAAG : LoadAndOpRSY<"laag", 0xEBE8, atomic_load_add_64, GR64>;

lib/Target/SystemZ/SystemZMachineFunctionInfo.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ class SystemZMachineFunctionInfo : public MachineFunctionInfo {
2222
unsigned VarArgsFirstFPR;
2323
unsigned VarArgsFrameIndex;
2424
unsigned RegSaveFrameIndex;
25+
int FramePointerSaveIndex;
2526
bool ManipulatesSP;
2627
unsigned NumLocalDynamics;
2728

2829
public:
2930
explicit SystemZMachineFunctionInfo(MachineFunction &MF)
3031
: LowSavedGPR(0), HighSavedGPR(0), VarArgsFirstGPR(0), VarArgsFirstFPR(0),
31-
VarArgsFrameIndex(0), RegSaveFrameIndex(0), ManipulatesSP(false),
32-
NumLocalDynamics(0) {}
32+
VarArgsFrameIndex(0), RegSaveFrameIndex(0), FramePointerSaveIndex(0),
33+
ManipulatesSP(false), NumLocalDynamics(0) {}
3334

3435
// Get and set the first call-saved GPR that should be saved and restored
3536
// by this function. This is 0 if no GPRs need to be saved or restored.
@@ -59,6 +60,10 @@ class SystemZMachineFunctionInfo : public MachineFunctionInfo {
5960
unsigned getRegSaveFrameIndex() const { return RegSaveFrameIndex; }
6061
void setRegSaveFrameIndex(unsigned FI) { RegSaveFrameIndex = FI; }
6162

63+
// Get and set the frame index of where the old frame pointer is stored.
64+
int getFramePointerSaveIndex() const { return FramePointerSaveIndex; }
65+
void setFramePointerSaveIndex(int Idx) { FramePointerSaveIndex = Idx; }
66+
6267
// Get and set whether the function directly manipulates the stack pointer,
6368
// e.g. through STACKSAVE or STACKRESTORE.
6469
bool getManipulatesSP() const { return ManipulatesSP; }

lib/Target/SystemZ/SystemZOperators.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ def z_udivrem64 : SDNode<"SystemZISD::UDIVREM64", SDT_ZGR128Binary64>;
188188

189189
def z_serialize : SDNode<"SystemZISD::SERIALIZE", SDTNone,
190190
[SDNPHasChain, SDNPMayStore]>;
191+
def z_membarrier : SDNode<"SystemZISD::MEMBARRIER", SDTNone,
192+
[SDNPHasChain, SDNPSideEffect]>;
191193

192194
// Defined because the index is an i32 rather than a pointer.
193195
def z_vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT",

lib/Target/SystemZ/SystemZRegisterInfo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,20 @@ SystemZRegisterInfo::SystemZRegisterInfo()
2424

2525
const MCPhysReg *
2626
SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
27+
if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&
28+
MF->getFunction()->getAttributes().hasAttrSomewhere(
29+
Attribute::SwiftError))
30+
return CSR_SystemZ_SwiftError_SaveList;
2731
return CSR_SystemZ_SaveList;
2832
}
2933

3034
const uint32_t *
3135
SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
3236
CallingConv::ID CC) const {
37+
if (MF.getSubtarget().getTargetLowering()->supportSwiftError() &&
38+
MF.getFunction()->getAttributes().hasAttrSomewhere(
39+
Attribute::SwiftError))
40+
return CSR_SystemZ_SwiftError_RegMask;
3341
return CSR_SystemZ_RegMask;
3442
}
3543

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; Test (fast) serialization.
2+
;
3+
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=Z10
4+
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s --check-prefix=Z196
5+
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s --check-prefix=ZEC12
6+
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s --check-prefix=Z13
7+
8+
define void @test() {
9+
; Z10: bcr 15, %r0
10+
; Z196: bcr 14, %r0
11+
; ZEC12: bcr 14, %r0
12+
; Z13: bcr 14, %r0
13+
fence seq_cst
14+
ret void
15+
}
16+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; Serialization is emitted only for fence seq_cst.
2+
;
3+
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4+
5+
define void @test() {
6+
; CHECK: #MEMBARRIER
7+
fence acquire
8+
; CHECK: #MEMBARRIER
9+
fence release
10+
; CHECK: #MEMBARRIER
11+
fence acq_rel
12+
ret void
13+
}

test/CodeGen/SystemZ/frameaddr-01.ll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
2+
3+
; The current function's frame address is the address of
4+
; the optional back chain slot.
5+
define i8* @fp0() nounwind {
6+
entry:
7+
; CHECK-LABEL: fp0:
8+
; CHECK: la %r2, 0(%r15)
9+
; CHECK: br %r14
10+
%0 = tail call i8* @llvm.frameaddress(i32 0)
11+
ret i8* %0
12+
}
13+
14+
; Check that the frame address is correct in a presence
15+
; of a stack frame.
16+
define i8* @fp0f() nounwind {
17+
entry:
18+
; CHECK-LABEL: fp0f:
19+
; CHECK: aghi %r15, -168
20+
; CHECK: la %r2, 168(%r15)
21+
; CHECK: aghi %r15, 168
22+
; CHECK: br %r14
23+
%0 = alloca i64, align 8
24+
%1 = tail call i8* @llvm.frameaddress(i32 0)
25+
ret i8* %1
26+
}
27+
28+
declare i8* @llvm.frameaddress(i32) nounwind readnone

0 commit comments

Comments
 (0)