Skip to content

Commit

Permalink
Run Souffle HPT
Browse files Browse the repository at this point in the history
  • Loading branch information
andorp committed May 1, 2020
1 parent 9887597 commit bc8f9d3
Show file tree
Hide file tree
Showing 8 changed files with 650 additions and 65 deletions.
340 changes: 340 additions & 0 deletions datalog/hpt/hpt.dl
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).
1 change: 1 addition & 0 deletions grin/app/CLI/Lib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ pipelineOpts =
<|> (T <$> transformOpts)
<|> flg ConfluenceTest "confluence-test" "Checks transformation confluence by generating random two pipelines which reaches the fix points."
<|> flg PrintErrors "print-errors" "Prints the error log"
<|> flg DatalogHPT "datalog-hpt" "Run HPT in souffle"


maybeRenderingOpt :: String -> Maybe RenderingOption
Expand Down
1 change: 1 addition & 0 deletions grin/grin.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ library
Transformations.ExtendedSyntax.Optimising.CSE
Transformations.ExtendedSyntax.Optimising.EvaluatedCaseElimination
Transformations.ExtendedSyntax.Optimising.TrivialCaseElimination
Transformations.ExtendedSyntax.Normalisation

Transformations.BindNormalisation
Transformations.CountVariableUse
Expand Down
Loading

0 comments on commit bc8f9d3

Please sign in to comment.