From 585513830e96c09edb94cd381ad87250e56c76fb Mon Sep 17 00:00:00 2001 From: Alistair Michael Date: Thu, 19 Dec 2024 17:42:25 +1000 Subject: [PATCH] support new lifter error format --- src/main/scala/translating/GTIRBLoader.scala | 30 +++++++++++------ src/main/scala/translating/GTIRBToIR.scala | 2 +- src/main/scala/util/RunUtils.scala | 35 +++++++++++++++++--- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/main/scala/translating/GTIRBLoader.scala b/src/main/scala/translating/GTIRBLoader.scala index 836ed5de0..587651ac9 100644 --- a/src/main/scala/translating/GTIRBLoader.scala +++ b/src/main/scala/translating/GTIRBLoader.scala @@ -13,7 +13,7 @@ import scala.collection.mutable.ArrayBuffer import com.grammatech.gtirb.proto.Module.ByteOrder.LittleEndian import util.Logger -class GTIRBLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]]) { +class GTIRBLoader(parserMap: immutable.Map[String, List[Either[(String, String), List[StmtContext]]]]) { private val constMap = mutable.Map[String, IRType]() private val varMap = mutable.Map[String, IRType]() @@ -30,20 +30,27 @@ class GTIRBLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]]) { val statements: ArrayBuffer[Statement] = ArrayBuffer() - for (instruction <- instructions) { + for (instsem <- instructions) { constMap.clear varMap.clear - for ((s, i) <- instruction.zipWithIndex) { - - val label = blockAddress.map {(a: BigInt) => - val instructionAddress = a + (opcodeSize * instructionCount) - instructionAddress.toString + "$" + i + val s = instsem match { + case Left((op, err)) => { + statements.append(Assert(FalseLiteral, Some(s"Decode error: $op ${err.replace("\n", " :: ")}"))) + instructionCount += 1 + } + case Right(instruction) => { + for ((s, i) <- instruction.zipWithIndex) { + val label = blockAddress.map {(a: BigInt) => + val instructionAddress = a + (opcodeSize * instructionCount) + instructionAddress.toString + "$" + i + } + + statements.appendAll(visitStmt(s, label)) + } + instructionCount += 1 } - - statements.appendAll(visitStmt(s, label)) } - instructionCount += 1 } statements } @@ -301,7 +308,8 @@ class GTIRBLoader(parserMap: immutable.Map[String, Array[Array[StmtContext]]]) { checkArgs(function, 0, 1, typeArgs.size, args.size, ctx.getText) val expr = visitExprOnly(args.head) val result = expr.map { - case b: BinaryExpr if b.op == BVEQ => BinaryExpr(BVCOMP, b.arg1, b.arg2) + case BinaryExpr(BVEQ, l, r) => BinaryExpr(BVCOMP, l, r) + case UnaryExpr(BoolNOT, BinaryExpr(BVEQ, l, r)) => UnaryExpr(BVNOT, BinaryExpr(BVCOMP, l, r)) case FalseLiteral => BitVecLiteral(0, 1) case TrueLiteral => BitVecLiteral(1, 1) case _ => throw Exception(s"unhandled conversion from bool to bitvector: ${ctx.getText}") diff --git a/src/main/scala/translating/GTIRBToIR.scala b/src/main/scala/translating/GTIRBToIR.scala index 31049706c..ad0795192 100644 --- a/src/main/scala/translating/GTIRBToIR.scala +++ b/src/main/scala/translating/GTIRBToIR.scala @@ -49,7 +49,7 @@ class TempIf(val cond: Expr, * @param mainAddress: The address of the main function * */ -class GTIRBToIR(mods: Seq[Module], parserMap: immutable.Map[String, Array[Array[StmtContext]]], cfg: CFG, mainAddress: BigInt) { +class GTIRBToIR(mods: Seq[Module], parserMap: immutable.Map[String, List[Either[(String, String), List[StmtContext]]]], cfg: CFG, mainAddress: BigInt) { private val functionNames = MapDecoder.decode_uuid(mods.map(_.auxData("functionNames").data)) private val functionEntries = MapDecoder.decode_set(mods.map(_.auxData("functionEntries").data)) private val functionBlocks = MapDecoder.decode_set(mods.map(_.auxData("functionBlocks").data)) diff --git a/src/main/scala/util/RunUtils.scala b/src/main/scala/util/RunUtils.scala index c7cb1ae59..783cc70f5 100644 --- a/src/main/scala/util/RunUtils.scala +++ b/src/main/scala/util/RunUtils.scala @@ -120,9 +120,29 @@ object IRLoading { val mods = ir.modules val cfg = ir.cfg.get - val semantics = mods.map(_.auxData("ast").data.toStringUtf8.parseJson.convertTo[Map[String, Array[Array[String]]]]) + enum InsnSemantics { + case Result(value: Array[String]) + case Error(opcode: String, error: String) + } + + implicit object InsnSemanticsFormat extends JsonFormat[InsnSemantics] { + def write(m: InsnSemantics) = ??? + def read(json: JsValue) = json match { + case JsObject(fields) => { + val m : Map[String, JsValue] = fields.get("decode_error") match { + case Some(JsObject(m)) => m + case _ => deserializationError(s"Bad sem format $json") + } + InsnSemantics.Error(m("opcode").convertTo[String], m("error").convertTo[String]) + } + case array @ JsArray(_) => InsnSemantics.Result(array.convertTo[Array[String]]) + case s => deserializationError(s"Bad sem format $s") + } + } + + val semantics = mods.map(_.auxData("ast").data.toStringUtf8.parseJson.convertTo[Map[String, Array[InsnSemantics]]]) - def parse_insn(line: String): StmtContext = { + def parse_asl_stmt(line: String): StmtContext = { val lexer = ASLpLexer(CharStreams.fromString(line)) val tokens = CommonTokenStream(lexer) val parser = ASLpParser(tokens) @@ -143,16 +163,20 @@ object IRLoading { ${line.replace('\n', ' ')} ${" " * token.getStartIndex}^ here! """.stripIndent - case _ => "" + case o => o.toString } Logger.error(s"""Semantics parse error:\n line: $line\n$extra""") throw e } } - val parserMap = semantics.map(_.map((k: String, v: Array[Array[String]]) => (k, v.map(_.map(parse_insn))))) + val parserMap : Map[String, List[Either[(String,String), List[StmtContext]]]] = + semantics.toList.map(_.map((k: String, v: Array[InsnSemantics]) => (k, v.toList.map { + case InsnSemantics.Result(s) => Right(s.toList.map(parse_asl_stmt)) + case InsnSemantics.Error(op, err) => Left((op, err)) + }))).flatten.toMap - val GTIRBConverter = GTIRBToIR(mods, parserMap.flatten.toMap, cfg, mainAddress) + val GTIRBConverter = GTIRBToIR(mods, parserMap, cfg, mainAddress) GTIRBConverter.createIR() } @@ -163,6 +187,7 @@ object IRLoading { val lexer = ReadELFLexer(CharStreams.fromFileName(fileName)) val tokens = CommonTokenStream(lexer) val parser = ReadELFParser(tokens) + parser.setErrorHandler(BailErrorStrategy()) parser.setBuildParseTree(true) ReadELFLoader.visitSyms(parser.syms(), config) }