Skip to content

Commit

Permalink
gtirb: update grammar and loader in line with new format.
Browse files Browse the repository at this point in the history
  • Loading branch information
katrinafyi committed Mar 13, 2024
1 parent 5afc399 commit f2137d9
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 67 deletions.
51 changes: 29 additions & 22 deletions src/main/antlr4/Semantics.g4
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,59 @@ grammar Semantics;
// See aslp/libASL/asl.ott for reference grammar Bap-ali-plugin/asli_lifer.ml may also be useful for
// visitors

statements: QUOTE stmt QUOTE (COMMA QUOTE stmt QUOTE)*;

stmt: 'Stmt_Assign' OPEN_PAREN lexpr COMMA expr CLOSE_PAREN # Assign
| 'Stmt_ConstDecl' OPEN_PAREN type COMMA lvar=ID COMMA expr CLOSE_PAREN # ConstDecl
| 'Stmt_VarDecl' OPEN_PAREN type COMMA lvar=ID COMMA expr CLOSE_PAREN # VarDecl
| 'Stmt_ConstDecl' OPEN_PAREN type COMMA lvar=ident COMMA expr CLOSE_PAREN # ConstDecl
| 'Stmt_VarDecl' OPEN_PAREN type COMMA lvar=ident COMMA expr CLOSE_PAREN # VarDecl
| 'Stmt_VarDeclsNoInit' OPEN_PAREN type COMMA OPEN_BRACKET lvars CLOSE_BRACKET CLOSE_PAREN # VarDeclsNoInit
| 'Stmt_Assert' OPEN_PAREN expr CLOSE_PAREN # Assert
| 'Stmt_TCall' OPEN_PAREN name=ID COMMA OPEN_BRACKET tes=exprs? CLOSE_BRACKET COMMA OPEN_BRACKET args=exprs? CLOSE_BRACKET CLOSE_PAREN # TCall
| 'Stmt_If' OPEN_PAREN cond=expr COMMA OPEN_BRACKET stmt+ CLOSE_BRACKET COMMA OPEN_BRACKET CLOSE_BRACKET COMMA elseStmt? CLOSE_PAREN # If // theoretically some sort of 'Elsif' could be within the middle brackets?
| 'Stmt_Throw' OPEN_PAREN str=ID* CLOSE_PAREN # Throw
| 'Stmt_TCall' OPEN_PAREN name=ident COMMA OPEN_BRACKET tes=exprs? CLOSE_BRACKET COMMA OPEN_BRACKET args=exprs? CLOSE_BRACKET CLOSE_PAREN # TCall
| 'Stmt_If' OPEN_PAREN cond=expr COMMA OPEN_BRACKET thenStmts=stmts? CLOSE_BRACKET COMMA OPEN_BRACKET CLOSE_BRACKET COMMA OPEN_BRACKET elseStmts=stmts? CLOSE_BRACKET CLOSE_PAREN # If // ASLp transforms else-if into nested if/else statements.
| 'Stmt_Throw' OPEN_PAREN str=ident* CLOSE_PAREN # Throw
;

lvars: OPEN_PAREN ID CLOSE_PAREN (SCOLON OPEN_PAREN ID CLOSE_PAREN)* ;
statements: QUOTE stmt QUOTE (COMMA QUOTE stmt QUOTE)*;

lvars: ident (SCOLON ident)*;

exprs: OPEN_PAREN expr CLOSE_PAREN (SCOLON OPEN_PAREN expr CLOSE_PAREN)*;
exprs: expr (SCOLON expr)*;

elseStmt: OPEN_PAREN 'else' stmt+ CLOSE_PAREN;
stmts: stmt (SCOLON stmt)*;

type: 'Type_Bits' OPEN_PAREN size=expr CLOSE_PAREN # TypeBits
| 'Type_Constructor' OPEN_PAREN str=ID CLOSE_PAREN # TypeConstructor
| 'Type_Register' OPEN_PAREN QUOTE size=(DEC | BINARY) QUOTE COMMA regfield (COMMA regfield)* CLOSE_PAREN # TypeRegister
| 'Type_Constructor' OPEN_PAREN str=ident CLOSE_PAREN # TypeConstructor
| 'Type_Register' OPEN_PAREN QUOTE size=integer QUOTE COMMA regfield (COMMA regfield)* CLOSE_PAREN # TypeRegister
;

regfield: OPEN_PAREN OPEN_BRACKET slice CLOSE_BRACKET COMMA id=ID CLOSE_PAREN;
regfield: OPEN_PAREN OPEN_BRACKET slice CLOSE_BRACKET COMMA id=ident CLOSE_PAREN;

lexpr: 'LExpr_Var' OPEN_PAREN ID CLOSE_PAREN # LExprVar
| 'LExpr_Field' OPEN_PAREN lexpr COMMA field=ID CLOSE_PAREN # LExprField
lexpr: 'LExpr_Var' OPEN_PAREN ident CLOSE_PAREN # LExprVar
| 'LExpr_Field' OPEN_PAREN lexpr COMMA field=ident CLOSE_PAREN # LExprField
| 'LExpr_Array' OPEN_PAREN lexpr COMMA index=expr CLOSE_PAREN # LExprArray
;

expr: 'Expr_Var' OPEN_PAREN ID CLOSE_PAREN # ExprVar
| 'Expr_TApply' OPEN_PAREN ID COMMA OPEN_BRACKET tes=exprs? CLOSE_BRACKET COMMA OPEN_BRACKET args=exprs? CLOSE_BRACKET CLOSE_PAREN # ExprTApply
expr: 'Expr_Var' OPEN_PAREN ident CLOSE_PAREN # ExprVar
| 'Expr_TApply' OPEN_PAREN ident COMMA OPEN_BRACKET tes=exprs? CLOSE_BRACKET COMMA OPEN_BRACKET args=exprs? CLOSE_BRACKET CLOSE_PAREN # ExprTApply
| 'Expr_Slices' OPEN_PAREN expr COMMA OPEN_BRACKET slices CLOSE_BRACKET CLOSE_PAREN # ExprSlices
| 'Expr_Field' OPEN_PAREN expr COMMA field=ID CLOSE_PAREN # ExprField
| 'Expr_Field' OPEN_PAREN expr COMMA field=ident CLOSE_PAREN # ExprField
| 'Expr_Array' OPEN_PAREN array=expr COMMA index=expr CLOSE_PAREN # ExprArray
| 'Expr_LitInt' OPEN_PAREN QUOTE value=(DEC | BINARY) QUOTE CLOSE_PAREN # ExprLitInt
| 'Expr_LitBits' OPEN_PAREN QUOTE value=BINARY QUOTE CLOSE_PAREN # ExprLitBits // in future may need to account for case where whitespace is in the binary string
| integer # ExprLitInt
| bits # ExprLitBits
;

// Slice_HiLo only ever appears within Type_Register fields
slice: 'Slice_LoWd' OPEN_PAREN lo=expr COMMA wd=expr CLOSE_PAREN # Slice_LoWd
| 'Slice_HiLo' OPEN_PAREN hi=expr COMMA lo=expr CLOSE_PAREN # Slice_HiLo
;

// multiple of 'slice' - distinct from Expr_Slices
slices: OPEN_PAREN slice CLOSE_PAREN (SCOLON OPEN_PAREN slice CLOSE_PAREN)*;
slices: slice (SCOLON slice)*;

ident: QUOTE ID QUOTE;

integer: DEC;
bits: BINARY; // in future may need to account for case where whitespace is in the binary string

BINARY: [0-1]+;
BINARY: SQUOTE [0-1]+ SQUOTE;
DEC: [0-9]+;
ID: [a-zA-Z_][a-zA-Z0-9_.]*;

Expand All @@ -60,6 +66,7 @@ COMMA: ',';
OPEN_BRACKET: '[';
CLOSE_BRACKET: ']';
QUOTE: '"';
SQUOTE: '\'';
SCOLON: ';';

// Ignored
Expand Down
89 changes: 44 additions & 45 deletions src/main/scala/translating/SemanticsLoader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,15 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]
}

private def visitThrow(ctx: ThrowContext, label: Option[String] = None): Assert = {
val message = ctx.ID().asScala.map(_.getText).mkString(" ,")
val message = ctx.ident().asScala.map(visitIdent).mkString(" ,")
Assert(FalseLiteral, Some(message), label)
}

private def visitTCall(ctx: TCallContext, label: Option[String] = None): Option[Statement] = {
val function = ctx.ID.getText
val function = visitIdent(ctx.ident)

val typeArgs = Option(ctx.tes) match {
case Some(e) => e.expr().asScala
case None => Nil
}
val args = Option(ctx.args) match {
case Some(e) => e.expr().asScala
case None => Nil
}
val typeArgs = Option(ctx.tes).toList.flatMap(_.expr.asScala)
val args = Option(ctx.args).toList.flatMap(_.expr.asScala)

function match {
case "Mem.set.0" =>
Expand Down Expand Up @@ -129,16 +123,16 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]
}

private def parseInt(ctx: ExprContext) = ctx match {
case e: ExprLitIntContext => e.value.getText.toInt
case e: ExprLitIntContext => visitInteger(e.integer)
case _ => throw Exception(s"expected ${ctx.getText} to be an integer literal")
}

private def visitIf(ctx: IfContext, label: Option[String] = None): Option[TempIf] = {
val condition = visitExpr(ctx.cond)
val thenStmts = ctx.stmt().asScala.flatMap(visitStmt(_, label))
val thenStmts = ctx.thenStmts.stmt.asScala.flatMap(visitStmt(_, label))

val elseStmts = Option(ctx.elseStmt) match {
case Some(_) => ctx.elseStmt.stmt().asScala.flatMap(visitStmt(_, label))
val elseStmts = Option(ctx.elseStmts) match {
case Some(_) => ctx.elseStmts.stmt.asScala.flatMap(visitStmt(_, label))
case None => mutable.Buffer()
}

Expand All @@ -151,35 +145,28 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]

private def visitVarDeclsNoInit(ctx: VarDeclsNoInitContext): Unit = {
val ty = visitType(ctx.`type`())
ctx.lvars.ID().asScala.foreach(lvar => varMap += (lvar.getText -> ty))
val newVars = ctx.lvars.ident.asScala.map(visitIdent(_) -> ty)
varMap ++= newVars
}

private def visitVarDecl(ctx: VarDeclContext, label: Option[String] = None): Option[LocalAssign] = {
val ty = visitType(ctx.`type`())
val name = ctx.lvar.getText
val name = visitIdent(ctx.lvar)
varMap += (name -> ty)

val expr = visitExpr(ctx.expr())
if (expr.isDefined) {
Some(LocalAssign(LocalVar(name, ty), expr.get, label))
} else {
None
}
expr.map(LocalAssign(LocalVar(name, ty), _, label))
}

private def visitAssign(ctx: AssignContext, label: Option[String] = None): Option[LocalAssign] = {
val lhs = visitLexpr(ctx.lexpr)
val rhs = visitExpr(ctx.expr)
if (lhs.isDefined && rhs.isDefined) {
Some(LocalAssign(lhs.get, rhs.get, label))
} else {
None
}
lhs.zip(rhs).map((lhs, rhs) => LocalAssign(lhs, rhs, label))
}

private def visitConstDecl(ctx: ConstDeclContext, label: Option[String] = None): Option[LocalAssign] = {
val ty = visitType(ctx.`type`())
val name = ctx.lvar.getText
val name = visitIdent(ctx.lvar)
constMap += (name -> ty)
val expr = visitExpr(ctx.expr)
if (expr.isDefined) {
Expand All @@ -195,8 +182,8 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]
case r: TypeRegisterContext =>
// this is a special register - not the same as a register in the IR
// ignoring the register's fields for now
BitVecType(r.size.getText.toInt)
case c: TypeConstructorContext => c.str.getText.match {
BitVecType(visitInteger(r.size))
case c: TypeConstructorContext => visitIdent(c.str).match {
case "FPRounding" => BitVecType(2)
case _ => throw Exception(s"unknown type ${ctx.getText}")
}
Expand All @@ -216,7 +203,7 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]
}

private def visitExprVar(ctx: ExprVarContext): Option[Expr] = {
val name = ctx.ID.getText
val name = visitIdent(ctx.ident)
name match {
case n if constMap.contains(n) => Some(LocalVar(n + "$" + blockCount + "$" + instructionCount, constMap(n)))
case v if varMap.contains(v) => Some(LocalVar(v, varMap(v)))
Expand All @@ -234,8 +221,7 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]
}

private def visitExprTApply(ctx: ExprTApplyContext): Option[Expr] = {

val function = ctx.ID.getText
val function = visitIdent(ctx.ident)

val typeArgs: mutable.Buffer[ExprContext] = Option(ctx.tes) match {
case Some(e) => e.expr().asScala
Expand Down Expand Up @@ -434,17 +420,17 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]

private def visitExprField(ctx: ExprFieldContext): LocalVar = {
val name = ctx.expr match {
case e: ExprVarContext => e.ID.getText
case e: ExprVarContext => visitIdent(e.ident)
case _ => throw Exception(s"expected ${ctx.getText} to have an Expr_Var as first parameter")
}
val field = ctx.field.getText
val field = visitIdent(ctx.field)

resolveFieldExpr(name, field)
}

private def visitExprArray(ctx: ExprArrayContext): Register = {
val name = ctx.array match {
case e: ExprVarContext => e.ID.getText
case e: ExprVarContext => visitIdent(e.ident)
case _ => throw Exception(s"expected ${ctx.getText} to have an Expr_Var as first parameter")
}
val index = parseInt(ctx.index)
Expand All @@ -453,12 +439,7 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]
}

private def visitExprLitBits(ctx: ExprLitBitsContext): BitVecLiteral = {
var num = BigInt(ctx.value.getText, 2)
val len = ctx.value.getText.length
if (num < 0) {
num = num + (BigInt(1) << len)
}
BitVecLiteral(num, len)
visitBits(ctx.bits)
}

private def visitLexpr(ctx: LexprContext): Option[Variable] = {
Expand All @@ -470,7 +451,7 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]
}

private def visitLExprVar(ctx: LExprVarContext): Option[Variable] = {
val name = ctx.ID.getText
val name = visitIdent(ctx.ident)
name match {
case n if constMap.contains(n) => Some(LocalVar(n + "$" + blockCount + "$" + instructionCount, constMap(n)))
case v if varMap.contains(v) => Some(LocalVar(v, varMap(v)))
Expand All @@ -488,24 +469,42 @@ class SemanticsLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]

private def visitLExprField(ctx: LExprFieldContext): LocalVar = {
val name = ctx.lexpr match {
case l: LExprVarContext => l.ID.getText
case l: LExprVarContext => visitIdent(l.ident)
case _ => throw Exception(s"expected ${ctx.getText} to have an LExpr_Var as first parameter")
}
val field = ctx.field.getText
val field = visitIdent(ctx.field)

resolveFieldExpr(name, field)
}

private def visitLExprArray(ctx: LExprArrayContext): Register = {
val name = ctx.lexpr match {
case l: LExprVarContext => l.ID.getText
case l: LExprVarContext => visitIdent(l.ident)
case _ => throw Exception(s"expected ${ctx.getText} to have an LExpr_Var as first parameter")
}
val index = parseInt(ctx.index)

resolveArrayExpr(name, index)
}

private def visitIdent(ctx: IdentContext): String = {
ctx.ID.getText.stripPrefix("\"").stripSuffix("\"")
}

private def visitInteger(ctx: IntegerContext): Int = {
ctx.DEC.getText.toInt
}

private def visitBits(ctx: BitsContext): BitVecLiteral = {
val str = ctx.BINARY.getText.stripPrefix("'").stripSuffix("'")
val width = str.length
var num = BigInt(str, 2)
if (num < 0) {
num = num + (BigInt(1) << width)
}
BitVecLiteral(num, width)
}

private def resolveFieldExpr(name: String, field: String): LocalVar = {
name match {
case "PSTATE" if field == "V" || field == "C" || field == "Z" || field == "N" =>
Expand Down

0 comments on commit f2137d9

Please sign in to comment.