diff options
-rw-r--r-- | compiler/llvmGen/Llvm/Types.hs | 26 | ||||
-rw-r--r-- | compiler/main/DynFlags.hs | 2 | ||||
-rw-r--r-- | mk/flavours/validate.mk | 1 |
3 files changed, 28 insertions, 1 deletions
diff --git a/compiler/llvmGen/Llvm/Types.hs b/compiler/llvmGen/Llvm/Types.hs index d533b4a993..5c2ce5e3ee 100644 --- a/compiler/llvmGen/Llvm/Types.hs +++ b/compiler/llvmGen/Llvm/Types.hs @@ -217,7 +217,31 @@ ppLit f@(LMFloatLit _ _) = sdocWithDynFlags (\dflags -> error $ "Can't print this float literal!" ++ showSDoc dflags (ppr f)) ppLit (LMVectorLit ls ) = char '<' <+> ppCommaJoin ls <+> char '>' ppLit (LMNullLit _ ) = text "null" -ppLit (LMUndefLit _ ) = text "undef" +-- Trac 11487 was an issue where we passed undef for some arguments +-- that were actually live. By chance the registers holding those +-- arguments usually happened to have the right values anyways, but +-- that was not guaranteed. To find such bugs reliably, we set the +-- flag below when validating, which replaces undef literals (at +-- common types) with values that are likely to cause a crash or test +-- failure. +ppLit (LMUndefLit t ) = sdocWithDynFlags f + where f dflags + | gopt Opt_LlvmFillUndefWithGarbage dflags, + Just lit <- garbageLit t = ppLit lit + | otherwise = text "undef" + +garbageLit :: LlvmType -> Maybe LlvmLit +garbageLit t@(LMInt w) = Just (LMIntLit (0xbbbbbbbbbbbbbbb0 `mod` (2^w)) t) + -- Use a value that looks like an untagged pointer, so we are more + -- likely to try to enter it +garbageLit t + | isFloat t = Just (LMFloatLit 12345678.9 t) +garbageLit t@(LMPointer _) = Just (LMNullLit t) + -- Using null isn't totally ideal, since some functions may check for null. + -- But producing another value is inconvenient since it needs a cast, + -- and the knowledge for how to format casts is in PpLlvm. +garbageLit _ = Nothing + -- More cases could be added, but this should do for now. -- | Return the 'LlvmType' of the 'LlvmVar' getVarType :: LlvmVar -> LlvmType diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs index 83de48c621..b86d1a7958 100644 --- a/compiler/main/DynFlags.hs +++ b/compiler/main/DynFlags.hs @@ -422,6 +422,7 @@ data GeneralFlag | Opt_PedanticBottoms -- Be picky about how we treat bottom | Opt_LlvmTBAA -- Use LLVM TBAA infastructure for improving AA (hidden flag) | Opt_LlvmPassVectorsInRegisters -- Pass SIMD vectors in registers (requires a patched LLVM) (hidden flag) + | Opt_LlvmFillUndefWithGarbage -- Testing for undef bugs (hidden flag) | Opt_IrrefutableTuples | Opt_CmmSink | Opt_CmmElimCommonBlocks @@ -3055,6 +3056,7 @@ fFlags = [ flagSpec "liberate-case" Opt_LiberateCase, flagHiddenSpec "llvm-pass-vectors-in-regs" Opt_LlvmPassVectorsInRegisters, flagHiddenSpec "llvm-tbaa" Opt_LlvmTBAA, + flagHiddenSpec "llvm-fill-undef-with-garbage" Opt_LlvmFillUndefWithGarbage, flagSpec "loopification" Opt_Loopification, flagSpec "omit-interface-pragmas" Opt_OmitInterfacePragmas, flagSpec "omit-yields" Opt_OmitYields, diff --git a/mk/flavours/validate.mk b/mk/flavours/validate.mk index 94892d465f..1a636faea4 100644 --- a/mk/flavours/validate.mk +++ b/mk/flavours/validate.mk @@ -1,4 +1,5 @@ SRC_HC_OPTS = -O0 -H64m +SRC_HC_OPTS_STAGE1 = -fllvm-fill-undef-with-garbage # See Trac 11487 GhcStage1HcOpts = -O GhcStage2HcOpts = -O -dcore-lint GhcLibHcOpts = -O -dcore-lint |