6b1bbea173ba — Leonard Ritter 9 months ago
* uvm: initial float op support
M include/uvm.h +2 -2
@@ 97,7 97,7 @@ typedef enum uvm_type_ {
 
 typedef union uvm_instruction_ {
 #define Fu32(NAME) uint32_t NAME;
-#define Fu8(NAME) uint8_t NAME;
+#define Flogsize(NAME) uint8_t NAME;
 #define Fref(NAME) uvm_ref NAME;
 #define F1(OP, NAME) OP(NAME)
 #define F(T, NAME) F1(F ## T, NAME)

          
@@ 117,7 117,7 @@ typedef union uvm_instruction_ {
 #undef F
 #undef F1
 #undef Fref
-#undef Fu8
+#undef Flogsize
 #undef Fu32
     struct {
         uint8_t kind;

          
M include/uvm_instructions.inc +28 -4
@@ 10,12 10,10 @@ T2(i, alloc , F(ref , size), F(ref , cou
 T3(i, resize , F(ref , value), F(ref , size), F(ref , count))\
 T2(i, get , F(ref , value), F(ref , index))\
 T3(i, set , F(ref , value), F(ref , element), F(ref , index))\
-T1(i, countof , F(ref , value))\
 T2(i, unfold , F(ref , value), F(ref , index))\
 T3(i, fold , F(ref , value), F(ref , element), F(ref , index))\
 T3(i, slice , F(ref , value), F(ref , offset), F(ref , size))\
 T3(i, replace , F(ref , value), F(ref , offset), F(ref , element))\
-T1(i, sizeof , F(ref , value))\
 T1(i, findmsb , F(ref , value))\
 T1(i, findlsb , F(ref , value))\
 T1(i, bitcount , F(ref , value))\

          
@@ 43,8 41,34 @@ T2(i, ishl , F(ref , a), F(ref , b))\
 T2(i, sshr , F(ref , a), F(ref , b))\
 T2(i, ushr , F(ref , a), F(ref , b))\
 T3(i, select , F(ref , cond), F(ref , t), F(ref , f))\
-T2(i, uconvert , F(ref , value), F(u8 , stride))\
-T2(i, sconvert , F(ref , value), F(u8 , stride))\
+T2(i, utou , F(ref , value), F(logsize , stride))\
+T2(i, stos , F(ref , value), F(logsize , stride))\
+T2(i, fadd , F(ref , a), F(ref , b))\
+T2(i, fsub , F(ref , a), F(ref , b))\
+T2(i, fmul , F(ref , a), F(ref , b))\
+T2(i, fdiv , F(ref , a), F(ref , b))\
+T2(i, frem , F(ref , a), F(ref , b))\
+T2(i, fpow , F(ref , a), F(ref , b))\
+T1(i, fneg , F(ref , value))\
+T1(i, sin , F(ref , value))\
+T1(i, cos , F(ref , value))\
+T1(i, sqrt , F(ref , value))\
+T1(i, exp , F(ref , value))\
+T1(i, exp2 , F(ref , value))\
+T1(i, log , F(ref , value))\
+T1(i, log2 , F(ref , value))\
+T1(i, fabs , F(ref , value))\
+T2(i, foeq , F(ref , a), F(ref , b))\
+T2(i, fune , F(ref , a), F(ref , b))\
+T2(i, folt , F(ref , a), F(ref , b))\
+T2(i, fole , F(ref , a), F(ref , b))\
+T2(i, fogt , F(ref , a), F(ref , b))\
+T2(i, foge , F(ref , a), F(ref , b))\
+T2(i, ftof , F(ref , value), F(logsize , stride))\
+T2(i, ftou , F(ref , value), F(logsize , stride))\
+T2(i, ftos , F(ref , value), F(logsize , stride))\
+T2(i, utof , F(ref , value), F(logsize , stride))\
+T2(i, stof , F(ref , value), F(logsize , stride))\
 T2(i, call , F(ref , block), F(ref , scope))\
 T3(i, ccall , F(ref , mem), F(ref , target), F(ref , value))\
 T1(i, csym , F(ref , target))\

          
M lib/scopes/compiler/target/UVM/api.sc +1 -1
@@ 261,7 261,7 @@ sugar-inline define-block (...)
         'toblock this-builder
 
 uvm-instr-types... := pass
-    u8 = u8
+    logsize = u8
     ref = uvm_cell_t
 
 #uvm-globals := do

          
M lib/scopes/compiler/target/UVM/init.sc +55 -67
@@ 205,11 205,11 @@ struct UVMGenerator
         T := scalar-type T
         s := 'sizeof T
         switch s
-        case 1 0:u8
-        case 2 1:u8
-        case 4 2:u8
-        case 8 3:u8
-        case 16 4:u8
+        case 1 I8
+        case 2 I16
+        case 4 I32
+        case 8 I64
+        case 16 I128
         default
             errorf "unsupported stride for type {0}" T
 

          
@@ 268,45 268,33 @@ struct UVMGenerator
             case icmp-kind-ugt (binop uvm.ugt)
             default
                 error "unhandled icmp op kind"
-        #case ValueKind.FCmp
+        case ValueKind.FCmp
             op := 'typed-op-kind instr
             lhs := 'typed-attribute@ instr 0 0
             rhs := 'typed-attribute@ instr 0 1
-
-            inline cmpbinop (token)
-                cmpbinop self ctx instr token lhs rhs
+            a := 'translate-value self ctx lhs
+            b := 'translate-value self ctx rhs
+            inline binop (f)
+                'map ctx instr
+                    f
+                        a = a
+                        b = b
+            using ('builder ctx)
             switch op
-            case fcmp-kind-oeq
-                cmpbinop S"OpFOrdEqual"
-            case fcmp-kind-one
-                cmpbinop S"OpFOrdNotEqual"
-            case fcmp-kind-ord
-                cmpbinop S"OpOrdered"
-            case fcmp-kind-ogt
-                cmpbinop S"OpFOrdGreaterThan"
-            case fcmp-kind-oge
-                cmpbinop S"OpFOrdGreaterThanEqual"
-            case fcmp-kind-olt
-                cmpbinop S"OpFOrdLessThan"
-            case fcmp-kind-ole
-                cmpbinop S"OpFOrdLessThanEqual"
-            case fcmp-kind-ueq
-                cmpbinop S"OpFUnordEqual"
-            #case fcmp-kind-une # not supported
-                cmpbinop S"OpFUnordNotEqual"
-                cmpbinop S"OpFOrdNotEqual"
-            case fcmp-kind-une
-                cmpbinop S"OpFOrdNotEqual"
-            case fcmp-kind-uno
-                cmpbinop S"OpUnordered"
-            case fcmp-kind-ugt
-                cmpbinop S"OpFUnordGreaterThan"
-            case fcmp-kind-uge
-                cmpbinop S"OpFUnordGreaterThanEqual"
-            case fcmp-kind-ult
-                cmpbinop S"OpFUnordLessThan"
-            case fcmp-kind-ule
-                cmpbinop S"OpFUnordLessThanEqual"
+            case fcmp-kind-oeq (binop uvm.foeq)
+            case fcmp-kind-one (binop uvm.fune)
+            case fcmp-kind-ord (binop uvm.foeq) # todo
+            case fcmp-kind-ogt (binop uvm.fogt)
+            case fcmp-kind-oge (binop uvm.foge)
+            case fcmp-kind-olt (binop uvm.folt)
+            case fcmp-kind-ole (binop uvm.fole)
+            case fcmp-kind-ueq (binop uvm.foeq) # todo
+            case fcmp-kind-une (binop uvm.fune) # todo
+            case fcmp-kind-uno (binop uvm.fune) # todo
+            case fcmp-kind-ugt (binop uvm.fogt) # todo
+            case fcmp-kind-uge (binop uvm.foge) # todo
+            case fcmp-kind-ult (binop uvm.folt) # todo
+            case fcmp-kind-ule (binop uvm.fole) # todo
             default
                 error "unhandled fcmp op kind"
         #case ValueKind.UnOp

          
@@ 400,15 388,15 @@ struct UVMGenerator
             case binop-kind-band (binop uvm.iand)
             case binop-kind-bor (binop uvm.ior)
             case binop-kind-bxor (binop uvm.ixor)
-            #case binop-kind-fadd (binop uvm.fadd)
-            #case binop-kind-fsub (binop uvm.fsub)
-            #case binop-kind-fmul (binop uvm.fmul)
-            #case binop-kind-fdiv (binop uvm.fdiv)
-            #case binop-kind-frem (binop uvm.frem)
+
+            case binop-kind-fadd (binop uvm.fadd)
+            case binop-kind-fsub (binop uvm.fsub)
+            case binop-kind-fmul (binop uvm.fmul)
+            case binop-kind-fdiv (binop uvm.fdiv)
+            case binop-kind-frem (binop uvm.frem)
+            case binop-kind-pow (binop uvm.fpow)
             #case binop-kind-atan2
                 glsl-func "Atan2"
-            #case binop-kind-pow
-                glsl-func "Pow"
             #
                 binop-kind-add-nuw
                 binop-kind-add-nsw

          
@@ 502,7 490,7 @@ struct UVMGenerator
             T := 'elementof ('storageof T)
             bytesize := if array?
                 count := 'translate-value self ctx ('typed-attribute@ instr 0 0)
-                count := uvm.uconvert (value = count) (stride = I64)
+                count := uvm.utou (value = count) (stride = I64)
                 uvm.imul (a = count) (b = 'sizeof T)
             else
                 uvm.const ('sizeof T)

          
@@ 516,7 504,7 @@ struct UVMGenerator
             T := 'elementof ('storageof T)
             bytesize := if array?
                 count := 'translate-value self ctx ('typed-attribute@ instr 0 0)
-                count := uvm.uconvert (value = count) (stride = I64)
+                count := uvm.utou (value = count) (stride = I64)
                 uvm.imul (a = count) (b = 'sizeof T)
             else
                 uvm.const ('sizeof T)

          
@@ 620,7 608,7 @@ struct UVMGenerator
                     IT := 'typeof index
                     index := 'translate-value self ctx index
                     index := if (('sizeof IT) != (sizeof usize))
-                        uvm.uconvert (value = index) (stride = type-stride usize)
+                        uvm.utou (value = index) (stride = type-stride usize)
                     else index
                     ET := 'element@ T 0
                     pass ET

          
@@ 733,29 721,29 @@ struct UVMGenerator
             #case cast-kind-inttoptr
                 cast-op "OpConvertUToPtr" 'u '*
             case cast-kind-ptrotint
-                uvm.uconvert (value = value) (stride = type-stride T)
+                uvm.utou (value = value) (stride = type-stride T)
             case cast-kind-sext
-                uvm.sconvert (value = value) (stride = type-stride T)
+                uvm.stos (value = value) (stride = type-stride T)
             case cast-kind-zext
-                uvm.uconvert (value = value) (stride = type-stride T)
+                uvm.utou (value = value) (stride = type-stride T)
             case cast-kind-itrunc
                 stride := type-stride T
                 if (type-signed? ST)
-                    uvm.sconvert (value = value) (stride = stride)
+                    uvm.stos (value = value) (stride = stride)
                 else
-                    uvm.uconvert (value = value) (stride = stride)
-            #pass cast-kind-fptrunc
-            #pass cast-kind-fpext
-            #do
-                cast-op "OpFConvert" 'f 'f
-            #case cast-kind-fptoui
-                cast-op "OpConvertFToU" 'f 'u
-            #case cast-kind-fptosi
-                cast-op "OpConvertFToS" 'f 's
-            #case cast-kind-uitofp
-                cast-op "OpConvertUToF" 'u 'f
-            #case cast-kind-sitofp
-                cast-op "OpConvertUToF" 's 'f
+                    uvm.utou (value = value) (stride = stride)
+            pass cast-kind-fptrunc
+            pass cast-kind-fpext
+            do
+                uvm.ftof (value = value) (stride = type-stride T)
+            case cast-kind-fptoui
+                uvm.ftou (value = value) (stride = type-stride T)
+            case cast-kind-fptosi
+                uvm.ftos (value = value) (stride = type-stride T)
+            case cast-kind-uitofp
+                uvm.utof (value = value) (stride = type-stride T)
+            case cast-kind-sitofp
+                uvm.stof (value = value) (stride = type-stride T)
             pass cast-kind-ptrtoref
             pass cast-kind-reftoptr
             do value

          
M lib/scopes/compiler/target/UVM/instructions.sc +28 -4
@@ 8,12 8,10 @@ inline INSTRUCTIONS (T F)
         T 'i 'resize (F 'ref 'value) (F 'ref 'size) (F 'ref 'count)
         T 'i 'get (F 'ref 'value) (F 'ref 'index)
         T 'i 'set (F 'ref 'value) (F 'ref 'element) (F 'ref 'index)
-        T 'i 'countof (F 'ref 'value)
         T 'i 'unfold (F 'ref 'value) (F 'ref 'index)
         T 'i 'fold (F 'ref 'value) (F 'ref 'element) (F 'ref 'index)
         T 'i 'slice (F 'ref 'value) (F 'ref 'offset) (F 'ref 'size)
         T 'i 'replace (F 'ref 'value) (F 'ref 'offset) (F 'ref 'element)
-        T 'i 'sizeof (F 'ref 'value)
         T 'i 'findmsb (F 'ref 'value)
         T 'i 'findlsb (F 'ref 'value)
         T 'i 'bitcount (F 'ref 'value)

          
@@ 41,8 39,34 @@ inline INSTRUCTIONS (T F)
         T 'i 'sshr (F 'ref 'a) (F 'ref 'b)
         T 'i 'ushr (F 'ref 'a) (F 'ref 'b)
         T 'i 'select (F 'ref 'cond) (F 'ref 't) (F 'ref 'f)
-        T 'i 'uconvert (F 'ref 'value) (F 'u8 'stride)
-        T 'i 'sconvert (F 'ref 'value) (F 'u8 'stride)
+        T 'i 'utou (F 'ref 'value) (F 'logsize 'stride)
+        T 'i 'stos (F 'ref 'value) (F 'logsize 'stride)
+        T 'i 'fadd (F 'ref 'a) (F 'ref 'b)
+        T 'i 'fsub (F 'ref 'a) (F 'ref 'b)
+        T 'i 'fmul (F 'ref 'a) (F 'ref 'b)
+        T 'i 'fdiv (F 'ref 'a) (F 'ref 'b)
+        T 'i 'frem (F 'ref 'a) (F 'ref 'b)
+        T 'i 'fpow (F 'ref 'a) (F 'ref 'b)
+        T 'i 'fneg (F 'ref 'value)
+        T 'i 'sin (F 'ref 'value)
+        T 'i 'cos (F 'ref 'value)
+        T 'i 'sqrt (F 'ref 'value)
+        T 'i 'exp (F 'ref 'value)
+        T 'i 'exp2 (F 'ref 'value)
+        T 'i 'log (F 'ref 'value)
+        T 'i 'log2 (F 'ref 'value)
+        T 'i 'fabs (F 'ref 'value)
+        T 'i 'foeq (F 'ref 'a) (F 'ref 'b)
+        T 'i 'fune (F 'ref 'a) (F 'ref 'b)
+        T 'i 'folt (F 'ref 'a) (F 'ref 'b)
+        T 'i 'fole (F 'ref 'a) (F 'ref 'b)
+        T 'i 'fogt (F 'ref 'a) (F 'ref 'b)
+        T 'i 'foge (F 'ref 'a) (F 'ref 'b)
+        T 'i 'ftof (F 'ref 'value) (F 'logsize 'stride)
+        T 'i 'ftou (F 'ref 'value) (F 'logsize 'stride)
+        T 'i 'ftos (F 'ref 'value) (F 'logsize 'stride)
+        T 'i 'utof (F 'ref 'value) (F 'logsize 'stride)
+        T 'i 'stof (F 'ref 'value) (F 'logsize 'stride)
         T 'i 'call (F 'ref 'block) (F 'ref 'scope)
         T 'i 'ccall (F 'ref 'mem) (F 'ref 'target) (F 'ref 'value)
         T 'i 'csym (F 'ref 'target)

          
M src/uvm/gen_uvm.sc +44 -10
@@ 84,19 84,53 @@ UVM_OPS := sugar-quote
       -----------------------
     select cond:ref t:ref f:ref
 
-    # TODO: scalar arithmetic float operations
-    # TODO: scalar unary float operations
-    # TODO: scalar float comparisons (ordered)
-    # TODO: scalar float comparisons (unordered)
-        to be added later
-
     # scalar integer expansion/truncation
       -----------------------------------
-    # stride follows the same rules as with extract
-    uconvert value:ref stride:u8
-    sconvert value:ref stride:u8
+    utou value:ref stride:logsize
+    stos value:ref stride:logsize
+
+    # scalar arithmetic float operations
+      ----------------------------------
+
+    fadd a:ref b:ref
+    fsub a:ref b:ref
+    fmul a:ref b:ref
+    fdiv a:ref b:ref
+    frem a:ref b:ref
+    fpow a:ref b:ref
+
+    # scalar unary float operations
+      -----------------------------
 
-    # TODO: fconvert
+    fneg value:ref
+    sin value:ref
+    cos value:ref
+    sqrt value:ref
+    exp value:ref
+    exp2 value:ref
+    log value:ref
+    log2 value:ref
+    fabs value:ref
+
+    # scalar float comparisons
+      ------------------------
+
+    # fu/fo = un/ordered float comparison
+    foeq a:ref b:ref
+    fune a:ref b:ref
+    folt a:ref b:ref
+    fole a:ref b:ref
+    fogt a:ref b:ref
+    foge a:ref b:ref
+
+    # scalar float conversion
+      -----------------------
+
+    ftof value:ref stride:logsize
+    ftou value:ref stride:logsize
+    ftos value:ref stride:logsize
+    utof value:ref stride:logsize
+    stof value:ref stride:logsize
 
     # call block on stack
       -------------------

          
M src/uvm/uvm.cpp +60 -12
@@ 18,6 18,7 @@ receives parameters, is evaluated and pr
 #include <algorithm>
 #include <set>
 #include <map>
+#include <cmath>
 #include "../cache.hpp"
 #include "lmdb/lmdb.h"
 #include "ffi.h"

          
@@ 1306,7 1307,7 @@ template<template<typename... Args> clas
 struct FixedVectorOp {
     template<class... Types>
     static inline void f(void *dest, const Types *... args) {
-#if 0
+#if 1
         for (size_t i = 0; i < count; ++i) {
             ((R *)dest)[i] = OpT<R, T ...>::f(((const T *)args)[i]...);
         }

          
@@ 1322,11 1323,13 @@ int findmsb64(uint64_t x) {
 
 template<typename R, typename A> struct FindMSB {
     // todo: properly do this for 128 bit
-    static inline R f(A a) { return __builtin_clzll(a[0]) ^ 63; }
+    static inline R f(A a) { return __builtin_clzll(a) ^ 63; }
 };
 
 #define IFX_OP2_TEMPLATE(NAME, OP) \
     template<typename R, typename A, typename B> struct NAME { static inline R f(A a, B b) { return a OP b; }; };
+#define AFX_OP2_TEMPLATE(NAME, OP) \
+    template<typename R, typename A, typename B> struct NAME { static inline R f(A a, B b) { return OP(a, b); }; };
 #define IFX_BOOL_OP2_TEMPLATE(NAME, OP) \
     template<typename R, typename A, typename B> struct NAME { \
         static inline R f(A a, B b) { return (a OP b) & 1; }; \

          
@@ 1352,6 1355,12 @@ IFX_OP2_TEMPLATE(IXOr, ^)
 IFX_OP2_TEMPLATE(IShl, <<)
 IFX_OP2_TEMPLATE(IShr, >>)
 
+IFX_OP2_TEMPLATE(FAdd, +)
+IFX_OP2_TEMPLATE(FSub, -)
+IFX_OP2_TEMPLATE(FMul, *)
+IFX_OP2_TEMPLATE(FDiv, /)
+AFX_OP2_TEMPLATE(FRem, std::fmod)
+
 IFX_BOOL_OP2_TEMPLATE(IEq, ==)
 IFX_BOOL_OP2_TEMPLATE(INe, !=)
 IFX_BOOL_OP2_TEMPLATE(ILt, <)

          
@@ 1375,7 1384,7 @@ template<typename U, typename V, typenam
 };
 
 template<typename R, typename A> struct IConvert {
-    static inline R f(A a) { return __builtin_convertvector(a, R); };
+    static inline R f(A a) { return R(a); };
 };
 
 #undef IFX_OP2_TEMPLATE

          
@@ 1776,8 1785,24 @@ inline Cell &uvm_apply_countof(UVM &vm, 
 
 const char *uvm_instruction_kind_name(InstructionKind kind) {
     switch(kind) {
+    #define F(T, NAME)
+    #define T0(CLASS,NAME) case uvmi_ ## NAME: return #NAME;
+    #define T1(CLASS,NAME, ...) T0(CLASS,NAME)
+    #define T2(CLASS,NAME, ...) T0(CLASS,NAME)
+    #define T3(CLASS,NAME, ...) T0(CLASS,NAME)
+    #define T4(CLASS,NAME, ...) T0(CLASS,NAME)
+    #define T5(CLASS,NAME, ...) T0(CLASS,NAME)
+        UVM_INSTRUCTIONS()
+    #undef T0
+    #undef T1
+    #undef T2
+    #undef T3
+    #undef T4
+    #undef T5
+    #undef F
     default: return "?";
     }
+
 }
 
 bool uvm_is_final_instruction(InstructionKind kind) {

          
@@ 1798,6 1823,8 @@ bool uvm_is_final_instruction(Instructio
     #undef T3
     #undef T4
     #undef T5
+    #undef Ti
+    #undef Tf
     #undef F
         return true;
     default: return false;

          
@@ 1856,7 1883,7 @@ BlockValidationResult uvm_check_valid_bl
         }
         switch(instr.f_any.kind) {
 #define Fu32(NAME)
-#define Fu8(NAME) \
+#define Flogsize(NAME) \
     if (size_t(v.NAME) > 4) return Validated_HugeStride;
 #define Fref(NAME) \
     if (v.NAME < 0) { \

          
@@ 1900,7 1927,7 @@ BlockValidationResult uvm_check_valid_bl
 #undef F
 #undef F1
 #undef Fref
-#undef Fu8
+#undef Flogsize
 #undef Fu32
         default: return Validated_StrangeInstruction;
         }

          
@@ 1956,7 1983,7 @@ BlockInfo &uvm_block_info(UVM &vm, Cell 
         uint8_t arg = 0;
         switch(instr.f_any.kind) {
 #define Fu32(NAME) arg++;
-#define Fu8(NAME) arg++;
+#define Flogsize(NAME) arg++;
 #define Fref(NAME) \
     if (v.NAME >= 0) { \
         uvm_ref pos = v.NAME; \

          
@@ 1999,7 2026,7 @@ BlockInfo &uvm_block_info(UVM &vm, Cell 
 #undef F
 #undef F1
 #undef Fref
-#undef Fu8
+#undef Flogsize
 #undef Fu32
         default: assert(false && "unknown instruction"); break;
         }

          
@@ 2053,7 2080,7 @@ void uvm_dump_disas_instr(UVM &vm, Cell 
     switch(instr.f_any.kind) {
 #define Fu32(NAME) \
     w += fprintf(stderr, "%u ", v.NAME);
-#define Fu8(NAME) \
+#define Flogsize(NAME) \
     w += fprintf(stderr, "i%zu ", (size_t(8) << size_t(v.NAME)));
 #define Fref(NAME) \
     if (v.NAME < 0) { \

          
@@ 2118,7 2145,7 @@ void uvm_dump_disas_instr(UVM &vm, Cell 
 #undef F
 #undef F1
 #undef Fref
-#undef Fu8
+#undef Flogsize
 #undef Fu32
     default: w += fprintf(stderr, "?"); break;
     }

          
@@ 3111,6 3138,12 @@ inline void uvm_eval(UVM &vm, uvm_ref ip
             uint8_t, uint16_t, uint32_t, uint64_t, __uint128_t, \
             CLASS>(vm, uvm_deref(vm, v.value, Weak)); \
     UVM_CASE_END()
+#define UVM_FOP2(NAME, CLASS) \
+    UVM_CASE_BEGIN(NAME) \
+        result = &uvm_apply_op2< \
+            float, float, float, double, double, \
+            CLASS>(vm, uvm_deref(vm, v.a, Weak), uvm_deref(vm, v.b, Weak)); \
+    UVM_CASE_END()
 #define UVM_UOP2(NAME, CLASS) \
     UVM_CASE_BEGIN(NAME) \
         result = &uvm_apply_op2< \

          
@@ 3185,10 3218,12 @@ inline void uvm_eval(UVM &vm, uvm_ref ip
             uvm_deref(vm, v.element, Taken),
             uvm_deref(vm, v.index, Weak));
     UVM_CASE_END()
+    #if 0
     UVM_CASE_BEGIN(countof)
         result = &uvm_apply_countof(vm,
             uvm_deref(vm, v.value, Weak));
     UVM_CASE_END()
+    #endif
 
     UVM_OP1(findmsb, FindMSB)
 

          
@@ 3200,6 3235,12 @@ inline void uvm_eval(UVM &vm, uvm_ref ip
     UVM_SOP2(srem, IRem)
     UVM_UOP2(urem, IRem)
 
+    UVM_FOP2(fadd, FAdd)
+    UVM_FOP2(fsub, FSub)
+    UVM_FOP2(fmul, FMul)
+    UVM_FOP2(fdiv, FDiv)
+    UVM_FOP2(frem, FRem)
+
     UVM_UOP2(iand, IAnd)
     UVM_UOP2(ior, IOr)
     UVM_UOP2(ixor, IXOr)

          
@@ 3232,10 3273,12 @@ inline void uvm_eval(UVM &vm, uvm_ref ip
             uvm_deref(vm, v.element, Weak));
     UVM_CASE_END()
 
+    #if 0
     UVM_CASE_BEGIN(sizeof)
         result = &uvm_apply_sizeof(vm,
             uvm_deref(vm, v.value, Weak));
     UVM_CASE_END()
+    #endif
 
     UVM_CASE_BEGIN(select)
         result = &uvm_apply_select<ISelect>(vm,

          
@@ 3244,7 3287,7 @@ inline void uvm_eval(UVM &vm, uvm_ref ip
             uvm_deref(vm, v.f, Weak));
     UVM_CASE_END()
 
-    UVM_CASE_BEGIN(uconvert)
+    UVM_CASE_BEGIN(utou)
         result = &uvm_apply_convert<
             uint8_t, uint16_t, uint32_t, uint64_t, __uint128_t,
             uint8_t, uint16_t, uint32_t, uint64_t, __uint128_t,

          
@@ 3252,7 3295,7 @@ inline void uvm_eval(UVM &vm, uvm_ref ip
                 uvm_deref(vm, v.value, Weak),
                 v.stride);
     UVM_CASE_END()
-    UVM_CASE_BEGIN(sconvert)
+    UVM_CASE_BEGIN(stos)
         result = &uvm_apply_convert<
             int8_t, int16_t, int32_t, int64_t, __int128_t,
             int8_t, int16_t, int32_t, int64_t, __int128_t,

          
@@ 3379,7 3422,12 @@ inline void uvm_eval(UVM &vm, uvm_ref ip
     UVM_CASE_END()
     UVM_CASE_BEGIN0(source)
     UVM_CASE_END()
-    default: assert(false && "unsupported instruction"); break;
+    default:
+        fprintf(stderr, "UVM: unsupported instruction: '%s'\n",
+            uvm_instruction_kind_name((uvm_instruction_kind_t)instr.f_any.kind));
+        assert(false && "unsupported instruction");
+        exit(1);
+        break;
     }
     // move reference to stack
     uvm_stack_push(vm, result);

          
M testing/test_uvm.sc +18 -1
@@ 99,6 99,10 @@ inline uvm-test-with-args (f ...)
                 pass tflags
                     'dump-disassembly
                     cflags...
+            elseif (arg == 'module)
+                pass tflags
+                    'dump-module
+                    cflags...
 
     func_uref module... := compile-uvm f cflags...
 

          
@@ 228,7 232,7 @@ fn ()
     printf "\n"
     ;
 
-@@ uvm-test #'disassembly #'memory #'execution #
+@@ uvm-test #'modue #'memory #'execution #
 fn ()
     # complex dynamic array example with our cool printer
     using import print

          
@@ 242,6 246,19 @@ fn ()
 
 ################################################################################
 
+@@ uvm-test #'execution
+fn ()
+    # float arithmetic
+    fn unconst (x) x
+    a := unconst 3.5
+    b := unconst 1.5
+    c := unconst 7.1
+    printf "%f\n"
+        a * b + c
+    ;
+
+################################################################################
+
 #do
     using import compiler.target.UVM compiler.target.UVM.api format C.stdio
         \ Array String print