-
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
650 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,340 @@ | ||
.type Function | ||
.type Variable | ||
.type Tag | ||
.type Literal | ||
.type SimpleType | ||
.type CodeName = Variable | Function | ||
|
||
// External function (name, effectful) | ||
.decl External(f:Function,effectful:number,ret:SimpleType) | ||
.decl ExternalParam(f:Function, i:number, st:SimpleType) | ||
|
||
// variable | ||
// example: result <- pure value | ||
.decl Move(result:Variable, value:Variable) | ||
|
||
// literal value | ||
// example: result <- pure 1 | ||
.decl LitAssign(result:Variable, st:SimpleType, l:Literal) | ||
|
||
// node value | ||
// example: result_node <- pure (Ctag item0 item1) | ||
.decl Node(result_node:Variable, t:Tag) | ||
.decl NodeArgument(result_node:Variable, i:number, item:Variable) | ||
|
||
// store/fetch/update | ||
// example: result <- fetch value | ||
.decl Fetch(result:Variable, value:Variable) | ||
// example: result <- store value | ||
.decl Store(result:Variable, value:Variable) | ||
// example: result <- update target value | ||
.decl Update(result:Variable, target:Variable, value:Variable) | ||
|
||
|
||
// app a.k.a. call | ||
// example: call_result <- f value0 value1 | ||
.decl Call(call_result:Variable, f:Function) | ||
.decl CallArgument(call_result:Variable, i:number, value:Variable) | ||
|
||
// bind pattern | ||
// example: node@(Ctag param0 param1) <- pure input_value | ||
.decl NodePattern(node:Variable, t:Tag, input_value:Variable) | ||
.decl NodeParameter(node:Variable, i:number, parameter:Variable) | ||
|
||
// function | ||
// example: f param0 param1 = ... | ||
.decl FunctionParameter(f:Function, i:number, parameter:Variable) | ||
|
||
// case + alt | ||
// example: | ||
// case_result <- case scrut of | ||
// alt_value@(Ctag param0 param1) -> basic_block_name arg0 arg1 | ||
.decl Case(case_result:Variable, scrutinee:Variable) | ||
.decl Alt(case_result:Variable, alt_value:Variable, t:Tag) | ||
.decl AltParameter(case_result:Variable, t:Tag, i:number, parameter:Variable) | ||
.decl AltLiteral(case_result:Variable, alt_value:Variable, st:SimpleType, l:Literal) | ||
.decl AltDefault(case_result:Variable, alt_value:Variable) | ||
|
||
// pure a.k.a. return value | ||
// example: pure value | ||
.decl ReturnValue(n:CodeName, value:Variable) | ||
|
||
// instruction ordering | ||
.decl FirstInst(n:CodeName, result:Variable) | ||
.decl NextInst(prev:Variable, next:Variable) | ||
|
||
.decl EntryPoint(n:CodeName) | ||
|
||
.input External | ||
.input ExternalParam | ||
.input Move | ||
.input LitAssign | ||
.input Node | ||
.input NodeArgument | ||
.input Fetch | ||
.input Store | ||
.input Update | ||
.input Call | ||
.input CallArgument | ||
.input NodePattern | ||
.input NodeParameter | ||
.input FunctionParameter | ||
.input Case | ||
.input Alt | ||
.input AltParameter | ||
.input AltLiteral | ||
.input AltDefault | ||
.input ReturnValue | ||
.input FirstInst | ||
.input NextInst | ||
.input EntryPoint | ||
|
||
// Reachability | ||
.decl ReachableCode(n:CodeName) | ||
.output ReachableCode(delimiter=",") | ||
.decl CodeNameInst(n:CodeName, v:Variable) | ||
.output CodeNameInst(delimiter=",") | ||
|
||
CodeNameInst(n, v) :- | ||
FirstInst(n, v). | ||
CodeNameInst(n, v) :- | ||
CodeNameInst(n, v0), | ||
NextInst(v0, v). | ||
|
||
ReachableCode(n) :- | ||
EntryPoint(n). | ||
ReachableCode(n) :- | ||
ReachableCode(n0), | ||
CodeNameInst(n0, v), | ||
Call(v, n). | ||
|
||
.decl ReachableInst(v:Variable) | ||
|
||
ReachableInst(v) :- | ||
ReachableCode(n), | ||
CodeNameInst(n, v). | ||
|
||
.decl VarPointsTo(v:Variable, target:Variable) | ||
.output VarPointsTo(delimiter=",") | ||
|
||
VarPointsTo(v,t) :- | ||
Store(v, t), | ||
ReachableInst(v). | ||
|
||
VarPointsTo(v,t) :- | ||
Move(v, v0), | ||
ReachableInst(v), | ||
VarPointsTo(v0, t). | ||
|
||
VarPointsTo(v,t) :- | ||
Update(r, v, t), | ||
ReachableInst(r). | ||
|
||
VarPointsTo(v,t) :- | ||
FunctionParameter(_, i, v), | ||
CallArgument(r, i, v0), | ||
VarPointsTo(v0, t), | ||
ReachableInst(r). | ||
|
||
// Value Computation | ||
.decl Value(v:Variable, value:Variable) | ||
.output Value(delimiter=",") | ||
|
||
.decl Heap(orig:Variable, item:Variable) | ||
.output Heap(delimiter=",") | ||
|
||
Heap(v,i) :- Store(v,i). | ||
|
||
// HPT: update | ||
Heap(heap_orig, sv) :- | ||
Update(_, heap, sv), | ||
Value(heap, heap_orig), | ||
Heap(heap_orig, _), | ||
SharedLocation(heap). | ||
|
||
Value(n,n) :- | ||
LitAssign(n,_,_). | ||
|
||
Value(n, n) :- | ||
Node(n, _). | ||
|
||
Value(v, v) :- | ||
Store(v, _). | ||
|
||
Value(v,v) :- | ||
Update(v,_,_). | ||
|
||
Value(v,v) :- | ||
External(f,_,_), | ||
Call(v,f). | ||
|
||
Value(v, n) :- | ||
Node(n, _), | ||
Move(v, n). | ||
|
||
Value(v1,v2) :- | ||
FunctionParameter(_,_,p), | ||
Value(v1,p), | ||
Value(p,v2). | ||
|
||
// HPT: fetch | ||
Value(v, item_origin) :- | ||
Fetch(v, heap), | ||
Value(heap, heap_orig), | ||
Heap(heap_orig, item), | ||
Value(item, item_origin). | ||
|
||
// fun param | ||
Value(p, val) :- | ||
CallArgument(r, i, a), | ||
Call(r, f), | ||
FunctionParameter(f, i, p), | ||
Value(a, val). | ||
|
||
// fun return | ||
Value(r, val) :- | ||
Call(r, f), | ||
ReturnValue(f, v), | ||
Value(v, val). | ||
|
||
// Node parameter matching node value created somewhere | ||
Value(param, argval) :- | ||
NodePattern(v, tag, n), | ||
NodeParameter(v, i, param), | ||
Value(n, nval), | ||
Node(nval, tag), | ||
NodeArgument(nval, i, arg), | ||
Value(arg, argval). | ||
|
||
// Alt value when matched on tag. | ||
Value(alt_val, scrut_val) :- | ||
Case(case_result, scrut), | ||
AltLiteral(case_result, alt_val, _, _), | ||
Value(scrut, scrut_val). | ||
|
||
// Alt value when matched on tag | ||
Value(alt_val, scrut_val) :- | ||
Case(case_result, scrut), | ||
Alt(case_result, alt_val, tag), | ||
Value(scrut, scrut_val), | ||
Node(scrut_val, tag). | ||
|
||
// Value of alt parameter when matched on tag | ||
Value(parameter, val) :- | ||
Case(case_res, scrut), | ||
Alt(case_res, _alt_value, tag), | ||
AltParameter(case_res, tag, i, parameter), | ||
Value(scrut, scrut_val), | ||
Node(scrut_val,tag), | ||
NodeArgument(scrut_val,i,val). | ||
|
||
// Result of case/alt when matched on a node. | ||
Value(case_result, val) :- | ||
Case(case_result, _), | ||
Alt(case_result, alt_value, _), | ||
ReturnValue(alt_value, v), | ||
Value(v, val). | ||
|
||
// Result of case/alt when matched on a literal. | ||
Value(case_result, val) :- | ||
Case(case_result, _), | ||
AltLiteral(case_result, alt_value, _, _), | ||
ReturnValue(alt_value, v), | ||
Value(v, val). | ||
|
||
// Result of case/alt when matched on the default alternative. | ||
Value(case_result, val) :- | ||
Case(case_result, _), | ||
AltDefault(case_result, alt_value), | ||
ReturnValue(alt_value, v), | ||
Value(v, val). | ||
|
||
// Type Env | ||
|
||
.type NodeParamType = Variable | SimpleType | ||
.decl AbstractLocation(n: Variable) | ||
.decl VariableSimpleType(n: Variable, st:SimpleType) | ||
.decl VariableAbstractLocation(n:Variable, loc:Variable) | ||
.decl VariableNodeTag(n:Variable, t:Tag) | ||
.decl VariableNodeParamType(n: Variable, t:Tag, i:number, nt:NodeParamType) | ||
|
||
.output AbstractLocation(delimiter=",") | ||
AbstractLocation(n) :- Heap(n,_). | ||
|
||
.output VariableSimpleType(delimiter=",") | ||
VariableSimpleType(n,st) :- LitAssign(n,st,_). | ||
VariableSimpleType(n,"Unit") :- Update(n,_,_). | ||
VariableSimpleType(n,st) :- External(f,_,st), Call(n,f). | ||
VariableSimpleType(n,st) :- ExternalParam(f,i,st), Call(r,f), CallArgument(r,i,n). | ||
VariableSimpleType(n,st) :- Value(n,r), VariableSimpleType(r,st). | ||
|
||
.output VariableNodeParamType(delimiter=",") | ||
VariableNodeParamType(n,t,i,al) | ||
:- Node(n,t), NodeArgument(n,i,arg), Value(arg,al), AbstractLocation(al). | ||
VariableNodeParamType(n,t,i,st) | ||
:- Node(n,t), NodeArgument(n,i,arg), Value(arg,v), VariableSimpleType(v,st). | ||
VariableNodeParamType(n,t,i,ty) | ||
:- Value(n,n0), VariableNodeParamType(n0,t,i,ty). | ||
|
||
.output VariableNodeTag(delimiter=",") | ||
VariableNodeTag(n,t) :- Value(n,r), Node(r,t). | ||
|
||
.output VariableAbstractLocation(delimiter=",") | ||
VariableAbstractLocation(n,n) :- AbstractLocation(n). | ||
VariableAbstractLocation(n,v) :- Value(n,v), AbstractLocation(v). | ||
|
||
.decl FunName(f: Function) | ||
.output FunName(delimiter=",") | ||
|
||
.decl FunReturn(f:Function, n:Variable) | ||
.output FunReturn(delimiter=",") | ||
|
||
.decl FunParam(f:Function, i:number, n:Variable) | ||
.output FunParam(delimiter=",") | ||
|
||
FunName("main"). | ||
FunName(f) :- Call(_,f), ReachableCode(f). | ||
|
||
FunReturn(f,n) :- FunName(f), ReturnValue(f,n). | ||
FunReturn(f,n) :- External(f,_,_), Call(n,f). | ||
|
||
FunParam(f,i,p) :- FunctionParameter(f,i,p). | ||
FunParam(f,i,p) :- ExternalParam(f,i,_), Call(r,f), CallArgument(r,i,p). | ||
|
||
/* If a concrete instance of the abstract location may be subject to a fetch more than once, */ | ||
.decl SharedLocation(n:Variable) | ||
.output SharedLocation(delimiter=",") | ||
|
||
SharedLocation(l) :- | ||
AbstractLocation(l), Value(v,l), NonLinearVar(v). | ||
|
||
// For non-linear variables | ||
// A location may only become shared if it is a possible value of a nonlinear variable. | ||
// | ||
|
||
.decl AfterInst(b:Variable,a:Variable) | ||
.output AfterInst(delimiter=",") | ||
|
||
AfterInst(b,a) :- NextInst(b,a). | ||
AfterInst(b,c) :- AfterInst(b,a), NextInst(a,c). | ||
|
||
.decl NonLinearVar(v:Variable) | ||
.output NonLinearVar(delimiter=",") | ||
|
||
// Variable used in different use cases. | ||
// CA F M NP RV | ||
// CallArgument CA -- - x xx xx | ||
// Move M -- - - xx xx | ||
// NodeParameter NP -- - - -- xx | ||
// ReturnValue RV -- - - -- -- | ||
|
||
NonLinearVar(n) :- CallArgument(f,_,n), CallArgument(g,_,n), !(f=g). | ||
NonLinearVar(n) :- CallArgument(_,i,n), CallArgument(_,j,n), !(i=j). | ||
NonLinearVar(n) :- CallArgument(_,_,n), Move(_,n). | ||
NonLinearVar(n) :- CallArgument(_,_,n), NodeArgument(_,_,n). | ||
NonLinearVar(n) :- CallArgument(_,_,n), ReturnValue(_,n). | ||
NonLinearVar(n) :- Fetch(r,n), Fetch(q,n), !(r=q). | ||
NonLinearVar(n) :- Update(_,v0,n), Fetch(_,v1), AfterInst(v0,v1). | ||
NonLinearVar(n) :- Move(_,n), NodeArgument(_,_,n). | ||
NonLinearVar(n) :- Move(_,n), ReturnValue(_,n). | ||
NonLinearVar(n) :- NodeParameter(_,_,n), ReturnValue(_,n). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.