Skip to content

Commit c957125

Browse files
committed
Syntax and parsing of unique specifier
1 parent 99d9cc5 commit c957125

File tree

9 files changed

+73
-5
lines changed

9 files changed

+73
-5
lines changed

examples/concepts/unique/arrays.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
/*@
3+
context_everywhere x0 != NULL ** \pointer_length(x0) == n ** (\forall* int i; 0<=i && i<n; Perm(&x0[i], write));
4+
context_everywhere x1 != NULL ** \pointer_length(x1) == n ** (\forall* int i; 0<=i && i<n; Perm(&x1[i], 1\2));
5+
context_everywhere x2 != NULL ** \pointer_length(x2) == n ** (\forall* int i; 0<=i && i<n; Perm(&x2[i], 1\2));
6+
ensures (\forall int i; 0<=i && i<n; x0[i] == x1[i] + x2[i] );
7+
@*/
8+
int main(int n, /*@ unique<1> @*/ int* x0, /*@ unique<1> @*/ /*@ unique<2> @*/ int* x1, /*@ unique<2> @*/ int* x2){
9+
/*@
10+
loop_invariant 0 <= j && j <= n;
11+
loop_invariant (\forall int i; 0<=i && i<j; x0[i] == x1[i] + x2[i] );
12+
@*/
13+
for(int j=0; j<n; j++){
14+
x0[j] = x1[j] + x2[j];
15+
}
16+
}

src/col/vct/col/ast/Node.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,6 +2489,8 @@ final case class CPure[G]()(implicit val o: Origin)
24892489
extends CSpecificationModifier[G] with CPureImpl[G]
24902490
final case class CInline[G]()(implicit val o: Origin)
24912491
extends CSpecificationModifier[G] with CInlineImpl[G]
2492+
final case class CUnique[G](i: BigInt)(implicit val o: Origin)
2493+
extends CSpecificationModifier[G] with CUniqueImpl[G]
24922494

24932495
sealed trait CStorageClassSpecifier[G]
24942496
extends CDeclarationSpecifier[G] with CStorageClassSpecifierImpl[G]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package vct.col.ast.lang.c
2+
3+
import vct.col.ast.CUnique
4+
import vct.col.ast.ops.CUniqueOps
5+
import vct.col.print._
6+
7+
trait CUniqueImpl[G] extends CUniqueOps[G] { this: CUnique[G] =>
8+
override def layout(implicit ctx: Ctx): Doc = Doc.inlineSpec(Text("unique<") <> i.toString() <> ">")
9+
}

src/parsers/antlr4/SpecLexer.g4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ VAL_STRING: 'string';
5858
VAL_PURE: 'pure';
5959
VAL_THREAD_LOCAL: 'thread_local';
6060
VAL_BIP_ANNOTATION: 'bip_annotation';
61+
VAL_UNIQUE: 'unique';
6162

6263
VAL_WITH: 'with';
6364
VAL_THEN: 'then';

src/parsers/antlr4/SpecParser.g4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ valImpureDef
417417
valModifier
418418
: ('pure' | 'inline' | 'thread_local' | 'bip_annotation')
419419
| langStatic # valStatic
420+
| 'unique' '<' langConstInt '>' # valUnique
420421
;
421422

422423
valArgList

src/parsers/vct/parsers/transform/CToCol.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,13 @@ case class CToCol[G](
168168
else if (m.consume(m.inline))
169169
CInline[G]()
170170
else
171+
m.consume(m.unique).map(CUnique[G](_)).getOrElse(
172+
171173
fail(
172174
m.nodes.head,
173175
"This modifier cannot be attached to a declaration in C",
174176
)
177+
)
175178
},
176179
)
177180
}
@@ -1183,6 +1186,7 @@ case class CToCol[G](
11831186
case "thread_local" => collector.threadLocal += mod
11841187
}
11851188
case ValStatic(_) => collector.static += mod
1189+
case ValUnique(_, _, i, _) => collector.unique += ((mod, convert(i)))
11861190
}
11871191

11881192
def convertEmbedWith(

src/parsers/vct/parsers/transform/ToCol.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,22 @@ abstract class ToCol[G](
130130
val static: mutable.ArrayBuffer[ParserRuleContext] = mutable.ArrayBuffer()
131131
val bipAnnotation: mutable.ArrayBuffer[ParserRuleContext] = mutable
132132
.ArrayBuffer()
133+
val unique: mutable.ArrayBuffer[(ParserRuleContext, BigInt)] = mutable
134+
.ArrayBuffer()
133135

134136
def consume(buffer: mutable.ArrayBuffer[ParserRuleContext]): Boolean = {
135137
val result = buffer.nonEmpty
136138
buffer.clear()
137139
result
138140
}
139141

142+
def consume(buffer: mutable.ArrayBuffer[(ParserRuleContext, BigInt)]): Option[BigInt] = {
143+
buffer match {
144+
case mutable.ArrayBuffer() => None
145+
case (_, i) +: _ => buffer.clear(); Some(i)
146+
}
147+
}
148+
140149
def nodes: Seq[ParserRuleContext] =
141150
Seq(pure, inline, threadLocal, static, bipAnnotation).flatten
142151
}

src/rewrite/vct/rewrite/lang/LangCToCol.scala

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ case object LangCToCol {
3030
example.o.messageInContext("Global variables in C are not supported.")
3131
}
3232

33+
case class CDeclarationSpecifierNotSupported(spec: CDeclarationSpecifier[_]) extends UserError {
34+
override def code: String = "notSupportedTypeDecl"
35+
override def text: String =
36+
spec.o.messageInContext("This decleration specifier is not supported.")
37+
}
38+
3339
case class MultipleSharedMemoryDeclaration(decl: Node[_]) extends UserError {
3440
override def code: String = "multipleSharedMemoryDeclaration"
3541
override def text: String =
@@ -860,22 +866,36 @@ case class LangCToCol[Pre <: Generation](rw: LangSpecificToCol[Pre])
860866
var extern = false
861867
var innerType: Option[Type[Pre]] = None
862868
var arraySize: Option[Expr[Pre]] = None
869+
var mainType: Option[Type[Pre]] = None
870+
863871
var sizeBlame: Option[Blame[ArraySizeError]] = None
872+
var pure = false
873+
var inline = false
874+
var unique: Option[BigInt] = None
875+
var static = false
864876

865877
specs.foreach {
866878
case GPULocal() => shared = true
867879
case GPUGlobal() => global = true
868-
case CSpecificationType(CTPointer(t)) =>
880+
case CSpecificationType(t@CTPointer(it)) =>
869881
arrayOrPointer = true
870-
innerType = Some(t)
882+
innerType = Some(it)
883+
mainType = Some(t)
871884
case CSpecificationType(ctarr @ CTArray(size, t)) =>
872885
arraySize = size
873886
innerType = Some(t)
874887
sizeBlame = Some(
875888
ctarr.blame
876889
) // we set the blame here, together with the size
877890
arrayOrPointer = true
891+
mainType = Some(t)
892+
case CSpecificationType(t) =>
893+
mainType = Some(t)
878894
case CExtern() => extern = true
895+
case CUnique(i) => unique = Some(i)
896+
case CPure() => pure = true
897+
case CInline() => inline = true
898+
case CStatic() => static = true
879899
case _ =>
880900
}
881901

@@ -894,7 +914,6 @@ case class LangCToCol[Pre <: Generation](rw: LangSpecificToCol[Pre])
894914
}
895915

896916
def addStaticShared(
897-
decl: CDeclarator[Pre],
898917
cRef: CNameTarget[Pre],
899918
t: Type[Pre],
900919
o: Origin,
@@ -942,7 +961,6 @@ case class LangCToCol[Pre <: Generation](rw: LangSpecificToCol[Pre])
942961
!prop.extern
943962
) {
944963
addStaticShared(
945-
init.decl,
946964
cRef,
947965
prop.innerType.get,
948966
varO,
@@ -958,7 +976,6 @@ case class LangCToCol[Pre <: Generation](rw: LangSpecificToCol[Pre])
958976
!prop.extern
959977
) {
960978
addStaticShared(
961-
init.decl,
962979
cRef,
963980
prop.innerType.get,
964981
varO,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package vct.test.integration.examples
2+
3+
import vct.test.integration.helper.VercorsSpec
4+
5+
class UniqueFieldsSpec extends VercorsSpec {
6+
vercors should verify using silicon example "concepts/unique/arrays.c"
7+
8+
vercors should error withCode "???" in """int main(/*@ unique<1> @*/ /*@ unique<2> @*/ int* x0){}"""
9+
}

0 commit comments

Comments
 (0)