Skip to content

Commit

Permalink
add old notes
Browse files Browse the repository at this point in the history
  • Loading branch information
csabahruska committed May 4, 2020
1 parent 667df0b commit 259d477
Show file tree
Hide file tree
Showing 11 changed files with 542 additions and 0 deletions.
11 changes: 11 additions & 0 deletions cmm-info
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/cmm-type
https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/cmm-syntax
https://gitlab.haskell.org/ghc/ghc/wikis/commentary/rts/cmm

Stack Traces in Haskell
ARASH ROUHANI
https://www.arashrouhani.com/papers/master-thesis.pdf

Low Level Virtual Machine for Glasgow Haskell Compiler
David Terei
https://llvm.org/pubs/2009-10-TereiThesis.pdf
7 changes: 7 additions & 0 deletions external-stg/data-con-from-type
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- | Attempts to tease a type apart into a type constructor and the application
-- of a number of arguments to that constructor
splitTyConApp_maybe :: HasDebugCallStack => Type -> Maybe (TyCon, [Type])

-- | As 'tyConDataCons_maybe', but returns the empty list of constructors if no
-- constructors could be found
tyConDataCons :: TyCon -> [DataCon]
62 changes: 62 additions & 0 deletions external-stg/stg-type-query-experiment
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[OK] isUnboxedTupleCon - worked unconditionally for all DataCons that external stg deals with

isUnboxedTupleType


experiments:
OK - no type, just DC isUTup, type PP
OK - no type, just datacon, type PP ; this validates the full DataCon conversion => [DATACON CONVERSION IS ALL OK]
NO - isUnboxedTupleType test for all types in Stg AST
A: no, it does not work for leviti polymorphic type
NO - isTypeLevPoly + isUnboxedTupleType
A: isUnboxedTupleType still fails
OK - no StgApp ty + isTypeLevPoly + isUnboxedTupleType + cvtBinderIdClosureParam, data con, type PP
OK - full type (no StgApp ty), data con, type PP
NO - only StgApp ty (original) + isTypeLevPoly ; check if App result type is valid at core to stg conversion step
A: core to stg res_ty is already messed up, use core app expre type instead
it is possible that it is
NO - not valid from the begining ; pass core's ret_ty promptly + add unboxed sum checking to cvtType
OK got examples - catch exceptions ; dump the types ; store original fun type + arg types + result type ; GOAL: collect example cases of failure
- stg optimization messes it up ; cse or unarise
OK - use original core app exp type in StgApp result type + igonre StgApp added by stg optimizations cse/unarise
OK - use core App result type + cse + unarise + with unboxed sum types (no type unarisation)
- do not support unboxed sums ; check if there is any in the base
- use core App result type + cse + unarise + unarise unboxes sum types


- export stg before cse and unarisation
- disable stg cse

StgApp thoughs:
- StgApp [] ; variable, does not force, result type is the variable type
- StgApp args are always single values
- StgApp as scrutinee ; case binder decides the type
- StgApp as

to consider
- is case scrutinee (app in case)
- is saturated
- is variable

2 APPROACH to extract fun app rep type:
- from core type (PREFERRED)
- from stg ast


NOTE:
ubxSumRepType :: [[PrimRep]] -> [SlotTy]

unbox tuple can not be thunk

TODO:
external stg pretty printer
include pretty printed core in stgbin
include the origin of stgapp (Var/Coercion/App)

QUESTIONS:
Is all core App mapped to StgApp?
A: yes

Is StgApp strict?

Can an StgApp create thunk?
63 changes: 63 additions & 0 deletions ghc-primop-gen/higher-order-primops
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// pass primop argument to higher-order function
"clearCCS#" :: (State# s -> (# State# s, a #))
-> State# s
-> (# State# s, a #)

// pass primop argument to higher-order function
"atomically#" :: (State# RealWorld -> (# State# RealWorld, a #) )
-> State# RealWorld
-> (# State# RealWorld, a #)

// the function just gets called with the proper state/realworld token value
// the second function parameter is collected from raise and raiseIO values
"catch#" :: (State# RealWorld -> (# State# RealWorld, a #) )
-> (b -> State# RealWorld -> (# State# RealWorld, a #) )
-> State# RealWorld
-> (# State# RealWorld, a #)

// each function gets called with the proper state/realworld token value
"catchRetry#" :: (State# RealWorld -> (# State# RealWorld, a #) )
-> (State# RealWorld -> (# State# RealWorld, a #) )
-> State# RealWorld
-> (# State# RealWorld, a #)

// the function just gets called with the proper state/realworld token value
// the second function parameter is collected from raise and raiseIO values
"catchSTM#" :: (State# RealWorld -> (# State# RealWorld, a #) )
-> (b -> State# RealWorld -> (# State# RealWorld, a #) )
-> State# RealWorld
-> (# State# RealWorld, a #)

// the primop returns is its single function argument
"maskAsyncExceptions#" :: (State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld
-> (# State# RealWorld, a #)

// the primop returns is its single function argument
"maskUninterruptible#" :: (State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld
-> (# State# RealWorld, a #)

// the primop returns is its single function argument
"unmaskAsyncExceptions#" :: (State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld
-> (# State# RealWorld, a #)


// the primop returns a function ; the primop is the origin of that function, it also should be treated as a primop function
"finalizeWeak#" :: Weak# a
-> State# RealWorld
-> (# State# RealWorld, Int#, (State# RealWorld -> (# State# RealWorld, b #) ) #)

// gets parameter from mutvar content, the result is function result value
"atomicModifyMutVar#" :: MutVar# s a
-> (a -> b)
-> State# s
-> (# State# s, c #)

// the function just gets called with the proper state/realworld token value
"mkWeak#" :: o
-> b
-> (State# RealWorld -> (# State# RealWorld, c #))
-> State# RealWorld
-> (# State# RealWorld, Weak# b #)
29 changes: 29 additions & 0 deletions ghc-primop-gen/primops-info
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
section "Char#"
section "Int#"
section "Word#"
section "Narrowings"
section "Double#"
section "Float#"
section "Arrays"
section "Small Arrays"
section "Byte Arrays"
section "Arrays of arrays"
section "Addr#"
section "Mutable variables"
section "Exceptions"
section "STM-accessible Mutable Variables"
section "Synchronized Mutable Variables"
section "Delay/wait operations"
section "Concurrency primitives"
section "Weak pointers"
section "Stable pointers and names"
section "Compact normal form"
section "Unsafe pointer equality"
section "Parallelism"
section "Tag to enum stuff"
section "Bytecode operations"
section "Misc"
section "Etc"
section "Safe coercions"
section "SIMD Vectors"
section "Prefetch"
126 changes: 126 additions & 0 deletions ghc-primop-gen/primops-problem
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
higher order function problem:
atomicModifyMutVar# :: MutVar# s a -> (a -> b) -> State# s -> (# State# s, c #)
maskAsyncExceptions# :: (State# RealWorld -> (# State# RealWorld, a #)) -> (State# RealWorld -> (# State# RealWorld, a #))
maskUninterruptible# :: (State# RealWorld -> (# State# RealWorld, a #)) -> (State# RealWorld -> (# State# RealWorld, a #))
unmaskAsyncExceptions# :: (State# RealWorld -> (# State# RealWorld, a #)) -> (State# RealWorld -> (# State# RealWorld, a #))

catch# :: (State# RealWorld -> (# State# RealWorld, a #) ) -> (b -> State# RealWorld -> (# State# RealWorld, a #) ) -> State# RealWorld -> (# State# RealWorld, a #)
atomically# :: (State# RealWorld -> (# State# RealWorld, a #) ) -> State# RealWorld -> (# State# RealWorld, a #)
catchRetry# :: (State# RealWorld -> (# State# RealWorld, a #) ) -> (State# RealWorld -> (# State# RealWorld, a #) ) -> (State# RealWorld -> (# State# RealWorld, a #) )
catchSTM# :: (State# RealWorld -> (# State# RealWorld, a #) ) -> (b -> State# RealWorld -> (# State# RealWorld, a #) ) -> (State# RealWorld -> (# State# RealWorld, a #) )
clearCCS# :: (State# s -> (# State# s, a #)) -> State# s -> (# State# s, a #)
mkWeak# :: o -> b -> (State# RealWorld -> (# State# RealWorld, c #)) -> State# RealWorld -> (# State# RealWorld, Weak# b #)

QUESTION:
how to handle higher order primops? (external defs)
how to track data-flow accurately? (use site specialization)
should we handle GHC higher order primops specially or sould we support higher order functions in general?
can the wrapper semantics be replaced with begin/end first order commands?
how do related project handle exception primitives?
- JHC ; ioError only
- LHC ;
- UHC ; Exceptional GRIN
- HRC ; generates code which use HRR runtime i.e. ihrExceptionHandlerGet, ihrExceptionExnGet

NOTES:
These primops should be modele according the meaning and not the type signature.
Each higher order primop acts as a wrapper function or does callback registration.

vector primops (not supported):
broadcast#
pack#
unpack#
insert#
plus#
minus#
times#
divide#
quot#
rem#
negate#
indexOffAddr#
readOffAddr#
writeOffAddr#
indexArrayAs#
readArrayAs#
writeArrayAs#
indexOffAddrAs#
readOffAddrAs#
writeOffAddrAs#

IDEA:
express problematic GHC primops in GRIN as code (as implementation)
Q: what would it look like for each problematic primop?
A: check how GHC implements them

Higher-order details:

# simple identity wrapper with monomorph input ; first order output
atomically# :: (State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld
-> (# State# RealWorld, a #)

# simple identity wrapper with monomorph input ; higher order output
maskAsyncExceptions# :: (State# RealWorld -> (# State# RealWorld, a #))
-> (State# RealWorld -> (# State# RealWorld, a #))

maskUninterruptible# :: (State# RealWorld -> (# State# RealWorld, a #))
-> (State# RealWorld -> (# State# RealWorld, a #))

unmaskAsyncExceptions# :: (State# RealWorld -> (# State# RealWorld, a #))
-> (State# RealWorld -> (# State# RealWorld, a #))

catchRetry# :: (State# RealWorld -> (# State# RealWorld, a #))
-> (State# RealWorld -> (# State# RealWorld, a #))
-> (State# RealWorld -> (# State# RealWorld, a #))

# simple identity wrapper with parametric input ; first order output
clearCCS# :: (State# s -> (# State# s, a #))
-> State# s
-> (# State# s, a #)

# callback registration
mkWeak# :: o
-> b
-> (State# RealWorld -> (# State# RealWorld, c #))
-> State# RealWorld
-> (# State# RealWorld, Weak# b #)

# invalid / hacky type signature
atomicModifyMutVar# :: MutVar# s a -> (a -> b) -> State# s -> (# State# s, c #)

# first order output ; parameter comes from argument function implicitly through raise
catch# :: (State# RealWorld -> (# State# RealWorld, a #))
-> (b -> State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld
-> (# State# RealWorld, a #)

# higher order output ; parameter comes from argument function implicitly through raise
catchSTM# :: (State# RealWorld -> (# State# RealWorld, a #))
-> (b -> State# RealWorld -> (# State# RealWorld, a #))
-> (State# RealWorld -> (# State# RealWorld, a #))

IDEA: Temporal hack for
identity wrappers ; replace the wrapper primop with its argument ; ok for:
done - atomically#
done - maskAsyncExceptions#
done - maskUninterruptible#
done - unmaskAsyncExceptions#
done catchRetry#
done - clearCCS#

callback registration ; ignore the callback
done - mkWeak#

implement in grin
atomicModifyMutVar#
mv f s =
lock mv
x0 <- readMutVar mv
x1 <- apply f x0
writeMutVar mv x1
unlock mv

TO SOLVE:
done - catch#
done - catchSTM#
Loading

0 comments on commit 259d477

Please sign in to comment.