Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize GenC annotations #1129

Merged
merged 1 commit into from
Jul 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/src/main/scala/stainless/genc/CAST.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ object CAST { // C Abstract Syntax Tree
case class Prog(
includes: Set[Include],
// boolean is set to true when for global declarations that are declared outside of the Stainless program
decls: Seq[(Decl, Boolean)],
decls: Seq[(Decl, DeclarationMode)],
typeDefs: Set[TypeDef],
enums: Set[Enum],
types: Seq[DataType], // Both structs and unions, order IS important! See NOTE above.
Expand Down
11 changes: 7 additions & 4 deletions core/src/main/scala/stainless/genc/CPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ class CPrinter(
sep = "\n\n")
}
|${nary(
decls.filter(!_._2).map(_._1),
decls.filter(_._2 != External).map {
case (decl, Static) => StaticStorage(decl)
case (decl, Normal) => decl
case _ => sys.error("unreachable code")
},
opening = separator("global variables"),
closing = ";\n\n",
sep = ";\n")
Expand Down Expand Up @@ -269,8 +273,7 @@ class CPrinter(
}

private[genc] def pp(wt: WrapperTree)(implicit pctx: PrinterContext): Unit = wt match {
case StaticStorage(id) if id.name == "main" => /* Nothing */
case StaticStorage(_) => c"static "
case StaticStorage(decl) => c"static $decl"

case TypeId(FunType(ret, params), id) => c"$ret (*$id)($params)"
case TypeId(FixedArrayType(base, length), id) => c"$base $id[$length]"
Expand Down Expand Up @@ -316,7 +319,7 @@ class CPrinter(

/** Wrappers to distinguish how the data should be printed **/
private[genc] sealed abstract class WrapperTree
private case class StaticStorage(id: Id) extends WrapperTree
private case class StaticStorage(decl: Decl) extends WrapperTree
private case class TypeId(typ: Type, id: Id) extends WrapperTree
private case class FunSign(f: Fun) extends WrapperTree

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/stainless/genc/GenCComponent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class GenCRun(override val pipeline: extraction.StainlessPipeline) // pipeline i
override val results = ids.flatMap { id =>
val fd = symbols.getFunction(id)
val pos = fd.getPos.toString
if (fd.flags.exists(_.name == "export"))
if (fd.flags.exists(_.name == "cCode.export"))
Some(GenCRun.Result(fd, Compiled, 0))
else
None
Expand Down
3 changes: 1 addition & 2 deletions core/src/main/scala/stainless/genc/ir/IR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ private[genc] sealed trait IR { ir =>
sealed abstract class Def extends Tree

case class Prog(
// boolean is set to true when for global declarations that are declared outside of the Stainless program
decls: Seq[(Decl, Boolean)],
decls: Seq[(Decl, DeclarationMode)],
functions: Seq[FunDef],
classes: Seq[ClassDef]
) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/stainless/genc/ir/IRPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ final class IRPrinter[S <: IR](val ir: S) {
val post = ptx.newLine + "}"

(if (fd.isPure) "@pure\n" else "") +
(if (fd.isExported) "@export\n" else "") +
(if (fd.isExported) "@cCode.export\n" else "") +
pre + body + post
}

Expand Down
6 changes: 6 additions & 0 deletions core/src/main/scala/stainless/genc/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ package object genc {

// FIXME: see leon definition
def pathFromRoot(df: Definition)(implicit syms: Symbols): List[Definition] = List(df)

// declaration mode for global variables
sealed abstract class DeclarationMode
case object Normal extends DeclarationMode
case object Static extends DeclarationMode // static annotation
case object External extends DeclarationMode // no declaration in the produced code
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import ExtraOps._
import collection.mutable.{Set => MutableSet}

/*
* Compute the dependencies of the @export functions
* Generic functions cannot be marked @export (only specialized versions that are
* Compute the dependencies of the @cCode.export functions
* Generic functions cannot be marked @cCode.export (only specialized versions that are
* used by exported functions are exported to C).
*
* Moreover, the list of dependencies only contains top level functions. For nested
Expand All @@ -26,11 +26,6 @@ import collection.mutable.{Set => MutableSet}
* some type T, then T (and all its class hierarchy if T is a class) will be included
* in the dependency set.
*
* This phase also make sures @cCode.drop functions are not used. The same is *NOT*
* done for dropped types as they might still be present in function signature. They
* should be removed in a later (transformation) phase. Additionally, this phase
* ensures that the annotation set on class and function is sane.
*
* NOTE We cannot rely on purescala.DependencyFinder as it will traverse functions
* annotated with @cCode.function and we don't want that. The same applies for
* classes annotated with @cCode.typdef. We therefore implement a simpler version
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/stainless/genc/phases/ExtraOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private[genc] object ExtraOps {

def isExtern = fd.flags contains Extern
def isDropped = hasAnnotation("cCode.drop") || fd.flags.contains(Ghost)
def isExported = hasAnnotation("export")
def isExported = hasAnnotation("cCode.export")
def isManuallyDefined = hasAnnotation(manualDefAnnotation)

def extAnnotations: Map[String, Seq[Any]] = fd.flags.collect {
Expand Down Expand Up @@ -77,7 +77,7 @@ private[genc] object ExtraOps {
implicit class ClassDefOps(val cd: ClassDef) {
def isManuallyTyped = hasAnnotation(manualTypeAnnotation)
def isDropped = hasAnnotation(droppedAnnotation)
def isExported = hasAnnotation("export")
def isExported = hasAnnotation("cCode.export")
def isGlobal = cd.flags.exists(_.name.startsWith("cCode.global"))
def isGlobalDefault = cd.flags.exists(_.name == "cCode.global")
def isGlobalUninitialized = cd.flags.exists(_.name == "cCode.globalUninitialized")
Expand Down
14 changes: 8 additions & 6 deletions core/src/main/scala/stainless/genc/phases/Scala2IRPhase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private class S2IRImpl(val context: inox.Context, val ctxDB: FunCtxDB, val deps:
def run(): Unit = {
checkGlobalUsage()

// Start the transformation from `@exported` (and `@cCode.global`) functions and classes
// Start the transformation from `@cCode.export` (and `@cCode.global`) functions and classes
for (df <- deps.deps) {
df match {
case fd: FunDef if fd.isExported =>
Expand All @@ -123,7 +123,7 @@ private class S2IRImpl(val context: inox.Context, val ctxDB: FunCtxDB, val deps:
* Caches *
****************************************************************************************************/

var declResults = new scala.collection.mutable.ListBuffer[(CIR.Decl, Boolean)]()
var declResults = new scala.collection.mutable.ListBuffer[(CIR.Decl, DeclarationMode)]()

// For functions, we associate each TypedFunDef to a CIR.FunDef for each "type context" (TypeMapping).
// This is very important for (non-generic) functions nested in a generic function because for N
Expand Down Expand Up @@ -643,18 +643,20 @@ private class S2IRImpl(val context: inox.Context, val ctxDB: FunCtxDB, val deps:
s"We found ${paramInits.length} initializations instead of ${fields.length}."
)
}
for ((field, paramInit) <- fields.zip(paramInits)) {
for (((field, paramInit), static) <- fields.zip(paramInits).zip(nonGhostFields.map(vd => vd.flags.exists(_.name == "cCode.static")))) {
implicit val emptyEnv = Env(Map(), Map(), false)
val decl = (CIR.Decl(field, Some(rec(paramInit.fullBody))), false)
val decl = (CIR.Decl(field, Some(rec(paramInit.fullBody))), if (static) Static else Normal)
if (declResults.map(_._1.vd).contains(field)) {
reporter.fatalError(cd.getPos, s"Global variable ${field.id} is defined twice")
}
declResults.append(decl)
}
} else if (cd.isGlobalUninitialized) {
for (field <- fields) declResults.append((CIR.Decl(field, None), false))
for ((field, static) <- fields.zip(nonGhostFields.map(vd => vd.flags.exists(_.name == "cCode.static")))) {
declResults.append((CIR.Decl(field, None), if (static) Static else Normal))
}
} else if (cd.isGlobalExternal) {
for (field <- fields) declResults.append((CIR.Decl(field, None), true))
for (field <- fields) declResults.append((CIR.Decl(field, None), External))
}
newAcc
} else {
Expand Down
4 changes: 2 additions & 2 deletions core/src/sphinx/genc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ See below for a case class with a fixed length array and its transformation in C
val CONSTANT2: UInt16 = 12
val CONSTANT3: UInt16 = CONSTANT1 + CONSTANT2

@export
@cCode.export
case class W(x: Int, a: Array[Int], y: Int) {
require(
a.length == CONSTANT3.toInt &&
Expand Down Expand Up @@ -340,7 +340,7 @@ make sure that the instance is created using the default values:

.. code-block:: scala

@export
@cCode.export
def main() {
implicit val gs = GlobalState()
StdOut.print(gs.x)
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/ArgumentsEffects.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object ArgumentsEffects {
StdOut.println(x3)
}

@export
@cCode.export
def main(): Unit = {
var x = 0

Expand Down
8 changes: 4 additions & 4 deletions frontends/benchmarks/genc/FixedArray.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object FixedArray {
val CONSTANT2: UInt16 = 3
val CONSTANT3: UInt16 = CONSTANT1 + CONSTANT2

@export
@cCode.export
case class W(x: Int, a: Array[Int], y: Int) {
require(
a.length == CONSTANT3.toInt &&
Expand All @@ -17,7 +17,7 @@ object FixedArray {
)
}

@export
@cCode.export
def f(w: W): Int = {
require(0 <= w.a(0) && w.a(0) <= 1000)
require(0 <= w.a(1) && w.a(1) <= 1000)
Expand All @@ -30,15 +30,15 @@ object FixedArray {
w.a(0) + w.a(1) + w.a(2) + w.a(3) + w.a(4) + w.x + w.y
}

@export
@cCode.export
def g(a: Array[Int]): Unit = {
require(a.length > 0)
require(0 <= a(0) && a(0) <= 1000)

a(0) += 1
}

@export
@cCode.export
def main(): Unit = {
val w = W(30, Array(10, 20, 30, 20, 42), 100)
val w2 = W(30, Array(10, 20, 30, 20, 42), { w.a(0) += 1; 100 })
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object Global {
if (state.y > 0) move()
}.ensuring(_ => state.stable)

@export
@cCode.export
def main() {
implicit val gs = GlobalState()
StdOut.print(gs.x)
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/GlobalUninitialized.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object GlobalUninitialized {
if (state.y > 0) move()
}.ensuring(_ => state.stable)

@export
@cCode.export
def main() {
implicit val gs = GlobalState(Array.fill(100)(0), false, 0, 0)
gs.x = 8
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/ImageProcessing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ object ImageProcessing {
else StdOut.println("false")
}

@export
@cCode.export
def main(): Int = {
implicit val state = stainless.io.newState
val input = FIS.open("input.bmp")
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/LZWa.scala
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ object LZWa {
case _ => false
}

@export
@cCode.export
def main() = {
implicit val state = stainless.io.newState

Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/LZWb.scala
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ object LZWb {
case _ => false
}

@export
@cCode.export
def main() = {
implicit val state = stainless.io.newState

Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/Nested.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import stainless.io._

object Nested {

@export
@cCode.export
def main(): Int = {
f(100)
}
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/Normalisation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object Normalisation {
}
case class B(a1: A, i: UInt8, j: UInt32, a2: A)

@export
@cCode.export
def main(): Unit = {
val a = A(100, 9, 200)
val x = a.sum + a.sum
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/Pointer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object Pointer {
r2.x = 250
}

@export
@cCode.export
def main(): Unit = {
val r = Pointer(100)
val r2 = Pointer(100)
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/Return.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ object Return {
else StdOut.println("ERROR")
}

@export
@cCode.export
def main() = {
verify(return10 == 10)
verify(findIndex(Array(0,100,200,250), 0) == 0)
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/StateTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import stainless.lang._

object StateTest {

@export
@cCode.export
def main(): Int = {
implicit val state = stainless.io.newState
f()
Expand Down
4 changes: 2 additions & 2 deletions frontends/benchmarks/genc/TwoOptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import stainless.annotation._

object TwoOptions {

@export
@cCode.export
def twoOptions: Unit = {
var opt1: Option[Long] = None()
val opt2: Option[Int] = None()
opt1.isEmpty
opt2.isEmpty
}

@export
@cCode.export
def main() = {
}

Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/Unsigned.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import stainless.io._

object Unsigned {

@export
@cCode.export
def main(): Unit = {
val a = fa(16, 84)
val b = fb(84, 14)
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/genc/WhileInLet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import stainless.annotation._

object WhileInLet {

@export
@cCode.export
def main(): Unit = {
val noLoop = while (false) {}
()
Expand Down
2 changes: 1 addition & 1 deletion frontends/benchmarks/imperative/valid/LetTargets.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object LetTargets {
case class C(bs: Array[B])
case class D(val c: C)

@export
@cCode.export
def reset(d: D): Unit = {
require(d.c.bs.length > 0)
require(d.c.bs(0).as.length > 0)
Expand Down
4 changes: 0 additions & 4 deletions frontends/library/stainless/annotation/annotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,6 @@ class erasable extends Annotation
@ignore
class indexedAt(n: BigInt) extends Annotation

/** Export function to C for GenC translation */
@ignore
class export extends Annotation

@ignore
class refEq extends Annotation

Expand Down
Loading