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