X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=c%CE%BBash%2FCLasH%2FNormalize.hs;h=31474d59328bd0342fc6244262061eba736b8c80;hb=0e45b79dac5dd4bf4b340a515b61a03953f673a2;hp=3505408081218e4aeeccab2f4d8838d08921bc85;hpb=be3494f72d858395809d4c0073bb51df628b0dac;p=matthijs%2Fmaster-project%2Fc%CE%BBash.git diff --git "a/c\316\273ash/CLasH/Normalize.hs" "b/c\316\273ash/CLasH/Normalize.hs" index 3505408..31474d5 100644 --- "a/c\316\273ash/CLasH/Normalize.hs" +++ "b/c\316\273ash/CLasH/Normalize.hs" @@ -338,36 +338,56 @@ inlinenonreptop = everywhere ("inlinenonrep", inlinebind ((Monad.liftM not) . is -- doesn't seem to set all those names as "system names", we apply some -- guessing here. inlinetoplevel, inlinetopleveltop :: Transform +-- HACK: Don't inline == and /=. The default (derived) implementation +-- for /= uses the polymorphic version of ==, which gets a dictionary +-- for Eq passed in, which contains a reference to itself, resulting in +-- an infinite loop in transformation. Not inlining == is really a hack, +-- but for now it keeps things working with the most common symptom of +-- this problem. +inlinetoplevel expr@(Var f) | Name.getOccString f `elem` ["==", "/="] = return expr -- Any system name is candidate for inlining. Never inline user-defined -- functions, to preserve structure. inlinetoplevel expr@(Var f) | not $ isUserDefined f = do - norm_maybe <- Trans.lift $ getNormalized_maybe f - case norm_maybe of - -- No body or not normalizeable. - Nothing -> return expr - Just norm -> if needsInline norm then do + body_maybe <- needsInline f + case body_maybe of + Just body -> do -- Regenerate all uniques in the to-be-inlined expression - norm_uniqued <- Trans.lift $ genUniques norm + body_uniqued <- Trans.lift $ genUniques body -- And replace the variable reference with the unique'd body. - change norm_uniqued - else + change body_uniqued -- No need to inline - return expr + Nothing -> return expr + -- Leave all other expressions unchanged inlinetoplevel expr = return expr inlinetopleveltop = everywhere ("inlinetoplevel", inlinetoplevel) - -needsInline :: CoreExpr -> Bool -needsInline expr = case splitNormalized expr of - -- Inline any function that only has a single definition, it is probably - -- simple enough. This might inline some stuff that it shouldn't though it - -- will never inline user-defined functions (inlinetoplevel only tries - -- system names) and inlining should never break things. - (args, [bind], res) -> True - _ -> False - - + +-- | Does the given binder need to be inlined? If so, return the body to +-- be used for inlining. +needsInline :: CoreBndr -> TransformMonad (Maybe CoreExpr) +needsInline f = do + body_maybe <- Trans.lift $ getGlobalBind f + case body_maybe of + -- No body available? + Nothing -> return Nothing + Just body -> case CoreSyn.collectArgs body of + -- The body is some (top level) binder applied to 0 or more + -- arguments. That should be simple enough to inline. + (Var f, args) -> return $ Just body + -- Body is more complicated, try normalizing it + _ -> do + norm_maybe <- Trans.lift $ getNormalized_maybe f + case norm_maybe of + -- Noth normalizeable + Nothing -> return Nothing + Just norm -> case splitNormalized norm of + -- The function has just a single binding, so that's simple + -- enough to inline. + (args, [bind], res) -> return $ Just norm + -- More complicated function, don't inline + _ -> return Nothing + -------------------------------- -- Dictionary inlining -------------------------------- @@ -425,12 +445,12 @@ classopresolution expr@(App (App (Var sel) ty) dict) | not is_builtin = Just cls -> case collectArgs dict of (_, []) -> return expr -- Dict is not an application (e.g., not inlined yet) (Var dictdc, (ty':selectors)) | not (Maybe.isJust (Id.isDataConId_maybe dictdc)) -> return expr -- Dictionary is not a datacon yet (but e.g., a top level binder) - | tyargs_neq ty ty' -> error $ "Applying class selector to dictionary without matching type?\n" ++ pprString expr + | tyargs_neq ty ty' -> error $ "Normalize.classopresolution: Applying class selector to dictionary without matching type?\n" ++ pprString expr | otherwise -> let selector_ids = Class.classSelIds cls in -- Find the selector used in the class' list of selectors case List.elemIndex sel selector_ids of - Nothing -> error $ "Selector not found in class' selector list? This should not happen!\nExpression: " ++ pprString expr ++ "\nClass: " ++ show cls ++ "\nSelectors: " ++ show selector_ids + Nothing -> error $ "Normalize.classopresolution: Selector not found in class' selector list? This should not happen!\nExpression: " ++ pprString expr ++ "\nClass: " ++ show cls ++ "\nSelectors: " ++ show selector_ids -- Get the corresponding argument from the dictionary Just n -> change (selectors!!n) (_, _) -> return expr -- Not applying a variable? Don't touch