Skip to content

Commit bb61f7f

Browse files
katrinafyiailrst
andcommitted
blah procedure param big fix !!!
Co-authored-by: am <[email protected]>
1 parent ffa7614 commit bb61f7f

File tree

4 files changed

+125
-38
lines changed

4 files changed

+125
-38
lines changed

src/main/scala/ir/transforms/ProcedureParameters.scala

Lines changed: 104 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ def liftProcedureCallAbstraction(ctx: util.IRContext): util.IRContext = {
160160

161161
while (removeDeadInParams(ctx.program)) {}
162162

163-
ctx.copy(specification = specToProcForm(ctx.specification, formalParams.mappingInparam, formalParams.mappingOutparam))
163+
ctx.program.procedures.foreach(SpecFixer.updateInlineSpec(formalParams.mappingInparam, formalParams.mappingOutparam))
164+
ctx.copy(specification = SpecFixer.specToProcForm(ctx.specification, formalParams.mappingInparam, formalParams.mappingOutparam))
164165
}
165166

166167
def clearParams(p: Program) = {
@@ -395,22 +396,25 @@ def inOutParams(
395396

396397
val alwaysReturnParams = (0 to 7).map(i => Register(s"R$i", 64))
397398

399+
400+
val pc = Register("_PC", 64)
401+
398402
val inout = readWrites.collect {
399403
case (proc, rws) if p.mainProcedure == proc => {
400404
// no callers of main procedure so keep the whole read/write set
401405
// of registers
402406

403407
val outParams = (overapprox.intersect(DefinedOnAllPaths.proc(proc)))
404408
val inParams = lives(proc)._1
405-
proc -> (inParams, outParams)
409+
proc -> (inParams + pc, outParams + pc)
406410
}
407411
case (proc, rws) => {
408412
val liveStart = lives(proc)._1
409413
val liveEnd = lives(proc)._2 ++ alwaysReturnParams
410414

411415
val outParams = liveEnd.intersect(rws.writes)
412416
val inParams = liveStart
413-
proc -> (inParams, outParams)
417+
proc -> (inParams + pc, outParams + pc)
414418
}
415419
}.toMap
416420

@@ -540,18 +544,49 @@ class SetActualParams(
540544

541545
}
542546

543-
def specToProcForm(
544-
spec: Specification,
545-
mappingInparam: Map[Procedure, Map[LocalVar, Variable]],
546-
mappingOutparam: Map[Procedure, Map[LocalVar, Variable]]
547-
): Specification = {
547+
548+
object SpecFixer {
548549
import boogie.*
549550

550-
def toNameMapping(v: Map[LocalVar, Variable]): Map[String, String] = {
551-
v.map(v => (v._2.name, v._1.name)) ++ v.map(v => ("Gamma_" + v._2.name, "Gamma_" + v._1.name))
551+
class ExprToOld(varInPre: Map[String, Variable], varInPost: Map[String, Variable],
552+
initIsPost: Boolean = false) extends CILVisitor {
553+
554+
var isPost = initIsPost
555+
556+
override def vexpr(e : Expr) = e match {
557+
case OldExpr(inner) if !isPost => {
558+
throw Exception("nested Old or Old in single-state context")
559+
}
560+
case OldExpr(inner) if isPost => {
561+
isPost = false
562+
ChangeDoChildrenPost(inner, e => {
563+
isPost = true
564+
e
565+
})
566+
}
567+
case _ => DoChildren()
568+
}
569+
570+
def changeVar(v: Variable) = {
571+
val repl = v match {
572+
case l: Variable if isPost && varInPost.contains(l.name) => varInPost(l.name)
573+
case l: Variable if varInPre.contains(l.name) => varInPre(l.name)
574+
case o => o
575+
}
576+
ChangeTo(repl)
577+
}
578+
579+
override def vlvar(v: Variable) = changeVar(v)
580+
override def vrvar(v: Variable) = changeVar(v)
581+
582+
}
583+
584+
def convVarToOldExpr(varInPre: Map[String, Variable], varInPost: Map[String, Variable], isPost: Boolean = false)(
585+
b: Expr
586+
) : Expr = {
587+
val visitor = ExprToOld(varInPre, varInPost, isPost)
588+
visit_expr(visitor, b)
552589
}
553-
val varToInVar: Map[String, Map[String, String]] = mappingInparam.map(p => (p._1.procName -> toNameMapping(p._2)))
554-
val varToOutVar: Map[String, Map[String, String]] = mappingOutparam.map(p => (p._1.procName -> toNameMapping(p._2)))
555590

556591
def convVarToOld(varInPre: Map[String, String], varInPost: Map[String, String], isPost: Boolean = false)(
557592
b: BExpr
@@ -560,7 +595,10 @@ def specToProcForm(
560595
b match {
561596
case b: BVariable if isPost && varInPost.contains(b.name) => BVariable(varInPost(b.name), b.getType, b.scope)
562597
case b: BVariable if !isPost && varInPre.contains(b.name) => BVariable(varInPre(b.name), b.getType, b.scope)
563-
case b: BVar => b
598+
case b: BVariable if !isPost =>
599+
println("sad")
600+
println(b)
601+
b
564602
// case b : _ => varToOld(b)
565603
case b: BLiteral => b
566604
case b: BVExtract => b.copy(body = varToOld(b.body))
@@ -590,20 +628,61 @@ def specToProcForm(
590628
case b: GammaStore => b.copy(index = varToOld(b.index), value = varToOld(b.value))
591629
case b: L => b.copy(index = varToOld(b.index))
592630
case b: SpecVar => b
631+
case b: BVar =>
632+
println(b)
633+
???
593634
}
594635
}
595636

596-
val ns = spec.copy(subroutines = spec.subroutines.map(s => {
597-
if (s.requires.nonEmpty || s.ensures.nonEmpty) {
598-
val in = varToInVar(s.name)
599-
val out = varToOutVar(s.name)
600-
s.copy(
601-
requires = s.requires.map(convVarToOld(in, out, false)),
602-
ensures = s.ensures.map(convVarToOld(in, out, true))
603-
)
604-
} else {
605-
s
637+
def updateInlineSpec(
638+
mappingInparam: Map[Procedure, Map[LocalVar, Variable]],
639+
mappingOutparam: Map[Procedure, Map[LocalVar, Variable]])(p: Procedure) = {
640+
641+
642+
def toNameMapping(v: Map[LocalVar, Variable]): Map[String, String] = {
643+
v.map(v => (v._2.name, v._1.name)) ++ v.map(v => ("Gamma_" + v._2.name, "Gamma_" + v._1.name))
606644
}
607-
}))
608-
ns
645+
646+
val varToInVar = mappingInparam.map(p => (p._1 -> toNameMapping(p._2)))
647+
val varToOutVar = mappingOutparam.map(p => (p._1 -> toNameMapping(p._2)))
648+
649+
p.requires = p.requires.map(convVarToOld(varToInVar(p), varToOutVar(p), false))
650+
p.ensures = p.ensures.map(convVarToOld(varToInVar(p), varToOutVar(p), true))
651+
652+
def toVarMapping(v: Map[LocalVar, Variable]): Map[String, Variable] = {
653+
v.map(v => (v._2.name, v._1))
654+
}
655+
656+
p.requiresExpr = p.requiresExpr.map(convVarToOldExpr(toVarMapping(mappingInparam(p)), toVarMapping(mappingOutparam(p)), false))
657+
p.ensuresExpr = p.ensuresExpr.map(convVarToOldExpr(toVarMapping(mappingInparam(p)), toVarMapping(mappingOutparam(p)), true))
658+
659+
}
660+
661+
def specToProcForm(
662+
spec: Specification,
663+
mappingInparam: Map[Procedure, Map[LocalVar, Variable]],
664+
mappingOutparam: Map[Procedure, Map[LocalVar, Variable]]
665+
): Specification = {
666+
667+
def toNameMapping(v: Map[LocalVar, Variable]): Map[String, String] = {
668+
v.map(v => (v._2.name, v._1.name)) ++ v.map(v => ("Gamma_" + v._2.name, "Gamma_" + v._1.name))
669+
}
670+
val varToInVar: Map[String, Map[String, String]] = mappingInparam.map(p => (p._1.procName -> toNameMapping(p._2)))
671+
val varToOutVar: Map[String, Map[String, String]] = mappingOutparam.map(p => (p._1.procName -> toNameMapping(p._2)))
672+
673+
val ns = spec.copy(subroutines = spec.subroutines.map(s => {
674+
if (s.requires.nonEmpty || s.ensures.nonEmpty) {
675+
val in = varToInVar(s.name)
676+
val out = varToOutVar(s.name)
677+
s.copy(
678+
requires = s.requires.map(convVarToOld(in, out, false)),
679+
ensures = s.ensures.map(convVarToOld(in, out, true))
680+
)
681+
} else {
682+
s
683+
}
684+
}))
685+
ns
686+
}
609687
}
688+

src/main/scala/ir/transforms/Simp.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,11 @@ class GuardVisitor(validate: Boolean = false) extends CILVisitor {
567567

568568
/**
569569
*
570-
* This takes all variables in guards and substitutes them for their definitions IFF they have
570+
* This takes all variables in guards and substitutes them for their definitions IFF they have
571571
* exactly one definition (Assuming DSA form).
572572
*
573573
* Due to dsa form this heuristic alone should prevent any copies across loop iterations / clobbers etc
574-
* because transitively all definitions should dominate the use (the assume statement) we are propagating to.
574+
* because transitively all definitions should dominate the use (the assume statement) we are propagating to.
575575
*
576576
* The [[validate]] parameter further checks this is the case by checking the dsa property is preserved
577577
* by the propagation, by checking the reaching-definitions set at the use site.
@@ -884,11 +884,13 @@ def removeInvariantOutParameters(
884884
val proc = ret.parent.parent
885885
val inParams = proc.formalInParam.toSet
886886

887+
val specDependencies : Set[Variable] = proc.ensuresExpr.flatMap(_.variables).toSet
888+
887889
val doneAlready = alreadyInlined.getOrElse(proc, Set())
888890
var doneNow = Set[Variable]()
889891
var toRename = Map[Variable, LocalVar]()
890892

891-
val invariantParams = ret.outParams.collect {
893+
val invariantParams = ret.outParams.filterNot(x => specDependencies.contains(x._1)).collect {
892894
// we are returning a constant and can inline
893895
case (formalOut, binding: Literal) => (formalOut, binding)
894896
// we are returning the input parameter with the same name as the output parameter so can inline at callsite
@@ -1461,7 +1463,7 @@ class ExprComplexity extends CILVisitor {
14611463
* @param complexityThreshold
14621464
* Stop substituting after the AST node count has increased by this much
14631465
*
1464-
* TODO: The recursive substitution here is a broken when res produces substitution loops.
1466+
* TODO: The recursive substitution here is a broken when res produces substitution loops.
14651467
* I want a substituter that takes a set of replacements to a canonical
14661468
* closure under substitution, but is more subtle to implement than it initially appears.
14671469
* One possibility is a union find on the set of rewrites to partition cycles it into canonical representative

src/main/scala/translating/IRToBoogieNoVC.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ object BoogieTranslator {
113113
e.name,
114114
inparams,
115115
outparams,
116-
e.requires ++ e.requiresExpr.map(translateExpr),
117116
e.ensures ++ e.ensuresExpr.map(translateExpr),
117+
e.requires ++ e.requiresExpr.map(translateExpr),
118118
List(),
119119
List(),
120120
freeEnsures.toList,
@@ -149,18 +149,21 @@ object BoogieTranslator {
149149
val vvis = FindVars()
150150
visit_prog(vvis, p)
151151

152-
val globalVarDecls = vvis.globals.map(translateGlobal).map(BVarDecl(_))
153152

154153
val readOnlySections = p.usedMemory.values.filter(_.readOnly)
155154
val readOnlyMemory = memoryToConditionCoalesced(readOnlySections)
156155
val initialSections = p.usedMemory.values.filter(!_.readOnly)
157156
val initialMemory = memoryToConditionCoalesced(initialSections)
158157

158+
val memGlobals = (readOnlyMemory ++ initialMemory).flatMap(_.globals).map(BVarDecl(_))
159+
val globalVarDecls = vvis.globals.map(translateGlobal).map(BVarDecl(_)) ++ memGlobals
160+
159161
val procs = p.procedures.map {
160162
case proc if p.mainProcedure eq proc => translateProc(initialMemory ++ readOnlyMemory)(proc)
161163
case proc => translateProc(readOnlyMemory)(proc)
162164
}
163165

166+
164167
val functionOpDefinitions = functionOpToDecl(globalVarDecls ++ procs)
165168
val decls = globalVarDecls.toList ++ functionOpDefinitions ++ procs
166169

src/main/scala/util/RunUtils.scala

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,22 +1166,25 @@ object RunUtils {
11661166
val pcSubSpecs = proceduresWithPCs
11671167
.map((proc, addr) => {
11681168
// XXX: this does NOT work with parameter form! because the variables are changed
1169-
val pcVar = BVariable("_PC", BitVecBType(64), Scope.Global)
1170-
val r30Var = BVariable("R30", BitVecBType(64), Scope.Global)
1171-
val addrVar = BitVecBLiteral(addr, 64)
1172-
val pcRequires = BinaryBExpr(ir.EQ, pcVar, addrVar)
1173-
val pcEnsures = BinaryBExpr(ir.EQ, pcVar, Old(r30Var))
1169+
val pcVar = Register("_PC", (64))
1170+
val r30Var = Register("R30", (64))
1171+
val addrVar = BitVecLiteral(addr, 64)
1172+
val pcRequires = BinaryExpr(ir.EQ, pcVar, addrVar)
1173+
val pcEnsures = BinaryExpr(ir.EQ, pcVar, OldExpr(r30Var))
11741174

11751175
val name = proc.procName
1176-
(name -> SubroutineSpec(name, requires = List(pcRequires), ensures = List(pcEnsures)))
1176+
proc.requiresExpr = pcRequires +: proc.requiresExpr
1177+
proc.ensuresExpr = pcEnsures +: proc.ensuresExpr
1178+
(name -> SubroutineSpec(name, requires = List(), ensures = List()))
11771179
})
11781180
.toMap
11791181

11801182
val subSpecs = spec.subroutines.map(x => x.name -> x).toMap
11811183

11821184
val newSubroutineSpecs = util.functional.unionWith(pcSubSpecs, subSpecs, _ merge _)
11831185

1184-
spec.copy(subroutines = newSubroutineSpecs.values.toList)
1186+
// spec.copy(subroutines = newSubroutineSpecs.values.toList)
1187+
spec
11851188
}
11861189
}
11871190

0 commit comments

Comments
 (0)