Skip to content

Commit b1adb4d

Browse files
luqmanaalexcrichton
authored andcommitted
Splitstack support for arm/linux.
1 parent 1df0a78 commit b1adb4d

File tree

3 files changed

+67
-22
lines changed

3 files changed

+67
-22
lines changed

include/llvm/ADT/Triple.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ class Triple {
323323
return getOS() == Triple::NaCl;
324324
}
325325

326+
/// \brief Tests whether the OS is Linux
327+
bool isOSLinux() const {
328+
return getOS() == Triple::Linux;
329+
}
330+
326331
/// \brief Tests whether the OS uses the ELF binary format.
327332
bool isOSBinFormatELF() const {
328333
return !isOSDarwin() && !isOSWindows();

lib/Target/ARM/ARMFrameLowering.cpp

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,17 +1465,16 @@ static uint32_t AlignToARMConstant(uint32_t Value) {
14651465
static const uint64_t kSplitStackAvailable = 256;
14661466

14671467
// Adjust function prologue to enable split stack.
1468-
// Only support android.
1468+
// Only support android and linux.
14691469
void
14701470
ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
14711471
const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>();
14721472

14731473
// Doesn't support vararg function.
14741474
if (MF.getFunction()->isVarArg())
14751475
report_fatal_error("Segmented stacks do not support vararg functions.");
1476-
// Doesn't support other than android.
1477-
if (!ST->isTargetAndroid())
1478-
report_fatal_error("Segmented statks not supported on this platfrom.");
1476+
if (!ST->isTargetAndroid() && !ST->isTargetLinux())
1477+
report_fatal_error("Segmented stacks not supported on this platfrom.");
14791478

14801479
MachineBasicBlock &prologueMBB = MF.front();
14811480
MachineFrameInfo* MFI = MF.getFrameInfo();
@@ -1488,26 +1487,39 @@ ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
14881487
// leave the function.
14891488
unsigned ScratchReg0 = ARM::R4;
14901489
unsigned ScratchReg1 = ARM::R5;
1491-
// Use the last tls slot.
1492-
unsigned TlsOffset = 63;
1490+
unsigned TlsOffset;
14931491
uint64_t AlignedStackSize;
14941492

1493+
if (ST->isTargetAndroid()) {
1494+
// Use the last tls slot.
1495+
TlsOffset = 63;
1496+
} else if (ST->isTargetLinux()) {
1497+
// Use private field of the TCB
1498+
TlsOffset = 1;
1499+
}
1500+
14951501
MachineBasicBlock* prevStackMBB = MF.CreateMachineBasicBlock();
14961502
MachineBasicBlock* postStackMBB = MF.CreateMachineBasicBlock();
14971503
MachineBasicBlock* allocMBB = MF.CreateMachineBasicBlock();
1498-
MachineBasicBlock* checkMBB = MF.CreateMachineBasicBlock();
1504+
MachineBasicBlock* getMBB = MF.CreateMachineBasicBlock();
1505+
MachineBasicBlock* mcrMBB = MF.CreateMachineBasicBlock();
1506+
MachineBasicBlock* magicMBB = MF.CreateMachineBasicBlock();
14991507

15001508
for (MachineBasicBlock::livein_iterator i = prologueMBB.livein_begin(),
15011509
e = prologueMBB.livein_end(); i != e; ++i) {
15021510
allocMBB->addLiveIn(*i);
1503-
checkMBB->addLiveIn(*i);
1511+
getMBB->addLiveIn(*i);
1512+
magicMBB->addLiveIn(*i);
1513+
mcrMBB->addLiveIn(*i);
15041514
prevStackMBB->addLiveIn(*i);
15051515
postStackMBB->addLiveIn(*i);
15061516
}
15071517

15081518
MF.push_front(postStackMBB);
15091519
MF.push_front(allocMBB);
1510-
MF.push_front(checkMBB);
1520+
MF.push_front(getMBB);
1521+
MF.push_front(magicMBB);
1522+
MF.push_front(mcrMBB);
15111523
MF.push_front(prevStackMBB);
15121524

15131525
// The required stack size that is aligend to ARM constant critarion.
@@ -1541,41 +1553,63 @@ ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
15411553

15421554
if (CompareStackPointer) {
15431555
// mov SR1, sp
1544-
AddDefaultPred(BuildMI(checkMBB, DL, TII.get(ARM::MOVr), ScratchReg1)
1556+
AddDefaultPred(BuildMI(mcrMBB, DL, TII.get(ARM::MOVr), ScratchReg1)
15451557
.addReg(ARM::SP)).addReg(0);
15461558
} else {
15471559
// sub SR1, sp, #StackSize
1548-
AddDefaultPred(BuildMI(checkMBB, DL, TII.get(ARM::SUBri), ScratchReg1)
1560+
AddDefaultPred(BuildMI(mcrMBB, DL, TII.get(ARM::SUBri), ScratchReg1)
15491561
.addReg(ARM::SP).addImm(AlignedStackSize)).addReg(0);
15501562
}
15511563

15521564
// Get TLS base address.
1565+
// First try to get it from the coprocessor
15531566
// mrc p15, #0, SR0, c13, c0, #3
1554-
AddDefaultPred(BuildMI(checkMBB, DL, TII.get(ARM::MRC), ScratchReg0)
1567+
AddDefaultPred(BuildMI(mcrMBB, DL, TII.get(ARM::MRC), ScratchReg0)
15551568
.addImm(15)
15561569
.addImm(0)
15571570
.addImm(13)
15581571
.addImm(0)
15591572
.addImm(3));
15601573

1561-
// The last slot, assume that the last tls slot holds the stack limit
1562-
// add SR0, SR0, #252
1563-
AddDefaultPred(BuildMI(checkMBB, DL, TII.get(ARM::ADDri), ScratchReg0)
1574+
// Success?
1575+
// cmp SR0, #0
1576+
AddDefaultPred(BuildMI(mcrMBB, DL, TII.get(ARM::CMPri))
1577+
.addReg(ScratchReg0)
1578+
.addImm(0));
1579+
1580+
// This jump is taken if SR0 is not null
1581+
BuildMI(mcrMBB, DL, TII.get(ARM::Bcc)).addMBB(getMBB)
1582+
.addImm(ARMCC::NE)
1583+
.addReg(ARM::CPSR);
1584+
1585+
// Next, try to get it from the special address 0xFFFF0FF0
1586+
// mvn SR0, #0xF000
1587+
AddDefaultPred(BuildMI(magicMBB, DL, TII.get(ARM::MVNi), ScratchReg0)
1588+
.addImm(0xF000)).addReg(0);
1589+
// ldr SR0, [SR0, #-15]
1590+
AddDefaultPred(BuildMI(magicMBB, DL, TII.get(ARM::LDRi12), ScratchReg0)
1591+
.addReg(ScratchReg0)
1592+
.addImm(-15));
1593+
1594+
1595+
// Get the stack limit from the right offset
1596+
// add SR0, SR0, offset*4
1597+
AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::ADDri), ScratchReg0)
15641598
.addReg(ScratchReg0).addImm(4*TlsOffset)).addReg(0);
15651599

15661600
// Get stack limit.
15671601
// ldr SR0, [sr0]
1568-
AddDefaultPred(BuildMI(checkMBB, DL, TII.get(ARM::LDRi12), ScratchReg0)
1602+
AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::LDRi12), ScratchReg0)
15691603
.addReg(ScratchReg0).addImm(0));
15701604

15711605
// Compare stack limit with stack size requested.
15721606
// cmp SR0, SR1
1573-
AddDefaultPred(BuildMI(checkMBB, DL, TII.get(ARM::CMPrr))
1607+
AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::CMPrr))
15741608
.addReg(ScratchReg0)
15751609
.addReg(ScratchReg1));
15761610

15771611
// This jump is taken if StackLimit < SP - stack required.
1578-
BuildMI(checkMBB, DL, TII.get(ARM::Bcc)).addMBB(postStackMBB)
1612+
BuildMI(getMBB, DL, TII.get(ARM::Bcc)).addMBB(postStackMBB)
15791613
.addImm(ARMCC::LO)
15801614
.addReg(ARM::CPSR);
15811615

@@ -1638,11 +1672,16 @@ ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
16381672
postStackMBB->addSuccessor(&prologueMBB);
16391673

16401674
allocMBB->addSuccessor(postStackMBB);
1675+
1676+
getMBB->addSuccessor(postStackMBB);
1677+
getMBB->addSuccessor(allocMBB);
1678+
1679+
magicMBB->addSuccessor(getMBB);
1680+
1681+
mcrMBB->addSuccessor(getMBB);
1682+
mcrMBB->addSuccessor(magicMBB);
16411683

1642-
checkMBB->addSuccessor(postStackMBB);
1643-
checkMBB->addSuccessor(allocMBB);
1644-
1645-
prevStackMBB->addSuccessor(checkMBB);
1684+
prevStackMBB->addSuccessor(mcrMBB);
16461685

16471686
#ifdef XDEBUG
16481687
MF.verify();

lib/Target/ARM/ARMSubtarget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
270270

271271
bool isTargetIOS() const { return TargetTriple.getOS() == Triple::IOS; }
272272
bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
273+
bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
273274
bool isTargetNaCl() const {
274275
return TargetTriple.getOS() == Triple::NaCl;
275276
}

0 commit comments

Comments
 (0)