diff options
Diffstat (limited to 'compiler/nativeGen/PIC.hs')
-rw-r--r-- | compiler/nativeGen/PIC.hs | 83 |
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" |