-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Const structs #476
base: master
Are you sure you want to change the base?
Const structs #476
Conversation
Replacing uses with ArgInt. This conversion happened anyway, later in the compiler, so not much is gained by having that PrimArg constructor. Huge number of changes to .exp files, but most are trivial changes to putchar calls.
Still generates bogus code in some cases.
Also recognise that constant structs are always not equal to 0
LLVM aligns structure fields, so we can't just use a single undef int the right size to fill in holes in a structure. Instead, we allocate the needed number of 1-byte undefs, plus the needed number of word-size undefs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will get back to the large files that I haven't read in some time. I also need to go through the changes in at least one of the larger exp files in more detail, but they seems sensible!
It's most unfortunate that there's a 100x in the mallocs in the drone test case. I suppose that's harder to get back now that the first drone is static and the compiler isn't smart enough to use a specialisation after that fact :/
@@ -2,4 +2,4 @@ n: energy: -0.169075 | |||
energy: -0.169088 | |||
|
|||
malloc count: (should be 5005 with multi-specz and 10006 without it) | |||
5005 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. A 0.1% efficiency improvement!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we update the comment above?
else do | ||
gFlows <- getProcGlobalFlows pspec | ||
globalFlowsUnions . (gFlows:) <$> mapM constGlobalFlows fields | ||
constsGlobalFlows fields = return emptyGlobalFlows -- XXX need to recurse! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it also possible there are global flows in the other fields? I think it's possible that there is another function pointer nested inside one of the other fields, and I think that should be considered.
@@ -13,7 +13,7 @@ | |||
---------------------------------------------------------------------- | |||
(0, 0, 0) #0 | |||
(-1, -6, 3) #100 | |||
** malloc count: 1 | |||
** malloc count: 100 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unfortunate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very much so. The two possible fixes I can think of would be to get multiple specialisation working for the recursive call, or to turn the constant back into code to create a fresh structure when that would allow the update to be destructive. Both of these seem pretty difficult to wrangle, so I put in the PR without fixing this.
return $ Just $ FloatStructMember n (sz `div` 8) | ||
argConstValue ArgClosure{} = return Nothing -- const closures already handled | ||
argConstValue (ArgGlobal info _) = do | ||
-- XXX is ArgGlobal a constant? Does it give the address, or value, of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this has come up before. I can't recall exactly what I thought last time, but I think that the address makes sense -- in order to get the value you must load
.
-- | The LLVM constant name for the specified StructID | ||
structConstName :: StructID -> Ident | ||
structConstName (StructID md num _) = | ||
specialName2 (showModSpec md) $ "constant" ++ specialChar : show num |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a specialName{N}
variant, for N > 2. Seems annoying...
Maybe
specialNames :: [String] -> String
specialNames = intercalate [specialChar]
is more ergonomic.
tryLookupConstant spec = | ||
gets $ Map.lookup spec . constNames | ||
writeConstDeclaration :: StructID -> LLVM () | ||
-- writeConstDeclaration spec@(WybeStringSpec str) n = do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete?
@@ -785,7 +817,7 @@ writeWybeCall wybeProc args pos = do | |||
-- | Generate a Wybe proc call instruction, or defer it if necessary. | |||
writeHOCall :: PrimArg -> [PrimArg] -> OptPos -> LLVM () | |||
writeHOCall (ArgClosure pspec closed _) args pos = do | |||
-- NB: this case doesn't seem to ever occur | |||
-- NB: this case doesn't seem to ever occur -- probably handled earlier |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right. The body builder should always lower a call to a known higher order term to a first order call. I think I added this special case a while back, probably before I tackled it in the body builder! Should be safe to remove.
typeRep ty = | ||
trustFromJust ("lookupTypeRepresentation of unknown type " ++ show ty) | ||
<$> lift (lookupTypeRepresentation ty) | ||
typeRep = lift . typeRepresentation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need this shorthand now?
-- ^ Static constants appearing in module | ||
constNames :: Map StaticConstSpec Ident, | ||
-- ^ local name given to static constants | ||
-- constNames :: Map StaticConstSpec Ident, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete?
Map.insert var (newBlock size) $ constStructs st} | ||
|
||
|
||
-- | Does the specified variable hold a constant structure? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc is wrong here
stringExpr str = do | ||
cStringArg <- Unplaced <$> cStringExpr str | ||
return $ Typed | ||
(Fncall ["wybe","string"] "unsafe_cstring_to_string" False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just make the buffer
ctor pub
? Or do you like the name having unsafe
?
-- | Return the representation of a StructMember | ||
constValueRepresentation :: ConstValue -> TypeRepresentation | ||
constValueRepresentation (IntStructMember _ size) = Bits $ size * 8 | ||
constValueRepresentation (FloatStructMember _ size) = Floating $ size * 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recall having constants for these 8
s. Can we use them here too, for clarity?
@@ -3761,6 +4020,18 @@ envPrimParam = PrimParam envParamName AnyType FlowIn Ordinary (ParamInfo False e | |||
makeGlobalResourceName :: ResourceSpec -> String | |||
makeGlobalResourceName spec = specialName2 "resource" $ show spec | |||
|
|||
-- These are defined in Snippets.hs, but we can't import that as it imports AST |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-recursive modules is painful 😖
case members of | ||
[(n,PointerStructMember id),(0,IntStructMember len _)] -> | ||
lift (lookupConstInfo id) >>= \case | ||
Just (CStringInfo str) | len == fromIntegral (length str) -> do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there ever a case where this isn't true?
I'm overall not sure why we need this...
I'm reviewing this via my phone at the airport, so can't access my laptop. Unfortunately, it seems that after a certain number of files, GitHub refuses to load diffs. I noticed, by chance in one of the commits a change that is odd. This should be the reference to it: https://github.com/pschachte/wybe/blob/const_structs/test-cases%2Ffinal-dump%2Fearly_error.exp#L74 Any chance we can avoid these changes? I assume the issue is before types, so perhaps in Flatten/Normalise, where string constants are replaced with tmp variables (that hold the constant value). I think this is also causing one of the error messages changing too, that I commented on before. |
@@ -1,4 +1,4 @@ | |||
Error detected during type checking of module(s) bug228-type | |||
final-dump/bug228-type.wybe:5:2: Type error in call to proc =, argument 1 | |||
final-dump/bug228-type.wybe:5:2: Type error in call to proc =, argument 2 | |||
final-dump/bug228-type.wybe:5:2: Type of "1.0" incompatible with ?bar | |||
final-dump/bug228-type.wybe:5:2: Type of tmp#0:wybe.string incompatible with ?bar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thus is unfortunate
return $ typeAndPlace expr ty castFrom pos | ||
flattenExp expr@(StringValue str WybeString) ty castFrom pos = do | ||
exp' <- lift $ stringExpr str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose this is what is causing the errors around string constants, as extra "unreachable" statements are introduced.
I don't know how we can avoid this, unfortunately. Perhaps we can delay this until Clause? That has implications for the const structures that are referenced in the module, I believe.
Generate LLVM constant structures in place of code to create structures all of whose contents are constants. This also applies to constant closures, so the code to optimise them in LLVM generation is now not needed, and to strings of length >1.