///|
// Operation metadata - corresponds to struct Op and the optab in QBE
// (all.h + parse.c + ops.h)
// Class codes match QBE: Ke=-2 (erroneous), Kx=-1 (top), Kw=0, Kl=1, Ks=2, Kd=3
pub(all) struct OpInfo {
  name : String
  // arg class for each result class: [Kw, Kl, Ks, Kd]
  a0 : Array[Int]
  a1 : Array[Int]
  canfold : Bool
  nmem : Int // number of memory arguments
  zf : Int // sets zero flag
  lf : Int // leaves flags
} derive(Debug)

///|
fn mk(
  name : String,
  a0 : Array[Int],
  a1 : Array[Int],
  cf : Bool,
  x : (Int, Int, Int),
) -> OpInfo {
  OpInfo::{ name, a0, a1, canfold: cf, nmem: x.0, zf: x.1, lf: x.2, }
}

///|
fn cls(vals : Array[String]) -> Array[Int] {
  let r : Array[Int] = Array::new()
  for v in vals {
    let c = match v {
      "w" => 0
      "l" => 1
      "s" => 2
      "d" => 3
      "x" => -1
      "e" => -2
      "m" => 1
      _ => -1
    }
    r.push(c)
  }
  r
}

///|
let optab : Array[OpInfo] = [
  // placeholder Oxxx
  mk(
    "xxx",
    cls(["x", "x", "x", "x"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 0),
  ),
  // Arithmetic and Bits
  mk(
    "add",
    cls(["w", "l", "s", "d"]),
    cls(["w", "l", "s", "d"]),
    true,
    (2, 1, 0),
  ),
  mk(
    "sub",
    cls(["w", "l", "s", "d"]),
    cls(["w", "l", "s", "d"]),
    true,
    (2, 1, 0),
  ),
  mk(
    "div",
    cls(["w", "l", "s", "d"]),
    cls(["w", "l", "s", "d"]),
    true,
    (0, 0, 0),
  ),
  mk(
    "rem",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    true,
    (0, 0, 0),
  ),
  mk(
    "udiv",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    true,
    (0, 0, 0),
  ),
  mk(
    "urem",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    true,
    (0, 0, 0),
  ),
  mk(
    "mul",
    cls(["w", "l", "s", "d"]),
    cls(["w", "l", "s", "d"]),
    true,
    (2, 0, 0),
  ),
  mk(
    "and",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    true,
    (2, 1, 0),
  ),
  mk(
    "or",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    true,
    (2, 1, 0),
  ),
  mk(
    "xor",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    true,
    (2, 1, 0),
  ),
  mk(
    "sar",
    cls(["w", "l", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (1, 1, 0),
  ),
  mk(
    "shr",
    cls(["w", "l", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (1, 1, 0),
  ),
  mk(
    "shl",
    cls(["w", "l", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (1, 1, 0),
  ),
  // Comparisons - word
  mk(
    "ceqw",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cnew",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "csgew",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "csgtw",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cslew",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "csltw",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cugew",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cugtw",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "culew",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cultw",
    cls(["w", "w", "e", "e"]),
    cls(["w", "w", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  // Comparisons - long
  mk(
    "ceql",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cnel",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "csgel",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "csgtl",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cslel",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "csltl",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cugel",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cugtl",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "culel",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cultl",
    cls(["l", "l", "e", "e"]),
    cls(["l", "l", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  // Comparisons - single
  mk(
    "ceqs",
    cls(["s", "s", "e", "e"]),
    cls(["s", "s", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cges",
    cls(["s", "s", "e", "e"]),
    cls(["s", "s", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cgts",
    cls(["s", "s", "e", "e"]),
    cls(["s", "s", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cles",
    cls(["s", "s", "e", "e"]),
    cls(["s", "s", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "clts",
    cls(["s", "s", "e", "e"]),
    cls(["s", "s", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cnes",
    cls(["s", "s", "e", "e"]),
    cls(["s", "s", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cos",
    cls(["s", "s", "e", "e"]),
    cls(["s", "s", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cuos",
    cls(["s", "s", "e", "e"]),
    cls(["s", "s", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  // Comparisons - double
  mk(
    "ceqd",
    cls(["d", "d", "e", "e"]),
    cls(["d", "d", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cged",
    cls(["d", "d", "e", "e"]),
    cls(["d", "d", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cgtd",
    cls(["d", "d", "e", "e"]),
    cls(["d", "d", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cled",
    cls(["d", "d", "e", "e"]),
    cls(["d", "d", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cltd",
    cls(["d", "d", "e", "e"]),
    cls(["d", "d", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cned",
    cls(["d", "d", "e", "e"]),
    cls(["d", "d", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cod",
    cls(["d", "d", "e", "e"]),
    cls(["d", "d", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  mk(
    "cuod",
    cls(["d", "d", "e", "e"]),
    cls(["d", "d", "e", "e"]),
    true,
    (0, 1, 0),
  ),
  // Memory - stores
  mk(
    "storeb",
    cls(["w", "e", "e", "e"]),
    cls(["m", "e", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "storeh",
    cls(["w", "e", "e", "e"]),
    cls(["m", "e", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "storew",
    cls(["w", "e", "e", "e"]),
    cls(["m", "e", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "storel",
    cls(["l", "e", "e", "e"]),
    cls(["m", "e", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "stores",
    cls(["s", "e", "e", "e"]),
    cls(["m", "e", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "stored",
    cls(["d", "e", "e", "e"]),
    cls(["m", "e", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  // Memory - loads
  mk(
    "loadsb",
    cls(["m", "m", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "loadub",
    cls(["m", "m", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "loadsh",
    cls(["m", "m", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "loaduh",
    cls(["m", "m", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "loadsw",
    cls(["m", "m", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "loaduw",
    cls(["m", "m", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "load",
    cls(["m", "m", "m", "m"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 1),
  ),
  // Extensions and truncations
  mk(
    "extsb",
    cls(["w", "w", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "extub",
    cls(["w", "w", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "extsh",
    cls(["w", "w", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "extuh",
    cls(["w", "w", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "extsw",
    cls(["e", "w", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "extuw",
    cls(["e", "w", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "exts",
    cls(["e", "e", "e", "s"]),
    cls(["e", "e", "e", "x"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "truncd",
    cls(["e", "e", "d", "e"]),
    cls(["e", "e", "x", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "stosi",
    cls(["s", "s", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "dtosi",
    cls(["d", "d", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "swtof",
    cls(["e", "e", "w", "w"]),
    cls(["e", "e", "x", "x"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "sltof",
    cls(["e", "e", "l", "l"]),
    cls(["e", "e", "x", "x"]),
    true,
    (0, 0, 1),
  ),
  mk(
    "cast",
    cls(["s", "d", "w", "l"]),
    cls(["x", "x", "x", "x"]),
    true,
    (0, 0, 1),
  ),
  // Stack allocation
  mk(
    "alloc4",
    cls(["e", "l", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "alloc8",
    cls(["e", "l", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "alloc16",
    cls(["e", "l", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  // Variadic function helpers
  mk(
    "vaarg",
    cls(["m", "m", "m", "m"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "vastart",
    cls(["m", "e", "e", "e"]),
    cls(["x", "e", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "copy",
    cls(["w", "l", "s", "d"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 1),
  ),
  // Internal operations
  mk(
    "nop",
    cls(["x", "x", "x", "x"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "addr",
    cls(["m", "m", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "swap",
    cls(["w", "l", "s", "d"]),
    cls(["w", "l", "s", "d"]),
    false,
    (1, 0, 0),
  ),
  mk(
    "sign",
    cls(["w", "l", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "salloc",
    cls(["e", "l", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "xidiv",
    cls(["w", "l", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (1, 0, 0),
  ),
  mk(
    "xdiv",
    cls(["w", "l", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (1, 0, 0),
  ),
  mk(
    "xcmp",
    cls(["w", "l", "s", "d"]),
    cls(["w", "l", "s", "d"]),
    false,
    (1, 1, 0),
  ),
  mk(
    "xtest",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    false,
    (1, 1, 0),
  ),
  mk(
    "acmp",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "acmn",
    cls(["w", "l", "e", "e"]),
    cls(["w", "l", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "afcmp",
    cls(["e", "e", "s", "d"]),
    cls(["e", "e", "s", "d"]),
    false,
    (0, 0, 0),
  ),
  // Arguments, parameters, calls
  mk(
    "par",
    cls(["x", "x", "x", "x"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "parc",
    cls(["e", "x", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "pare",
    cls(["e", "x", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "arg",
    cls(["w", "l", "s", "d"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "argc",
    cls(["e", "x", "e", "e"]),
    cls(["e", "l", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "arge",
    cls(["e", "l", "e", "e"]),
    cls(["e", "x", "e", "e"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "call",
    cls(["m", "m", "m", "m"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 0),
  ),
  mk(
    "vacall",
    cls(["m", "m", "m", "m"]),
    cls(["x", "x", "x", "x"]),
    false,
    (0, 0, 0),
  ),
  // Flags setting - int
  mk(
    "flagieq",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagine",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagisge",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagisgt",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagisle",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagislt",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagiuge",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagiugt",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagiule",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagiult",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  // Flags setting - float
  mk(
    "flagfeq",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagfge",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagfgt",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagfle",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagflt",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagfne",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagfo",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
  mk(
    "flagfuo",
    cls(["x", "x", "e", "e"]),
    cls(["x", "x", "e", "e"]),
    false,
    (0, 0, 1),
  ),
]

///|
// Get OpInfo for an op
pub fn op_info(o : Op) -> OpInfo {
  let i = o.index()
  if i < 0 || i >= optab.length() {
    return optab[0]
  }
  optab[i]
}

///|
// Op name as string
pub fn Op::name(self : Op) -> String {
  op_info(self).name
}

///|
// Convert an optab index back to an Op
#as_free_fn(op_from_index, deprecated="use `Op::from_index` instead")
pub fn Op::from_index(i : Int) -> Op {
  match i {
    0 => Oxxx
    1 => Add
    2 => Sub
    3 => Div
    4 => Rem
    5 => Udiv
    6 => Urem
    7 => Mul
    8 => And
    9 => Or
    10 => Xor
    11 => Sar
    12 => Shr
    13 => Shl
    14 => Ceqw
    15 => Cnew
    16 => Csgew
    17 => Csgtw
    18 => Cslew
    19 => Csltw
    20 => Cugew
    21 => Cugtw
    22 => Culew
    23 => Cultw
    24 => Ceql
    25 => Cnel
    26 => Csgel
    27 => Csgtl
    28 => Cslel
    29 => Csltl
    30 => Cugel
    31 => Cugtl
    32 => Culel
    33 => Cultl
    34 => Ceqs
    35 => Cges
    36 => Cgts
    37 => Cles
    38 => Clts
    39 => Cnes
    40 => Cos
    41 => Cuos
    42 => Ceqd
    43 => Cged
    44 => Cgtd
    45 => Cled
    46 => Cltd
    47 => Cned
    48 => Cod
    49 => Cuod
    50 => Storeb
    51 => Storeh
    52 => Storew
    53 => Storel
    54 => Stores
    55 => Stored
    56 => Loadsb
    57 => Loadub
    58 => Loadsh
    59 => Loaduh
    60 => Loadsw
    61 => Loaduw
    62 => Load
    63 => Extsb
    64 => Extub
    65 => Extsh
    66 => Extuh
    67 => Extsw
    68 => Extuw
    69 => Exts
    70 => Truncd
    71 => Stosi
    72 => Dtosi
    73 => Swtof
    74 => Sltof
    75 => Cast
    76 => Alloc4
    77 => Alloc8
    78 => Alloc16
    79 => Vaarg
    80 => Vastart
    81 => Copy
    82 => Nop
    83 => Addr
    84 => Swap
    85 => Sign
    86 => Salloc
    87 => Xidiv
    88 => Xdiv
    89 => Xcmp
    90 => Xtest
    91 => Acmp
    92 => Acmn
    93 => Afcmp
    94 => Par
    95 => Parc
    96 => Pare
    97 => Arg
    98 => Argc
    99 => Arge
    100 => Call
    101 => Vacall
    102 => Flagieq
    103 => Flagine
    104 => Flagisge
    105 => Flagisgt
    106 => Flagisle
    107 => Flagislt
    108 => Flagiuge
    109 => Flagiugt
    110 => Flagiule
    111 => Flagiult
    112 => Flagfeq
    113 => Flagfge
    114 => Flagfgt
    115 => Flagfle
    116 => Flagflt
    117 => Flagfne
    118 => Flagfo
    119 => Flagfuo
    _ => Oxxx
  }
}

///|
// Get the zero-based index of an op in the optab
#as_free_fn(op_index, deprecated="use `Op::index` instead")
pub fn Op::index(self : Op) -> Int {
  match self {
    Oxxx => 0
    Add => 1
    Sub => 2
    Div => 3
    Rem => 4
    Udiv => 5
    Urem => 6
    Mul => 7
    And => 8
    Or => 9
    Xor => 10
    Sar => 11
    Shr => 12
    Shl => 13
    Ceqw => 14
    Cnew => 15
    Csgew => 16
    Csgtw => 17
    Cslew => 18
    Csltw => 19
    Cugew => 20
    Cugtw => 21
    Culew => 22
    Cultw => 23
    Ceql => 24
    Cnel => 25
    Csgel => 26
    Csgtl => 27
    Cslel => 28
    Csltl => 29
    Cugel => 30
    Cugtl => 31
    Culel => 32
    Cultl => 33
    Ceqs => 34
    Cges => 35
    Cgts => 36
    Cles => 37
    Clts => 38
    Cnes => 39
    Cos => 40
    Cuos => 41
    Ceqd => 42
    Cged => 43
    Cgtd => 44
    Cled => 45
    Cltd => 46
    Cned => 47
    Cod => 48
    Cuod => 49
    Storeb => 50
    Storeh => 51
    Storew => 52
    Storel => 53
    Stores => 54
    Stored => 55
    Loadsb => 56
    Loadub => 57
    Loadsh => 58
    Loaduh => 59
    Loadsw => 60
    Loaduw => 61
    Load => 62
    Extsb => 63
    Extub => 64
    Extsh => 65
    Extuh => 66
    Extsw => 67
    Extuw => 68
    Exts => 69
    Truncd => 70
    Stosi => 71
    Dtosi => 72
    Swtof => 73
    Sltof => 74
    Cast => 75
    Alloc4 => 76
    Alloc8 => 77
    Alloc16 => 78
    Vaarg => 79
    Vastart => 80
    Copy => 81
    Nop => 82
    Addr => 83
    Swap => 84
    Sign => 85
    Salloc => 86
    Xidiv => 87
    Xdiv => 88
    Xcmp => 89
    Xtest => 90
    Acmp => 91
    Acmn => 92
    Afcmp => 93
    Par => 94
    Parc => 95
    Pare => 96
    Arg => 97
    Argc => 98
    Arge => 99
    Call => 100
    Vacall => 101
    Flagieq => 102
    Flagine => 103
    Flagisge => 104
    Flagisgt => 105
    Flagisle => 106
    Flagislt => 107
    Flagiuge => 108
    Flagiugt => 109
    Flagiule => 110
    Flagiult => 111
    Flagfeq => 112
    Flagfge => 113
    Flagfgt => 114
    Flagfle => 115
    Flagflt => 116
    Flagfne => 117
    Flagfo => 118
    Flagfuo => 119
  }
}