summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/llvmGen/Llvm/Types.hs26
-rw-r--r--compiler/main/DynFlags.hs2
-rw-r--r--mk/flavours/validate.mk1
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