From 513beace42e50c9cbbd2aae5f9678f62701cda8d Mon Sep 17 00:00:00 2001
From: Petr Rockai <me@mornfall.net>
Date: Sat, 22 Jun 2019 13:40:51 +0000
Subject: [PATCH] VM: Move and rename dbg::print::opcode() to vm::opname().

---
 divine/dbg/print.cpp  | 112 ---------------------------------
 divine/dbg/print.hpp  |   5 --
 divine/dbg/print.tpp  |   5 +-
 divine/vm/opnames.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++
 divine/vm/opnames.hpp |   7 +++
 5 files changed, 151 insertions(+), 119 deletions(-)
 create mode 100644 divine/vm/opnames.cpp
 create mode 100644 divine/vm/opnames.hpp

diff --git a/divine/dbg/print.cpp b/divine/dbg/print.cpp
index cf91c9791..3e613d81d 100644
--- a/divine/dbg/print.cpp
+++ b/divine/dbg/print.cpp
@@ -25,117 +25,6 @@ using namespace std::literals;
 namespace divine::dbg::print
 {
 
-#define HANDLE_INST(num, opc, class) [num] = #opc ## s,
-static std::string _opcode[] = { "",
-#include <llvm/IR/Instruction.def>
-};
-#undef HANDLE_INST
-
-void opcode_tolower()
-{
-    static bool done = false;
-    if ( done )
-        return;
-    for ( int i = 0; i < int( sizeof( _opcode ) / sizeof( _opcode[0] ) ); ++i )
-        std::transform( _opcode[i].begin(), _opcode[i].end(),
-                        _opcode[i].begin(), ::tolower );
-    done = true;
-}
-
-std::string opcode( int op )
-{
-    if ( op == lx::OpDbgCall )
-        return "dbg.call";
-    if ( op == lx::OpDbg )
-        return "dbg";
-    if ( op == lx::OpHypercall )
-        return "vm";
-    opcode_tolower();
-    return _opcode[ op ];
-}
-
-template< typename I >
-decltype( I::opcode, std::string() ) opcode( I &insn )
-{
-    std::string op = opcode( insn.opcode );
-    if ( insn.opcode == llvm::Instruction::ICmp )
-        switch ( insn.subcode )
-        {
-            case llvm::ICmpInst::ICMP_EQ: op += ".eq"; break;
-            case llvm::ICmpInst::ICMP_NE: op += ".ne"; break;
-            case llvm::ICmpInst::ICMP_ULT: op += ".ult"; break;
-            case llvm::ICmpInst::ICMP_UGE: op += ".uge"; break;
-            case llvm::ICmpInst::ICMP_UGT: op += ".ugt"; break;
-            case llvm::ICmpInst::ICMP_ULE: op += ".ule"; break;
-            case llvm::ICmpInst::ICMP_SLT: op += ".slt"; break;
-            case llvm::ICmpInst::ICMP_SGT: op += ".sgt"; break;
-            case llvm::ICmpInst::ICMP_SLE: op += ".sle"; break;
-            case llvm::ICmpInst::ICMP_SGE: op += ".sge"; break;
-            default: UNREACHABLE( "unexpected icmp predicate" ); break;
-        }
-    if ( insn.opcode == llvm::Instruction::FCmp )
-        switch ( insn.subcode )
-        {
-            case llvm::FCmpInst::FCMP_OEQ: op += ".oeq"; break;
-            case llvm::FCmpInst::FCMP_ONE: op += ".one"; break;
-            case llvm::FCmpInst::FCMP_OLE: op += ".ole"; break;
-            case llvm::FCmpInst::FCMP_OLT: op += ".olt"; break;
-            case llvm::FCmpInst::FCMP_OGE: op += ".oge"; break;
-            case llvm::FCmpInst::FCMP_OGT: op += ".ogt"; break;
-
-            case llvm::FCmpInst::FCMP_UEQ: op += ".ueq"; break;
-            case llvm::FCmpInst::FCMP_UNE: op += ".une"; break;
-            case llvm::FCmpInst::FCMP_ULE: op += ".ule"; break;
-            case llvm::FCmpInst::FCMP_ULT: op += ".ult"; break;
-            case llvm::FCmpInst::FCMP_UGE: op += ".uge"; break;
-            case llvm::FCmpInst::FCMP_UGT: op += ".ugt"; break;
-
-            case llvm::FCmpInst::FCMP_FALSE: op += ".false"; break;
-            case llvm::FCmpInst::FCMP_TRUE: op += ".true"; break;
-            case llvm::FCmpInst::FCMP_ORD: op += ".ord"; break;
-            case llvm::FCmpInst::FCMP_UNO: op += ".uno"; break;
-            default: UNREACHABLE( "unexpected fcmp predicate" ); break;
-        }
-    if ( insn.opcode == lx::OpDbg )
-        switch ( insn.subcode )
-        {
-            case lx::DbgValue:   op += ".value"; break;
-            case lx::DbgDeclare: op += ".declare"; break;
-            case lx::DbgBitCast: op += ".bitcast"; break;
-            default: UNREACHABLE( "unexpected debug opcode" ); break;
-        }
-    if ( insn.opcode == lx::OpHypercall )
-        switch ( insn.subcode )
-        {
-            case lx::HypercallChoose: op += ".choose"; break;
-            case lx::HypercallFault: op += ".fault"; break;
-
-            case lx::HypercallCtlSet: op += ".ctl.set"; break;
-            case lx::HypercallCtlGet: op += ".ctl.get"; break;
-            case lx::HypercallCtlFlag: op += ".ctl.flag"; break;
-
-            case lx::HypercallTestCrit: op += ".test.crit"; break;
-            case lx::HypercallTestLoop: op += ".test.loop"; break;
-            case lx::HypercallTestTaint: op += ".test.taint"; break;
-
-            case lx::HypercallPeek: op += ".peek"; break;
-            case lx::HypercallPoke: op += ".poke"; break;
-
-            case lx::HypercallTrace : op += ".trace"; break;
-            case lx::HypercallSyscall: op += ".syscall"; break;
-
-            case lx::HypercallObjMake: op += ".obj.make"; break;
-            case lx::HypercallObjFree: op += ".obj.free"; break;
-            case lx::HypercallObjShared: op += ".obj.shared"; break;
-            case lx::HypercallObjResize: op += ".obj.resize"; break;
-            case lx::HypercallObjSize: op += ".obj.size"; break;
-            case lx::HypercallObjClone: op += ".obj.clone"; break;
-
-            default: UNREACHABLE( "unexpected hypercall opcode" ); break;
-        }
-    return op;
-}
-
 template< typename Heap >
 std::string raw( Heap &heap, vm::HeapPointer hloc, int sz )
 {
@@ -178,6 +67,5 @@ std::string raw( Heap &heap, vm::HeapPointer hloc, int sz )
 template struct Print< dbg::Context< vm::CowHeap > >;
 template struct Print< dbg::DNContext< vm::CowHeap > >;
 template std::string raw< vm::CowHeap >( vm::CowHeap &, vm::HeapPointer, int );
-template std::string opcode< vm::Program::Instruction >( vm::Program::Instruction & );
 
 }
diff --git a/divine/dbg/print.hpp b/divine/dbg/print.hpp
index 834ade3da..2d822c62c 100644
--- a/divine/dbg/print.hpp
+++ b/divine/dbg/print.hpp
@@ -37,8 +37,6 @@ namespace divine::dbg::print
 
 namespace lx = vm::lx;
 
-std::string opcode( int );
-
 static void pad( std::ostream &o, int &col, int target )
 {
     while ( col < target )
@@ -66,9 +64,6 @@ void ascbyte( std::ostream &o, int &col, B byte )
 
 enum class DisplayVal { Name, Value, PreferName };
 
-template< typename I >
-decltype( I::opcode, std::string() ) opcode( I &insn );
-
 template< typename Ctx >
 struct Print
 {
diff --git a/divine/dbg/print.tpp b/divine/dbg/print.tpp
index 533795c86..2e28b29b9 100644
--- a/divine/dbg/print.tpp
+++ b/divine/dbg/print.tpp
@@ -18,6 +18,7 @@
 
 #include <divine/dbg/print.hpp>
 #include <divine/vm/eval.tpp>
+#include <divine/vm/opnames.hpp>
 #include <brick-llvm>
 
 using namespace std::literals;
@@ -95,7 +96,7 @@ std::string Print< Ctx >::instruction( int padding, int colmax )
 
     auto I = dbg.find( nullptr, eval.pc() ).first;
     if ( !I )
-        return opcode( insn );
+        return vm::opname( insn );
 
     bool printres = true;
 
@@ -104,7 +105,7 @@ std::string Print< Ctx >::instruction( int padding, int colmax )
     else
         printres = false;
 
-    out << opcode( insn ) << " ";
+    out << vm::opname( insn ) << " ";
     uint64_t skipMask = 0;
 
     int argc = I->getNumOperands();
diff --git a/divine/vm/opnames.cpp b/divine/vm/opnames.cpp
new file mode 100644
index 000000000..2839885bb
--- /dev/null
+++ b/divine/vm/opnames.cpp
@@ -0,0 +1,141 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+
+/*
+ * (c) 2016 Petr RoÄŤkai <code@fixp.eu>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <divine/dbg/print.tpp>
+#include <divine/dbg/context.hpp>
+#include <divine/vm/eval.tpp>
+
+using namespace std::literals;
+
+namespace divine::vm
+{
+
+#define HANDLE_INST(num, opc, class) [num] = #opc ## s,
+    static std::string _opname[] = { "",
+#include <llvm/IR/Instruction.def>
+    };
+#undef HANDLE_INST
+
+    static void opnames_tolower()
+    {
+        static bool done = false;
+        if ( done )
+            return;
+        for ( int i = 0; i < int( sizeof( _opname ) / sizeof( _opname[0] ) ); ++i )
+            std::transform( _opname[i].begin(), _opname[i].end(),
+                            _opname[i].begin(), ::tolower );
+        done = true;
+    }
+
+    std::string opname( int op )
+    {
+        if ( op == lx::OpDbgCall )
+            return "dbg.call";
+        if ( op == lx::OpDbg )
+            return "dbg";
+        if ( op == lx::OpHypercall )
+            return "vm";
+        opnames_tolower();
+        return _opname[ op ];
+    }
+
+    template< typename I >
+    decltype( I::opcode, std::string() ) opname( I &insn )
+    {
+        std::string op = opname( insn.opcode );
+        if ( insn.opcode == llvm::Instruction::ICmp )
+            switch ( insn.subcode )
+            {
+                case llvm::ICmpInst::ICMP_EQ: op += ".eq"; break;
+                case llvm::ICmpInst::ICMP_NE: op += ".ne"; break;
+                case llvm::ICmpInst::ICMP_ULT: op += ".ult"; break;
+                case llvm::ICmpInst::ICMP_UGE: op += ".uge"; break;
+                case llvm::ICmpInst::ICMP_UGT: op += ".ugt"; break;
+                case llvm::ICmpInst::ICMP_ULE: op += ".ule"; break;
+                case llvm::ICmpInst::ICMP_SLT: op += ".slt"; break;
+                case llvm::ICmpInst::ICMP_SGT: op += ".sgt"; break;
+                case llvm::ICmpInst::ICMP_SLE: op += ".sle"; break;
+                case llvm::ICmpInst::ICMP_SGE: op += ".sge"; break;
+                default: UNREACHABLE( "unexpected icmp predicate" ); break;
+            }
+        if ( insn.opcode == llvm::Instruction::FCmp )
+            switch ( insn.subcode )
+            {
+                case llvm::FCmpInst::FCMP_OEQ: op += ".oeq"; break;
+                case llvm::FCmpInst::FCMP_ONE: op += ".one"; break;
+                case llvm::FCmpInst::FCMP_OLE: op += ".ole"; break;
+                case llvm::FCmpInst::FCMP_OLT: op += ".olt"; break;
+                case llvm::FCmpInst::FCMP_OGE: op += ".oge"; break;
+                case llvm::FCmpInst::FCMP_OGT: op += ".ogt"; break;
+
+                case llvm::FCmpInst::FCMP_UEQ: op += ".ueq"; break;
+                case llvm::FCmpInst::FCMP_UNE: op += ".une"; break;
+                case llvm::FCmpInst::FCMP_ULE: op += ".ule"; break;
+                case llvm::FCmpInst::FCMP_ULT: op += ".ult"; break;
+                case llvm::FCmpInst::FCMP_UGE: op += ".uge"; break;
+                case llvm::FCmpInst::FCMP_UGT: op += ".ugt"; break;
+
+                case llvm::FCmpInst::FCMP_FALSE: op += ".false"; break;
+                case llvm::FCmpInst::FCMP_TRUE: op += ".true"; break;
+                case llvm::FCmpInst::FCMP_ORD: op += ".ord"; break;
+                case llvm::FCmpInst::FCMP_UNO: op += ".uno"; break;
+                default: UNREACHABLE( "unexpected fcmp predicate" ); break;
+            }
+        if ( insn.opcode == lx::OpDbg )
+            switch ( insn.subcode )
+            {
+                case lx::DbgValue:   op += ".value"; break;
+                case lx::DbgDeclare: op += ".declare"; break;
+                case lx::DbgBitCast: op += ".bitcast"; break;
+                default: UNREACHABLE( "unexpected debug opcode" ); break;
+            }
+        if ( insn.opcode == lx::OpHypercall )
+            switch ( insn.subcode )
+            {
+                case lx::HypercallChoose: op += ".choose"; break;
+                case lx::HypercallFault: op += ".fault"; break;
+
+                case lx::HypercallCtlSet: op += ".ctl.set"; break;
+                case lx::HypercallCtlGet: op += ".ctl.get"; break;
+                case lx::HypercallCtlFlag: op += ".ctl.flag"; break;
+
+                case lx::HypercallTestCrit: op += ".test.crit"; break;
+                case lx::HypercallTestLoop: op += ".test.loop"; break;
+                case lx::HypercallTestTaint: op += ".test.taint"; break;
+
+                case lx::HypercallPeek: op += ".peek"; break;
+                case lx::HypercallPoke: op += ".poke"; break;
+
+                case lx::HypercallTrace : op += ".trace"; break;
+                case lx::HypercallSyscall: op += ".syscall"; break;
+
+                case lx::HypercallObjMake: op += ".obj.make"; break;
+                case lx::HypercallObjFree: op += ".obj.free"; break;
+                case lx::HypercallObjShared: op += ".obj.shared"; break;
+                case lx::HypercallObjResize: op += ".obj.resize"; break;
+                case lx::HypercallObjSize: op += ".obj.size"; break;
+                case lx::HypercallObjClone: op += ".obj.clone"; break;
+
+                default: UNREACHABLE( "unexpected hypercall opcode" ); break;
+            }
+        return op;
+    }
+
+    template std::string opname< vm::Program::Instruction >( vm::Program::Instruction & );
+
+}
diff --git a/divine/vm/opnames.hpp b/divine/vm/opnames.hpp
new file mode 100644
index 000000000..da706a8c1
--- /dev/null
+++ b/divine/vm/opnames.hpp
@@ -0,0 +1,7 @@
+namespace divine::vm
+{
+    std::string opname( int );
+
+    template< typename I >
+    decltype( I::opcode, std::string() ) opname( I &insn );
+}
-- 
GitLab