summaryrefslogtreecommitdiff
path: root/compiler/nativeGen/PIC.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/nativeGen/PIC.hs')
-rw-r--r--compiler/nativeGen/PIC.hs83
1 files changed, 71 insertions, 12 deletions
diff --git a/compiler/nativeGen/PIC.hs b/compiler/nativeGen/PIC.hs
index d4739cb7d9..ca556759ed 100644
--- a/compiler/nativeGen/PIC.hs
+++ b/compiler/nativeGen/PIC.hs
@@ -158,7 +158,14 @@ cmmMakePicReference dflags lbl
-- everything gets relocated at runtime
| OSMinGW32 <- platformOS $ targetPlatform dflags
= CmmLit $ CmmLabel lbl
-
+ -- both ABI versions default to medium code model
+ | ArchPPC_64 _ <- platformArch $ targetPlatform dflags
+ = CmmMachOp (MO_Add W32) -- code model medium
+ [ CmmReg (CmmGlobal PicBaseReg)
+ , CmmLit $ picRelative
+ (platformArch $ targetPlatform dflags)
+ (platformOS $ targetPlatform dflags)
+ lbl ]
| (gopt Opt_PIC dflags || not (gopt Opt_Static dflags)) && absoluteLabel lbl
= CmmMachOp (MO_Add (wordWidth dflags))
@@ -293,13 +300,17 @@ howToAccessLabel dflags arch OSDarwin this_mod _ lbl
-- from position independent code. It is also required from the main program
-- when dynamic libraries containing Haskell code are used.
-howToAccessLabel _ ArchPPC_64 os _ kind _
+howToAccessLabel _ (ArchPPC_64 _) os _ kind _
| osElfTarget os
- = if kind == DataReference
- -- ELF PPC64 (powerpc64-linux), AIX, MacOS 9, BeOS/PPC
- then AccessViaSymbolPtr
- -- actually, .label instead of label
- else AccessDirectly
+ = case kind of
+ -- ELF PPC64 (powerpc64-linux), AIX, MacOS 9, BeOS/PPC
+ DataReference -> AccessViaSymbolPtr
+ -- RTLD does not generate stubs for function descriptors
+ -- in tail calls. Create a symbol pointer and generate
+ -- the code to load the function descriptor at the call site.
+ JumpReference -> AccessViaSymbolPtr
+ -- regular calls are handled by the runtime linker
+ _ -> AccessDirectly
howToAccessLabel dflags _ os _ _ _
-- no PIC -> the dynamic linker does everything for us;
@@ -430,9 +441,14 @@ needImportedSymbols dflags arch os
, arch == ArchPPC
= gopt Opt_PIC dflags || not (gopt Opt_Static dflags)
+ -- PowerPC 64 Linux: always
+ | osElfTarget os
+ , arch == ArchPPC_64 ELF_V1 || arch == ArchPPC_64 ELF_V2
+ = True
+
-- i386 (and others?): -dynamic but not -fPIC
| osElfTarget os
- , arch /= ArchPPC_64
+ , arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
= not (gopt Opt_Static dflags) && not (gopt Opt_PIC dflags)
| otherwise
@@ -467,16 +483,30 @@ pprGotDeclaration dflags ArchX86 OSDarwin
pprGotDeclaration _ _ OSDarwin
= empty
+-- PPC 64 ELF v1needs a Table Of Contents (TOC) on Linux
+pprGotDeclaration _ (ArchPPC_64 ELF_V1) OSLinux
+ = ptext (sLit ".section \".toc\",\"aw\"")
+-- In ELF v2 we also need to tell the assembler that we want ABI
+-- version 2. This would normally be done at the top of the file
+-- right after a file directive, but I could not figure out how
+-- to do that.
+pprGotDeclaration _ (ArchPPC_64 ELF_V2) OSLinux
+ = vcat [ ptext (sLit ".abiversion 2"),
+ ptext (sLit ".section \".toc\",\"aw\"")
+ ]
+pprGotDeclaration _ (ArchPPC_64 _) _
+ = panic "pprGotDeclaration: ArchPPC_64 only Linux supported"
+
-- Emit GOT declaration
-- Output whatever needs to be output once per .s file.
pprGotDeclaration dflags arch os
| osElfTarget os
- , arch /= ArchPPC_64
+ , arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
, not (gopt Opt_PIC dflags)
= empty
| osElfTarget os
- , arch /= ArchPPC_64
+ , arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
= vcat [
-- See Note [.LCTOC1 in PPC PIC code]
ptext (sLit ".section \".got2\",\"aw\""),
@@ -635,9 +665,16 @@ pprImportedSymbol _ (Platform { platformOS = OSDarwin }) _
-- the NCG will keep track of all DynamicLinkerLabels it uses
-- and output each of them using pprImportedSymbol.
-pprImportedSymbol _ platform@(Platform { platformArch = ArchPPC_64 }) _
+pprImportedSymbol _ platform@(Platform { platformArch = ArchPPC_64 _ })
+ importedLbl
| osElfTarget (platformOS platform)
- = empty
+ = case dynamicLinkerLabelInfo importedLbl of
+ Just (SymbolPtr, lbl)
+ -> vcat [
+ ptext (sLit ".section \".toc\", \"aw\""),
+ ptext (sLit ".LC_") <> pprCLabel platform lbl <> char ':',
+ ptext (sLit "\t.quad") <+> pprCLabel platform lbl ]
+ _ -> empty
pprImportedSymbol dflags platform importedLbl
| osElfTarget (platformOS platform)
@@ -735,6 +772,28 @@ initializePicBase_ppc ArchPPC OSDarwin picReg
where BasicBlock bID insns = entry
b' = BasicBlock bID (PPC.FETCHPC picReg : insns)
+-------------------------------------------------------------------------
+-- Load TOC into register 2
+-- PowerPC 64-bit ELF ABI 2.0 requires the address of the callee
+-- in register 12.
+-- We pass the label to FETCHTOC and create a .localentry too.
+-- TODO: Explain this better and refer to ABI spec!
+{-
+We would like to do approximately this, but spill slot allocation
+might be added before the first BasicBlock. That violates the ABI.
+
+For now we will emit the prologue code in the pretty printer,
+which is also what we do for ELF v1.
+initializePicBase_ppc (ArchPPC_64 ELF_V2) OSLinux picReg
+ (CmmProc info lab live (ListGraph (entry:blocks)) : statics)
+ = do
+ bID <-getUniqueM
+ return (CmmProc info lab live (ListGraph (b':entry:blocks))
+ : statics)
+ where BasicBlock entryID _ = entry
+ b' = BasicBlock bID [PPC.FETCHTOC picReg lab,
+ PPC.BCC PPC.ALWAYS entryID]
+-}
initializePicBase_ppc _ _ _ _
= panic "initializePicBase_ppc: not needed"