Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
84a087d5
by Sylvain Henry at 2025-11-28T17:35:28-05:00
-
82db7042
by Zubin Duggal at 2025-11-28T17:36:10-05:00
-
b419a523
by Ben Gamari at 2025-11-28T18:08:55-05:00
-
5e0e1b15
by Matthew Pickering at 2025-11-28T18:08:56-05:00
-
80858c56
by Georgios Karachalias at 2025-11-28T18:09:03-05:00
22 changed files:
- .gitlab-ci.yml
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/Data/OsPath.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/CodeOutput.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Utils/Misc.hs
- compiler/GHC/Utils/Outputable.hs
- docs/users_guide/phases.rst
- rts/linker/PEi386.c
- + testsuite/tests/codeGen/should_run/T24016.hs
- + testsuite/tests/codeGen/should_run/T24016.stdout
- testsuite/tests/codeGen/should_run/all.T
Changes:
| ... | ... | @@ -1184,6 +1184,10 @@ project-version: |
| 1184 | 1184 | image: nixos/nix:2.25.2
|
| 1185 | 1185 | dependencies: null
|
| 1186 | 1186 | tags:
|
| 1187 | + # N.B. we use the OpenCape runners here since this job involves a significant
|
|
| 1188 | + # amount of artifact fetching. This is much more efficient on these runners
|
|
| 1189 | + # as they are near the GitLab box.
|
|
| 1190 | + - opencape
|
|
| 1187 | 1191 | - x86_64-linux
|
| 1188 | 1192 | variables:
|
| 1189 | 1193 | BUILD_FLAVOUR: default
|
| ... | ... | @@ -376,7 +376,7 @@ stmtToInstrs bid stmt = do |
| 376 | 376 | --We try to arrange blocks such that the likely branch is the fallthrough
|
| 377 | 377 | --in GHC.Cmm.ContFlowOpt. So we can assume the condition is likely false here.
|
| 378 | 378 | CmmCondBranch arg true false _ -> genCondBranch bid true false arg
|
| 379 | - CmmSwitch arg ids -> genSwitch arg ids
|
|
| 379 | + CmmSwitch arg ids -> genSwitch arg ids bid
|
|
| 380 | 380 | CmmCall { cml_target = arg
|
| 381 | 381 | , cml_args_regs = gregs } -> genJump arg (jumpRegs platform gregs)
|
| 382 | 382 | _ ->
|
| ... | ... | @@ -489,13 +489,6 @@ is32BitInteger i = i64 <= 0x7fffffff && i64 >= -0x80000000 |
| 489 | 489 | where i64 = fromIntegral i :: Int64
|
| 490 | 490 | |
| 491 | 491 | |
| 492 | --- | Convert a BlockId to some CmmStatic data
|
|
| 493 | -jumpTableEntry :: NCGConfig -> Maybe BlockId -> CmmStatic
|
|
| 494 | -jumpTableEntry config Nothing = CmmStaticLit (CmmInt 0 (ncgWordWidth config))
|
|
| 495 | -jumpTableEntry _ (Just blockid) = CmmStaticLit (CmmLabel blockLabel)
|
|
| 496 | - where blockLabel = blockLbl blockid
|
|
| 497 | - |
|
| 498 | - |
|
| 499 | 492 | -- -----------------------------------------------------------------------------
|
| 500 | 493 | -- General things for putting together code sequences
|
| 501 | 494 | |
| ... | ... | @@ -5375,11 +5368,52 @@ index (1), |
| 5375 | 5368 | indexExpr = UU_Conv(indexOffset); // == 1::I64
|
| 5376 | 5369 | |
| 5377 | 5370 | See #21186.
|
| 5378 | --}
|
|
| 5379 | 5371 | |
| 5380 | -genSwitch :: CmmExpr -> SwitchTargets -> NatM InstrBlock
|
|
| 5372 | +Note [Jump tables]
|
|
| 5373 | +~~~~~~~~~~~~~~~~~~
|
|
| 5374 | +The x86 backend has a virtual JMP_TBL instruction which payload can be used to
|
|
| 5375 | +generate both the jump instruction and the jump table contents. `genSwitch` is
|
|
| 5376 | +responsible for generating these JMP_TBL instructions.
|
|
| 5377 | + |
|
| 5378 | +Depending on `-fPIC` flag and on the architecture, we generate the following
|
|
| 5379 | +jump table variants:
|
|
| 5380 | + |
|
| 5381 | + | Variant | Arch | Table's contents | Reference to the table |
|
|
| 5382 | + |---------|--------|----------------------------------------|------------------------|
|
|
| 5383 | + | PIC | Both | Relative offset: target_lbl - base_lbl | PIC |
|
|
| 5384 | + | Non-PIC | 64-bit | Absolute: target_lbl | Non-PIC (rip-relative) |
|
|
| 5385 | + | Non-PIC | 32-bit | Absolute: target_lbl | Non-PIC (absolute) |
|
|
| 5386 | + |
|
| 5387 | +For the PIC variant, we store relative entries (`target_lbl - base_lbl`) in the
|
|
| 5388 | +jump table. Using absolute entries with PIC would require target_lbl symbols to
|
|
| 5389 | +be resolved at link time, hence to be global labels (currently they are local
|
|
| 5390 | +labels).
|
|
| 5391 | + |
|
| 5392 | +We use the block_id of the code containing the jump as `base_lbl`. It ensures
|
|
| 5393 | +that target_lbl and base_lbl are close enough to each others, avoiding
|
|
| 5394 | +overflows.
|
|
| 5395 | + |
|
| 5396 | +Historical note: in the past we used the table label `table_lbl` as base_lbl. It
|
|
| 5397 | +allowed the jumping code to only compute one global address (table_lbl) both to
|
|
| 5398 | +read the table and to compute the target address. However:
|
|
| 5381 | 5399 | |
| 5382 | -genSwitch expr targets = do
|
|
| 5400 | + * the table could be too far from the jump and on Windows which only
|
|
| 5401 | + has 32-bit relative relocations (IMAGE_REL_AMD64_REL64 doesn't exist),
|
|
| 5402 | + `dest_lbl - table_lbl` overflowed (see #24016)
|
|
| 5403 | + |
|
| 5404 | + * Mac OS X/x86-64 linker was unable to handle `.quad L1 - L0`
|
|
| 5405 | + relocations if L0 wasn't preceded by a non-anonymous label in its
|
|
| 5406 | + section (which was the case with table_lbl). Hence we used to put the
|
|
| 5407 | + jump table in the .text section in this case.
|
|
| 5408 | + |
|
| 5409 | + |
|
| 5410 | +-}
|
|
| 5411 | + |
|
| 5412 | +-- | Generate a JMP_TBL instruction
|
|
| 5413 | +--
|
|
| 5414 | +-- See Note [Jump tables]
|
|
| 5415 | +genSwitch :: CmmExpr -> SwitchTargets -> BlockId -> NatM InstrBlock
|
|
| 5416 | +genSwitch expr targets bid = do
|
|
| 5383 | 5417 | config <- getConfig
|
| 5384 | 5418 | let platform = ncgPlatform config
|
| 5385 | 5419 | expr_w = cmmExprWidth platform expr
|
| ... | ... | @@ -5390,79 +5424,76 @@ genSwitch expr targets = do |
| 5390 | 5424 | indexExpr = CmmMachOp
|
| 5391 | 5425 | (MO_UU_Conv expr_w (platformWordWidth platform))
|
| 5392 | 5426 | [indexExpr0]
|
| 5393 | - if ncgPIC config
|
|
| 5394 | - then do
|
|
| 5395 | - (reg,e_code) <- getNonClobberedReg indexExpr
|
|
| 5396 | - -- getNonClobberedReg because it needs to survive across t_code
|
|
| 5397 | - lbl <- getNewLabelNat
|
|
| 5398 | - let is32bit = target32Bit platform
|
|
| 5399 | - os = platformOS platform
|
|
| 5400 | - -- Might want to use .rodata.<function we're in> instead, but as
|
|
| 5401 | - -- long as it's something unique it'll work out since the
|
|
| 5402 | - -- references to the jump table are in the appropriate section.
|
|
| 5403 | - rosection = case os of
|
|
| 5404 | - -- on Mac OS X/x86_64, put the jump table in the text section to
|
|
| 5405 | - -- work around a limitation of the linker.
|
|
| 5406 | - -- ld64 is unable to handle the relocations for
|
|
| 5407 | - -- .quad L1 - L0
|
|
| 5408 | - -- if L0 is not preceded by a non-anonymous label in its section.
|
|
| 5409 | - OSDarwin | not is32bit -> Section Text lbl
|
|
| 5410 | - _ -> Section ReadOnlyData lbl
|
|
| 5411 | - dynRef <- cmmMakeDynamicReference config DataReference lbl
|
|
| 5412 | - (tableReg,t_code) <- getSomeReg $ dynRef
|
|
| 5413 | - let op = OpAddr (AddrBaseIndex (EABaseReg tableReg)
|
|
| 5414 | - (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0))
|
|
| 5415 | - |
|
| 5416 | - return $ e_code `appOL` t_code `appOL` toOL [
|
|
| 5417 | - ADD (intFormat (platformWordWidth platform)) op (OpReg tableReg),
|
|
| 5418 | - JMP_TBL (OpReg tableReg) ids rosection lbl
|
|
| 5419 | - ]
|
|
| 5420 | - else do
|
|
| 5421 | - (reg,e_code) <- getSomeReg indexExpr
|
|
| 5422 | - lbl <- getNewLabelNat
|
|
| 5423 | - let is32bit = target32Bit platform
|
|
| 5424 | - if is32bit
|
|
| 5425 | - then let op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (platformWordSizeInBytes platform)) (ImmCLbl lbl))
|
|
| 5426 | - jmp_code = JMP_TBL op ids (Section ReadOnlyData lbl) lbl
|
|
| 5427 | - in return $ e_code `appOL` unitOL jmp_code
|
|
| 5428 | - else do
|
|
| 5427 | + |
|
| 5428 | + (offset, blockIds) = switchTargetsToTable targets
|
|
| 5429 | + ids = map (fmap DestBlockId) blockIds
|
|
| 5430 | + |
|
| 5431 | + is32bit = target32Bit platform
|
|
| 5432 | + fmt = archWordFormat is32bit
|
|
| 5433 | + |
|
| 5434 | + table_lbl <- getNewLabelNat
|
|
| 5435 | + let bid_lbl = blockLbl bid
|
|
| 5436 | + let table_section = Section ReadOnlyData table_lbl
|
|
| 5437 | + |
|
| 5438 | + -- see Note [Jump tables] for a description of the following 3 variants.
|
|
| 5439 | + if
|
|
| 5440 | + | ncgPIC config -> do
|
|
| 5441 | + -- PIC support: store relative offsets in the jump table to allow the code
|
|
| 5442 | + -- to be relocated without updating the table. The table itself and the
|
|
| 5443 | + -- block label used to make the relative labels absolute are read in a PIC
|
|
| 5444 | + -- way (via cmmMakeDynamicReference).
|
|
| 5445 | + (reg,e_code) <- getNonClobberedReg indexExpr -- getNonClobberedReg because it needs to survive across t_code and j_code
|
|
| 5446 | + (tableReg,t_code) <- getNonClobberedReg =<< cmmMakeDynamicReference config DataReference table_lbl
|
|
| 5447 | + (targetReg,j_code) <- getSomeReg =<< cmmMakeDynamicReference config DataReference bid_lbl
|
|
| 5448 | + pure $ e_code `appOL` t_code `appOL` j_code `appOL` toOL
|
|
| 5449 | + [ ADD fmt (OpAddr (AddrBaseIndex (EABaseReg tableReg) (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0)))
|
|
| 5450 | + (OpReg targetReg)
|
|
| 5451 | + , JMP_TBL (OpReg targetReg) ids table_section table_lbl (Just bid_lbl)
|
|
| 5452 | + ]
|
|
| 5453 | + |
|
| 5454 | + | not is32bit -> do
|
|
| 5455 | + -- 64-bit non-PIC code
|
|
| 5456 | + (reg,e_code) <- getSomeReg indexExpr
|
|
| 5457 | + tableReg <- getNewRegNat (intFormat (platformWordWidth platform))
|
|
| 5458 | + targetReg <- getNewRegNat (intFormat (platformWordWidth platform))
|
|
| 5459 | + pure $ e_code `appOL` toOL
|
|
| 5429 | 5460 | -- See Note [%rip-relative addressing on x86-64].
|
| 5430 | - tableReg <- getNewRegNat (intFormat (platformWordWidth platform))
|
|
| 5431 | - targetReg <- getNewRegNat (intFormat (platformWordWidth platform))
|
|
| 5432 | - let op = OpAddr (AddrBaseIndex (EABaseReg tableReg) (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0))
|
|
| 5433 | - fmt = archWordFormat is32bit
|
|
| 5434 | - code = e_code `appOL` toOL
|
|
| 5435 | - [ LEA fmt (OpAddr (AddrBaseIndex EABaseRip EAIndexNone (ImmCLbl lbl))) (OpReg tableReg)
|
|
| 5436 | - , MOV fmt op (OpReg targetReg)
|
|
| 5437 | - , JMP_TBL (OpReg targetReg) ids (Section ReadOnlyData lbl) lbl
|
|
| 5438 | - ]
|
|
| 5439 | - return code
|
|
| 5440 | - where
|
|
| 5441 | - (offset, blockIds) = switchTargetsToTable targets
|
|
| 5442 | - ids = map (fmap DestBlockId) blockIds
|
|
| 5461 | + [ LEA fmt (OpAddr (AddrBaseIndex EABaseRip EAIndexNone (ImmCLbl table_lbl))) (OpReg tableReg)
|
|
| 5462 | + , MOV fmt (OpAddr (AddrBaseIndex (EABaseReg tableReg) (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0)))
|
|
| 5463 | + (OpReg targetReg)
|
|
| 5464 | + , JMP_TBL (OpReg targetReg) ids table_section table_lbl Nothing
|
|
| 5465 | + ]
|
|
| 5466 | + |
|
| 5467 | + | otherwise -> do
|
|
| 5468 | + -- 32-bit non-PIC code is a straightforward jump to &table[entry].
|
|
| 5469 | + (reg,e_code) <- getSomeReg indexExpr
|
|
| 5470 | + pure $ e_code `appOL` unitOL
|
|
| 5471 | + ( JMP_TBL (OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (platformWordSizeInBytes platform)) (ImmCLbl table_lbl)))
|
|
| 5472 | + ids table_section table_lbl Nothing
|
|
| 5473 | + )
|
|
| 5443 | 5474 | |
| 5444 | 5475 | generateJumpTableForInstr :: NCGConfig -> Instr -> Maybe (NatCmmDecl (Alignment, RawCmmStatics) Instr)
|
| 5445 | -generateJumpTableForInstr config (JMP_TBL _ ids section lbl)
|
|
| 5446 | - = let getBlockId (DestBlockId id) = id
|
|
| 5447 | - getBlockId _ = panic "Non-Label target in Jump Table"
|
|
| 5448 | - blockIds = map (fmap getBlockId) ids
|
|
| 5449 | - in Just (createJumpTable config blockIds section lbl)
|
|
| 5450 | -generateJumpTableForInstr _ _ = Nothing
|
|
| 5451 | - |
|
| 5452 | -createJumpTable :: NCGConfig -> [Maybe BlockId] -> Section -> CLabel
|
|
| 5453 | - -> GenCmmDecl (Alignment, RawCmmStatics) h g
|
|
| 5454 | -createJumpTable config ids section lbl
|
|
| 5455 | - = let jumpTable
|
|
| 5456 | - | ncgPIC config =
|
|
| 5457 | - let ww = ncgWordWidth config
|
|
| 5458 | - jumpTableEntryRel Nothing
|
|
| 5459 | - = CmmStaticLit (CmmInt 0 ww)
|
|
| 5460 | - jumpTableEntryRel (Just blockid)
|
|
| 5461 | - = CmmStaticLit (CmmLabelDiffOff blockLabel lbl 0 ww)
|
|
| 5462 | - where blockLabel = blockLbl blockid
|
|
| 5463 | - in map jumpTableEntryRel ids
|
|
| 5464 | - | otherwise = map (jumpTableEntry config) ids
|
|
| 5465 | - in CmmData section (mkAlignment 1, CmmStaticsRaw lbl jumpTable)
|
|
| 5476 | +generateJumpTableForInstr config = \case
|
|
| 5477 | + JMP_TBL _ ids section table_lbl mrel_lbl ->
|
|
| 5478 | + let getBlockId (DestBlockId id) = id
|
|
| 5479 | + getBlockId _ = panic "Non-Label target in Jump Table"
|
|
| 5480 | + block_ids = map (fmap getBlockId) ids
|
|
| 5481 | + |
|
| 5482 | + jumpTable = case mrel_lbl of
|
|
| 5483 | + Nothing -> map mk_absolute block_ids -- absolute entries
|
|
| 5484 | + Just rel_lbl -> map (mk_relative rel_lbl) block_ids -- offsets relative to rel_lbl
|
|
| 5485 | + |
|
| 5486 | + mk_absolute = \case
|
|
| 5487 | + Nothing -> CmmStaticLit (CmmInt 0 (ncgWordWidth config))
|
|
| 5488 | + Just blockid -> CmmStaticLit (CmmLabel (blockLbl blockid))
|
|
| 5489 | + |
|
| 5490 | + mk_relative rel_lbl = \case
|
|
| 5491 | + Nothing -> CmmStaticLit (CmmInt 0 (ncgWordWidth config))
|
|
| 5492 | + Just blockid -> CmmStaticLit (CmmLabelDiffOff (blockLbl blockid) rel_lbl 0 (ncgWordWidth config))
|
|
| 5493 | + |
|
| 5494 | + in Just (CmmData section (mkAlignment 1, CmmStaticsRaw table_lbl jumpTable))
|
|
| 5495 | + |
|
| 5496 | + _ -> Nothing
|
|
| 5466 | 5497 | |
| 5467 | 5498 | extractUnwindPoints :: [Instr] -> [UnwindPoint]
|
| 5468 | 5499 | extractUnwindPoints instrs =
|
| ... | ... | @@ -252,6 +252,7 @@ data Instr |
| 252 | 252 | [Maybe JumpDest] -- Targets of the jump table
|
| 253 | 253 | Section -- Data section jump table should be put in
|
| 254 | 254 | CLabel -- Label of jump table
|
| 255 | + !(Maybe CLabel) -- Label used to compute relative offsets. Otherwise we store absolute addresses.
|
|
| 255 | 256 | -- | X86 call instruction
|
| 256 | 257 | | CALL (Either Imm Reg) -- ^ Jump target
|
| 257 | 258 | [RegWithFormat] -- ^ Arguments (required for register allocation)
|
| ... | ... | @@ -486,7 +487,7 @@ regUsageOfInstr platform instr |
| 486 | 487 | JXX _ _ -> mkRU [] []
|
| 487 | 488 | JXX_GBL _ _ -> mkRU [] []
|
| 488 | 489 | JMP op regs -> mkRU (use_R addrFmt op regs) []
|
| 489 | - JMP_TBL op _ _ _ -> mkRU (use_R addrFmt op []) []
|
|
| 490 | + JMP_TBL op _ _ _ _ -> mkRU (use_R addrFmt op []) []
|
|
| 490 | 491 | CALL (Left _) params -> mkRU params (map mkFmt $ callClobberedRegs platform)
|
| 491 | 492 | CALL (Right reg) params -> mkRU (mk addrFmt reg:params) (map mkFmt $ callClobberedRegs platform)
|
| 492 | 493 | CLTD fmt -> mkRU [mk fmt eax] [mk fmt edx]
|
| ... | ... | @@ -812,7 +813,7 @@ patchRegsOfInstr platform instr env |
| 812 | 813 | POP fmt op -> patch1 (POP fmt) op
|
| 813 | 814 | SETCC cond op -> patch1 (SETCC cond) op
|
| 814 | 815 | JMP op regs -> JMP (patchOp op) regs
|
| 815 | - JMP_TBL op ids s lbl -> JMP_TBL (patchOp op) ids s lbl
|
|
| 816 | + JMP_TBL op ids s tl jl -> JMP_TBL (patchOp op) ids s tl jl
|
|
| 816 | 817 | |
| 817 | 818 | FMA3 fmt perm var x1 x2 x3 -> patch3 (FMA3 fmt perm var) x1 x2 x3
|
| 818 | 819 | |
| ... | ... | @@ -1016,9 +1017,9 @@ isJumpishInstr instr |
| 1016 | 1017 | canFallthroughTo :: Instr -> BlockId -> Bool
|
| 1017 | 1018 | canFallthroughTo insn bid
|
| 1018 | 1019 | = case insn of
|
| 1019 | - JXX _ target -> bid == target
|
|
| 1020 | - JMP_TBL _ targets _ _ -> all isTargetBid targets
|
|
| 1021 | - _ -> False
|
|
| 1020 | + JXX _ target -> bid == target
|
|
| 1021 | + JMP_TBL _ targets _ _ _ -> all isTargetBid targets
|
|
| 1022 | + _ -> False
|
|
| 1022 | 1023 | where
|
| 1023 | 1024 | isTargetBid target = case target of
|
| 1024 | 1025 | Nothing -> True
|
| ... | ... | @@ -1031,9 +1032,9 @@ jumpDestsOfInstr |
| 1031 | 1032 | |
| 1032 | 1033 | jumpDestsOfInstr insn
|
| 1033 | 1034 | = case insn of
|
| 1034 | - JXX _ id -> [id]
|
|
| 1035 | - JMP_TBL _ ids _ _ -> [id | Just (DestBlockId id) <- ids]
|
|
| 1036 | - _ -> []
|
|
| 1035 | + JXX _ id -> [id]
|
|
| 1036 | + JMP_TBL _ ids _ _ _ -> [id | Just (DestBlockId id) <- ids]
|
|
| 1037 | + _ -> []
|
|
| 1037 | 1038 | |
| 1038 | 1039 | |
| 1039 | 1040 | patchJumpInstr
|
| ... | ... | @@ -1042,8 +1043,8 @@ patchJumpInstr |
| 1042 | 1043 | patchJumpInstr insn patchF
|
| 1043 | 1044 | = case insn of
|
| 1044 | 1045 | JXX cc id -> JXX cc (patchF id)
|
| 1045 | - JMP_TBL op ids section lbl
|
|
| 1046 | - -> JMP_TBL op (map (fmap (patchJumpDest patchF)) ids) section lbl
|
|
| 1046 | + JMP_TBL op ids section table_lbl rel_lbl
|
|
| 1047 | + -> JMP_TBL op (map (fmap (patchJumpDest patchF)) ids) section table_lbl rel_lbl
|
|
| 1047 | 1048 | _ -> insn
|
| 1048 | 1049 | where
|
| 1049 | 1050 | patchJumpDest f (DestBlockId id) = DestBlockId (f id)
|
| ... | ... | @@ -1504,14 +1505,14 @@ shortcutJump fn insn = shortcutJump' fn (setEmpty :: LabelSet) insn |
| 1504 | 1505 | Just (DestBlockId id') -> shortcutJump' fn seen' (JXX cc id')
|
| 1505 | 1506 | Just (DestImm imm) -> shortcutJump' fn seen' (JXX_GBL cc imm)
|
| 1506 | 1507 | where seen' = setInsert id seen
|
| 1507 | - shortcutJump' fn _ (JMP_TBL addr blocks section tblId) =
|
|
| 1508 | + shortcutJump' fn _ (JMP_TBL addr blocks section table_lbl rel_lbl) =
|
|
| 1508 | 1509 | let updateBlock (Just (DestBlockId bid)) =
|
| 1509 | 1510 | case fn bid of
|
| 1510 | 1511 | Nothing -> Just (DestBlockId bid )
|
| 1511 | 1512 | Just dest -> Just dest
|
| 1512 | 1513 | updateBlock dest = dest
|
| 1513 | 1514 | blocks' = map updateBlock blocks
|
| 1514 | - in JMP_TBL addr blocks' section tblId
|
|
| 1515 | + in JMP_TBL addr blocks' section table_lbl rel_lbl
|
|
| 1515 | 1516 | shortcutJump' _ _ other = other
|
| 1516 | 1517 | |
| 1517 | 1518 | -- Here because it knows about JumpDest
|
| ... | ... | @@ -895,7 +895,7 @@ pprInstr platform i = case i of |
| 895 | 895 | JMP op _
|
| 896 | 896 | -> line $ text "\tjmp *" <> pprOperand platform (archWordFormat (target32Bit platform)) op
|
| 897 | 897 | |
| 898 | - JMP_TBL op _ _ _
|
|
| 898 | + JMP_TBL op _ _ _ _
|
|
| 899 | 899 | -> pprInstr platform (JMP op [])
|
| 900 | 900 | |
| 901 | 901 | CALL (Left imm) _
|
| ... | ... | @@ -11,6 +11,15 @@ module GHC.Data.OsPath |
| 11 | 11 | -- * Common utility functions
|
| 12 | 12 | , (</>)
|
| 13 | 13 | , (<.>)
|
| 14 | + , splitSearchPath
|
|
| 15 | + , isRelative
|
|
| 16 | + , dropTrailingPathSeparator
|
|
| 17 | + , takeDirectory
|
|
| 18 | + , isSuffixOf
|
|
| 19 | + , doesDirectoryExist
|
|
| 20 | + , doesFileExist
|
|
| 21 | + , getDirectoryContents
|
|
| 22 | + , createDirectoryIfMissing
|
|
| 14 | 23 | )
|
| 15 | 24 | where
|
| 16 | 25 | |
| ... | ... | @@ -20,6 +29,8 @@ import GHC.Utils.Misc (HasCallStack) |
| 20 | 29 | import GHC.Utils.Panic (panic)
|
| 21 | 30 | |
| 22 | 31 | import System.OsPath
|
| 32 | +import System.OsString (isSuffixOf)
|
|
| 33 | +import System.Directory.OsPath (doesDirectoryExist, doesFileExist, getDirectoryContents, createDirectoryIfMissing)
|
|
| 23 | 34 | import System.Directory.Internal (os)
|
| 24 | 35 | |
| 25 | 36 | -- | Decode an 'OsPath' to 'FilePath', throwing an 'error' if decoding failed.
|
| ... | ... | @@ -441,7 +441,7 @@ addUnit u = do |
| 441 | 441 | Nothing -> panic "addUnit: called too early"
|
| 442 | 442 | Just dbs ->
|
| 443 | 443 | let newdb = UnitDatabase
|
| 444 | - { unitDatabasePath = "(in memory " ++ showSDoc dflags0 (ppr (unitId u)) ++ ")"
|
|
| 444 | + { unitDatabasePath = unsafeEncodeUtf $ "(in memory " ++ showSDoc dflags0 (ppr (unitId u)) ++ ")"
|
|
| 445 | 445 | , unitDatabaseUnits = [u]
|
| 446 | 446 | }
|
| 447 | 447 | in return (dbs ++ [newdb]) -- added at the end because ordering matters
|
| ... | ... | @@ -789,8 +789,8 @@ summariseRequirement pn mod_name = do |
| 789 | 789 | |
| 790 | 790 | env <- getBkpEnv
|
| 791 | 791 | src_hash <- liftIO $ getFileHash (bkp_filename env)
|
| 792 | - hi_timestamp <- liftIO $ modificationTimeIfExists (ml_hi_file location)
|
|
| 793 | - hie_timestamp <- liftIO $ modificationTimeIfExists (ml_hie_file location)
|
|
| 792 | + hi_timestamp <- liftIO $ modificationTimeIfExists (ml_hi_file_ospath location)
|
|
| 793 | + hie_timestamp <- liftIO $ modificationTimeIfExists (ml_hie_file_ospath location)
|
|
| 794 | 794 | let loc = srcLocSpan (mkSrcLoc (mkFastString (bkp_filename env)) 1 1)
|
| 795 | 795 | |
| 796 | 796 | let fc = hsc_FC hsc_env
|
| ... | ... | @@ -875,8 +875,8 @@ hsModuleToModSummary home_keys pn hsc_src modname |
| 875 | 875 | HsSrcFile -> os "hs")
|
| 876 | 876 | hsc_src
|
| 877 | 877 | -- This duplicates a pile of logic in GHC.Driver.Make
|
| 878 | - hi_timestamp <- liftIO $ modificationTimeIfExists (ml_hi_file location)
|
|
| 879 | - hie_timestamp <- liftIO $ modificationTimeIfExists (ml_hie_file location)
|
|
| 878 | + hi_timestamp <- liftIO $ modificationTimeIfExists (ml_hi_file_ospath location)
|
|
| 879 | + hie_timestamp <- liftIO $ modificationTimeIfExists (ml_hie_file_ospath location)
|
|
| 880 | 880 | |
| 881 | 881 | -- Also copied from 'getImports'
|
| 882 | 882 | let (src_idecls, ord_idecls) = partition ((== IsBoot) . ideclSource . unLoc) imps
|
| ... | ... | @@ -38,7 +38,7 @@ import GHC.Driver.LlvmConfigCache (LlvmConfigCache) |
| 38 | 38 | import GHC.Driver.Ppr
|
| 39 | 39 | import GHC.Driver.Backend
|
| 40 | 40 | |
| 41 | -import GHC.Data.OsPath
|
|
| 41 | +import GHC.Data.OsPath qualified as OsPath
|
|
| 42 | 42 | import qualified GHC.Data.ShortText as ST
|
| 43 | 43 | import GHC.Data.Stream ( liftIO )
|
| 44 | 44 | import qualified GHC.Data.Stream as Stream
|
| ... | ... | @@ -61,8 +61,6 @@ import GHC.Types.ForeignStubs |
| 61 | 61 | import GHC.Types.Unique.DSM
|
| 62 | 62 | import GHC.Types.Unique.Supply ( UniqueTag(..) )
|
| 63 | 63 | |
| 64 | -import System.Directory
|
|
| 65 | -import System.FilePath
|
|
| 66 | 64 | import System.IO
|
| 67 | 65 | import Data.Set (Set)
|
| 68 | 66 | import qualified Data.Set as Set
|
| ... | ... | @@ -321,10 +319,9 @@ outputForeignStubs logger tmpfs dflags unit_state mod location stubs |
| 321 | 319 | stub_h_file_exists <-
|
| 322 | 320 | case mkStubPaths (initFinderOpts dflags) (moduleName mod) location of
|
| 323 | 321 | Nothing -> pure False
|
| 324 | - Just path -> do
|
|
| 325 | - let stub_h = unsafeDecodeUtf path
|
|
| 326 | - createDirectoryIfMissing True (takeDirectory stub_h)
|
|
| 327 | - outputForeignStubs_help stub_h stub_h_output_w
|
|
| 322 | + Just stub_h -> do
|
|
| 323 | + OsPath.createDirectoryIfMissing True (OsPath.takeDirectory stub_h)
|
|
| 324 | + outputForeignStubs_help (OsPath.unsafeDecodeUtf stub_h) stub_h_output_w
|
|
| 328 | 325 | ("#include <HsFFI.h>\n" ++ cplusplus_hdr) cplusplus_ftr
|
| 329 | 326 | |
| 330 | 327 | putDumpFileMaybe logger Opt_D_dump_foreign
|
| ... | ... | @@ -1265,7 +1265,7 @@ checkSummaryHash |
| 1265 | 1265 | | ms_hs_hash old_summary == src_hash &&
|
| 1266 | 1266 | not (gopt Opt_ForceRecomp (hsc_dflags hsc_env)) = do
|
| 1267 | 1267 | -- update the object-file timestamp
|
| 1268 | - obj_timestamp <- modificationTimeIfExists (ml_obj_file location)
|
|
| 1268 | + obj_timestamp <- modificationTimeIfExists (ml_obj_file_ospath location)
|
|
| 1269 | 1269 | |
| 1270 | 1270 | -- We have to repopulate the Finder's cache for file targets
|
| 1271 | 1271 | -- because the file might not even be on the regular search path
|
| ... | ... | @@ -1277,8 +1277,8 @@ checkSummaryHash |
| 1277 | 1277 | hsc_src = ms_hsc_src old_summary
|
| 1278 | 1278 | addModuleToFinder fc mod location hsc_src
|
| 1279 | 1279 | |
| 1280 | - hi_timestamp <- modificationTimeIfExists (ml_hi_file location)
|
|
| 1281 | - hie_timestamp <- modificationTimeIfExists (ml_hie_file location)
|
|
| 1280 | + hi_timestamp <- modificationTimeIfExists (ml_hi_file_ospath location)
|
|
| 1281 | + hie_timestamp <- modificationTimeIfExists (ml_hie_file_ospath location)
|
|
| 1282 | 1282 | |
| 1283 | 1283 | return $ Right
|
| 1284 | 1284 | ( old_summary
|
| ... | ... | @@ -1482,11 +1482,11 @@ data MakeNewModSummary |
| 1482 | 1482 | makeNewModSummary :: HscEnv -> MakeNewModSummary -> IO ModSummary
|
| 1483 | 1483 | makeNewModSummary hsc_env MakeNewModSummary{..} = do
|
| 1484 | 1484 | let PreprocessedImports{..} = nms_preimps
|
| 1485 | - obj_timestamp <- modificationTimeIfExists (ml_obj_file nms_location)
|
|
| 1486 | - dyn_obj_timestamp <- modificationTimeIfExists (ml_dyn_obj_file nms_location)
|
|
| 1487 | - hi_timestamp <- modificationTimeIfExists (ml_hi_file nms_location)
|
|
| 1488 | - hie_timestamp <- modificationTimeIfExists (ml_hie_file nms_location)
|
|
| 1489 | - bytecode_timestamp <- modificationTimeIfExists (ml_bytecode_file nms_location)
|
|
| 1485 | + obj_timestamp <- modificationTimeIfExists (ml_obj_file_ospath nms_location)
|
|
| 1486 | + dyn_obj_timestamp <- modificationTimeIfExists (ml_dyn_obj_file_ospath nms_location)
|
|
| 1487 | + hi_timestamp <- modificationTimeIfExists (ml_hi_file_ospath nms_location)
|
|
| 1488 | + hie_timestamp <- modificationTimeIfExists (ml_hie_file_ospath nms_location)
|
|
| 1489 | + bytecode_timestamp <- modificationTimeIfExists (ml_bytecode_file_ospath nms_location)
|
|
| 1490 | 1490 | extra_sig_imports <- findExtraSigImports hsc_env nms_hsc_src pi_mod_name
|
| 1491 | 1491 | (implicit_sigs, _inst_deps) <- implicitRequirementsShallow (hscSetActiveUnitId (moduleUnitId nms_mod) hsc_env) pi_theimps
|
| 1492 | 1492 |
| ... | ... | @@ -101,6 +101,7 @@ import GHC.Core.Unfold |
| 101 | 101 | import GHC.Data.Bool
|
| 102 | 102 | import GHC.Data.EnumSet (EnumSet)
|
| 103 | 103 | import GHC.Data.Maybe
|
| 104 | +import GHC.Data.OsPath ( OsPath )
|
|
| 104 | 105 | import GHC.Builtin.Names ( mAIN_NAME )
|
| 105 | 106 | import GHC.Driver.Backend
|
| 106 | 107 | import GHC.Driver.Flags
|
| ... | ... | @@ -953,7 +954,7 @@ setDynamicNow dflags0 = |
| 953 | 954 | data PkgDbRef
|
| 954 | 955 | = GlobalPkgDb
|
| 955 | 956 | | UserPkgDb
|
| 956 | - | PkgDbPath FilePath
|
|
| 957 | + | PkgDbPath OsPath
|
|
| 957 | 958 | deriving Eq
|
| 958 | 959 | |
| 959 | 960 |
| ... | ... | @@ -1091,7 +1091,7 @@ loadIfaceByteCode hsc_env iface location type_env = |
| 1091 | 1091 | linkable $ pure $ DotGBC bco
|
| 1092 | 1092 | |
| 1093 | 1093 | linkable parts = do
|
| 1094 | - if_time <- modificationTimeIfExists (ml_hi_file location)
|
|
| 1094 | + if_time <- modificationTimeIfExists (ml_hi_file_ospath location)
|
|
| 1095 | 1095 | time <- maybe getCurrentTime pure if_time
|
| 1096 | 1096 | return $! Linkable time (mi_module iface) parts
|
| 1097 | 1097 | |
| ... | ... | @@ -1112,7 +1112,7 @@ loadIfaceByteCodeLazy hsc_env iface location type_env = |
| 1112 | 1112 | linkable $ NE.singleton (DotGBC bco)
|
| 1113 | 1113 | |
| 1114 | 1114 | linkable parts = do
|
| 1115 | - if_time <- modificationTimeIfExists (ml_hi_file location)
|
|
| 1115 | + if_time <- modificationTimeIfExists (ml_hi_file_ospath location)
|
|
| 1116 | 1116 | time <- maybe getCurrentTime pure if_time
|
| 1117 | 1117 | return $!Linkable time (mi_module iface) parts
|
| 1118 | 1118 | |
| ... | ... | @@ -2240,7 +2240,7 @@ generateAndWriteByteCodeLinkable hsc_env cgguts mod_location = do |
| 2240 | 2240 | -- Either, get the same time as the .gbc file if it exists, or just the current time.
|
| 2241 | 2241 | -- It's important the time of the linkable matches the time of the .gbc file for recompilation
|
| 2242 | 2242 | -- checking.
|
| 2243 | - bco_time <- maybe getCurrentTime pure =<< modificationTimeIfExists (ml_bytecode_file mod_location)
|
|
| 2243 | + bco_time <- maybe getCurrentTime pure =<< modificationTimeIfExists (ml_bytecode_file_ospath mod_location)
|
|
| 2244 | 2244 | return $ mkModuleByteCodeLinkable bco_time bco_object
|
| 2245 | 2245 | |
| 2246 | 2246 | mkModuleByteCode :: HscEnv -> Module -> ModLocation -> CgInteractiveGuts -> IO ModuleByteCode
|
| ... | ... | @@ -730,17 +730,17 @@ runHscPhase pipe_env hsc_env0 input_fn src_flavour = do |
| 730 | 730 | -- the object file for one module.)
|
| 731 | 731 | -- Note the nasty duplication with the same computation in compileFile above
|
| 732 | 732 | location <- mkOneShotModLocation pipe_env dflags src_flavour mod_name
|
| 733 | - let o_file = ml_obj_file location -- The real object file
|
|
| 734 | - hi_file = ml_hi_file location
|
|
| 735 | - hie_file = ml_hie_file location
|
|
| 736 | - dyn_o_file = ml_dyn_obj_file location
|
|
| 733 | + let o_file = ml_obj_file_ospath location -- The real object file
|
|
| 734 | + hi_file = ml_hi_file_ospath location
|
|
| 735 | + hie_file = ml_hie_file_ospath location
|
|
| 736 | + dyn_o_file = ml_dyn_obj_file_ospath location
|
|
| 737 | 737 | |
| 738 | 738 | src_hash <- getFileHash (basename <.> suff)
|
| 739 | 739 | hi_date <- modificationTimeIfExists hi_file
|
| 740 | 740 | hie_date <- modificationTimeIfExists hie_file
|
| 741 | 741 | o_mod <- modificationTimeIfExists o_file
|
| 742 | 742 | dyn_o_mod <- modificationTimeIfExists dyn_o_file
|
| 743 | - bytecode_date <- modificationTimeIfExists (ml_bytecode_file location)
|
|
| 743 | + bytecode_date <- modificationTimeIfExists (ml_bytecode_file_ospath location)
|
|
| 744 | 744 | |
| 745 | 745 | -- Tell the finder cache about this module
|
| 746 | 746 | mod <- do
|
| ... | ... | @@ -300,6 +300,8 @@ import qualified Data.Set as Set |
| 300 | 300 | import GHC.Types.Unique.Set
|
| 301 | 301 | import Data.Word
|
| 302 | 302 | import System.FilePath
|
| 303 | +import qualified GHC.Data.OsPath as OsPath
|
|
| 304 | + |
|
| 303 | 305 | import Text.ParserCombinators.ReadP hiding (char)
|
| 304 | 306 | import Text.ParserCombinators.ReadP as R
|
| 305 | 307 | |
| ... | ... | @@ -2071,7 +2073,7 @@ package_flags_deps :: [(Deprecation, Flag (CmdLineP DynFlags))] |
| 2071 | 2073 | package_flags_deps = [
|
| 2072 | 2074 | ------- Packages ----------------------------------------------------
|
| 2073 | 2075 | make_ord_flag defFlag "package-db"
|
| 2074 | - (HasArg (addPkgDbRef . PkgDbPath))
|
|
| 2076 | + (HasArg (addPkgDbRef . PkgDbPath . OsPath.unsafeEncodeUtf))
|
|
| 2075 | 2077 | , make_ord_flag defFlag "clear-package-db" (NoArg clearPkgDb)
|
| 2076 | 2078 | , make_ord_flag defFlag "no-global-package-db" (NoArg removeGlobalPkgDb)
|
| 2077 | 2079 | , make_ord_flag defFlag "no-user-package-db" (NoArg removeUserPkgDb)
|
| ... | ... | @@ -2081,7 +2083,7 @@ package_flags_deps = [ |
| 2081 | 2083 | (NoArg (addPkgDbRef UserPkgDb))
|
| 2082 | 2084 | -- backwards compat with GHC<=7.4 :
|
| 2083 | 2085 | , make_dep_flag defFlag "package-conf"
|
| 2084 | - (HasArg $ addPkgDbRef . PkgDbPath) "Use -package-db instead"
|
|
| 2086 | + (HasArg $ addPkgDbRef . PkgDbPath . OsPath.unsafeEncodeUtf) "Use -package-db instead"
|
|
| 2085 | 2087 | , make_dep_flag defFlag "no-user-package-conf"
|
| 2086 | 2088 | (NoArg removeUserPkgDb) "Use -no-user-package-db instead"
|
| 2087 | 2089 | , make_ord_flag defGhcFlag "package-name" (HasArg $ \name ->
|
| ... | ... | @@ -3307,7 +3309,7 @@ parseEnvFile :: FilePath -> String -> DynP () |
| 3307 | 3309 | parseEnvFile envfile = mapM_ parseEntry . lines
|
| 3308 | 3310 | where
|
| 3309 | 3311 | parseEntry str = case words str of
|
| 3310 | - ("package-db": _) -> addPkgDbRef (PkgDbPath (envdir </> db))
|
|
| 3312 | + ("package-db": _) -> addPkgDbRef (PkgDbPath (OsPath.unsafeEncodeUtf (envdir </> db)))
|
|
| 3311 | 3313 | -- relative package dbs are interpreted relative to the env file
|
| 3312 | 3314 | where envdir = takeDirectory envfile
|
| 3313 | 3315 | db = drop 11 str
|
| ... | ... | @@ -658,8 +658,9 @@ findWholeCoreBindings hsc_env mod = do |
| 658 | 658 | |
| 659 | 659 | findBytecodeLinkableMaybe :: HscEnv -> Module -> ModLocation -> IO (Maybe Linkable)
|
| 660 | 660 | findBytecodeLinkableMaybe hsc_env mod locn = do
|
| 661 | - let bytecode_fn = ml_bytecode_file locn
|
|
| 662 | - maybe_bytecode_time <- modificationTimeIfExists bytecode_fn
|
|
| 661 | + let bytecode_fn = ml_bytecode_file locn
|
|
| 662 | + bytecode_fn_os = ml_bytecode_file_ospath locn
|
|
| 663 | + maybe_bytecode_time <- modificationTimeIfExists bytecode_fn_os
|
|
| 663 | 664 | case maybe_bytecode_time of
|
| 664 | 665 | Nothing -> return Nothing
|
| 665 | 666 | Just bytecode_time -> do
|
| ... | ... | @@ -63,7 +63,6 @@ import GHC.Types.SourceFile |
| 63 | 63 | |
| 64 | 64 | import GHC.Fingerprint
|
| 65 | 65 | import Data.IORef
|
| 66 | -import System.Directory.OsPath
|
|
| 67 | 66 | import Control.Applicative ((<|>))
|
| 68 | 67 | import Control.Monad
|
| 69 | 68 | import Data.Time
|
| ... | ... | @@ -826,7 +825,7 @@ mkStubPaths fopts mod location = do |
| 826 | 825 | findObjectLinkableMaybe :: Module -> ModLocation -> IO (Maybe Linkable)
|
| 827 | 826 | findObjectLinkableMaybe mod locn
|
| 828 | 827 | = do let obj_fn = ml_obj_file locn
|
| 829 | - maybe_obj_time <- modificationTimeIfExists obj_fn
|
|
| 828 | + maybe_obj_time <- modificationTimeIfExists (ml_obj_file_ospath locn)
|
|
| 830 | 829 | case maybe_obj_time of
|
| 831 | 830 | Nothing -> return Nothing
|
| 832 | 831 | Just obj_time -> liftM Just (findObjectLinkable mod obj_fn obj_time)
|
| ... | ... | @@ -101,6 +101,8 @@ import GHC.Data.Maybe |
| 101 | 101 | |
| 102 | 102 | import System.Environment ( getEnv )
|
| 103 | 103 | import GHC.Data.FastString
|
| 104 | +import GHC.Data.OsPath ( OsPath )
|
|
| 105 | +import qualified GHC.Data.OsPath as OsPath
|
|
| 104 | 106 | import qualified GHC.Data.ShortText as ST
|
| 105 | 107 | import GHC.Utils.Logger
|
| 106 | 108 | import GHC.Utils.Error
|
| ... | ... | @@ -111,7 +113,7 @@ import System.FilePath as FilePath |
| 111 | 113 | import Control.Monad
|
| 112 | 114 | import Data.Graph (stronglyConnComp, SCC(..))
|
| 113 | 115 | import Data.Char ( toUpper )
|
| 114 | -import Data.List ( intersperse, partition, sortBy, isSuffixOf, sortOn )
|
|
| 116 | +import Data.List ( intersperse, partition, sortBy, sortOn )
|
|
| 115 | 117 | import Data.Set (Set)
|
| 116 | 118 | import Data.Monoid (First(..))
|
| 117 | 119 | import qualified Data.Semigroup as Semigroup
|
| ... | ... | @@ -407,7 +409,7 @@ initUnitConfig dflags cached_dbs home_units = |
| 407 | 409 | |
| 408 | 410 | where
|
| 409 | 411 | offsetPackageDb :: Maybe FilePath -> PackageDBFlag -> PackageDBFlag
|
| 410 | - offsetPackageDb (Just offset) (PackageDB (PkgDbPath p)) | isRelative p = PackageDB (PkgDbPath (offset </> p))
|
|
| 412 | + offsetPackageDb (Just offset) (PackageDB (PkgDbPath p)) | OsPath.isRelative p = PackageDB (PkgDbPath (OsPath.unsafeEncodeUtf offset OsPath.</> p))
|
|
| 411 | 413 | offsetPackageDb _ p = p
|
| 412 | 414 | |
| 413 | 415 | |
| ... | ... | @@ -502,12 +504,12 @@ emptyUnitState = UnitState { |
| 502 | 504 | |
| 503 | 505 | -- | Unit database
|
| 504 | 506 | data UnitDatabase unit = UnitDatabase
|
| 505 | - { unitDatabasePath :: FilePath
|
|
| 507 | + { unitDatabasePath :: OsPath
|
|
| 506 | 508 | , unitDatabaseUnits :: [GenUnitInfo unit]
|
| 507 | 509 | }
|
| 508 | 510 | |
| 509 | 511 | instance Outputable u => Outputable (UnitDatabase u) where
|
| 510 | - ppr (UnitDatabase fp _u) = text "DB:" <+> text fp
|
|
| 512 | + ppr (UnitDatabase fp _u) = text "DB:" <+> ppr fp
|
|
| 511 | 513 | |
| 512 | 514 | type UnitInfoMap = UniqMap UnitId UnitInfo
|
| 513 | 515 | |
| ... | ... | @@ -722,9 +724,9 @@ getUnitDbRefs cfg = do |
| 722 | 724 | Left _ -> system_conf_refs
|
| 723 | 725 | Right path
|
| 724 | 726 | | Just (xs, x) <- snocView path, isSearchPathSeparator x
|
| 725 | - -> map PkgDbPath (splitSearchPath xs) ++ system_conf_refs
|
|
| 727 | + -> map PkgDbPath (OsPath.splitSearchPath (OsPath.unsafeEncodeUtf xs)) ++ system_conf_refs
|
|
| 726 | 728 | | otherwise
|
| 727 | - -> map PkgDbPath (splitSearchPath path)
|
|
| 729 | + -> map PkgDbPath (OsPath.splitSearchPath (OsPath.unsafeEncodeUtf path))
|
|
| 728 | 730 | |
| 729 | 731 | -- Apply the package DB-related flags from the command line to get the
|
| 730 | 732 | -- final list of package DBs.
|
| ... | ... | @@ -753,24 +755,24 @@ getUnitDbRefs cfg = do |
| 753 | 755 | -- NB: This logic is reimplemented in Cabal, so if you change it,
|
| 754 | 756 | -- make sure you update Cabal. (Or, better yet, dump it in the
|
| 755 | 757 | -- compiler info so Cabal can use the info.)
|
| 756 | -resolveUnitDatabase :: UnitConfig -> PkgDbRef -> IO (Maybe FilePath)
|
|
| 757 | -resolveUnitDatabase cfg GlobalPkgDb = return $ Just (unitConfigGlobalDB cfg)
|
|
| 758 | +resolveUnitDatabase :: UnitConfig -> PkgDbRef -> IO (Maybe OsPath)
|
|
| 759 | +resolveUnitDatabase cfg GlobalPkgDb = return $ Just $ OsPath.unsafeEncodeUtf $ unitConfigGlobalDB cfg
|
|
| 758 | 760 | resolveUnitDatabase cfg UserPkgDb = runMaybeT $ do
|
| 759 | 761 | dir <- versionedAppDir (unitConfigProgramName cfg) (unitConfigPlatformArchOS cfg)
|
| 760 | 762 | let pkgconf = dir </> unitConfigDBName cfg
|
| 761 | 763 | exist <- tryMaybeT $ doesDirectoryExist pkgconf
|
| 762 | - if exist then return pkgconf else mzero
|
|
| 764 | + if exist then return (OsPath.unsafeEncodeUtf pkgconf) else mzero
|
|
| 763 | 765 | resolveUnitDatabase _ (PkgDbPath name) = return $ Just name
|
| 764 | 766 | |
| 765 | -readUnitDatabase :: Logger -> UnitConfig -> FilePath -> IO (UnitDatabase UnitId)
|
|
| 767 | +readUnitDatabase :: Logger -> UnitConfig -> OsPath -> IO (UnitDatabase UnitId)
|
|
| 766 | 768 | readUnitDatabase logger cfg conf_file = do
|
| 767 | - isdir <- doesDirectoryExist conf_file
|
|
| 769 | + isdir <- OsPath.doesDirectoryExist conf_file
|
|
| 768 | 770 | |
| 769 | 771 | proto_pkg_configs <-
|
| 770 | 772 | if isdir
|
| 771 | 773 | then readDirStyleUnitInfo conf_file
|
| 772 | 774 | else do
|
| 773 | - isfile <- doesFileExist conf_file
|
|
| 775 | + isfile <- OsPath.doesFileExist conf_file
|
|
| 774 | 776 | if isfile
|
| 775 | 777 | then do
|
| 776 | 778 | mpkgs <- tryReadOldFileStyleUnitInfo
|
| ... | ... | @@ -778,48 +780,49 @@ readUnitDatabase logger cfg conf_file = do |
| 778 | 780 | Just pkgs -> return pkgs
|
| 779 | 781 | Nothing -> throwGhcExceptionIO $ InstallationError $
|
| 780 | 782 | "ghc no longer supports single-file style package " ++
|
| 781 | - "databases (" ++ conf_file ++
|
|
| 783 | + "databases (" ++ show conf_file ++
|
|
| 782 | 784 | ") use 'ghc-pkg init' to create the database with " ++
|
| 783 | 785 | "the correct format."
|
| 784 | 786 | else throwGhcExceptionIO $ InstallationError $
|
| 785 | - "can't find a package database at " ++ conf_file
|
|
| 787 | + "can't find a package database at " ++ show conf_file
|
|
| 786 | 788 | |
| 787 | 789 | let
|
| 788 | 790 | -- Fix #16360: remove trailing slash from conf_file before calculating pkgroot
|
| 789 | - conf_file' = dropTrailingPathSeparator conf_file
|
|
| 790 | - top_dir = unitConfigGHCDir cfg
|
|
| 791 | - pkgroot = takeDirectory conf_file'
|
|
| 791 | + conf_file' = OsPath.dropTrailingPathSeparator conf_file
|
|
| 792 | + top_dir = OsPath.unsafeEncodeUtf (unitConfigGHCDir cfg)
|
|
| 793 | + pkgroot = OsPath.takeDirectory conf_file'
|
|
| 792 | 794 | pkg_configs1 = map (mungeUnitInfo top_dir pkgroot . mapUnitInfo (\(UnitKey x) -> UnitId x) . mkUnitKeyInfo)
|
| 793 | 795 | proto_pkg_configs
|
| 794 | 796 | --
|
| 795 | 797 | return $ UnitDatabase conf_file' pkg_configs1
|
| 796 | 798 | where
|
| 799 | + readDirStyleUnitInfo :: OsPath -> IO [DbUnitInfo]
|
|
| 797 | 800 | readDirStyleUnitInfo conf_dir = do
|
| 798 | - let filename = conf_dir </> "package.cache"
|
|
| 799 | - cache_exists <- doesFileExist filename
|
|
| 801 | + let filename = conf_dir OsPath.</> (OsPath.unsafeEncodeUtf "package.cache")
|
|
| 802 | + cache_exists <- OsPath.doesFileExist filename
|
|
| 800 | 803 | if cache_exists
|
| 801 | 804 | then do
|
| 802 | - debugTraceMsg logger 2 $ text "Using binary package database:" <+> text filename
|
|
| 803 | - readPackageDbForGhc filename
|
|
| 805 | + debugTraceMsg logger 2 $ text "Using binary package database:" <+> ppr filename
|
|
| 806 | + readPackageDbForGhc (OsPath.unsafeDecodeUtf filename)
|
|
| 804 | 807 | else do
|
| 805 | 808 | -- If there is no package.cache file, we check if the database is not
|
| 806 | 809 | -- empty by inspecting if the directory contains any .conf file. If it
|
| 807 | 810 | -- does, something is wrong and we fail. Otherwise we assume that the
|
| 808 | 811 | -- database is empty.
|
| 809 | 812 | debugTraceMsg logger 2 $ text "There is no package.cache in"
|
| 810 | - <+> text conf_dir
|
|
| 813 | + <+> ppr conf_dir
|
|
| 811 | 814 | <> text ", checking if the database is empty"
|
| 812 | - db_empty <- all (not . isSuffixOf ".conf")
|
|
| 813 | - <$> getDirectoryContents conf_dir
|
|
| 815 | + db_empty <- all (not . OsPath.isSuffixOf (OsPath.unsafeEncodeUtf ".conf"))
|
|
| 816 | + <$> OsPath.getDirectoryContents conf_dir
|
|
| 814 | 817 | if db_empty
|
| 815 | 818 | then do
|
| 816 | 819 | debugTraceMsg logger 3 $ text "There are no .conf files in"
|
| 817 | - <+> text conf_dir <> text ", treating"
|
|
| 820 | + <+> ppr conf_dir <> text ", treating"
|
|
| 818 | 821 | <+> text "package database as empty"
|
| 819 | 822 | return []
|
| 820 | 823 | else
|
| 821 | 824 | throwGhcExceptionIO $ InstallationError $
|
| 822 | - "there is no package.cache in " ++ conf_dir ++
|
|
| 825 | + "there is no package.cache in " ++ show conf_dir ++
|
|
| 823 | 826 | " even though package database is not empty"
|
| 824 | 827 | |
| 825 | 828 | |
| ... | ... | @@ -832,13 +835,13 @@ readUnitDatabase logger cfg conf_file = do |
| 832 | 835 | -- assumes it's a file and tries to overwrite with 'writeFile'.
|
| 833 | 836 | -- ghc-pkg also cooperates with this workaround.
|
| 834 | 837 | tryReadOldFileStyleUnitInfo = do
|
| 835 | - content <- readFile conf_file `catchIO` \_ -> return ""
|
|
| 838 | + content <- readFile (OsPath.unsafeDecodeUtf conf_file) `catchIO` \_ -> return ""
|
|
| 836 | 839 | if take 2 content == "[]"
|
| 837 | 840 | then do
|
| 838 | - let conf_dir = conf_file <.> "d"
|
|
| 839 | - direxists <- doesDirectoryExist conf_dir
|
|
| 841 | + let conf_dir = conf_file OsPath.<.> OsPath.unsafeEncodeUtf "d"
|
|
| 842 | + direxists <- OsPath.doesDirectoryExist conf_dir
|
|
| 840 | 843 | if direxists
|
| 841 | - then do debugTraceMsg logger 2 (text "Ignoring old file-style db and trying:" <+> text conf_dir)
|
|
| 844 | + then do debugTraceMsg logger 2 (text "Ignoring old file-style db and trying:" <+> ppr conf_dir)
|
|
| 842 | 845 | liftM Just (readDirStyleUnitInfo conf_dir)
|
| 843 | 846 | else return (Just []) -- ghc-pkg will create it when it's updated
|
| 844 | 847 | else return Nothing
|
| ... | ... | @@ -848,11 +851,11 @@ distrustAllUnits pkgs = map distrust pkgs |
| 848 | 851 | where
|
| 849 | 852 | distrust pkg = pkg{ unitIsTrusted = False }
|
| 850 | 853 | |
| 851 | -mungeUnitInfo :: FilePath -> FilePath
|
|
| 854 | +mungeUnitInfo :: OsPath -> OsPath
|
|
| 852 | 855 | -> UnitInfo -> UnitInfo
|
| 853 | 856 | mungeUnitInfo top_dir pkgroot =
|
| 854 | 857 | mungeDynLibFields
|
| 855 | - . mungeUnitInfoPaths (ST.pack top_dir) (ST.pack pkgroot)
|
|
| 858 | + . mungeUnitInfoPaths (ST.pack (OsPath.unsafeDecodeUtf top_dir)) (ST.pack (OsPath.unsafeDecodeUtf pkgroot))
|
|
| 856 | 859 | |
| 857 | 860 | mungeDynLibFields :: UnitInfo -> UnitInfo
|
| 858 | 861 | mungeDynLibFields pkg =
|
| ... | ... | @@ -1373,7 +1376,7 @@ mergeDatabases logger = foldM merge (emptyUniqMap, emptyUniqMap) . zip [1..] |
| 1373 | 1376 | where
|
| 1374 | 1377 | merge (pkg_map, prec_map) (i, UnitDatabase db_path db) = do
|
| 1375 | 1378 | debugTraceMsg logger 2 $
|
| 1376 | - text "loading package database" <+> text db_path
|
|
| 1379 | + text "loading package database" <+> ppr db_path
|
|
| 1377 | 1380 | forM_ (Set.toList override_set) $ \pkg ->
|
| 1378 | 1381 | debugTraceMsg logger 2 $
|
| 1379 | 1382 | text "package" <+> ppr pkg <+>
|
| ... | ... | @@ -137,6 +137,8 @@ import Control.Monad ( guard ) |
| 137 | 137 | import Control.Monad.IO.Class ( MonadIO, liftIO )
|
| 138 | 138 | import System.IO.Error as IO ( isDoesNotExistError )
|
| 139 | 139 | import System.Directory ( doesDirectoryExist, getModificationTime, renameFile )
|
| 140 | +import qualified System.Directory.OsPath as OsPath
|
|
| 141 | +import System.OsPath (OsPath)
|
|
| 140 | 142 | import System.FilePath
|
| 141 | 143 | |
| 142 | 144 | import Data.Bifunctor ( first, second )
|
| ... | ... | @@ -1248,9 +1250,9 @@ getModificationUTCTime = getModificationTime |
| 1248 | 1250 | -- --------------------------------------------------------------
|
| 1249 | 1251 | -- check existence & modification time at the same time
|
| 1250 | 1252 | |
| 1251 | -modificationTimeIfExists :: FilePath -> IO (Maybe UTCTime)
|
|
| 1253 | +modificationTimeIfExists :: OsPath -> IO (Maybe UTCTime)
|
|
| 1252 | 1254 | modificationTimeIfExists f =
|
| 1253 | - (do t <- getModificationUTCTime f; return (Just t))
|
|
| 1255 | + (do t <- OsPath.getModificationTime f; return (Just t))
|
|
| 1254 | 1256 | `catchIO` \e -> if isDoesNotExistError e
|
| 1255 | 1257 | then return Nothing
|
| 1256 | 1258 | else ioError e
|
| ... | ... | @@ -149,6 +149,7 @@ import Data.String |
| 149 | 149 | import Data.Word
|
| 150 | 150 | import System.IO ( Handle )
|
| 151 | 151 | import System.FilePath
|
| 152 | +import System.OsPath (OsPath, decodeUtf)
|
|
| 152 | 153 | import Text.Printf
|
| 153 | 154 | import Numeric (showFFloat)
|
| 154 | 155 | import Numeric.Natural (Natural)
|
| ... | ... | @@ -1101,6 +1102,8 @@ instance Outputable Extension where |
| 1101 | 1102 | instance Outputable ModuleName where
|
| 1102 | 1103 | ppr = pprModuleName
|
| 1103 | 1104 | |
| 1105 | +instance Outputable OsPath where
|
|
| 1106 | + ppr p = text $ either show id (decodeUtf p)
|
|
| 1104 | 1107 | |
| 1105 | 1108 | pprModuleName :: IsLine doc => ModuleName -> doc
|
| 1106 | 1109 | pprModuleName (ModuleName nm) =
|
| ... | ... | @@ -770,10 +770,9 @@ Options affecting code generation |
| 770 | 770 | :type: dynamic
|
| 771 | 771 | :category: codegen
|
| 772 | 772 | |
| 773 | - Generate position-independent code (code that can be put into shared
|
|
| 774 | - libraries). This currently works on Linux x86 and x86-64. On
|
|
| 775 | - Windows, position-independent code is never used so the flag is a
|
|
| 776 | - no-op on that platform.
|
|
| 773 | + Generate position-independent code (PIC). This code can be put into shared
|
|
| 774 | + libraries and is sometimes required by operating systems, e.g. systems using
|
|
| 775 | + Address Space Layout Randomization (ASLR).
|
|
| 777 | 776 | |
| 778 | 777 | .. ghc-flag:: -fexternal-dynamic-refs
|
| 779 | 778 | :shortdesc: Generate code for linking against dynamic libraries
|
| ... | ... | @@ -790,9 +789,7 @@ Options affecting code generation |
| 790 | 789 | :category: codegen
|
| 791 | 790 | |
| 792 | 791 | Generate code in such a way to be linkable into a position-independent
|
| 793 | - executable This currently works on Linux x86 and x86-64. On Windows,
|
|
| 794 | - position-independent code is never used so the flag is a no-op on that
|
|
| 795 | - platform. To link the final executable use :ghc-flag:`-pie`.
|
|
| 792 | + executable. To link the final executable use :ghc-flag:`-pie`.
|
|
| 796 | 793 | |
| 797 | 794 | .. ghc-flag:: -dynamic
|
| 798 | 795 | :shortdesc: Build dynamically-linked object files and executables
|
| ... | ... | @@ -552,7 +552,12 @@ static int compare_path(StgWord key1, StgWord key2) |
| 552 | 552 | |
| 553 | 553 | static void addLoadedDll(LoadedDllCache *cache, const pathchar *dll_name, HINSTANCE instance)
|
| 554 | 554 | {
|
| 555 | - insertHashTable_(cache->hash, (StgWord) dll_name, instance, hash_path);
|
|
| 555 | + // dll_name might be deallocated, we need to copy it to have a stable reference to the contents
|
|
| 556 | + // See #26613
|
|
| 557 | + size_t size = wcslen(dll_name) + 1;
|
|
| 558 | + pathchar* dll_name_copy = stgMallocBytes(size * sizeof(pathchar), "addLoadedDll");
|
|
| 559 | + wcsncpy(dll_name_copy, dll_name, size);
|
|
| 560 | + insertHashTable_(cache->hash, (StgWord) dll_name_copy, instance, hash_path);
|
|
| 556 | 561 | }
|
| 557 | 562 | |
| 558 | 563 | static HINSTANCE isDllLoaded(const LoadedDllCache *cache, const pathchar *dll_name)
|
| 1 | +module Main (main) where
|
|
| 2 | + |
|
| 3 | +data Command
|
|
| 4 | + = Command1
|
|
| 5 | + | Command2
|
|
| 6 | + | Command3
|
|
| 7 | + | Command4
|
|
| 8 | + | Command5
|
|
| 9 | + | Command6 -- Commenting this line works with -fPIC, uncommenting leads to a crash.
|
|
| 10 | + |
|
| 11 | +main :: IO ()
|
|
| 12 | +main = do
|
|
| 13 | + let x = case cmd of
|
|
| 14 | + Command1 -> 1 :: Int
|
|
| 15 | + Command2 -> 2
|
|
| 16 | + Command3 -> 3
|
|
| 17 | + Command4 -> 4
|
|
| 18 | + Command5 -> 5
|
|
| 19 | + Command6 -> 6
|
|
| 20 | + putStrLn (show x)
|
|
| 21 | + |
|
| 22 | +{-# NOINLINE cmd #-}
|
|
| 23 | +cmd :: Command
|
|
| 24 | +cmd = Command6 |
| 1 | +6 |
| ... | ... | @@ -257,3 +257,4 @@ test('CCallConv', [req_c], compile_and_run, ['CCallConv_c.c']) |
| 257 | 257 | test('T25364', normal, compile_and_run, [''])
|
| 258 | 258 | test('T26061', normal, compile_and_run, [''])
|
| 259 | 259 | test('T26537', normal, compile_and_run, ['-O2 -fregs-graph'])
|
| 260 | +test('T24016', normal, compile_and_run, ['-O1 -fPIC']) |