Skip to content

Commit bbf73eb

Browse files
authored
Merge branch 'master' into trace-ensuring-newspecs
2 parents 2b3cc53 + a4d70fd commit bbf73eb

40 files changed

+495
-201
lines changed

core/src/main/scala/stainless/ast/ExprOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ trait ExprOps extends inox.ast.ExprOps { self =>
275275
withSpec(expr, pred.filterNot(_.body == BooleanLiteral(true)).map(Postcondition).toLeft(PostconditionKind))
276276

277277
final def withMeasure(expr: Expr, measure: Option[Expr]): Expr =
278-
withSpec(expr, measure.map(Measure).toLeft(MeasureKind))
278+
withSpec(expr, measure.map(expr => Measure(expr).setPos(expr)).toLeft(MeasureKind))
279279

280280
/** Adds a body to a specification
281281
*

core/src/main/scala/stainless/extraction/package.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ package object extraction {
5757
"PartialEvaluation" -> "Partially evaluate marked function calls",
5858
"AssertionInjector" -> "Insert assertions which verify array accesses, casts, division by zero, etc.",
5959
"ChooseInjector" -> "Insert chooses where necessary",
60+
61+
"ComputeDependencies" -> "(GenC) Compute the dependencies of a given definition",
62+
"ComputeFunCtxPhase" -> "(GenC) Compute the context of each given function definition",
63+
"Scala2IRPhase" -> "(GenC) Convert the Stainless AST into GenC's IR",
64+
"StructInliningPhase" -> "(GenC) Inline structs which have just one member",
65+
"NormalisationPhase" -> "(GenC) Normalise IR to match the C execution model",
66+
"LiftingPhase" -> "(GenC) Lift class types to their hierarchy top class",
67+
"ReferencingPhase" -> "(GenC) Add 'referencing' to the input LIR program to produce a RIR program",
68+
"IR2CPhase" -> "(GenC) From IR to C",
6069
)
6170

6271
val phaseNames: Set[String] = phases.map(_._1).toSet

core/src/main/scala/stainless/genc/CAST.scala

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@ import ir.Literals._
2626
*/
2727
object CAST { // C Abstract Syntax Tree
2828

29-
sealed abstract class Tree
30-
29+
sealed abstract class Tree {
30+
override def toString = {
31+
val sb = new StringBuffer()
32+
new CPrinter("stainless.h", true, Set(), sb).print(this)
33+
sb.toString
34+
}
35+
}
3136

3237
/* ----------------------------------------------------- Definitions ----- */
3338
abstract class Def extends Tree
@@ -44,6 +49,7 @@ object CAST { // C Abstract Syntax Tree
4449
functions: Set[Fun]
4550
) extends Def {
4651
require(types.length == types.distinct.length) // no duplicates in `types`
52+
4753
}
4854

4955
// Manually defined function through the cCode.function annotation have a string
@@ -90,6 +96,8 @@ object CAST { // C Abstract Syntax Tree
9096
require(literals.nonEmpty)
9197
}
9298

99+
case class FixedArrayType(base: Type, length: Int) extends Type
100+
93101

94102
/* ------------------------------------------------------ Expressions ----- */
95103
abstract class Expr extends Tree

core/src/main/scala/stainless/genc/CASTDependencies.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class CASTTraverser(implicit ctx: inox.Context) {
2020
case FunType(ret, params) =>
2121
ret +: params
2222

23+
case FixedArrayType(base, _) =>
24+
Seq(base)
25+
2326
case Struct(id, fields, _) =>
2427
id +: fields
2528

core/src/main/scala/stainless/genc/CFileOutputPhase.scala

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ import java.io.File
77
import java.io.FileWriter
88
import java.io.BufferedWriter
99

10-
object CFileOutputPhase extends UnitPhase[CAST.Prog] {
10+
trait CFileOutputPhase extends UnitPhase[CAST.Prog] {
1111

1212
val name = "C File Output"
1313
val description = "Output converted C program to the specified file (default leon.c)"
1414

15-
def apply(ctx: inox.Context, program: CAST.Prog) {
16-
val timer = ctx.timers.genc.print.start()
15+
def apply(program: CAST.Prog) {
16+
val timer = context.timers.genc.print.start()
1717

1818
// Get the output file name from command line options, or use default
19-
val cFileName = ctx.options.findOptionOrDefault(optOutputFile)
19+
val cFileName = context.options.findOptionOrDefault(optOutputFile)
2020
val cOutputFile = new File(cFileName)
2121
val hFileName = cFileName.stripSuffix(".c") + ".h"
2222
val hOutputFile = new File(hFileName)
@@ -27,15 +27,15 @@ object CFileOutputPhase extends UnitPhase[CAST.Prog] {
2727
parent.mkdirs()
2828
}
2929
} catch {
30-
case _ : java.io.IOException => ctx.reporter.fatalError("Could not create directory " + parent)
30+
case _ : java.io.IOException => context.reporter.fatalError("Could not create directory " + parent)
3131
}
3232

3333
// Output C code to the file
3434
try {
3535
val cout = new BufferedWriter(new FileWriter(cOutputFile))
3636
val hout = new BufferedWriter(new FileWriter(hOutputFile))
3737

38-
val headerDependencies = CASTDependencies.headerDependencies(program)(ctx)
38+
val headerDependencies = CASTDependencies.headerDependencies(program)(context)
3939

4040
val ph = new CPrinter(hFileName, false, headerDependencies)
4141
ph.print(program)
@@ -47,12 +47,18 @@ object CFileOutputPhase extends UnitPhase[CAST.Prog] {
4747
cout.write(pc.sb.toString)
4848
cout.close()
4949

50-
ctx.reporter.info(s"Output written to $hOutputFile and $cOutputFile")
50+
context.reporter.info(s"Output written to $hOutputFile and $cOutputFile")
5151
} catch {
52-
case _ : java.io.IOException => ctx.reporter.fatalError("Could not write C ouptut on " + cOutputFile)
52+
case _ : java.io.IOException => context.reporter.fatalError("Could not write C ouptut on " + cOutputFile)
5353
}
5454

5555
timer.stop()
5656
}
5757

5858
}
59+
60+
object CFileOutputPhase {
61+
def apply(implicit ctx: inox.Context): LeonPipeline[CAST.Prog, CAST.Prog] = new {
62+
val context = ctx
63+
} with CFileOutputPhase
64+
}

core/src/main/scala/stainless/genc/CPrinter.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ class CPrinter(
260260
case StaticStorage(_) => c"static "
261261

262262
case TypeId(FunType(ret, params), id) => c"$ret (*$id)($params)"
263+
case TypeId(FixedArrayType(base, length), id) => c"$base $id[$length]"
263264
case TypeId(typ, id) => c"$typ $id"
264265

265266
case FunSign(Fun(id, FunType(retret, retparamTypes), params, _, _)) =>

core/src/main/scala/stainless/genc/GenCComponent.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import utils.{CheckFilter, DefinitionIdFinder, DependenciesFinder}
99
import extraction.xlang.{trees => xt}
1010
import extraction.throwing.{trees => tt}
1111
import extraction._
12-
// import inox.evaluators.EvaluationResults.{ EvaluatorError, RuntimeError, Successful }
1312

1413
import stainless.utils.JsonConvertions._
1514

@@ -18,7 +17,6 @@ import io.circe.syntax._
1817
import io.circe.generic.semiauto._
1918

2019
import scala.concurrent.Future
21-
// import scala.util.{ Success, Failure }
2220

2321
import scala.language.existentials
2422

@@ -86,7 +84,7 @@ class GenCRun(override val pipeline: extraction.StainlessPipeline) // pipeline i
8684

8785
val symbolsAfterPipeline: tt.Symbols = pipelineBegin.extract(filtered)
8886

89-
GenerateCPhase.run(context, symbolsAfterPipeline)
87+
GenerateC.run(symbolsAfterPipeline)
9088

9189
val p = inox.Program(trees)(filtered)
9290

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* Copyright 2009-2021 EPFL, Lausanne */
2+
3+
package stainless
4+
package genc
5+
6+
import extraction.throwing.trees._
7+
8+
import phases._
9+
10+
object GenerateC {
11+
12+
def pipeline(implicit ctx: inox.Context) =
13+
NamedLeonPhase("ComputeDependencies", ComputeDependenciesPhase(ctx)) andThen
14+
NamedLeonPhase("ComputeFunCtxPhase", LeonPipeline.both(NoopPhase[Dependencies], ComputeFunCtxPhase(ctx))) andThen
15+
NamedLeonPhase("Scala2IRPhase", Scala2IRPhase(ctx)) andThen
16+
NamedLeonPhase("NormalisationPhase", NormalisationPhase(ctx)) andThen
17+
NamedLeonPhase("LiftingPhase", LiftingPhase(ctx)) andThen
18+
NamedLeonPhase("ReferencingPhase", ReferencingPhase(ctx)) andThen
19+
NamedLeonPhase("StructInliningPhase", StructInliningPhase(ctx)) andThen
20+
NamedLeonPhase("IR2CPhase", IR2CPhase(ctx)) andThen
21+
CFileOutputPhase(ctx)
22+
23+
def run(symbols: Symbols)(implicit ctx: inox.Context) = pipeline.run(symbols)
24+
25+
}

core/src/main/scala/stainless/genc/GenerateCPhase.scala

Lines changed: 0 additions & 30 deletions
This file was deleted.

core/src/main/scala/stainless/genc/LeonPhase.scala

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,67 @@
22

33
package stainless.genc
44

5+
import stainless.extraction.utils._
6+
57
trait NamedLeonPhase[F, T] extends LeonPipeline[F, T] {
68
val underlying: LeonPipeline[F, T]
79
val name: String
810

9-
private implicit val debugSection = DebugSectionGenC
11+
lazy val phases = context.options.findOption(optDebugPhases).map(_.toSet)
12+
13+
lazy val debugTrees: Boolean =
14+
(phases.isEmpty || phases.exists(_.contains(name))) &&
15+
context.reporter.debugSections.contains(DebugSectionTrees)
1016

11-
override def run(ctx: inox.Context, p: F): T = {
12-
ctx.reporter.debug("\n" * 2)
13-
ctx.reporter.debug("=" * 100)
14-
ctx.reporter.debug(s"Running phase $name on")
15-
ctx.reporter.debug(p)
16-
val res = ctx.timers.genc.get(name).run {
17-
underlying.run(ctx, p)
17+
private implicit val debugSection = DebugSectionTrees
18+
19+
override def run(p: F): T = {
20+
if (debugTrees) {
21+
context.reporter.debug("\n" * 2)
22+
context.reporter.debug("=" * 100)
23+
context.reporter.debug(s"Running phase $name on:\n")
24+
context.reporter.debug(p)
25+
}
26+
val res = context.timers.genc.get(name).run {
27+
underlying.run(p)
28+
}
29+
if (debugTrees) {
30+
context.reporter.debug("\n")
31+
context.reporter.debug("-" * 100)
32+
context.reporter.debug(s"Finished running phase $name:\n")
33+
context.reporter.debug(res)
34+
context.reporter.debug("=" * 100)
35+
context.reporter.debug("\n" * 4)
1836
}
19-
ctx.reporter.debug(s"Finished running phase $name")
20-
ctx.reporter.debug(res)
21-
ctx.reporter.debug("=" * 100)
22-
ctx.reporter.debug("\n" * 4)
2337
res
2438
}
2539
}
2640

2741
object NamedLeonPhase {
2842

29-
def apply[F, T](s: String, pipeline: LeonPipeline[F, T]): LeonPipeline[F, T] {
43+
def apply[F, T](s: String, pipeline: LeonPipeline[F, T])(implicit ctx: inox.Context): LeonPipeline[F, T] {
3044
} = new {
3145
override val underlying: pipeline.type = pipeline
3246
override val name: String = s
47+
override val context = ctx
3348
} with NamedLeonPhase[F, T]
3449
}
3550

36-
abstract class UnitPhase[T] extends LeonPipeline[T, T] {
37-
def apply(ctx: inox.Context, p: T): Unit
51+
trait UnitPhase[T] extends LeonPipeline[T, T] {
52+
def apply(p: T): Unit
3853

39-
override def run(ctx: inox.Context, p: T) = {
40-
apply(ctx, p)
54+
override def run(p: T) = {
55+
apply(p)
4156
p
4257
}
4358
}
4459

45-
case class NoopPhase[T]() extends LeonPipeline[T, T] {
46-
override def run(ctx: inox.Context, v: T) = v
60+
object NoopPhase {
61+
def apply[T](implicit ctx: inox.Context): LeonPipeline[T, T] = {
62+
new {
63+
override val context = ctx
64+
} with LeonPipeline[T, T] {
65+
override def run(v: T) = v
66+
}
67+
}
4768
}

0 commit comments

Comments
 (0)