 BITWISE = [ '<<', '>>', '>>>', '~', '&', '|' ]
 COMPARE = [ '===', '!==', '<', '>', '<=', '>=' ]
 
-binopType = (op, ty1, ty2) ->
+binopType = (o, op, ty1, ty2, node) ->
   if (op is '+' or op is '-') and ty1 instanceof PointerType
     if ty2 in integral
       ty1
     else if op is '-' and ty2 instanceof PointerType
       unless unify o.types, ty1.base, ty2.base
-        printWarn "pointer subtraction on incompatible pointer types `#{ty1}' and `#{ty2}'"
+        printWarn "pointer subtraction on incompatible pointer types `#{tystr(ty1)}' and `#{ty2}'"
       i32ty
     else
-      error this, "invalid operand type `#{ty2}' for pointer arithmetic"
+      error node, "invalid operand type `#{tystr(ty2)}' for pointer arithmetic"
   else if op is '%'
     i32ty
   else if op in COMPARE
     if ty1 instanceof PointerType and ty2 instanceof PointerType and
        not unify o.types, ty1, ty2
-      printWarn "comparison between incompatible pointer types `#{ty1}' and `#{ty2}'"
+      printWarn "comparison between incompatible pointer types `#{tystr(ty1)}' and `#{tystr(ty2)}'"
     i32ty
   else if op in BITWISE
     i32ty

          arg.save = freshVariable arg.name
          plh = new Value new Literal arg.name
          prh = new Value arg.save
          assign = new Assign plh, prh
          assign.computedType = plh.computedType = prh.computedType = arg.type
          plh.computedBinding = arg.binding
          exprs.unshift assign
    o.frameSize = frameSize
    stackFence o, exprs, frameSize, @spOffsets
    for param in @params

# Unify two types, if possible, into a single type. If `assign` is true, then
# this behaves asymmetrically for pointer types and automatic promotions of
# primitive types.
unify = (types, lty, rty, assigning) ->
  # Unify is reflexive.
  return lty if lty is rty
  # If the left side is dynamic, the entire expression is dynamic.
  return unless lty and rty
  # Two pointer types are unifiable iff their bases are size compatible.
  if lty instanceof PointerType and rty instanceof PointerType
    if assigning
      # Assigning a narrower pointer to a wider one may mess up due to
      # alignment, since all views are aligned.
      if rty.base and rty.baseAlignment() < lty.baseAlignment()
