summaryrefslogtreecommitdiff
path: root/compiler/nativeGen/PIC.hs
diff options
context:
space:
mode:
authorSergei Trofimovich <siarheit@google.com>2014-12-14 14:30:12 +0000
committerSergei Trofimovich <siarheit@google.com>2014-12-14 14:30:12 +0000
commitfa31e8f4a0f853848d96549a429083941877bf8d (patch)
treec45f86f090dd27aae6dbe522336ab6e74e13fbb4 /compiler/nativeGen/PIC.hs
parentef7eb8f30532c8f85f05b318c85c7d819f61d715 (diff)
downloadhaskell-fa31e8f4a0f853848d96549a429083941877bf8d.tar.gz
powerpc: fix and enable shared libraries by default on linux
Summary: And fix things all the way down to it. Namely: - remove 'r30' from free registers, it's an .LCTOC1 register for gcc. generated .plt stubs expect it to be initialised. - fix PicBase computation, which originally forgot to use 'tmp' reg in 'initializePicBase_ppc.fetchPC' - mark 'ForeighTarget's as implicitly using 'PicBase' register (see comment for details) - add 64-bit MO_Sub and test on alloclimit3/4 regtests - fix dynamic label offsets to match with .LCTOC1 offset Signed-off-by: Sergei Trofimovich <siarheit@google.com> Test Plan: validate passes equal amount of vanilla/dyn tests Reviewers: simonmar, erikd, austin Reviewed By: erikd, austin Subscribers: carter, thomie Differential Revision: https://phabricator.haskell.org/D560 GHC Trac Issues: #8024, #9831
Diffstat (limited to 'compiler/nativeGen/PIC.hs')
-rw-r--r--compiler/nativeGen/PIC.hs45
1 files changed, 18 insertions, 27 deletions
diff --git a/compiler/nativeGen/PIC.hs b/compiler/nativeGen/PIC.hs
index 9b5c080b5b..6326a8bdaf 100644
--- a/compiler/nativeGen/PIC.hs
+++ b/compiler/nativeGen/PIC.hs
@@ -54,7 +54,6 @@ import qualified X86.Instr as X86
import Platform
import Instruction
-import Size
import Reg
import NCGMonad
@@ -468,11 +467,8 @@ pprGotDeclaration dflags ArchX86 OSDarwin
pprGotDeclaration _ _ OSDarwin
= empty
--- pprGotDeclaration
+-- Emit GOT declaration
-- Output whatever needs to be output once per .s file.
--- The .LCTOC1 label is defined to point 32768 bytes into the table,
--- to make the most of the PPC's 16-bit displacements.
--- Only needed for PIC.
pprGotDeclaration dflags arch os
| osElfTarget os
, arch /= ArchPPC_64
@@ -482,6 +478,7 @@ pprGotDeclaration dflags arch os
| osElfTarget os
, arch /= ArchPPC_64
= vcat [
+ -- See Note [.LCTOC1 in PPC PIC code]
ptext (sLit ".section \".got2\",\"aw\""),
ptext (sLit ".LCTOC1 = .+32768") ]
@@ -688,12 +685,7 @@ pprImportedSymbol _ _ _
-- Get a pointer to our own fake GOT, which is defined on a per-module basis.
--- This is exactly how GCC does it, and it's quite horrible:
--- We first fetch the address of a local label (mkPicBaseLabel).
--- Then we add a 16-bit offset to that to get the address of a .long that we
--- define in .text space right next to the proc. This .long literal contains
--- the (32-bit) offset from our local label to our global offset table
--- (.LCTOC1 aka gotOffLabel).
+-- This is exactly how GCC does it in linux.
initializePicBase_ppc
:: Arch -> OS -> Reg
@@ -704,18 +696,9 @@ initializePicBase_ppc ArchPPC os picReg
(CmmProc info lab live (ListGraph blocks) : statics)
| osElfTarget os
= do
- dflags <- getDynFlags
- gotOffLabel <- getNewLabelNat
- tmp <- getNewRegNat $ intSize (wordWidth dflags)
let
- gotOffset = CmmData Text $ Statics gotOffLabel [
- CmmStaticLit (CmmLabelDiffOff gotLabel
- mkPicBaseLabel
- 0)
- ]
- offsetToOffset
- = PPC.ImmConstantDiff
- (PPC.ImmCLbl gotOffLabel)
+ gotOffset = PPC.ImmConstantDiff
+ (PPC.ImmCLbl gotLabel)
(PPC.ImmCLbl mkPicBaseLabel)
blocks' = case blocks of
@@ -726,15 +709,23 @@ initializePicBase_ppc ArchPPC os picReg
| bID `mapMember` info = fetchPC b
| otherwise = b
+ -- GCC does PIC prologs thusly:
+ -- bcl 20,31,.L1
+ -- .L1:
+ -- mflr 30
+ -- addis 30,30,.LCTOC1-.L1@ha
+ -- addi 30,30,.LCTOC1-.L1@l
+ -- TODO: below we use it over temporary register,
+ -- it can and should be optimised by picking
+ -- correct PIC reg.
fetchPC (BasicBlock bID insns) =
BasicBlock bID (PPC.FETCHPC picReg
- : PPC.ADDIS tmp picReg (PPC.HI offsetToOffset)
- : PPC.LD PPC.archWordSize tmp
- (PPC.AddrRegImm tmp (PPC.LO offsetToOffset))
- : PPC.ADD picReg picReg (PPC.RIReg picReg)
+ : PPC.ADDIS picReg picReg (PPC.HA gotOffset)
+ : PPC.ADDI picReg picReg (PPC.LO gotOffset)
+ : PPC.MR PPC.r30 picReg
: insns)
- return (CmmProc info lab live (ListGraph blocks') : gotOffset : statics)
+ return (CmmProc info lab live (ListGraph blocks') : statics)
initializePicBase_ppc ArchPPC OSDarwin picReg