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