Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC

Commits:

22 changed files:

Changes:

  • .gitlab-ci.yml
    ... ... @@ -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
    

  • compiler/GHC/CmmToAsm/X86/CodeGen.hs
    ... ... @@ -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 =
    

  • compiler/GHC/CmmToAsm/X86/Instr.hs
    ... ... @@ -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
    

  • compiler/GHC/CmmToAsm/X86/Ppr.hs
    ... ... @@ -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) _
    

  • compiler/GHC/Data/OsPath.hs
    ... ... @@ -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.
    

  • compiler/GHC/Driver/Backpack.hs
    ... ... @@ -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
    

  • compiler/GHC/Driver/CodeOutput.hs
    ... ... @@ -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
    

  • compiler/GHC/Driver/Downsweep.hs
    ... ... @@ -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
     
    

  • compiler/GHC/Driver/DynFlags.hs
    ... ... @@ -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
     
    

  • compiler/GHC/Driver/Main.hs
    ... ... @@ -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
    

  • compiler/GHC/Driver/Pipeline/Execute.hs
    ... ... @@ -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
    

  • compiler/GHC/Driver/Session.hs
    ... ... @@ -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
    

  • compiler/GHC/Linker/Loader.hs
    ... ... @@ -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
    

  • compiler/GHC/Unit/Finder.hs
    ... ... @@ -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)
    

  • compiler/GHC/Unit/State.hs
    ... ... @@ -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 <+>
    

  • compiler/GHC/Utils/Misc.hs
    ... ... @@ -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
    

  • compiler/GHC/Utils/Outputable.hs
    ... ... @@ -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) =
    

  • docs/users_guide/phases.rst
    ... ... @@ -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
    

  • rts/linker/PEi386.c
    ... ... @@ -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)
    

  • testsuite/tests/codeGen/should_run/T24016.hs
    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

  • testsuite/tests/codeGen/should_run/T24016.stdout
    1
    +6

  • testsuite/tests/codeGen/should_run/all.T
    ... ... @@ -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'])