Remove all target-specific portions of Config.hs
[ghc.git] / compiler / nativeGen / PIC.hs
1 {-
2 This module handles generation of position independent code and
3 dynamic-linking related issues for the native code generator.
4
5 This depends both the architecture and OS, so we define it here
6 instead of in one of the architecture specific modules.
7
8 Things outside this module which are related to this:
9
10 + module CLabel
11 - PIC base label (pretty printed as local label 1)
12 - DynamicLinkerLabels - several kinds:
13 CodeStub, SymbolPtr, GotSymbolPtr, GotSymbolOffset
14 - labelDynamic predicate
15 + module Cmm
16 - The GlobalReg datatype has a PicBaseReg constructor
17 - The CmmLit datatype has a CmmLabelDiffOff constructor
18 + codeGen & RTS
19 - When tablesNextToCode, no absolute addresses are stored in info tables
20 any more. Instead, offsets from the info label are used.
21 - For Win32 only, SRTs might contain addresses of __imp_ symbol pointers
22 because Win32 doesn't support external references in data sections.
23 TODO: make sure this still works, it might be bitrotted
24 + NCG
25 - The cmmToCmm pass in AsmCodeGen calls cmmMakeDynamicReference for all
26 labels.
27 - nativeCodeGen calls pprImportedSymbol and pprGotDeclaration to output
28 all the necessary stuff for imported symbols.
29 - The NCG monad keeps track of a list of imported symbols.
30 - MachCodeGen invokes initializePicBase to generate code to initialize
31 the PIC base register when needed.
32 - MachCodeGen calls cmmMakeDynamicReference whenever it uses a CLabel
33 that wasn't in the original Cmm code (e.g. floating point literals).
34 -}
35
36 module PIC (
37 cmmMakeDynamicReference,
38 CmmMakeDynamicReferenceM(..),
39 ReferenceKind(..),
40 needImportedSymbols,
41 pprImportedSymbol,
42 pprGotDeclaration,
43
44 initializePicBase_ppc,
45 initializePicBase_x86
46 )
47
48 where
49
50 import GhcPrelude
51
52 import qualified PPC.Instr as PPC
53 import qualified PPC.Regs as PPC
54
55 import qualified X86.Instr as X86
56
57 import Platform
58 import Instruction
59 import Reg
60 import NCGMonad
61
62
63 import Hoopl.Collections
64 import Cmm
65 import CLabel ( CLabel, ForeignLabelSource(..), pprCLabel,
66 mkDynamicLinkerLabel, DynamicLinkerLabelInfo(..),
67 dynamicLinkerLabelInfo, mkPicBaseLabel,
68 labelDynamic, externallyVisibleCLabel )
69
70 import CLabel ( mkForeignLabel )
71
72
73 import BasicTypes
74 import Module
75
76 import Outputable
77
78 import DynFlags
79 import FastString
80
81
82
83 --------------------------------------------------------------------------------
84 -- It gets called by the cmmToCmm pass for every CmmLabel in the Cmm
85 -- code. It does The Right Thing(tm) to convert the CmmLabel into a
86 -- position-independent, dynamic-linking-aware reference to the thing
87 -- in question.
88 -- Note that this also has to be called from MachCodeGen in order to
89 -- access static data like floating point literals (labels that were
90 -- created after the cmmToCmm pass).
91 -- The function must run in a monad that can keep track of imported symbols
92 -- A function for recording an imported symbol must be passed in:
93 -- - addImportCmmOpt for the CmmOptM monad
94 -- - addImportNat for the NatM monad.
95
96 data ReferenceKind
97 = DataReference
98 | CallReference
99 | JumpReference
100 deriving(Eq)
101
102 class Monad m => CmmMakeDynamicReferenceM m where
103 addImport :: CLabel -> m ()
104 getThisModule :: m Module
105
106 instance CmmMakeDynamicReferenceM NatM where
107 addImport = addImportNat
108 getThisModule = getThisModuleNat
109
110 cmmMakeDynamicReference
111 :: CmmMakeDynamicReferenceM m
112 => DynFlags
113 -> ReferenceKind -- whether this is the target of a jump
114 -> CLabel -- the label
115 -> m CmmExpr
116
117 cmmMakeDynamicReference dflags referenceKind lbl
118 | Just _ <- dynamicLinkerLabelInfo lbl
119 = return $ CmmLit $ CmmLabel lbl -- already processed it, pass through
120
121 | otherwise
122 = do this_mod <- getThisModule
123 case howToAccessLabel
124 dflags
125 (platformArch $ targetPlatform dflags)
126 (platformOS $ targetPlatform dflags)
127 this_mod
128 referenceKind lbl of
129
130 AccessViaStub -> do
131 let stub = mkDynamicLinkerLabel CodeStub lbl
132 addImport stub
133 return $ CmmLit $ CmmLabel stub
134
135 AccessViaSymbolPtr -> do
136 let symbolPtr = mkDynamicLinkerLabel SymbolPtr lbl
137 addImport symbolPtr
138 return $ CmmLoad (cmmMakePicReference dflags symbolPtr) (bWord dflags)
139
140 AccessDirectly -> case referenceKind of
141 -- for data, we might have to make some calculations:
142 DataReference -> return $ cmmMakePicReference dflags lbl
143 -- all currently supported processors support
144 -- PC-relative branch and call instructions,
145 -- so just jump there if it's a call or a jump
146 _ -> return $ CmmLit $ CmmLabel lbl
147
148
149 -- -----------------------------------------------------------------------------
150 -- Create a position independent reference to a label.
151 -- (but do not bother with dynamic linking).
152 -- We calculate the label's address by adding some (platform-dependent)
153 -- offset to our base register; this offset is calculated by
154 -- the function picRelative in the platform-dependent part below.
155
156 cmmMakePicReference :: DynFlags -> CLabel -> CmmExpr
157 cmmMakePicReference dflags lbl
158
159 -- Windows doesn't need PIC,
160 -- everything gets relocated at runtime
161 | OSMinGW32 <- platformOS $ targetPlatform dflags
162 = CmmLit $ CmmLabel lbl
163
164 | OSAIX <- platformOS $ targetPlatform dflags
165 = CmmMachOp (MO_Add W32)
166 [ CmmReg (CmmGlobal PicBaseReg)
167 , CmmLit $ picRelative dflags
168 (platformArch $ targetPlatform dflags)
169 (platformOS $ targetPlatform dflags)
170 lbl ]
171
172 -- both ABI versions default to medium code model
173 | ArchPPC_64 _ <- platformArch $ targetPlatform dflags
174 = CmmMachOp (MO_Add W32) -- code model medium
175 [ CmmReg (CmmGlobal PicBaseReg)
176 , CmmLit $ picRelative dflags
177 (platformArch $ targetPlatform dflags)
178 (platformOS $ targetPlatform dflags)
179 lbl ]
180
181 | (positionIndependent dflags || gopt Opt_ExternalDynamicRefs dflags)
182 && absoluteLabel lbl
183 = CmmMachOp (MO_Add (wordWidth dflags))
184 [ CmmReg (CmmGlobal PicBaseReg)
185 , CmmLit $ picRelative dflags
186 (platformArch $ targetPlatform dflags)
187 (platformOS $ targetPlatform dflags)
188 lbl ]
189
190 | otherwise
191 = CmmLit $ CmmLabel lbl
192
193
194 absoluteLabel :: CLabel -> Bool
195 absoluteLabel lbl
196 = case dynamicLinkerLabelInfo lbl of
197 Just (GotSymbolPtr, _) -> False
198 Just (GotSymbolOffset, _) -> False
199 _ -> True
200
201
202 --------------------------------------------------------------------------------
203 -- Knowledge about how special dynamic linker labels like symbol
204 -- pointers, code stubs and GOT offsets look like is located in the
205 -- module CLabel.
206
207 -- We have to decide which labels need to be accessed
208 -- indirectly or via a piece of stub code.
209 data LabelAccessStyle
210 = AccessViaStub
211 | AccessViaSymbolPtr
212 | AccessDirectly
213
214 howToAccessLabel
215 :: DynFlags -> Arch -> OS -> Module -> ReferenceKind -> CLabel -> LabelAccessStyle
216
217
218 -- Windows
219 -- In Windows speak, a "module" is a set of objects linked into the
220 -- same Portable Exectuable (PE) file. (both .exe and .dll files are PEs).
221 --
222 -- If we're compiling a multi-module program then symbols from other modules
223 -- are accessed by a symbol pointer named __imp_SYMBOL. At runtime we have the
224 -- following.
225 --
226 -- (in the local module)
227 -- __imp_SYMBOL: addr of SYMBOL
228 --
229 -- (in the other module)
230 -- SYMBOL: the real function / data.
231 --
232 -- To access the function at SYMBOL from our local module, we just need to
233 -- dereference the local __imp_SYMBOL.
234 --
235 -- If not compiling with -dynamic we assume that all our code will be linked
236 -- into the same .exe file. In this case we always access symbols directly,
237 -- and never use __imp_SYMBOL.
238 --
239 howToAccessLabel dflags _ OSMinGW32 this_mod _ lbl
240
241 -- Assume all symbols will be in the same PE, so just access them directly.
242 | not (gopt Opt_ExternalDynamicRefs dflags)
243 = AccessDirectly
244
245 -- If the target symbol is in another PE we need to access it via the
246 -- appropriate __imp_SYMBOL pointer.
247 | labelDynamic dflags this_mod lbl
248 = AccessViaSymbolPtr
249
250 -- Target symbol is in the same PE as the caller, so just access it directly.
251 | otherwise
252 = AccessDirectly
253
254
255 -- Mach-O (Darwin, Mac OS X)
256 --
257 -- Indirect access is required in the following cases:
258 -- * things imported from a dynamic library
259 -- * (not on x86_64) data from a different module, if we're generating PIC code
260 -- It is always possible to access something indirectly,
261 -- even when it's not necessary.
262 --
263 howToAccessLabel dflags arch OSDarwin this_mod DataReference lbl
264 -- data access to a dynamic library goes via a symbol pointer
265 | labelDynamic dflags this_mod lbl
266 = AccessViaSymbolPtr
267
268 -- when generating PIC code, all cross-module data references must
269 -- must go via a symbol pointer, too, because the assembler
270 -- cannot generate code for a label difference where one
271 -- label is undefined. Doesn't apply t x86_64.
272 -- Unfortunately, we don't know whether it's cross-module,
273 -- so we do it for all externally visible labels.
274 -- This is a slight waste of time and space, but otherwise
275 -- we'd need to pass the current Module all the way in to
276 -- this function.
277 | arch /= ArchX86_64
278 , positionIndependent dflags && externallyVisibleCLabel lbl
279 = AccessViaSymbolPtr
280
281 | otherwise
282 = AccessDirectly
283
284 howToAccessLabel dflags arch OSDarwin this_mod JumpReference lbl
285 -- dyld code stubs don't work for tailcalls because the
286 -- stack alignment is only right for regular calls.
287 -- Therefore, we have to go via a symbol pointer:
288 | arch == ArchX86 || arch == ArchX86_64
289 , labelDynamic dflags this_mod lbl
290 = AccessViaSymbolPtr
291
292
293 howToAccessLabel dflags arch OSDarwin this_mod _ lbl
294 -- Code stubs are the usual method of choice for imported code;
295 -- not needed on x86_64 because Apple's new linker, ld64, generates
296 -- them automatically.
297 | arch /= ArchX86_64
298 , labelDynamic dflags this_mod lbl
299 = AccessViaStub
300
301 | otherwise
302 = AccessDirectly
303
304
305 ----------------------------------------------------------------------------
306 -- AIX
307
308 -- quite simple (for now)
309 howToAccessLabel _dflags _arch OSAIX _this_mod kind _lbl
310 = case kind of
311 DataReference -> AccessViaSymbolPtr
312 CallReference -> AccessDirectly
313 JumpReference -> AccessDirectly
314
315 -- ELF (Linux)
316 --
317 -- ELF tries to pretend to the main application code that dynamic linking does
318 -- not exist. While this may sound convenient, it tends to mess things up in
319 -- very bad ways, so we have to be careful when we generate code for a non-PIE
320 -- main program (-dynamic but no -fPIC).
321 --
322 -- Indirect access is required for references to imported symbols
323 -- from position independent code. It is also required from the main program
324 -- when dynamic libraries containing Haskell code are used.
325
326 howToAccessLabel _ (ArchPPC_64 _) os _ kind _
327 | osElfTarget os
328 = case kind of
329 -- ELF PPC64 (powerpc64-linux), AIX, MacOS 9, BeOS/PPC
330 DataReference -> AccessViaSymbolPtr
331 -- RTLD does not generate stubs for function descriptors
332 -- in tail calls. Create a symbol pointer and generate
333 -- the code to load the function descriptor at the call site.
334 JumpReference -> AccessViaSymbolPtr
335 -- regular calls are handled by the runtime linker
336 _ -> AccessDirectly
337
338 howToAccessLabel dflags _ os _ _ _
339 -- no PIC -> the dynamic linker does everything for us;
340 -- if we don't dynamically link to Haskell code,
341 -- it actually manages to do so without messing things up.
342 | osElfTarget os
343 , not (positionIndependent dflags) &&
344 not (gopt Opt_ExternalDynamicRefs dflags)
345 = AccessDirectly
346
347 howToAccessLabel dflags arch os this_mod DataReference lbl
348 | osElfTarget os
349 = case () of
350 -- A dynamic label needs to be accessed via a symbol pointer.
351 _ | labelDynamic dflags this_mod lbl
352 -> AccessViaSymbolPtr
353
354 -- For PowerPC32 -fPIC, we have to access even static data
355 -- via a symbol pointer (see below for an explanation why
356 -- PowerPC32 Linux is especially broken).
357 | arch == ArchPPC
358 , positionIndependent dflags
359 -> AccessViaSymbolPtr
360
361 | otherwise
362 -> AccessDirectly
363
364
365 -- In most cases, we have to avoid symbol stubs on ELF, for the following reasons:
366 -- on i386, the position-independent symbol stubs in the Procedure Linkage Table
367 -- require the address of the GOT to be loaded into register %ebx on entry.
368 -- The linker will take any reference to the symbol stub as a hint that
369 -- the label in question is a code label. When linking executables, this
370 -- will cause the linker to replace even data references to the label with
371 -- references to the symbol stub.
372
373 -- This leaves calling a (foreign) function from non-PIC code
374 -- (AccessDirectly, because we get an implicit symbol stub)
375 -- and calling functions from PIC code on non-i386 platforms (via a symbol stub)
376
377 howToAccessLabel dflags arch os this_mod CallReference lbl
378 | osElfTarget os
379 , labelDynamic dflags this_mod lbl && not (positionIndependent dflags)
380 = AccessDirectly
381
382 | osElfTarget os
383 , arch /= ArchX86
384 , labelDynamic dflags this_mod lbl
385 , positionIndependent dflags
386 = AccessViaStub
387
388 howToAccessLabel dflags _ os this_mod _ lbl
389 | osElfTarget os
390 = if labelDynamic dflags this_mod lbl
391 then AccessViaSymbolPtr
392 else AccessDirectly
393
394 -- all other platforms
395 howToAccessLabel dflags _ _ _ _ _
396 | not (positionIndependent dflags)
397 = AccessDirectly
398
399 | otherwise
400 = panic "howToAccessLabel: PIC not defined for this platform"
401
402
403
404 -- -------------------------------------------------------------------
405 -- | Says what we have to add to our 'PIC base register' in order to
406 -- get the address of a label.
407
408 picRelative :: DynFlags -> Arch -> OS -> CLabel -> CmmLit
409
410 -- Darwin, but not x86_64:
411 -- The PIC base register points to the PIC base label at the beginning
412 -- of the current CmmDecl. We just have to use a label difference to
413 -- get the offset.
414 -- We have already made sure that all labels that are not from the current
415 -- module are accessed indirectly ('as' can't calculate differences between
416 -- undefined labels).
417 picRelative dflags arch OSDarwin lbl
418 | arch /= ArchX86_64
419 = CmmLabelDiffOff lbl mkPicBaseLabel 0 (wordWidth dflags)
420
421 -- On AIX we use an indirect local TOC anchored by 'gotLabel'.
422 -- This way we use up only one global TOC entry per compilation-unit
423 -- (this is quite similiar to GCC's @-mminimal-toc@ compilation mode)
424 picRelative dflags _ OSAIX lbl
425 = CmmLabelDiffOff lbl gotLabel 0 (wordWidth dflags)
426
427 -- PowerPC Linux:
428 -- The PIC base register points to our fake GOT. Use a label difference
429 -- to get the offset.
430 -- We have made sure that *everything* is accessed indirectly, so this
431 -- is only used for offsets from the GOT to symbol pointers inside the
432 -- GOT.
433 picRelative dflags ArchPPC os lbl
434 | osElfTarget os
435 = CmmLabelDiffOff lbl gotLabel 0 (wordWidth dflags)
436
437
438 -- Most Linux versions:
439 -- The PIC base register points to the GOT. Use foo@got for symbol
440 -- pointers, and foo@gotoff for everything else.
441 -- Linux and Darwin on x86_64:
442 -- The PIC base register is %rip, we use foo@gotpcrel for symbol pointers,
443 -- and a GotSymbolOffset label for other things.
444 -- For reasons of tradition, the symbol offset label is written as a plain label.
445 picRelative _ arch os lbl
446 | osElfTarget os || (os == OSDarwin && arch == ArchX86_64)
447 = let result
448 | Just (SymbolPtr, lbl') <- dynamicLinkerLabelInfo lbl
449 = CmmLabel $ mkDynamicLinkerLabel GotSymbolPtr lbl'
450
451 | otherwise
452 = CmmLabel $ mkDynamicLinkerLabel GotSymbolOffset lbl
453
454 in result
455
456 picRelative _ _ _ _
457 = panic "PositionIndependentCode.picRelative undefined for this platform"
458
459
460
461 --------------------------------------------------------------------------------
462
463 needImportedSymbols :: DynFlags -> Arch -> OS -> Bool
464 needImportedSymbols dflags arch os
465 | os == OSDarwin
466 , arch /= ArchX86_64
467 = True
468
469 | os == OSAIX
470 = True
471
472 -- PowerPC Linux: -fPIC or -dynamic
473 | osElfTarget os
474 , arch == ArchPPC
475 = positionIndependent dflags || gopt Opt_ExternalDynamicRefs dflags
476
477 -- PowerPC 64 Linux: always
478 | osElfTarget os
479 , arch == ArchPPC_64 ELF_V1 || arch == ArchPPC_64 ELF_V2
480 = True
481
482 -- i386 (and others?): -dynamic but not -fPIC
483 | osElfTarget os
484 , arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
485 = gopt Opt_ExternalDynamicRefs dflags &&
486 not (positionIndependent dflags)
487
488 | otherwise
489 = False
490
491 -- gotLabel
492 -- The label used to refer to our "fake GOT" from
493 -- position-independent code.
494 gotLabel :: CLabel
495 gotLabel
496 -- HACK: this label isn't really foreign
497 = mkForeignLabel
498 (fsLit ".LCTOC1")
499 Nothing ForeignLabelInThisPackage IsData
500
501
502
503 --------------------------------------------------------------------------------
504 -- We don't need to declare any offset tables.
505 -- However, for PIC on x86, we need a small helper function.
506 pprGotDeclaration :: DynFlags -> Arch -> OS -> SDoc
507 pprGotDeclaration dflags ArchX86 OSDarwin
508 | positionIndependent dflags
509 = vcat [
510 text ".section __TEXT,__textcoal_nt,coalesced,no_toc",
511 text ".weak_definition ___i686.get_pc_thunk.ax",
512 text ".private_extern ___i686.get_pc_thunk.ax",
513 text "___i686.get_pc_thunk.ax:",
514 text "\tmovl (%esp), %eax",
515 text "\tret" ]
516
517 pprGotDeclaration _ _ OSDarwin
518 = empty
519
520 -- Emit XCOFF TOC section
521 pprGotDeclaration _ _ OSAIX
522 = vcat $ [ text ".toc"
523 , text ".tc ghc_toc_table[TC],.LCTOC1"
524 , text ".csect ghc_toc_table[RW]"
525 -- See Note [.LCTOC1 in PPC PIC code]
526 , text ".set .LCTOC1,$+0x8000"
527 ]
528
529
530 -- PPC 64 ELF v1 needs a Table Of Contents (TOC)
531 pprGotDeclaration _ (ArchPPC_64 ELF_V1) _
532 = text ".section \".toc\",\"aw\""
533 -- In ELF v2 we also need to tell the assembler that we want ABI
534 -- version 2. This would normally be done at the top of the file
535 -- right after a file directive, but I could not figure out how
536 -- to do that.
537 pprGotDeclaration _ (ArchPPC_64 ELF_V2) _
538 = vcat [ text ".abiversion 2",
539 text ".section \".toc\",\"aw\""
540 ]
541
542 -- Emit GOT declaration
543 -- Output whatever needs to be output once per .s file.
544 pprGotDeclaration dflags arch os
545 | osElfTarget os
546 , arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
547 , not (positionIndependent dflags)
548 = empty
549
550 | osElfTarget os
551 , arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
552 = vcat [
553 -- See Note [.LCTOC1 in PPC PIC code]
554 text ".section \".got2\",\"aw\"",
555 text ".LCTOC1 = .+32768" ]
556
557 pprGotDeclaration _ _ _
558 = panic "pprGotDeclaration: no match"
559
560
561 --------------------------------------------------------------------------------
562 -- On Darwin, we have to generate our own stub code for lazy binding..
563 -- For each processor architecture, there are two versions, one for PIC
564 -- and one for non-PIC.
565 --
566
567 pprImportedSymbol :: DynFlags -> Platform -> CLabel -> SDoc
568 pprImportedSymbol dflags (Platform { platformArch = ArchX86, platformOS = OSDarwin }) importedLbl
569 | Just (CodeStub, lbl) <- dynamicLinkerLabelInfo importedLbl
570 = case positionIndependent dflags of
571 False ->
572 vcat [
573 text ".symbol_stub",
574 text "L" <> pprCLabel dflags lbl <> ptext (sLit "$stub:"),
575 text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
576 text "\tjmp *L" <> pprCLabel dflags lbl
577 <> text "$lazy_ptr",
578 text "L" <> pprCLabel dflags lbl
579 <> text "$stub_binder:",
580 text "\tpushl $L" <> pprCLabel dflags lbl
581 <> text "$lazy_ptr",
582 text "\tjmp dyld_stub_binding_helper"
583 ]
584 True ->
585 vcat [
586 text ".section __TEXT,__picsymbolstub2,"
587 <> text "symbol_stubs,pure_instructions,25",
588 text "L" <> pprCLabel dflags lbl <> ptext (sLit "$stub:"),
589 text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
590 text "\tcall ___i686.get_pc_thunk.ax",
591 text "1:",
592 text "\tmovl L" <> pprCLabel dflags lbl
593 <> text "$lazy_ptr-1b(%eax),%edx",
594 text "\tjmp *%edx",
595 text "L" <> pprCLabel dflags lbl
596 <> text "$stub_binder:",
597 text "\tlea L" <> pprCLabel dflags lbl
598 <> text "$lazy_ptr-1b(%eax),%eax",
599 text "\tpushl %eax",
600 text "\tjmp dyld_stub_binding_helper"
601 ]
602 $+$ vcat [ text ".section __DATA, __la_sym_ptr"
603 <> (if positionIndependent dflags then int 2 else int 3)
604 <> text ",lazy_symbol_pointers",
605 text "L" <> pprCLabel dflags lbl <> ptext (sLit "$lazy_ptr:"),
606 text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
607 text "\t.long L" <> pprCLabel dflags lbl
608 <> text "$stub_binder"]
609
610 | Just (SymbolPtr, lbl) <- dynamicLinkerLabelInfo importedLbl
611 = vcat [
612 text ".non_lazy_symbol_pointer",
613 char 'L' <> pprCLabel dflags lbl <> text "$non_lazy_ptr:",
614 text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
615 text "\t.long\t0"]
616
617 | otherwise
618 = empty
619
620
621 pprImportedSymbol _ (Platform { platformOS = OSDarwin }) _
622 = empty
623
624 -- XCOFF / AIX
625 --
626 -- Similiar to PPC64 ELF v1, there's dedicated TOC register (r2). To
627 -- workaround the limitation of a global TOC we use an indirect TOC
628 -- with the label `ghc_toc_table`.
629 --
630 -- See also GCC's `-mminimal-toc` compilation mode or
631 -- http://www.ibm.com/developerworks/rational/library/overview-toc-aix/
632 --
633 -- NB: No DSO-support yet
634
635 pprImportedSymbol dflags (Platform { platformOS = OSAIX }) importedLbl
636 = case dynamicLinkerLabelInfo importedLbl of
637 Just (SymbolPtr, lbl)
638 -> vcat [
639 text "LC.." <> pprCLabel dflags lbl <> char ':',
640 text "\t.long" <+> pprCLabel dflags lbl ]
641 _ -> empty
642
643 -- ELF / Linux
644 --
645 -- In theory, we don't need to generate any stubs or symbol pointers
646 -- by hand for Linux.
647 --
648 -- Reality differs from this in two areas.
649 --
650 -- 1) If we just use a dynamically imported symbol directly in a read-only
651 -- section of the main executable (as GCC does), ld generates R_*_COPY
652 -- relocations, which are fundamentally incompatible with reversed info
653 -- tables. Therefore, we need a table of imported addresses in a writable
654 -- section.
655 -- The "official" GOT mechanism (label@got) isn't intended to be used
656 -- in position dependent code, so we have to create our own "fake GOT"
657 -- when not Opt_PIC && WayDyn `elem` ways dflags.
658 --
659 -- 2) PowerPC Linux is just plain broken.
660 -- While it's theoretically possible to use GOT offsets larger
661 -- than 16 bit, the standard crt*.o files don't, which leads to
662 -- linker errors as soon as the GOT size exceeds 16 bit.
663 -- Also, the assembler doesn't support @gotoff labels.
664 -- In order to be able to use a larger GOT, we have to circumvent the
665 -- entire GOT mechanism and do it ourselves (this is also what GCC does).
666
667
668 -- When needImportedSymbols is defined,
669 -- the NCG will keep track of all DynamicLinkerLabels it uses
670 -- and output each of them using pprImportedSymbol.
671
672 pprImportedSymbol dflags platform@(Platform { platformArch = ArchPPC_64 _ })
673 importedLbl
674 | osElfTarget (platformOS platform)
675 = case dynamicLinkerLabelInfo importedLbl of
676 Just (SymbolPtr, lbl)
677 -> vcat [
678 text ".section \".toc\", \"aw\"",
679 text ".LC_" <> pprCLabel dflags lbl <> char ':',
680 text "\t.quad" <+> pprCLabel dflags lbl ]
681 _ -> empty
682
683 pprImportedSymbol dflags platform importedLbl
684 | osElfTarget (platformOS platform)
685 = case dynamicLinkerLabelInfo importedLbl of
686 Just (SymbolPtr, lbl)
687 -> let symbolSize = case wordWidth dflags of
688 W32 -> sLit "\t.long"
689 W64 -> sLit "\t.quad"
690 _ -> panic "Unknown wordRep in pprImportedSymbol"
691
692 in vcat [
693 text ".section \".got2\", \"aw\"",
694 text ".LC_" <> pprCLabel dflags lbl <> char ':',
695 ptext symbolSize <+> pprCLabel dflags lbl ]
696
697 -- PLT code stubs are generated automatically by the dynamic linker.
698 _ -> empty
699
700 pprImportedSymbol _ _ _
701 = panic "PIC.pprImportedSymbol: no match"
702
703 --------------------------------------------------------------------------------
704 -- Generate code to calculate the address that should be put in the
705 -- PIC base register.
706 -- This is called by MachCodeGen for every CmmProc that accessed the
707 -- PIC base register. It adds the appropriate instructions to the
708 -- top of the CmmProc.
709
710 -- It is assumed that the first NatCmmDecl in the input list is a Proc
711 -- and the rest are CmmDatas.
712
713 -- Darwin is simple: just fetch the address of a local label.
714 -- The FETCHPC pseudo-instruction is expanded to multiple instructions
715 -- during pretty-printing so that we don't have to deal with the
716 -- local label:
717
718 -- PowerPC version:
719 -- bcl 20,31,1f.
720 -- 1: mflr picReg
721
722 -- i386 version:
723 -- call 1f
724 -- 1: popl %picReg
725
726
727
728 -- Get a pointer to our own fake GOT, which is defined on a per-module basis.
729 -- This is exactly how GCC does it in linux.
730
731 initializePicBase_ppc
732 :: Arch -> OS -> Reg
733 -> [NatCmmDecl CmmStatics PPC.Instr]
734 -> NatM [NatCmmDecl CmmStatics PPC.Instr]
735
736 initializePicBase_ppc ArchPPC os picReg
737 (CmmProc info lab live (ListGraph blocks) : statics)
738 | osElfTarget os
739 = do
740 let
741 gotOffset = PPC.ImmConstantDiff
742 (PPC.ImmCLbl gotLabel)
743 (PPC.ImmCLbl mkPicBaseLabel)
744
745 blocks' = case blocks of
746 [] -> []
747 (b:bs) -> fetchPC b : map maybeFetchPC bs
748
749 maybeFetchPC b@(BasicBlock bID _)
750 | bID `mapMember` info = fetchPC b
751 | otherwise = b
752
753 -- GCC does PIC prologs thusly:
754 -- bcl 20,31,.L1
755 -- .L1:
756 -- mflr 30
757 -- addis 30,30,.LCTOC1-.L1@ha
758 -- addi 30,30,.LCTOC1-.L1@l
759 -- TODO: below we use it over temporary register,
760 -- it can and should be optimised by picking
761 -- correct PIC reg.
762 fetchPC (BasicBlock bID insns) =
763 BasicBlock bID (PPC.FETCHPC picReg
764 : PPC.ADDIS picReg picReg (PPC.HA gotOffset)
765 : PPC.ADD picReg picReg
766 (PPC.RIImm (PPC.LO gotOffset))
767 : PPC.MR PPC.r30 picReg
768 : insns)
769
770 return (CmmProc info lab live (ListGraph blocks') : statics)
771
772 -------------------------------------------------------------------------
773 -- Load TOC into register 2
774 -- PowerPC 64-bit ELF ABI 2.0 requires the address of the callee
775 -- in register 12.
776 -- We pass the label to FETCHTOC and create a .localentry too.
777 -- TODO: Explain this better and refer to ABI spec!
778 {-
779 We would like to do approximately this, but spill slot allocation
780 might be added before the first BasicBlock. That violates the ABI.
781
782 For now we will emit the prologue code in the pretty printer,
783 which is also what we do for ELF v1.
784 initializePicBase_ppc (ArchPPC_64 ELF_V2) OSLinux picReg
785 (CmmProc info lab live (ListGraph (entry:blocks)) : statics)
786 = do
787 bID <-getUniqueM
788 return (CmmProc info lab live (ListGraph (b':entry:blocks))
789 : statics)
790 where BasicBlock entryID _ = entry
791 b' = BasicBlock bID [PPC.FETCHTOC picReg lab,
792 PPC.BCC PPC.ALWAYS entryID]
793 -}
794
795 initializePicBase_ppc _ _ _ _
796 = panic "initializePicBase_ppc: not needed"
797
798
799 -- We cheat a bit here by defining a pseudo-instruction named FETCHGOT
800 -- which pretty-prints as:
801 -- call 1f
802 -- 1: popl %picReg
803 -- addl __GLOBAL_OFFSET_TABLE__+.-1b, %picReg
804 -- (See PprMach.hs)
805
806 initializePicBase_x86
807 :: Arch -> OS -> Reg
808 -> [NatCmmDecl (Alignment, CmmStatics) X86.Instr]
809 -> NatM [NatCmmDecl (Alignment, CmmStatics) X86.Instr]
810
811 initializePicBase_x86 ArchX86 os picReg
812 (CmmProc info lab live (ListGraph blocks) : statics)
813 | osElfTarget os
814 = return (CmmProc info lab live (ListGraph blocks') : statics)
815 where blocks' = case blocks of
816 [] -> []
817 (b:bs) -> fetchGOT b : map maybeFetchGOT bs
818
819 -- we want to add a FETCHGOT instruction to the beginning of
820 -- every block that is an entry point, which corresponds to
821 -- the blocks that have entries in the info-table mapping.
822 maybeFetchGOT b@(BasicBlock bID _)
823 | bID `mapMember` info = fetchGOT b
824 | otherwise = b
825
826 fetchGOT (BasicBlock bID insns) =
827 BasicBlock bID (X86.FETCHGOT picReg : insns)
828
829 initializePicBase_x86 ArchX86 OSDarwin picReg
830 (CmmProc info lab live (ListGraph (entry:blocks)) : statics)
831 = return (CmmProc info lab live (ListGraph (block':blocks)) : statics)
832
833 where BasicBlock bID insns = entry
834 block' = BasicBlock bID (X86.FETCHPC picReg : insns)
835
836 initializePicBase_x86 _ _ _ _
837 = panic "initializePicBase_x86: not needed"
838