ec3cd9c27fee — Leonard Ritter 8 days ago
* llvm_gen.cpp is ported
M lib/scopes/compiler/retcon/Value.sx +44 -44
@@ 411,8 411,8 @@ abstract type Value
             value : Value
         type CGenInvalidRedeclarationError
             msg = "codegen: unexpected previous declaration of symbol '{sym}' while declaring {decl}"
-            sym : String
-            decl : String
+            sym : builtin_string
+            decl : builtin_string
         type CGenUnsupportedBuiltinError
             msg = "codegen: builtin {value} is unsupported for this target"
             value : Builtin

          
@@ 453,10 453,10 @@ abstract type Value
             cycle : Global
         type CGenBackendFailedError
             msg = "codegen backend failed: {reason}"
-            reason : String
+            reason : builtin_string
         type CGenBackendFailedErrnoError
             msg = "codegen backend failed: {reason} ({code})"
-            reason : String
+            reason : builtin_string
             code : errno
         type CGenCannotSerializeConstPointerError
             msg = "codegen: cannot serialize constant pointer of type {type}."

          
@@ 579,13 579,13 @@ abstract type Value
             path : Symbol
         type UserError
             msg = "{reason}"
-            reason : String
+            reason : builtin_string
         type ExecutionEngineFailedError
             msg = "execution engine failed: {reason}"
-            reason : String
+            reason : builtin_string
         type OptimizationPassFailedError
             msg = "optimization pass failed: {reason}"
-            reason : String
+            reason : builtin_string
         type StackOverflowError
             msg = "stack overflow encountered"
 

          
@@ 955,7 955,7 @@ abstract type Value
             insert_index : i32
             flags : BlockFlags
             body : Instructions
-            terminator : Instruction
+            terminator : ? Terminator
             function : Function
             valid : IDSet
             owner : Instruction

          
@@ 1015,11 1015,10 @@ abstract type Value
             typedef Consts : Array Const
             abstract type Const
                 type ConstNull
-                abstract type ConstNumber
-                    type ConstInt
-                        words : Array u64
-                    type ConstReal
-                        value : f64
+                type ConstInt
+                    words : Array u64
+                type ConstReal
+                    value : f64
                 type ConstString
                     value : String
                 type ConstAggregate

          
@@ 1077,8 1076,8 @@ abstract type Value
             type Call
                 callee : TypedValue
                 args : TypedValues
-                except : Exception
-                except_body : Block
+                except : ? Exception
+                except_body : ? Block
             type Select
                 cond : TypedValue
                 value1 : TypedValue

          
@@ 1148,37 1147,38 @@ abstract type Value
                 type BarrierMemoryImage
                 type BarrierMemoryBuffer
                 type BarrierMemoryShared
-            abstract type Cmp
+            abstract type ICmp
+                enum ICmpKind
                 value1 : TypedValue
                 value2 : TypedValue
-                abstract type ICmp
-                    enum ICmpKind
-                    type ICmpEQ
-                    type ICmpNE
-                    type ICmpUGT
-                    type ICmpUGE
-                    type ICmpULT
-                    type ICmpULE
-                    type ICmpSGT
-                    type ICmpSGE
-                    type ICmpSLT
-                    type ICmpSLE
-                abstract type FCmp
-                    enum FCmpKind
-                    type FCmpOEQ
-                    type FCmpONE
-                    type FCmpORD
-                    type FCmpOGT
-                    type FCmpOGE
-                    type FCmpOLT
-                    type FCmpOLE
-                    type FCmpUEQ
-                    type FCmpUNE
-                    type FCmpUNO
-                    type FCmpUGT
-                    type FCmpUGE
-                    type FCmpULT
-                    type FCmpULE
+                type ICmpEQ
+                type ICmpNE
+                type ICmpUGT
+                type ICmpUGE
+                type ICmpULT
+                type ICmpULE
+                type ICmpSGT
+                type ICmpSGE
+                type ICmpSLT
+                type ICmpSLE
+            abstract type FCmp
+                enum FCmpKind
+                value1 : TypedValue
+                value2 : TypedValue
+                type FCmpOEQ
+                type FCmpONE
+                type FCmpORD
+                type FCmpOGT
+                type FCmpOGE
+                type FCmpOLT
+                type FCmpOLE
+                type FCmpUEQ
+                type FCmpUNE
+                type FCmpUNO
+                type FCmpUGT
+                type FCmpUGE
+                type FCmpULT
+                type FCmpULE
             abstract type UnOp
                 enum UnOpKind
                 value : TypedValue

          
M src/anchor.hpp +3 -0
@@ 64,6 64,9 @@ public:
 Anchor builtin_anchor();
 Anchor unknown_anchor();
 
+// return most significant source location
+SourceLocation anchor_location(Anchor anchor);
+
 bool is_boring(Anchor anchor);
 bool contains(SourceLocation a, SourceLocation b);
 

          
M src/execution.cpp +10 -6
@@ 177,13 177,17 @@ void print_disassembly(std::string symbo
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static String LLVMConvertMessageString(char *err) {
-    auto result = string_from_cstr(err);
-    LLVMDisposeErrorMessage(err);
-    return result;
+static std::string LLVMConvertMessageString(char *err) {
+    if (err) {
+        auto result = err;
+        LLVMDisposeErrorMessage(err);
+        return result;
+    } else {
+        return "null";
+    }
 }
 
-static String LLVMGetErrorMessageString(LLVMErrorRef err) {
+static std::string LLVMGetErrorMessageString(LLVMErrorRef err) {
     return LLVMConvertMessageString(LLVMGetErrorMessage(err));
 }
 

          
@@ 237,7 241,7 @@ static LLVMTargetMachineRef object_targe
 //static std::vector<void *> loaded_libs;
 static std::unordered_map<Symbol, void *> cached_dlsyms;
 
-String get_default_target_triple() {
+std::string get_default_target_triple() {
     return LLVMConvertMessageString(LLVMGetDefaultTargetTriple());
 }
 

          
M src/execution.hpp +1 -1
@@ 24,7 24,7 @@ namespace scopes {
 
 typedef std::unordered_map<std::string, const void *> PointerMap;
 
-String get_default_target_triple();
+std::string get_default_target_triple();
 SCOPES_RESULT(void) init_execution();
 SCOPES_RESULT(void) add_module(LLVMModuleRef module,
     const PointerMap &map, uint64_t compiler_flags);

          
M src/gen_llvm.cpp +357 -284
@@ 14,6 14,7 @@ 
 #include "scope.hpp"
 #include "timer.hpp"
 #include "value.hpp"
+#include "string.hpp"
 #include "stream_expr.hpp"
 #include "compiler_flags.hpp"
 #include "prover.hpp"

          
@@ 82,6 83,7 @@ struct PointerNamespace {
     size_t next_pointer_id = 1;
     char kind = '?';
     std::unordered_map<const void *, std::string> ptr2id;
+    std::unordered_map<size_t, std::string> id2id;
 
     std::string get_pointer_id(const void *ptr) {
         auto it = ptr2id.find(ptr);

          
@@ 89,10 91,24 @@ struct PointerNamespace {
             return it->second;
         }
         auto id = next_pointer_id++;
-        StringPrinter sp;
+        NameStringPrinter sp;
+        sp(Pcat("$*",kind,Phex(name),"_",Phex(id)));
+        auto result = sp.tostring();
+        ptr2id.insert({ptr, result});
+        return result;
+    }
+
+    std::string get_id(Value value) {
+        size_t ptr = value.id();
+        auto it = id2id.find(ptr);
+        if (it != id2id.end()) {
+            return it->second;
+        }
+        auto id = next_pointer_id++;
+        NameStringPrinter sp;
         sp(Pcat("$",kind,Phex(name),"_",Phex(id)));
         auto result = sp.tostring();
-        ptr2id.insert({ptr, result});
+        id2id.insert({ptr, result});
         return result;
     }
 };

          
@@ 441,24 457,24 @@ struct LLVMIRGenerator {
         return _ns->local.get_pointer_id(ptr);
     }
 
-    std::string get_global_pointer_id(const void *ptr) {
+    std::string get_global_id(Value value) {
         assert(_ns);
-        return _ns->global.get_pointer_id(ptr);
+        return _ns->global.get_id(value);
     }
-    std::string get_func_pointer_id(const void *ptr) {
+    std::string get_func_id(Value value) {
         assert(_ns);
-        return _ns->func.get_pointer_id(ptr);
+        return _ns->func.get_id(value);
     }
 
-    static const Type *arguments_to_tuple(const Type *T) {
+    static Type arguments_to_tuple(Type T) {
         if (isa<ArgumentsType>(T)) {
             return to_tuple_type(cast<ArgumentsType>(T));
         }
         return T;
     }
 
-    static const Type *abi_return_type(const FunctionType *ft) {
-        if (ft->has_exception()) {
+    static Type abi_return_type(FunctionType ft) {
+        if (has_exception(ft)) {
             if (is_returning_value(ft->except_type)) {
                 Types types = { TYPE_Bool, arguments_to_tuple(ft->except_type) };
                 if (is_returning_value(ft->return_type)) {

          
@@ 509,9 525,9 @@ struct LLVMIRGenerator {
 
         static char _fname[PATH_MAX];
         static char _dname[PATH_MAX];
-        auto str = sf.name();
-        strncpy(_fname, str->data, PATH_MAX - 1);
-        strncpy(_dname, str->data, PATH_MAX - 1);
+        auto &&str = sf->data;
+        strncpy(_fname, str.data(), PATH_MAX - 1);
+        strncpy(_dname, str.data(), PATH_MAX - 1);
 
         char *fname = basename(_fname);
         char *dname = dirname(_dname);

          
@@ 527,13 543,13 @@ struct LLVMIRGenerator {
     LLVMMetadataRef function_to_subprogram(Function l) {
         assert(use_debug_info);
 
-        auto it = func2md.find(l.unref());
+        auto it = func2md.find(l);
         if (it != func2md.end())
             return it->second;
 
-        const Anchor *anchor = l.anchor();
-
-        LLVMMetadataRef difile = source_file_to_scope(anchor->path);
+        SourceLocation loc = anchor_location(anchorof(l));
+
+        LLVMMetadataRef difile = source_file_to_scope(loc->source->path);
 
         /*
         LLVMMetadataRef subroutinevalues[] = {

          
@@ 543,15 559,15 @@ struct LLVMIRGenerator {
         LLVMMetadataRef disrt = LLVMDIBuilderCreateSubroutineType(di_builder,
             difile, nullptr, 0, LLVMDIFlagZero);
 
-        auto name = l->name.name();
+        auto &&name = l->name->data;
         LLVMMetadataRef difunc = LLVMDIBuilderCreateFunction(
-            di_builder, difile, name->data, name->count,
+            di_builder, difile, name.data(), name.size(),
             // todo: insert actual linkage name here
-            name->data, name->count,
-            difile, anchor->first.lineno, disrt, false, true,
-            anchor->first.lineno, LLVMDIFlagZero, false);
-
-        func2md.insert({ l.unref(), difunc });
+            name.data(), name.size(),
+            difile, loc->line, disrt, false, true,
+            loc->line, LLVMDIFlagZero, false);
+
+        func2md.insert({ l, difunc });
         return difunc;
     }
 

          
@@ 873,7 889,7 @@ struct LLVMIRGenerator {
 //         return LLVMDIBuilderCreateStructType(di_builder, "", 0, nullptr, 0, LLVMStructType(types, sz, false);
 //     }
 
-    SCOPES_RESULT(LLVMValueRef) abi_import_argument(Builder &builder, const Type *param_type, LLVMValueRef func, size_t &k) {
+    SCOPES_RESULT(LLVMValueRef) abi_import_argument(Builder &builder, Type param_type, LLVMValueRef func, size_t &k) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
         ABIClass classes[MAX_ABI_CLASSES];
         size_t sz = abi_classify(param_type, classes);

          
@@ 913,7 929,7 @@ struct LLVMIRGenerator {
         return val;
     }
 
-    SCOPES_RESULT(void) abi_export_argument(Builder &builder, LLVMValueRef val, const Type *AT,
+    SCOPES_RESULT(void) abi_export_argument(Builder &builder, LLVMValueRef val, Type AT,
         LLVMValueRefs &values, LLVMTypeRefs &types, std::vector<size_t> &memptrs) {
         SCOPES_RESULT_TYPE(void);
         ABIClass classes[MAX_ABI_CLASSES];

          
@@ 959,7 975,7 @@ struct LLVMIRGenerator {
         return {};
     }
 
-    static SCOPES_RESULT(void) abi_transform_parameter(const Type *AT,
+    static SCOPES_RESULT(void) abi_transform_parameter(Type AT,
         LLVMTypeRefs &params) {
         SCOPES_RESULT_TYPE(void);
         ABIClass classes[MAX_ABI_CLASSES];

          
@@ 988,10 1004,10 @@ struct LLVMIRGenerator {
         return {};
     }
 
-    static SCOPES_RESULT(LLVMTypeRef) create_llvm_type(const Type *type) {
+    static SCOPES_RESULT(LLVMTypeRef) create_llvm_type(Type type) {
         SCOPES_RESULT_TYPE(LLVMTypeRef);
-        switch(type->kind()) {
-        case TK_Qualify: {
+        switch(type.subkind()) {
+        case TypeKind::QualifyType: {
             auto qt = cast<QualifyType>(type);
             auto lltype = SCOPES_GET_RESULT(_type_to_llvm_type(qt->type));
             auto rq = try_qualifier<ReferQualifier>(type);

          
@@ 1000,12 1016,12 @@ struct LLVMIRGenerator {
             }
             return lltype;
         } break;
-        case TK_Integer: {
+        case TypeKind::IntegerType: {
             //auto width = std::max(8ul, cast<IntegerType>(type)->width);
             auto width = cast<IntegerType>(type)->width;
             return LLVMIntType(width);
         } break;
-        case TK_Real:
+        case TypeKind::RealType:
             switch(cast<RealType>(type)->width) {
             case 32: return f32T;
             case 64: return f64T;

          
@@ 1014,24 1030,24 @@ struct LLVMIRGenerator {
             default: break;
             }
             break;
-        case TK_Pointer:
+        case TypeKind::PointerType:
             return LLVMPointerType(
                 SCOPES_GET_RESULT(_type_to_llvm_type(cast<PointerType>(type)->element_type)), 0);
-        case TK_Array:
-        case TK_Matrix: {
+        case TypeKind::ArrayType:
+        case TypeKind::MatrixType: {
             auto ai = cast<ArrayLikeType>(type);
-            return LLVMArrayType(SCOPES_GET_RESULT(_type_to_llvm_type(ai->element_type)), ai->full_count());
+            return LLVMArrayType(SCOPES_GET_RESULT(_type_to_llvm_type(ai->element_type)), fullcountof(ai));
         } break;
-        case TK_Vector: {
+        case TypeKind::VectorType: {
             auto vi = cast<ArrayLikeType>(type);
-            return LLVMVectorType(SCOPES_GET_RESULT(_type_to_llvm_type(vi->element_type)), vi->count());
+            return LLVMVectorType(SCOPES_GET_RESULT(_type_to_llvm_type(vi->element_type)), countof(vi));
         } break;
-        case TK_Arguments: {
+        case TypeKind::ArgumentsType: {
             if (type == empty_arguments_type())
                 return LLVMVoidType();
-            return create_llvm_type(cast<ArgumentsType>(type)->to_tuple_type());
+            return create_llvm_type(to_tuple_type(cast<ArgumentsType>(type)));
         } break;
-        case TK_Tuple: {
+        case TypeKind::TupleType: {
             auto ti = cast<TupleType>(type);
             size_t count = ti->values.size();
             LLVMTypeRef elements[count];

          
@@ 1040,25 1056,25 @@ struct LLVMIRGenerator {
             }
             return LLVMStructType(elements, count, ti->packed);
         } break;
-        case TK_Typename: {
+        case TypeKind::TypenameType: {
             if (type == TYPE_Sampler) {
                 SCOPES_ERROR(CGenTypeUnsupportedInTarget, TYPE_Sampler);
             }
             auto tn = cast<TypenameType>(type);
-            if (!tn->is_opaque()) {
-                switch(tn->storage()->kind()) {
-                case TK_Tuple: {
+            if (!is_opaque(tn)) {
+                switch(storageof(tn).subkind()) {
+                case TypeKind::TupleType: {
                     type_todo.push_back(type);
                 } break;
                 default: {
-                    return create_llvm_type(tn->storage());
+                    return create_llvm_type(storageof(tn));
                 } break;
                 }
             }
             return LLVMStructCreateNamed(
-                LLVMGetGlobalContext(), tn->name()->data);
+                LLVMGetGlobalContext(), typename_name(tn)->data.data());
         } break;
-        case TK_Function: {
+        case TypeKind::FunctionType: {
             auto fi = cast<FunctionType>(type);
             size_t count = fi->argument_types.size();
             auto rtype = abi_return_type(fi);

          
@@ 1089,15 1105,15 @@ struct LLVMIRGenerator {
                 SCOPES_CHECK_RESULT(abi_transform_parameter(AT, elements));
             }
             return LLVMFunctionType(rettype,
-                &elements[0], elements.size(), fi->vararg());
+                &elements[0], elements.size(), is_variadic(fi));
         } break;
-        case TK_SampledImage: {
+        case TypeKind::SampledImageType: {
             SCOPES_ERROR(CGenTypeUnsupportedInTarget, TYPE_SampledImage);
         } break;
-        case TK_Image: {
+        case TypeKind::ImageType: {
             SCOPES_ERROR(CGenTypeUnsupportedInTarget, TYPE_Image);
         } break;
-        case TK_Sampler: {
+        case TypeKind::SamplerType: {
             SCOPES_ERROR(CGenTypeUnsupportedInTarget, TYPE_Sampler);
         } break;
         default: break;

          
@@ 1110,15 1126,15 @@ struct LLVMIRGenerator {
         SCOPES_RESULT_TYPE(size_t);
         size_t result = type_todo.size();
         while (!type_todo.empty()) {
-            const Type *T = type_todo.back();
+            Type T = type_todo.back();
             type_todo.pop_back();
             auto tn = cast<TypenameType>(T);
-            if (tn->is_opaque())
+            if (is_opaque(tn))
                 continue;
             LLVMTypeRef LLT = SCOPES_GET_RESULT(_type_to_llvm_type(T));
-            const Type *ST = tn->storage();
-            switch(ST->kind()) {
-            case TK_Tuple: {
+            Type ST = storageof(tn);
+            switch(ST.subkind()) {
+            case TypeKind::TupleType: {
                 auto ti = cast<TupleType>(ST);
                 size_t count = ti->values.size();
                 LLVMTypeRef elements[count];

          
@@ 1133,7 1149,7 @@ struct LLVMIRGenerator {
         return result;
     }
 
-    static SCOPES_RESULT(LLVMTypeRef) _type_to_llvm_type(const Type *type) {
+    static SCOPES_RESULT(LLVMTypeRef) _type_to_llvm_type(Type type) {
         SCOPES_RESULT_TYPE(LLVMTypeRef);
         auto it = type_cache.find(type);
         if (it == type_cache.end()) {

          
@@ 1145,7 1161,7 @@ struct LLVMIRGenerator {
         }
     }
 
-    static SCOPES_RESULT(LLVMTypeRef) type_to_llvm_type(const Type *type) {
+    static SCOPES_RESULT(LLVMTypeRef) type_to_llvm_type(Type type) {
         SCOPES_RESULT_TYPE(LLVMTypeRef);
         auto typeref = SCOPES_GET_RESULT(_type_to_llvm_type(type));
         SCOPES_CHECK_RESULT(finalize_types());

          
@@ 1335,19 1351,21 @@ struct LLVMIRGenerator {
     }
 #endif
 
-    static Error *last_llvm_error;
+    static Maybe<Error> last_llvm_error;
     static void fatal_error_handler(const char *Reason) {
-        last_llvm_error = ErrorCGenBackendFailed::from(strdup(Reason));
+        last_llvm_error = CGenBackendFailedError::from({
+            .by = unknown_anchor(),
+            .reason = Reason });
     }
 
     SCOPES_RESULT(LLVMValueRef) write_return(Builder &builder, const LLVMValueRefs &values, bool is_except = false) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
         assert(builder.active_function);
-        auto fi = extract_function_type(builder.active_function->get_type());
+        auto fi = extract_function_type(builder.active_function->type);
         auto rtype = abi_return_type(fi);
         auto abiretT = SCOPES_GET_RESULT(type_to_llvm_type(rtype));
         LLVMValueRef value = nullptr;
-        if (fi->has_exception()) {
+        if (has_exception(fi)) {
             bool has_except_value = is_returning_value(fi->except_type);
             bool has_return_value = is_returning_value(fi->return_type);
 

          
@@ 1441,7 1459,7 @@ struct LLVMIRGenerator {
         assert(builder.active_function == node);
         LLVMValueRef func = resolve(builder, ValueIndex(node));
         assert(func);
-        auto ilfunctype = node->get_type();
+        auto ilfunctype = node->type;
         auto fi = extract_function_type(ilfunctype);
         auto rtype = abi_return_type(fi);
         bool use_sret = is_memory_class(rtype);

          
@@ 1453,7 1471,7 @@ struct LLVMIRGenerator {
             builder.try_info.bb_except = LLVMAppendBasicBlock(func, "except");
             builder.position_builder_at_end(builder.try_info.bb_except);
             if (use_debug_info)
-                set_debug_location(builder, node.anchor());
+                set_debug_location(builder, anchorof(node));
             SCOPES_CHECK_RESULT(build_phi(builder, builder.try_info.except_values, fi->except_type));
             SCOPES_CHECK_RESULT(write_return(builder, builder.try_info.except_values, true));
         }

          
@@ 1476,11 1494,11 @@ struct LLVMIRGenerator {
         size_t paramcount = params.size();
 
         if (use_debug_info)
-            set_debug_location(builder, node.anchor());
+            set_debug_location(builder, anchorof(node));
         size_t k = offset;
         for (size_t i = 0; i < paramcount; ++i) {
-            ParameterRef param = params[i];
-            LLVMValueRef val = SCOPES_GET_RESULT(abi_import_argument(builder, param->get_type(), func, k));
+            Parameter param = params[i];
+            LLVMValueRef val = SCOPES_GET_RESULT(abi_import_argument(builder, param->type, func, k));
 #if SCOPES_LLVM_EXTENDED_DEBUG_INFO
             if (use_debug_info) {
                 auto subprogram = LLVMGetSubprogram(func);

          
@@ 1500,7 1518,7 @@ struct LLVMIRGenerator {
 #endif
 
             assert(val);
-            builder.bind(ValueIndex(param), val);
+            builder.bind(value_index(param), val);
         }
         SCOPES_CHECK_RESULT(translate_block(builder, node->body));
 #if SCOPES_LLVM_EXTENDED_DEBUG_INFO

          
@@ 1514,43 1532,41 @@ struct LLVMIRGenerator {
     SCOPES_RESULT(LLVMValueRef) Function_to_value(Function node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
 
-        auto ilfunctype = extract_function_type(node->get_type());
+        auto ilfunctype = extract_function_type(node->type);
 
         bool is_export = false;
         std::string name;
         bool is_external = false;
 
         if (generate_object) {
-            auto it = func_export_table.find(node.unref());
+            auto it = func_export_table.find(node);
             if (it != func_export_table.end()) {
-                auto str = it->second.name();
-                name = std::string(str->data, str->count);
+                name = it->second->data;
                 is_export = true;
             }
         } else {
-            auto it = func_cache.find(node.unref());
+            auto it = func_cache.find(node);
             if (it == func_cache.end()) {
                 auto funcname = node->name;
-                StyledString ss = StyledString::plain();
+                NameStringPrinter sp;
                 if (funcname == SYM_Unnamed) {
-                    ss.out << "unnamed";
+                    sp("unnamed");
                 } else {
-                    ss.out << funcname.name()->data;
+                    sp(funcname->data);
                 }
 
-                ss.out << "<";
+                sp(Pcat,"<");
                 int index = 0;
                 for (auto T : ilfunctype->argument_types) {
                     if (index > 0)
-                        ss.out << ",";
-                    stream_type_name(ss.out, T);
+                        sp(Pcat,",");
+                    sp(Pcat, T);
                     index++;
                 }
-                ss.out << ">";
-                ss.out << get_func_pointer_id(node.unref());
-                name = ss.cppstr();
-
-                func_cache.insert({node.unref(), name});
+                sp(Pcat,">",Pcat,get_func_id(node));
+                name = sp.tostring();
+
+                func_cache.insert({node, name});
             } else {
                 name = it->second;
                 is_external = true;

          
@@ 1563,7 1579,7 @@ struct LLVMIRGenerator {
             auto result = GetNamedGlobalOrFunction(module, name.c_str());
             if (result) {
                 LLVMDumpValue(result);
-                SCOPES_ERROR(CGenInvalidRedeclaration, name.c_str(), "function");
+                SCOPES_ERROR(CGenInvalidRedeclaration, name, "function");
             }
         }
 

          
@@ 1589,7 1605,7 @@ struct LLVMIRGenerator {
             LLVMSetLinkage(func, LLVMPrivateLinkage);
             LLVMSetVisibility(func, LLVMHiddenVisibility);
         }
-        global_builder.bind(ValueIndex(node), func);
+        global_builder.bind(value_index(node), func);
         Builder builder(node);
         SCOPES_CHECK_RESULT(Function_finalize(builder, node));
 

          
@@ 1628,7 1644,7 @@ struct LLVMIRGenerator {
             SCOPES_CHECK_RESULT(translate_instruction(builder, entry));
         }
         if (node->terminator) {
-            SCOPES_CHECK_RESULT(translate_instruction(builder, node->terminator));
+            SCOPES_CHECK_RESULT(translate_instruction(builder, *node->terminator));
         }
 #if SCOPES_LLVM_EXTENDED_DEBUG_INFO
         if (use_debug_info) {

          
@@ 1653,14 1669,14 @@ struct LLVMIRGenerator {
     SCOPES_RESULT(void) build_merge_phi(Builder &builder, const LLVMValueRefs &phis, const TypedValues &values) {
         SCOPES_RESULT_TYPE(void);
         if (phis.size() != values.size()) {
-            StyledStream ss;
             for (auto phi : phis) {
                 LLVMDumpValue(phi);
-                ss << std::endl;
+                print2("");
             }
             for (auto value : values) {
-                stream_value(ss, value, StreamValueFormat::singleline());
+                print2(Pnolines(value),Pcat);
             }
+            print2("");
         }
         assert(phis.size() == values.size());
         LLVMBasicBlockRef bb = LLVMGetInsertBlock(builder);

          
@@ 1690,7 1706,7 @@ struct LLVMIRGenerator {
 
     SCOPES_RESULT(void) translate_Merge(Builder &builder, Merge node) {
         SCOPES_RESULT_TYPE(void);
-        auto label = node->label.cast<Label>();
+        auto label = cast<Label>(node->label);
         SCOPES_CHECK_RESULT(build_merge(builder, label, node->values));
         return {};
     }

          
@@ 1709,9 1725,9 @@ struct LLVMIRGenerator {
         LLVMBasicBlockRef bb = LLVMGetInsertBlock(builder);
         LLVMValueRef func = LLVMGetBasicBlockParent(bb);
         label_info.bb_merge = nullptr;
-        auto rtype = node->get_type();
+        auto rtype = node->type;
         if (is_returning(rtype)) {
-            label_info.bb_merge = LLVMAppendBasicBlock(func, node->name.name()->data);
+            label_info.bb_merge = LLVMAppendBasicBlock(func, node->name->data.data());
             builder.position_builder_at_end(label_info.bb_merge);
             SCOPES_CHECK_RESULT(build_phi(builder, label_info.merge_values, node));
         }

          
@@ 1746,7 1762,7 @@ struct LLVMIRGenerator {
 
     SCOPES_RESULT(void) build_phi(Builder &builder, LLVMValueRefs &refs, TypedValue node) {
         SCOPES_RESULT_TYPE(void);
-        SCOPES_CHECK_RESULT(build_phi(builder, refs, node->get_type()));
+        SCOPES_CHECK_RESULT(build_phi(builder, refs, node->type));
         builder.map_phi(refs, node);
         return {};
     }

          
@@ 1833,14 1849,14 @@ struct LLVMIRGenerator {
         auto callee = call->callee;
         auto &&args = call->args;
 
-        const Type *rtype = strip_lifetime(callee->get_type());
+        Type rtype = strip_lifetime(callee->type);
         if (!is_function_pointer(rtype)) {
-            SCOPES_ERROR(CGenInvalidCallee, callee->get_type());
+            SCOPES_ERROR(CGenInvalidCallee, callee->type);
         }
         SCOPES_CHECK_RESULT(build_call(builder, call,
             extract_function_type(rtype),
             SCOPES_GET_RESULT(ref_to_value(builder, callee)), args,
-            call->except, call->get_maybe_null_except_body()));
+            call->except, get_maybe_null_except_body(call)));
         return {};
     }
 

          
@@ 1852,7 1868,7 @@ struct LLVMIRGenerator {
     SCOPES_RESULT(void) translate_GetElementPtr(Builder &builder, GetElementPtr node) {
         SCOPES_RESULT_TYPE(void);
         auto ET = SCOPES_GET_RESULT(type_to_llvm_type(
-            SCOPES_GET_C_RESULT(sc_type_element_at(node->value->get_type(), 0))));
+            SCOPES_GET_C_RESULT(sc_type_element_at(node->value->type, 0))));
         auto pointer = SCOPES_GET_RESULT(ref_to_value(builder, node->value));
         assert(LLVMGetTypeKind(LLVMTypeOf(pointer)) == LLVMPointerTypeKind);
         auto &&src_indices = node->indices;

          
@@ 1939,7 1955,7 @@ struct LLVMIRGenerator {
         SCOPES_RESULT_TYPE(void);
         auto ty = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         LLVMValueRef val;
-        if (node->is_array()) {
+        if (is_array_alloc(node)) {
             auto count = SCOPES_GET_RESULT(ref_to_value(builder, node->count));
             val = safe_alloca(builder, ty, count);
         } else {

          
@@ 1968,7 1984,7 @@ struct LLVMIRGenerator {
         SCOPES_RESULT_TYPE(void);
         auto ty = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         LLVMValueRef val;
-        if (node->is_array()) {
+        if (is_array_alloc(node)) {
             auto count = SCOPES_GET_RESULT(ref_to_value(builder, node->count));
             val = LLVMBuildArrayMalloc(builder, ty, count, "");
         } else {

          
@@ 1987,7 2003,7 @@ struct LLVMIRGenerator {
 
     SCOPES_RESULT(void) translate_Load(Builder &builder, Load node) {
         SCOPES_RESULT_TYPE(void);
-        auto ET = SCOPES_GET_RESULT(type_to_llvm_type(node->get_type()));
+        auto ET = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         auto val = LLVMBuildLoad2(builder, ET, SCOPES_GET_RESULT(ref_to_value(builder, node->value)), "");
         if (node->is_volatile) {
             LLVMSetVolatile(val, true);

          
@@ 2012,18 2028,18 @@ struct LLVMIRGenerator {
         auto ptr = SCOPES_GET_RESULT(ref_to_value(builder, node->target));
         auto value = SCOPES_GET_RESULT(ref_to_value(builder, node->value));
         LLVMAtomicRMWBinOp op;
-        switch(node->op) {
-        case AtomicRMWOpXchg: op = LLVMAtomicRMWBinOpXchg; break;
-        case AtomicRMWOpAdd: op = LLVMAtomicRMWBinOpAdd; break;
-        case AtomicRMWOpSub: op = LLVMAtomicRMWBinOpSub; break;
-        case AtomicRMWOpAnd: op = LLVMAtomicRMWBinOpAnd; break;
-        case AtomicRMWOpNAnd: op = LLVMAtomicRMWBinOpNand; break;
-        case AtomicRMWOpOr: op = LLVMAtomicRMWBinOpOr; break;
-        case AtomicRMWOpXor: op = LLVMAtomicRMWBinOpXor; break;
-        case AtomicRMWOpSMin: op = LLVMAtomicRMWBinOpMin; break;
-        case AtomicRMWOpSMax: op = LLVMAtomicRMWBinOpMax; break;
-        case AtomicRMWOpUMin: op = LLVMAtomicRMWBinOpUMin; break;
-        case AtomicRMWOpUMax: op = LLVMAtomicRMWBinOpUMax; break;
+        switch(node.subkind()) {
+        case AtomicRMWOpKind::AtomicXchg: op = LLVMAtomicRMWBinOpXchg; break;
+        case AtomicRMWOpKind::AtomicAdd: op = LLVMAtomicRMWBinOpAdd; break;
+        case AtomicRMWOpKind::AtomicSub: op = LLVMAtomicRMWBinOpSub; break;
+        case AtomicRMWOpKind::AtomicBAnd: op = LLVMAtomicRMWBinOpAnd; break;
+        case AtomicRMWOpKind::AtomicBNAnd: op = LLVMAtomicRMWBinOpNand; break;
+        case AtomicRMWOpKind::AtomicBOr: op = LLVMAtomicRMWBinOpOr; break;
+        case AtomicRMWOpKind::AtomicBXor: op = LLVMAtomicRMWBinOpXor; break;
+        case AtomicRMWOpKind::AtomicSMin: op = LLVMAtomicRMWBinOpMin; break;
+        case AtomicRMWOpKind::AtomicSMax: op = LLVMAtomicRMWBinOpMax; break;
+        case AtomicRMWOpKind::AtomicUMin: op = LLVMAtomicRMWBinOpUMin; break;
+        case AtomicRMWOpKind::AtomicUMax: op = LLVMAtomicRMWBinOpUMax; break;
         default: {
             SCOPES_ERROR(CGenUnsupportedAtomicOp);
         } break;

          
@@ 2080,17 2096,17 @@ struct LLVMIRGenerator {
         auto a = SCOPES_GET_RESULT(ref_to_value(builder, node->value1));
         auto b = SCOPES_GET_RESULT(ref_to_value(builder, node->value2));
         LLVMIntPredicate pred = LLVMIntEQ;
-        switch(node->cmp_kind) {
-        case ICmpEQ: pred = LLVMIntEQ; break;
-        case ICmpNE: pred = LLVMIntNE; break;
-        case ICmpUGT: pred = LLVMIntUGT; break;
-        case ICmpUGE: pred = LLVMIntUGE; break;
-        case ICmpULT: pred = LLVMIntULT; break;
-        case ICmpULE: pred = LLVMIntULE; break;
-        case ICmpSGT: pred = LLVMIntSGT; break;
-        case ICmpSGE: pred = LLVMIntSGE; break;
-        case ICmpSLT: pred = LLVMIntSLT; break;
-        case ICmpSLE: pred = LLVMIntSLE; break;
+        switch(node.subkind()) {
+        case ICmpKind::ICmpEQ: pred = LLVMIntEQ; break;
+        case ICmpKind::ICmpNE: pred = LLVMIntNE; break;
+        case ICmpKind::ICmpUGT: pred = LLVMIntUGT; break;
+        case ICmpKind::ICmpUGE: pred = LLVMIntUGE; break;
+        case ICmpKind::ICmpULT: pred = LLVMIntULT; break;
+        case ICmpKind::ICmpULE: pred = LLVMIntULE; break;
+        case ICmpKind::ICmpSGT: pred = LLVMIntSGT; break;
+        case ICmpKind::ICmpSGE: pred = LLVMIntSGE; break;
+        case ICmpKind::ICmpSLT: pred = LLVMIntSLT; break;
+        case ICmpKind::ICmpSLE: pred = LLVMIntSLE; break;
         default: assert(false); break;
         }
         auto val = LLVMBuildICmp(builder, pred, a, b, "");

          
@@ 2103,21 2119,21 @@ struct LLVMIRGenerator {
         auto a = SCOPES_GET_RESULT(ref_to_value(builder, node->value1));
         auto b = SCOPES_GET_RESULT(ref_to_value(builder, node->value2));
         LLVMRealPredicate pred = LLVMRealOEQ;
-        switch(node->cmp_kind) {
-        case FCmpOEQ: pred = LLVMRealOEQ; break;
-        case FCmpONE: pred = LLVMRealONE; break;
-        case FCmpORD: pred = LLVMRealORD; break;
-        case FCmpOGT: pred = LLVMRealOGT; break;
-        case FCmpOGE: pred = LLVMRealOGE; break;
-        case FCmpOLT: pred = LLVMRealOLT; break;
-        case FCmpOLE: pred = LLVMRealOLE; break;
-        case FCmpUEQ: pred = LLVMRealUEQ; break;
-        case FCmpUNE: pred = LLVMRealUNE; break;
-        case FCmpUNO: pred = LLVMRealUNO; break;
-        case FCmpUGT: pred = LLVMRealUGT; break;
-        case FCmpUGE: pred = LLVMRealUGE; break;
-        case FCmpULT: pred = LLVMRealULT; break;
-        case FCmpULE: pred = LLVMRealULE; break;
+        switch(node.subkind()) {
+        case FCmpKind::FCmpOEQ: pred = LLVMRealOEQ; break;
+        case FCmpKind::FCmpONE: pred = LLVMRealONE; break;
+        case FCmpKind::FCmpORD: pred = LLVMRealORD; break;
+        case FCmpKind::FCmpOGT: pred = LLVMRealOGT; break;
+        case FCmpKind::FCmpOGE: pred = LLVMRealOGE; break;
+        case FCmpKind::FCmpOLT: pred = LLVMRealOLT; break;
+        case FCmpKind::FCmpOLE: pred = LLVMRealOLE; break;
+        case FCmpKind::FCmpUEQ: pred = LLVMRealUEQ; break;
+        case FCmpKind::FCmpUNE: pred = LLVMRealUNE; break;
+        case FCmpKind::FCmpUNO: pred = LLVMRealUNO; break;
+        case FCmpKind::FCmpUGT: pred = LLVMRealUGT; break;
+        case FCmpKind::FCmpUGE: pred = LLVMRealUGE; break;
+        case FCmpKind::FCmpULT: pred = LLVMRealULT; break;
+        case FCmpKind::FCmpULE: pred = LLVMRealULE; break;
         default: assert(false); break;
         }
         auto val = LLVMBuildFCmp(builder, pred, a, b, "");

          
@@ 2191,15 2207,15 @@ struct LLVMIRGenerator {
         SCOPES_RESULT_TYPE(void);
         auto x = SCOPES_GET_RESULT(ref_to_value(builder, node->value));
         LLVMValueRef val = nullptr;
-        switch(node->op) {
+        switch(node.subkind()) {
 #define UNOP(SRC, FUNC) \
-        case SRC: { val = translate_pm_unop(builder, node, x, FUNC); } break;
+        case UnOpKind::SRC: { val = translate_pm_unop(builder, node, x, FUNC); } break;
         UNOP(UnOpBitReverse, llvm_bitreverse)
         UNOP(UnOpBitCount, llvm_ctpop)
         UNOP(UnOpFindMSB, llvm_ctlz)
         UNOP(UnOpFindLSB, llvm_cttz)
 #undef UNOP
-        case UnOpFNeg: {
+        case UnOpKind::UnOpFNeg: {
             val = LLVMBuildFNeg(builder, x, "");
         } break;
         default: {

          
@@ 2210,9 2226,9 @@ struct LLVMIRGenerator {
             }
             LLVMValueRef func = nullptr;
             Intrinsic op = NumIntrinsics;
-            switch(node->op) {
+            switch(node.subkind()) {
 #define UNOP(SRC, FUNC) \
-    case SRC: { op = (ET == f64T)?FUNC ## _f64:FUNC ## _f32; } break;
+    case UnOpKind::SRC: { op = (ET == f64T)?FUNC ## _f64:FUNC ## _f32; } break;
             UNOP(UnOpSin, llvm_sin)
             UNOP(UnOpCos, llvm_cos)
             UNOP(UnOpTan, libc_tan)

          
@@ 2296,10 2312,10 @@ struct LLVMIRGenerator {
             ET = LLVMGetElementType(T);
         }
         LLVMValueRef val = nullptr;
-        switch(node->op) {
-#define BINOP(SRC, FUNC) case SRC: val = FUNC(builder, a, b, ""); break;
+        switch(node.subkind()) {
+#define BINOP(SRC, FUNC) case BinOpKind::SRC: val = FUNC(builder, a, b, ""); break;
 #define INTRINSIC_BINOP(SRC, FUNC) \
-    case SRC: { val = build_intrinsic_binop(builder, (ET == f64T)?FUNC ## _f64:FUNC ## _f32, a, b); } break;
+    case BinOpKind::SRC: { val = build_intrinsic_binop(builder, (ET == f64T)?FUNC ## _f64:FUNC ## _f32, a, b); } break;
         BINOP(BinOpAdd, LLVMBuildAdd)
         BINOP(BinOpAddNUW, LLVMBuildNUWAdd)
         BINOP(BinOpAddNSW, LLVMBuildNSWAdd)

          
@@ 2352,11 2368,11 @@ struct LLVMIRGenerator {
     SCOPES_RESULT(void) translate_Cast(Builder &builder, Cast node) {
         SCOPES_RESULT_TYPE(void);
         LLVMValueRef val = SCOPES_GET_RESULT(ref_to_value(builder, node->value));
-        auto ty = SCOPES_GET_RESULT(type_to_llvm_type(node->get_type()));
+        auto ty = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         auto T = LLVMTypeOf(val);
         if (T != ty) {
-            switch(node->op) {
-            case CastBitcast: {
+            switch(node.subkind()) {
+            case CastKind::CastBitcast: {
                 auto newval = build_struct_cast(builder, val, ty);
                 if (newval == val) {
                     val = LLVMBuildBitCast(builder, val, ty, "");

          
@@ 2364,9 2380,9 @@ struct LLVMIRGenerator {
                     val = newval;
                 }
             } break;
-            case CastPtrToRef: break;
-            case CastRefToPtr: break;
-#define CAST_OP(SRC, OP) case SRC: val = OP(builder, val, ty, ""); break;
+            case CastKind::CastPtrToRef: break;
+            case CastKind::CastRefToPtr: break;
+#define CAST_OP(SRC, OP) case CastKind::SRC: val = OP(builder, val, ty, ""); break;
             CAST_OP(CastIntToPtr, LLVMBuildIntToPtr);
             CAST_OP(CastPtrToInt, LLVMBuildPtrToInt);
             CAST_OP(CastSExt, LLVMBuildSExt);

          
@@ 2401,17 2417,17 @@ struct LLVMIRGenerator {
         int i = count;
         LLVMBasicBlockRef lastbb = nullptr;
         while (i-- > 0) {
-            auto &_case = *node->cases[i];
+            auto &&_case = node->cases[i];
             LLVMBasicBlockRef bbcase = nullptr;
-            if (_case.kind == CK_Default) {
+            if (!_case.literal) {
                 builder.position_builder_at_end(bbdefault);
                 bbcase = bbdefault;
-            } else if (_case.body->empty()) {
-                auto lit = SCOPES_GET_RESULT(ref_to_value(builder, ValueIndex(_case.literal)));
+            } else if (is_empty(_case.body)) {
+                auto lit = SCOPES_GET_RESULT(ref_to_value(builder, value_index(*_case.literal)));
                 LLVMAddCase(_sw, lit, lastbb);
                 continue;
             } else {
-                auto lit = SCOPES_GET_RESULT(ref_to_value(builder, ValueIndex(_case.literal)));
+                auto lit = SCOPES_GET_RESULT(ref_to_value(builder, value_index(*_case.literal)));
                 bbcase = LLVMAppendBasicBlock(func, "case");
                 builder.position_builder_at_end(bbcase);
                 LLVMAddCase(_sw, lit, bbcase);

          
@@ 2449,57 2465,100 @@ struct LLVMIRGenerator {
         return {};
     }
 
+    SCOPES_RESULT(void) translate_Terminator(Builder &builder, Terminator node) {
+        SCOPES_RESULT_TYPE(void);
+        switch(node.kind()) {
+        #define SCOPES_LLVM_PROCESS_SUBTYPE_Abstract(NAME)
+        #define SCOPES_LLVM_PROCESS_SUBTYPE_Concrete(NAME) \
+            case ValueKind::NAME: SCOPES_CHECK_RESULT(translate_ ## NAME(builder, cast<NAME>(node))); break;
+        #define SCOPES_LLVM_PROCESS_SUBTYPE(QUAL, NAME) \
+            SCOPES_LLVM_PROCESS_SUBTYPE_ ## QUAL(NAME)
+        TYPE_SUBTYPES_Terminator(SCOPES_LLVM_PROCESS_SUBTYPE)
+            default: assert(false); break;
+        }
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE_Concrete
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE_Abstract
+        return {};
+    }
+
     SCOPES_RESULT(void) translate_instruction(Builder &builder, Instruction node) {
         SCOPES_RESULT_TYPE(void);
-        SCOPES_TRACE_CODEGEN(node);
-        switch(node->kind()) {
-        #define T(NAME, BNAME, CLASS) \
-            case NAME: SCOPES_CHECK_RESULT(translate_ ## CLASS(builder, node.cast<CLASS>())); break;
-        SCOPES_INSTRUCTION_VALUE_KIND()
-        #undef T
+        switch(node.kind()) {
+        #define SCOPES_LLVM_PROCESS_ABST_SUBTYPE(QUAL, NAME) \
+            case ValueKind::NAME:
+        #define SCOPES_LLVM_PROCESS_SUBTYPE_Abstract(NAME) \
+            TYPE_SUBTYPES_ ## NAME(SCOPES_LLVM_PROCESS_ABST_SUBTYPE) \
+            SCOPES_CHECK_RESULT(translate_ ## NAME(builder, cast<NAME>(node))); break;
+        #define SCOPES_LLVM_PROCESS_SUBTYPE_Concrete(NAME) \
+            case ValueKind::NAME: SCOPES_CHECK_RESULT(translate_ ## NAME(builder, cast<NAME>(node))); break;
+        #define SCOPES_LLVM_PROCESS_SUBTYPE(QUAL, NAME) \
+            SCOPES_LLVM_PROCESS_SUBTYPE_ ## QUAL(NAME)
+        TYPE_SUBTYPES_Instruction(SCOPES_LLVM_PROCESS_SUBTYPE)
             default: assert(false); break;
         }
+        #undef SCOPES_LLVM_PROCESS_ABST_SUBTYPE
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE_Concrete
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE_Abstract
         return {};
     }
 
+    SCOPES_RESULT(LLVMValueRef) ref_to_value(Builder &builder, Value ref) {
+        return ref_to_value(builder, value_index(ref));
+    }
+
     SCOPES_RESULT(LLVMValueRef) ref_to_value(Builder &builder, const ValueIndex &ref) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
         LLVMValueRef value = resolve(builder, ref);
         if (value)
             return value;
-        SCOPES_TRACE_CODEGEN(ref.value);
-        switch(ref.value->kind()) {
-        #define T(NAME, BNAME, CLASS) \
-            case NAME: value = SCOPES_GET_RESULT( \
-                CLASS ## _to_value(ref.value.cast<CLASS>())); break;
-        SCOPES_PURE_VALUE_KIND()
-        #undef T
+        //SCOPES_TRACE_CODEGEN(ref.value);
+        switch(ref.value.kind()) {
+        #define SCOPES_LLVM_PROCESS_SUBTYPE2_Abstract(NAME) \
+            TYPE_SUBTYPES_ ## NAME(SCOPES_LLVM_PROCESS_SUBTYPE3)
+        #define SCOPES_LLVM_PROCESS_SUBTYPE2_Concrete SCOPES_LLVM_PROCESS_SUBTYPE_Concrete
+        #define SCOPES_LLVM_PROCESS_SUBTYPE2(QUAL, NAME) \
+            SCOPES_LLVM_PROCESS_SUBTYPE_ ## QUAL(NAME)
+        #define SCOPES_LLVM_PROCESS_SUBTYPE_Abstract(NAME) \
+            TYPE_SUBTYPES_ ## NAME(SCOPES_LLVM_PROCESS_SUBTYPE2)
+        #define SCOPES_LLVM_PROCESS_SUBTYPE_Concrete(NAME) \
+            case ValueKind::NAME: SCOPES_CHECK_RESULT(NAME ## _to_value(cast<NAME>(ref.value))); break;
+        #define SCOPES_LLVM_PROCESS_SUBTYPE(QUAL, NAME) \
+            SCOPES_LLVM_PROCESS_SUBTYPE_ ## QUAL(NAME)
+        TYPE_SUBTYPES_Pure(SCOPES_LLVM_PROCESS_SUBTYPE)
             default: {
-                SCOPES_ERROR(CGenFailedToTranslateValue, ref.value->kind());
+                SCOPES_ERROR(CGenFailedToTranslateValue, ref.value.kind());
             } break;
         }
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE_Concrete
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE_Abstract
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE2
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE2_Concrete
+        #undef SCOPES_LLVM_PROCESS_SUBTYPE2_Abstract
         global_builder.bind(ref, value);
         return value;
     }
 
     SCOPES_RESULT(LLVMValueRef) PureCast_to_value(PureCast node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
-        LLVMTypeRef LLT = SCOPES_GET_RESULT(type_to_llvm_type(node->get_type()));
+        LLVMTypeRef LLT = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         auto val = SCOPES_GET_RESULT(ref_to_value(global_builder, ValueIndex(node->value)));
         return LLVMConstBitCast(val, LLT);
     }
 
     SCOPES_RESULT(LLVMValueRef) Undef_to_value(Undef node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
-        LLVMTypeRef LLT = SCOPES_GET_RESULT(type_to_llvm_type(node->get_type()));
+        LLVMTypeRef LLT = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         return LLVMGetUndef(LLT);
     }
 
     SCOPES_RESULT(LLVMValueRef) ConstString_to_value(ConstString node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
-        LLVMTypeRef LLT = SCOPES_GET_RESULT(type_to_llvm_type(node->get_type()));
+        LLVMTypeRef LLT = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         //auto ET = LLVMGetElementType(LLT);
-        auto data = LLVMConstString(node->value->data, node->value->count, false);
+        auto data = LLVMConstString(node->value->data.data(), node->value->data.size(), false);
 
         LLVMValueRef result = LLVMAddGlobal(module, LLVMTypeOf(data), "");
         LLVMSetInitializer(result, data);

          
@@ 2532,10 2591,10 @@ struct LLVMIRGenerator {
 
     SCOPES_RESULT(LLVMValueRef) Global_to_value(Global node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
-        auto it = global2global.find(node.unref());
+        auto it = global2global.find(node);
         if (it == global2global.end()) {
             auto LLT = SCOPES_GET_RESULT(type_to_llvm_type(
-                strip_qualifiers(node->get_type())));
+                strip_qualifiers(node->type)));
 
             LLVMValueRef result = nullptr;
             if (node->storage_class == SYM_SPIRV_StorageClassPrivate) {

          
@@ 2546,25 2605,22 @@ struct LLVMIRGenerator {
 
                 if (generate_object) {
                     auto globname = node->name;
-                    auto it = func_export_table.find(node.unref());
+                    auto it = func_export_table.find(node);
                     if (it != func_export_table.end()) {
-                        auto str = it->second.name();
-                        name = std::string(str->data, str->count);
+                        name = it->second->data;
                         is_export = true;
                     } else {
-                        StyledString ss = StyledString::plain();
+                        NameStringPrinter sp;
                         if (globname == SYM_Unnamed) {
-                            ss.out << "unnamed";
+                            sp("unnamed");
                         } else {
-                            ss.out << globname.name()->data;
+                            sp(globname->data);
                         }
                         #if 1
-                        ss.out << "<";
-                        stream_type_name(ss.out, node->get_type());
-                        ss.out << ">";
+                        sp(Pcat,"<",Pcat,node->type,Pcat,">",Pcat);
                         #endif
-                        stream_address(ss.out, node.unref());
-                        name = quote_symbol_name(ss.cppstr().c_str());
+                        stream_uid(sp, node.id());
+                        name = quote_symbol_name(sp.tostring().c_str());
                     }
 
                     auto result = GetNamedGlobalOrFunction(module, name.c_str());

          
@@ 2573,21 2629,18 @@ struct LLVMIRGenerator {
                         SCOPES_ERROR(CGenInvalidRedeclaration, name.c_str(), "private global");
                     }
                 } else {
-                    auto it = global_cache.find(node.unref());
+                    auto it = global_cache.find(node);
                     if (it == global_cache.end()) {
                         auto globname = node->name;
-                        StyledString ss = StyledString::plain();
+                        NameStringPrinter sp;
                         if (globname == SYM_Unnamed) {
-                            ss.out << "unnamed";
+                            sp("unnamed");
                         } else {
-                            ss.out << globname.name()->data;
+                            sp(globname->data);
                         }
-                        ss.out << "<";
-                        stream_type_name(ss.out, node->get_type());
-                        ss.out << ">";
-                        ss.out << get_global_pointer_id(node.unref());
-                        name = ss.cppstr();
-                        global_cache.insert({node.unref(), name});
+                        sp(Pcat,"<",Pcat,node->type,Pcat,">",Pcat,get_global_id(node));
+                        name = sp.tostring();
+                        global_cache.insert({node, name});
                     } else {
                         name = it->second;
                         is_external = true;

          
@@ 2601,10 2654,10 @@ struct LLVMIRGenerator {
                     LLVMSetVisibility(result, LLVMDefaultVisibility);
                 }
 
-                global2global.insert({ node.unref(), result });
+                global2global.insert({ node, result });
                 global_stack.push_back(node);
 
-                if (node->flags & GF_ThreadLocal) {
+                if (node->flags & PointerTypeFlagsBit::ThreadLocal) {
                     LLVMSetThreadLocal(result, true);
                 }
                 if (!is_external) {

          
@@ 2613,7 2666,7 @@ struct LLVMIRGenerator {
 
                     if (node->initializer) {
                         init = SCOPES_GET_RESULT(
-                            ref_to_value(global_builder, TypedValueRef(node->initializer)));
+                            ref_to_value(global_builder, TypedValue(*node->initializer)));
                     } else {
                         init = LLVMConstNull(LLT);
                     }

          
@@ 2621,7 2674,7 @@ struct LLVMIRGenerator {
 
                     if (node->constructor) {
                         auto val = SCOPES_GET_RESULT(
-                            ref_to_value(global_builder, TypedValueRef(node->constructor)));
+                            ref_to_value(global_builder, TypedValue(*node->constructor)));
                         assert(val);
                         constructors.push_back(val);
                     }

          
@@ 2631,10 2684,10 @@ struct LLVMIRGenerator {
                 return result;
             } else {
 
-                const String *namestr = node->name.name();
-                const char *name = namestr->data;
+                auto &&namestr = node->name->data;
+                const char *name = namestr.data();
                 assert(name);
-                if ((namestr->count > 5) && !strncmp(name, "llvm.", 5)) {
+                if ((namestr.size() > 5) && !strncmp(name, "llvm.", 5)) {
                     result = LLVMGetNamedFunction(module, name);
                     if (result) {
                         LLT = LLVMPointerType(LLT, 0);

          
@@ 2658,14 2711,13 @@ struct LLVMIRGenerator {
                             bool KB = (LLVMGetTypeKind(LLVMGetElementType(
                                 LLT)) == LLVMFunctionTypeKind);
                             if (KA != KB) {
-                                StyledStream ss;
-                                ss << node << std::endl;
+                                print2(node);
                                 LLVMDumpType(LLT);
-                                ss << std::endl;
+                                print2("");
                                 LLVMDumpValue(result);
-                                ss << std::endl;
+                                print2("");
                                 LLVMDumpType(LLVMTypeOf(result));
-                                ss << std::endl;
+                                print2("");
                                 SCOPES_ERROR(CGenInvalidRedeclaration, name, "external global");
                             } else {
                                 result = LLVMConstBitCast(result, LLT);

          
@@ 2676,12 2728,12 @@ struct LLVMIRGenerator {
                             void *pptr = local_aware_dlsym(node->name);
                             uint64_t ptr = *(uint64_t*)&pptr;
                             if (!ptr) {
-                                last_llvm_error = nullptr;
+                                last_llvm_error = {};
                                 LLVMInstallFatalErrorHandler(fatal_error_handler);
                                 ptr = SCOPES_GET_RESULT(get_address(name));
                                 LLVMResetFatalErrorHandler();
                                 if (last_llvm_error) {
-                                    SCOPES_RETURN_ERROR(last_llvm_error);
+                                    SCOPES_RETURN_ERROR(*last_llvm_error);
                                 }
                             }
                             if (!ptr) {

          
@@ 2692,7 2744,7 @@ struct LLVMIRGenerator {
                             result = LLVMAddFunction(module, name, LLT);
                             LLVMSetLinkage(result, LLVMExternalLinkage);
 
-                            auto ilfunctype = node->get_type();
+                            auto ilfunctype = node->type;
                             auto fi = extract_function_type(ilfunctype);
                             auto rtype = abi_return_type(fi);
                             bool use_sret = is_memory_class(rtype);

          
@@ 2708,13 2760,13 @@ struct LLVMIRGenerator {
                         }
                     }
                 }
-                global2global.insert({ node.unref(), result });
+                global2global.insert({ node, result });
                 return result;
             }
         } else {
             size_t i = global_stack.size();
             while (i--) {
-                if (global_stack[i].unref() == node.unref() && (i + 1 != global_stack.size())) {
+                if (global_stack[i] == node && (i + 1 != global_stack.size())) {
                     SCOPES_ERROR(CGenRecursiveConstructor, global_stack.back(), node);
                 }
             }

          
@@ 2724,13 2776,13 @@ struct LLVMIRGenerator {
 
     SCOPES_RESULT(LLVMValueRef) ConstNull_to_value(ConstNull node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
-        auto T = SCOPES_GET_RESULT(type_to_llvm_type(node->get_type()));
+        auto T = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         return LLVMConstNull(T);
     }
 
     SCOPES_RESULT(LLVMValueRef) ConstInt_to_value(ConstInt node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
-        auto T = SCOPES_GET_RESULT(type_to_llvm_type(node->get_type()));
+        auto T = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         return LLVMConstIntOfArbitraryPrecision(T,
                                               node->words.size(),
                                               &node->words[0]);

          
@@ 2738,7 2790,7 @@ struct LLVMIRGenerator {
 
     SCOPES_RESULT(LLVMValueRef) ConstReal_to_value(ConstReal node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
-        auto T = SCOPES_GET_RESULT(type_to_llvm_type(node->get_type()));
+        auto T = SCOPES_GET_RESULT(type_to_llvm_type(node->type));
         return LLVMConstReal(T, node->value);
     }
 

          
@@ 2750,10 2802,15 @@ struct LLVMIRGenerator {
         return basevalue;
     }
 
+    SCOPES_RESULT(LLVMValueRef) ConstValue_to_value(ConstValue node) {
+        assert(false && "todo: implement me");
+        return nullptr;
+    }
+
     SCOPES_RESULT(LLVMValueRef) ConstPointer_to_value(ConstPointer node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
         auto LLT = SCOPES_GET_RESULT(type_to_llvm_type(
-            strip_qualifiers(node->get_type())));
+            strip_qualifiers(node->type)));
         if (!node->value) {
             return LLVMConstPointerNull(LLT);
 #if SCOPES_ALLOW_BAKING_POINTERS

          
@@ 2769,23 2826,23 @@ struct LLVMIRGenerator {
                     LLT);
             }
         } else {
-            PureRef g = SCOPES_GET_RESULT(node->to_global());
+            Maybe<Pure> g = SCOPES_GET_RESULT(to_global(node));
             if (g) {
-                return ref_to_value(global_builder, ValueIndex(g));
+                return ref_to_value(global_builder, value_index(*g));
             }
-            SCOPES_TRACE_CODEGEN(node);
-            SCOPES_ERROR(CGenCannotSerializeConstPointer, node->get_type());
+            //SCOPES_TRACE_CODEGEN(node);
+            SCOPES_ERROR(CGenCannotSerializeConstPointer, node->type);
         }
 #else
     } else {
-        SCOPES_ERROR(CGenCannotSerializeConstPointer, node->get_type());
+        SCOPES_ERROR(CGenCannotSerializeConstPointer, node->type);
     }
 #endif
     }
 
     SCOPES_RESULT(LLVMValueRef) ConstAggregate_to_value(ConstAggregate node) {
         SCOPES_RESULT_TYPE(LLVMValueRef);
-        auto T = node->get_type();
+        auto T = node->type;
         LLVMTypeRef LLT = SCOPES_GET_RESULT(type_to_llvm_type(T));
         size_t count = node->values.size();
         LLVMValueRef values[count+1];

          
@@ 2794,7 2851,7 @@ struct LLVMIRGenerator {
         }
         switch(LLVMGetTypeKind(LLT)) {
         case LLVMStructTypeKind: {
-            if (T->kind() == TK_Typename) {
+            if (T.subkind() == TypeKind::TypenameType) {
                 return LLVMConstNamedStruct(LLT, values, count);
             } else {
                 return LLVMConstStruct(values, count, false);

          
@@ 2802,7 2859,7 @@ struct LLVMIRGenerator {
         } break;
         case LLVMArrayTypeKind: {
             auto ai = cast<ArrayLikeType>(SCOPES_GET_RESULT(storage_type(T)));
-            if (ai->is_zterm()) {
+            if (is_zterm(ai)) {
                 values[count] = LLVMConstNull(LLVMGetElementType(LLT));
                 count++;
             }

          
@@ 2819,15 2876,15 @@ struct LLVMIRGenerator {
     }
 
     SCOPES_RESULT(void) build_call(Builder &builder, Instruction call,
-        const Type *functype, LLVMValueRef func, const TypedValues &args,
-        Exception call_except, Block call_except_body) {
+        Type functype, LLVMValueRef func, const TypedValues &args,
+        Maybe<Exception> call_except, Maybe<Block> call_except_body) {
         SCOPES_RESULT_TYPE(void);
         LLVMValueRefs values;
         Types argtypes;
         size_t argcount = args.size();
         for (size_t i = 0; i < argcount; ++i) {
             values.push_back(SCOPES_GET_RESULT(ref_to_value(builder, args[i])));
-            argtypes.push_back(args[i]->get_type());
+            argtypes.push_back(args[i]->type);
         }
         return build_call(
             builder, call, functype, func, values, argtypes,

          
@@ 2835,15 2892,15 @@ struct LLVMIRGenerator {
     }
 
     SCOPES_RESULT(void) build_call(Builder &builder, Instruction call,
-        const Type *functype, LLVMValueRef func, const LLVMValueRefs &args,
+        Type functype, LLVMValueRef func, const LLVMValueRefs &args,
         const Types &argtypes,
-        Exception call_except, Block call_except_body) {
+        Maybe<Exception> call_except, Maybe<Block> call_except_body) {
         SCOPES_RESULT_TYPE(void);
         size_t argcount = args.size();
 
         LLVMMetadataRef diloc = nullptr;
         if (use_debug_info) {
-            diloc = set_debug_location(builder, call.anchor());
+            diloc = set_debug_location(builder, anchorof(call));
             assert(diloc);
         }
 

          
@@ 2876,7 2933,7 @@ struct LLVMIRGenerator {
         size_t fargcount = fi->argument_types.size();
         assert(argcount >= fargcount);
         // make variadic calls C compatible
-        if (fi->flags & FF_Variadic) {
+        if (is_variadic(fi)) {
             for (size_t i = fargcount; i < argcount; ++i) {
                 auto value = values[i];
                 // floats need to be widened to doubles, sub-ints to ints

          
@@ 2887,7 2944,7 @@ struct LLVMIRGenerator {
                 } else if ((LLVMGetTypeKind(T) == LLVMIntegerTypeKind)
                     && (LLVMGetIntTypeWidth(T) < 32)) {
                     auto NT = storage_type(argtypes[i]).assert_ok();
-                    if (is_kind<TK_Integer>(NT) && cast<IntegerType>(NT)->issigned) {
+                    if (isa<IntegerType>(NT) && cast<IntegerType>(NT)->issigned) {
                         values[i] = LLVMBuildSExt(builder, value, i32T, "");
                     } else {
                         values[i] = LLVMBuildZExt(builder, value, i32T, "");

          
@@ 2929,20 2986,21 @@ struct LLVMIRGenerator {
             }
         }
 
-        if (fi->has_exception()) {
+        if (has_exception(fi)) {
             bool has_except_value = is_returning_value(fi->except_type);
             bool has_return_value = is_returning_value(fi->return_type);
             if (has_except_value) {
                 assert(call_except);
+                assert(call_except_body);
                 auto except = LLVMBuildExtractValue(builder, ret, 1, "");
                 LLVMValueRefs values;
                 struct_to_values(builder, values, fi->except_type, except);
-                builder.map_phi(values, call_except);
+                builder.map_phi(values, *call_except);
             }
             auto old_bb = LLVMGetInsertBlock(builder);
             auto bb_except = LLVMAppendBasicBlock(LLVMGetBasicBlockParent(old_bb), "call_failed");
             builder.position_builder_at_end(bb_except);
-            SCOPES_CHECK_RESULT(translate_block(builder, call_except_body));
+            SCOPES_CHECK_RESULT(translate_block(builder, *call_except_body));
             builder.position_builder_at_end(old_bb);
             if (!is_returning(fi->return_type)) {
                 // always raises

          
@@ 2976,7 3034,7 @@ struct LLVMIRGenerator {
 
     LLVMMetadataRef anchor_to_location(Builder &builder, Anchor anchor) {
         assert(use_debug_info);
-        assert(anchor);
+        //assert(anchor);
 
         assert(builder.active_function);
         auto old_bb = LLVMGetInsertBlock(builder);

          
@@ 2985,15 3043,19 @@ struct LLVMIRGenerator {
         LLVMMetadataRef disp = LLVMGetSubprogram(func);
 
         LLVMMetadataRef scope = disp;
-        assert(builder.active_function.anchor());
-        if (builder.active_function.anchor()->path != anchor->path) {
-            LLVMMetadataRef difile = source_file_to_scope(anchor->path);
+
+        auto loc = anchor_location(anchor);
+
+        auto active_loc = anchor_location(anchorof(*builder.active_function));
+
+        if (active_loc->source->path != loc->source->path) {
+            LLVMMetadataRef difile = source_file_to_scope(loc->source->path);
             scope = LLVMDIBuilderCreateLexicalBlock(di_builder, disp, difile, 1, 1);
         }
 
         LLVMMetadataRef result = LLVMDIBuilderCreateDebugLocation(
             LLVMGetGlobalContext(),
-            anchor->first.lineno, anchor->first.column, scope, nullptr);
+            loc->line, loc->column, scope, nullptr);
 
         return result;
     }

          
@@ 3209,32 3271,32 @@ struct LLVMIRGenerator {
     SCOPES_RESULT(LLVMModuleRef) generate(String name, Scope table) {
         SCOPES_RESULT_TYPE(LLVMModuleRef);
 
-        setup_generate(name->data);
+        setup_generate(name->data.data());
 
         std::vector<LLVMValueRef> exported_globals;
 
-        const Scope *t = table;
+        Scope t = table;
         while (t) {
             auto it = sc_scope_next(t, -1);
             while (it._2 != -1) {
-                auto key = it._0.cast<Const>();
+                auto key = cast<Const>(it._0);
                 auto val = it._1;
-                if (key->get_type() == TYPE_Symbol) {
-                    Symbol name = Symbol::wrap(key.cast<ConstInt>()->value());
-                    if (val->kind() == VK_Global) {
+                if (key->type == TYPE_Symbol) {
+                    auto name = cast<Symbol>(cast<ConstValue>(key)->value);
+                    if (val.kind() == ValueKind::Global) {
                         SCOPES_CHECK_RESULT(extract_global_constant(val));
                     } else {
                         SCOPES_CHECK_RESULT(extract_function_constant(val));
                     }
-                    auto typed_val = val.cast<TypedValue>();
-                    func_export_table.insert({typed_val.unref(), name});
-                    LLVMValueRef exported_value = SCOPES_GET_RESULT(ref_to_value(global_builder, ValueIndex(typed_val)));
+                    auto typed_val = cast<TypedValue>(val);
+                    func_export_table.insert({typed_val, name});
+                    LLVMValueRef exported_value = SCOPES_GET_RESULT(ref_to_value(global_builder, value_index(typed_val)));
                     assert(exported_value);
                     exported_globals.push_back(exported_value);
                 }
                 it = sc_scope_next(t, it._2);
             }
-            t = t->parent();
+            t = scope_parent(t);
         }
 
         build_constructors();

          
@@ 3262,7 3324,7 @@ struct LLVMIRGenerator {
     SCOPES_RESULT(ModuleValuePair) generate(Function entry) {
         SCOPES_RESULT_TYPE(ModuleValuePair);
 
-        const char *name = entry->name.name()->data;
+        const char *name = entry->name->data.data();
         setup_generate(name);
 
         {

          
@@ 3273,21 3335,21 @@ struct LLVMIRGenerator {
 
         entry_function = entry;
 
-        auto func = SCOPES_GET_RESULT(ref_to_value(global_builder, ValueIndex(entry)));
+        auto func = SCOPES_GET_RESULT(ref_to_value(global_builder, value_index(entry)));
         LLVMSetLinkage(func, LLVMExternalLinkage);
 
         build_constructor_function();
-        SCOPES_CHECK_RESULT(teardown_generate(entry));
+        SCOPES_CHECK_RESULT(teardown_generate());
 
         return ModuleValuePair(module, func);
     }
 
 };
 
-Error *LLVMIRGenerator::last_llvm_error = nullptr;
-std::unordered_map<const Type *, LLVMTypeRef> LLVMIRGenerator::type_cache;
-std::unordered_map<Function *, std::string> LLVMIRGenerator::func_cache;
-std::unordered_map<Global *, std::string> LLVMIRGenerator::global_cache;
+Maybe<Error> LLVMIRGenerator::last_llvm_error;
+std::unordered_map<Type, LLVMTypeRef> LLVMIRGenerator::type_cache;
+std::unordered_map<Function, std::string> LLVMIRGenerator::func_cache;
+std::unordered_map<Global, std::string> LLVMIRGenerator::global_cache;
 std::unordered_map<size_t, PointerNamespaces *> LLVMIRGenerator::pointer_namespaces;
 Types LLVMIRGenerator::type_todo;
 LLVMTypeRef LLVMIRGenerator::pointerT = nullptr;

          
@@ 3324,9 3386,22 @@ unsigned LLVMIRGenerator::attr_kind_byva
 // IL COMPILER
 //------------------------------------------------------------------------------
 
-
-SCOPES_RESULT(void) compile_object(const String *triple,
-    CompilerFileKind kind, const String *path, const Scope *scope, uint64_t flags) {
+static std::string LLVMConvertMessageString(char *err) {
+    if (err) {
+        auto result = err;
+        LLVMDisposeErrorMessage(err);
+        return result;
+    } else {
+        return "null";
+    }
+}
+
+static std::string LLVMGetErrorMessageString(LLVMErrorRef err) {
+    return LLVMConvertMessageString(LLVMGetErrorMessage(err));
+}
+
+SCOPES_RESULT(void) compile_object(String triple,
+    CompilerFileKind kind, String path, Scope scope, uint64_t flags) {
     SCOPES_RESULT_TYPE(void);
     Timer sum_compile_time(TIMER_Compile);
 

          
@@ 3342,7 3417,7 @@ SCOPES_RESULT(void) compile_object(const
         module = SCOPES_GET_RESULT(ctx.generate(path, scope));
     }
 
-    auto tt = LLVMNormalizeTargetTriple(triple->data);
+    auto tt = LLVMNormalizeTargetTriple(triple->data.data());
     static char triplestr[1024];
     strncpy(triplestr, tt, 1024 - 1);
     LLVMDisposeMessage(tt);

          
@@ 3350,7 3425,7 @@ SCOPES_RESULT(void) compile_object(const
     char *error_message = nullptr;
     LLVMTargetRef target = nullptr;
     if (LLVMGetTargetFromTriple(triplestr, &target, &error_message)) {
-        SCOPES_ERROR(CGenBackendFailed, error_message);
+        SCOPES_ERROR(CGenBackendFailed, LLVMConvertMessageString(error_message));
     }
     // code model must be JIT default for reasons beyond my comprehension
     auto tm = LLVMCreateTargetMachine(target, triplestr, "", "",

          
@@ 3372,43 3447,41 @@ SCOPES_RESULT(void) compile_object(const
         LLVMDumpModule(module);
     }
 
-    char *path_cstr = strdup(path->data);
+    std::string path_cstr = path->data;
     LLVMBool failed = false;
     switch(kind) {
     case CFK_Object: {
-        failed = LLVMTargetMachineEmitToFile(tm, module, path_cstr,
+        failed = LLVMTargetMachineEmitToFile(tm, module, path_cstr.data(),
             LLVMObjectFile, &error_message);
     } break;
     case CFK_ASM: {
-        failed = LLVMTargetMachineEmitToFile(tm, module, path_cstr,
+        failed = LLVMTargetMachineEmitToFile(tm, module, path_cstr.data(),
             LLVMAssemblyFile, &error_message);
     } break;
     case CFK_BC: {
-        failed = LLVMWriteBitcodeToFile(module, path_cstr);
+        failed = LLVMWriteBitcodeToFile(module, path_cstr.data());
     } break;
     case CFK_LLVM: {
-        failed = LLVMPrintModuleToFile(module, path_cstr, &error_message);
+        failed = LLVMPrintModuleToFile(module, path_cstr.data(), &error_message);
     } break;
     default: {
-        free(path_cstr);
         SCOPES_ERROR(CGenBackendFailed, "unknown file kind");
     } break;
     }
-    free(path_cstr);
     if (failed) {
-        SCOPES_ERROR(CGenBackendFailed, error_message);
+        SCOPES_ERROR(CGenBackendFailed, LLVMConvertMessageString(error_message));
     }
     return {};
 }
 
 sc_compile_func_t foreign_compile_hook = NULL;
 
-SCOPES_RESULT(ConstPointerRef) compile(const FunctionRef &fn, uint64_t flags) {
-    SCOPES_RESULT_TYPE(ConstPointerRef);
+SCOPES_RESULT(ConstPointer) compile(Function fn, uint64_t flags) {
+    SCOPES_RESULT_TYPE(ConstPointer);
     if (foreign_compile_hook) {
             auto _result = foreign_compile_hook(fn, flags);
             if (_result.ok) {
-                return _result._0.cast<ConstPointer>();
+                return cast<ConstPointer>(_result._0);
             } else {
                 SCOPES_RETURN_ERROR(_result.except);
             }

          
@@ 3424,7 3497,7 @@ SCOPES_RESULT(ConstPointerRef) compile(c
         flags |= CF_Cache;
     }
 
-   const Type *functype = native_opaque_pointer_type(strip_qualifiers(fn->get_type()));
+   Type functype = native_opaque_pointer_type(strip_qualifiers(fn->type));
 
     LLVMIRGenerator ctx;
     if (flags & CF_Cache) {

          
@@ 3497,7 3570,7 @@ SCOPES_RESULT(ConstPointerRef) compile(c
 #if 1
     for (auto sym : bindsyms) {
         void *ptr = (void *)SCOPES_GET_RESULT(get_address(sym.c_str()));
-        set_address_name(ptr, String::from(sym.c_str(), sym.size()));
+        set_address_name(ptr, string_from(sym.c_str(), sym.size()));
     }
 #endif
 

          
@@ 3507,14 3580,14 @@ SCOPES_RESULT(ConstPointerRef) compile(c
         print_disassembly(funcname, pfunc);
     }
 
-    return ConstPointer::from(functype, pfunc).cast<ConstPointer>();
+    return const_ptr(functype, pfunc);
 }
 
-uint64_t resolve_global_symbol(const ValueRef &node) {
+uint64_t resolve_global_symbol(Value node) {
     const char *name = nullptr;
-    if (node.isa<Global>()) {
-        name = node.cast<Global>()->name.name()->data;
-        auto it = LLVMIRGenerator::global_cache.find(node.cast<Global>().unref());
+    if (isa<Global>(node)) {
+        name = cast<Global>(node)->name->data.data();
+        auto it = LLVMIRGenerator::global_cache.find(cast<Global>(node));
         if (it != LLVMIRGenerator::global_cache.end()) {
             name = it->second.c_str();
         }

          
M src/gencc.inc +13 -0
@@ 44,6 44,10 @@ template<typename EnumTypeT> struct IdCl
         return std::hash<size_t>{}(_id);
     }
 
+    inline size_t id() const {
+        return _id;
+    }
+
 protected:
     inline IdClass(EnumType kind, size_t index) : _kind(kind), _index(index) {}
     inline IdClass(size_t id) : _id(id) {}

          
@@ 193,6 197,10 @@ struct IdAbstract : super_type {
     inline RowType &row();
     inline const RowType &row() const;
 
+    inline EnumType subkind() const {
+        return (EnumType)super_type::kind();
+    }
+
     inline RowType &operator *() {
         return row();
     }

          
@@ 384,10 392,15 @@ struct std::hash< scopes::Maybe<T> > {
 #define SCOPES_TYPEDEF(NAME, TYPE) typedef TYPE NAME;
 
 #define SCOPES_HASH_MEMBER(NAME, TYPE) H = scopes::hash2(H, std::hash< decltype(s.NAME) >{}(s.NAME));
+#define SCOPES_CMP_MEMBER(NAME, TYPE) if (this->NAME != other.NAME) return false;
 #define SCOPES_DEFINE_STRUCT_MEMBER(NAME, TYPE) TYPE NAME;
 #define SCOPES_DEFINE_STRUCT(NAME) \
     struct NAME { \
         STRUCT_FIELDS_ ## NAME(SCOPES_DEFINE_STRUCT_MEMBER) \
+        inline bool operator ==(const NAME &other) const { \
+            STRUCT_FIELDS_ ## NAME(SCOPES_CMP_MEMBER); \
+            return true; \
+        } \
     }; \
     SCOPES_END_MODULE \
     template<> struct std::hash< scopes::NAME > { \

          
M src/lexerparser.hpp +2 -2
@@ 134,7 134,7 @@ struct LexerParser {
     String get_unescaped_string();
     String get_unescaped_symbol();
     String get_block_string();
-    ConstNumber get_number();
+    Const get_number();
     //Const *get();
 
     // parses a list to its terminator and returns a handle to the first cell

          
@@ 164,7 164,7 @@ struct LexerParser {
     const char *string;
     int string_len;
 
-    ConstNumber value;
+    Const value;
     std::unordered_map<Symbol, Symbol> prefix_symbol_map;
 };
 

          
M src/print.hpp +1 -0
@@ 601,6 601,7 @@ typedef DefaultStyledPrinterConfig::Styl
 typedef DefaultStyledPrinterConfig::SetANSI<false>::StyledPrinter StyledFilePrinter;
 typedef DefaultStyledPrinterConfig::SetSuper<StringPrinterType>::StyledPrinter StyledStringPrinter;
 typedef StyledStringPrinter::Config::SetANSI<false>::StyledPrinter StringPrinter;
+typedef StringPrinter::Config::SetMultiline<false>::StyledPrinter NameStringPrinter;
 
 constexpr inline auto ErrorPrinter () {
     return StdPrinter(stderr);

          
M src/scope.hpp +2 -0
@@ 79,6 79,8 @@ public:
 
 #endif
 
+Scope scope_parent(Scope scope);
+
 Scope reparent(Scope content, Scope parent);
 void bind(Scope &scope, Const name, Value value, Maybe<String> doc = {});
 void bind(Scope &scope, Symbol name, Value value, Maybe<String> doc = {});

          
M src/styled_stream.hpp +4 -0
@@ 150,6 150,10 @@ void set_address_name(const void *ptr, c
 
 #endif
 
+void stream_uid(auto &&print, uint64_t uid);
+void stream_address(auto &&print, const void *ptr);
+void set_address_name(const void *ptr, String name);
+
 } // namespace scopes
 
 #endif // SCOPES_STYLED_STREAM_HPP

          
M src/type.hpp +19 -19
@@ 208,37 208,37 @@ B_TYPES()
 
 //------------------------------------------------------------------------------
 
-bool is_opaque(const Type *T);
-TypeKind storage_kind(const Type *T);
-SCOPES_RESULT(size_t) size_of(const Type *T);
-SCOPES_RESULT(size_t) bitsize_of(const Type *T);
-SCOPES_RESULT(size_t) qualified_size_of(const Type *T);
-SCOPES_RESULT(size_t) align_of(const Type *T);
-SCOPES_RESULT(size_t) qualified_align_of(const Type *T);
-const Type *superof(const Type *T);
-void stream_type_name(StyledStream &ss, const Type *T);
-bool is_returning(const Type *T);
-bool is_returning_value(const Type *T);
-bool types_compatible(const Type *paramT, const Type *argT);
+bool is_opaque(Type T);
+TypeKind storage_kind(Type T);
+SCOPES_RESULT(size_t) size_of(Type T);
+SCOPES_RESULT(size_t) bitsize_of(Type T);
+SCOPES_RESULT(size_t) qualified_size_of(Type T);
+SCOPES_RESULT(size_t) align_of(Type T);
+SCOPES_RESULT(size_t) qualified_align_of(Type T);
+Maybe<Type> superof(Type T);
+//void stream_type_name(StyledStream &ss, const Type *T);
+bool is_returning(Type T);
+bool is_returning_value(Type T);
+bool types_compatible(Type paramT, Type argT);
 bool all_plain(const Types &types);
 bool any_viewable(const Types &types);
 // can be copied implicitly, without needing a copy constructor (unless viewable)
-bool is_plain(const Type *T);
+bool is_plain(Type T);
 // can be prevented from being implicitly copied
-bool is_viewable(const Type *T);
+bool is_viewable(Type T);
 
 //------------------------------------------------------------------------------
 
-SCOPES_RESULT(const Type *) storage_type(const Type *T);
-SCOPES_RESULT(const Type *) qualified_storage_type(const Type *T);
+SCOPES_RESULT(Type) storage_type(Type T);
+SCOPES_RESULT(Type) qualified_storage_type(Type T);
 
 //------------------------------------------------------------------------------
 // TYPE CHECK PREDICATES
 //------------------------------------------------------------------------------
 
-SCOPES_RESULT(void) verify(const Type *typea, const Type *typeb);
-SCOPES_RESULT(void) verify_integer(const Type *type);
-SCOPES_RESULT(void) verify_real(const Type *type);
+SCOPES_RESULT(void) verify(Type typea, Type typeb);
+SCOPES_RESULT(void) verify_integer(Type type);
+SCOPES_RESULT(void) verify_real(Type type);
 
 #define verify_range(CLASS, IDX, COUNT) \
     ({ \

          
M src/type/function_type.hpp +6 -0
@@ 50,6 50,12 @@ struct FunctionType : Type {
 
 #endif
 
+bool has_exception(FunctionType T);
+bool is_variadic(FunctionType T);
+//bool returns_value(FunctionType T);
+//FunctionType strip_annotations(FunctionType T);
+//SCOPES_RESULT(Type) type_at_index(size_t i);
+
 void canonicalize_argument_types(Types &types);
 
 Type raising_function_type(Type except_type, Type return_type,

          
M src/type/sized_storage_type.hpp +10 -0
@@ 64,6 64,16 @@ protected:
 };
 #endif
 
+bool is_unsized(ArrayLikeType T);
+bool is_zterm(ArrayLikeType T);
+size_t countof(ArrayLikeType T);
+size_t fullcountof(ArrayLikeType T); // including zero terminating element
+SCOPES_RESULT(void *) getelementptr(ArrayLikeType T, void *src, size_t i);
+SCOPES_RESULT(Type) type_at_index(ArrayLikeType T, size_t i);
+
+bool is_plain(TupleLikeType T);
+bool is_viewable(TupleLikeType T);
+
 //------------------------------------------------------------------------------
 
 } // namespace scopes

          
M src/type/typename_type.hpp +13 -0
@@ 58,6 58,19 @@ protected:
 
 #endif
 
+String typename_name(TypenameType T);
+String typename_original_name(TypenameType T);
+
+SCOPES_RESULT(void) typename_complete(TypenameType T);
+SCOPES_RESULT(void) typename_complete(TypenameType T, Type _type, TypenameFlags flags);
+
+bool is_complete(TypenameType T);
+bool is_plain(TypenameType T);
+bool is_viewable(TypenameType T);
+bool is_opaque(TypenameType T);
+Type superof(TypenameType T);
+Type storageof(TypenameType T);
+
 // always generates a new type
 TypenameType incomplete_typename_type(String name, Type supertype);
 TypenameType opaque_typename_type(String name, Type supertype);

          
M src/value.hpp +21 -0
@@ 61,6 61,8 @@ struct ValueIndex {
 };
 #endif
 
+ValueIndex value_index(Value value, int index = 0);
+
 //------------------------------------------------------------------------------
 
 #if 0

          
@@ 151,7 153,11 @@ struct Block : TypedValue {
 protected:
     Block();
 };
+#endif
 
+bool is_empty(Block block);
+
+#if 0
 //------------------------------------------------------------------------------
 
 struct Instruction : TypedValue {

          
@@ 991,6 997,12 @@ struct Malloc : Instruction {
     const Type *type;
     TypedValueRef count;
 };
+#endif
+
+bool is_array_alloc(Alloca value);
+bool is_array_alloc(Malloc value);
+
+#if 0
 
 struct Free : Instruction {
     static bool classof(const Value *T);

          
@@ 1112,7 1124,12 @@ struct Call : Instruction {
 protected:
     BlockRef except_body;
 };
+#endif
 
+Block get_except_body(Call value);
+Maybe<Block> get_maybe_null_except_body(Call value);
+
+#if 0
 //------------------------------------------------------------------------------
 
 struct LoopLabel : Instruction {

          
@@ 1368,6 1385,8 @@ protected:
 
 #endif
 
+SCOPES_RESULT(Maybe<Pure>) to_global(ConstPointer value);
+
 ConstValue const_ast(Type type, Value value);
 ConstValue const_ast(Value value);
 ConstValue const_value(Anchor anchor);

          
@@ 1378,6 1397,8 @@ ConstValue const_value(Scope scope);
 ConstValue const_value(Anchor anchor);
 ConstValue const_value(Symbol anchor);
 
+ConstPointer const_ptr(Type T, const void *ptr);
+
 #if 0
 
 //------------------------------------------------------------------------------

          
M src/value_defs.hh +19 -27
@@ 302,7 302,7 @@ SCOPES_DEFINE_TYPE(Concrete, CGenTypeUns
 SCOPES_DEFINE_TYPE(Concrete, CGenFailedToTranslateTypeError, Error, ErrorKind)
 #define TYPE_FIELDS_CGenUnboundValueError(T) T(by, Anchor) T(value, Value)
 SCOPES_DEFINE_TYPE(Concrete, CGenUnboundValueError, Error, ErrorKind)
-#define TYPE_FIELDS_CGenInvalidRedeclarationError(T) T(by, Anchor) T(sym, String) T(decl, String)
+#define TYPE_FIELDS_CGenInvalidRedeclarationError(T) T(by, Anchor) T(sym, SCOPES_builtin_string) T(decl, SCOPES_builtin_string)
 SCOPES_DEFINE_TYPE(Concrete, CGenInvalidRedeclarationError, Error, ErrorKind)
 #define TYPE_FIELDS_CGenUnsupportedBuiltinError(T) T(by, Anchor) T(value, Builtin)
 SCOPES_DEFINE_TYPE(Concrete, CGenUnsupportedBuiltinError, Error, ErrorKind)

          
@@ 334,9 334,9 @@ SCOPES_DEFINE_TYPE(Concrete, CGenUnsuppo
 SCOPES_DEFINE_TYPE(Concrete, CGenFailedToResolveExternError, Error, ErrorKind)
 #define TYPE_FIELDS_CGenRecursiveConstructorError(T) T(by, Anchor) T(value, Global) T(cycle, Global)
 SCOPES_DEFINE_TYPE(Concrete, CGenRecursiveConstructorError, Error, ErrorKind)
-#define TYPE_FIELDS_CGenBackendFailedError(T) T(by, Anchor) T(reason, String)
+#define TYPE_FIELDS_CGenBackendFailedError(T) T(by, Anchor) T(reason, SCOPES_builtin_string)
 SCOPES_DEFINE_TYPE(Concrete, CGenBackendFailedError, Error, ErrorKind)
-#define TYPE_FIELDS_CGenBackendFailedErrnoError(T) T(by, Anchor) T(reason, String) T(code, SCOPES_errno)
+#define TYPE_FIELDS_CGenBackendFailedErrnoError(T) T(by, Anchor) T(reason, SCOPES_builtin_string) T(code, SCOPES_errno)
 SCOPES_DEFINE_TYPE(Concrete, CGenBackendFailedErrnoError, Error, ErrorKind)
 #define TYPE_FIELDS_CGenCannotSerializeConstPointerError(T) T(by, Anchor) T(type, Type)
 SCOPES_DEFINE_TYPE(Concrete, CGenCannotSerializeConstPointerError, Error, ErrorKind)

          
@@ 412,11 412,11 @@ SCOPES_DEFINE_TYPE(Concrete, InvalidFoot
 SCOPES_DEFINE_TYPE(Concrete, CoreModuleFunctionTypeMismatchError, Error, ErrorKind)
 #define TYPE_FIELDS_CoreMissingError(T) T(by, Anchor) T(path, Symbol)
 SCOPES_DEFINE_TYPE(Concrete, CoreMissingError, Error, ErrorKind)
-#define TYPE_FIELDS_UserError(T) T(by, Anchor) T(reason, String)
+#define TYPE_FIELDS_UserError(T) T(by, Anchor) T(reason, SCOPES_builtin_string)
 SCOPES_DEFINE_TYPE(Concrete, UserError, Error, ErrorKind)
-#define TYPE_FIELDS_ExecutionEngineFailedError(T) T(by, Anchor) T(reason, String)
+#define TYPE_FIELDS_ExecutionEngineFailedError(T) T(by, Anchor) T(reason, SCOPES_builtin_string)
 SCOPES_DEFINE_TYPE(Concrete, ExecutionEngineFailedError, Error, ErrorKind)
-#define TYPE_FIELDS_OptimizationPassFailedError(T) T(by, Anchor) T(reason, String)
+#define TYPE_FIELDS_OptimizationPassFailedError(T) T(by, Anchor) T(reason, SCOPES_builtin_string)
 SCOPES_DEFINE_TYPE(Concrete, OptimizationPassFailedError, Error, ErrorKind)
 #define TYPE_FIELDS_StackOverflowError(T) T(by, Anchor)
 SCOPES_DEFINE_TYPE(Concrete, StackOverflowError, Error, ErrorKind)

          
@@ 629,7 629,7 @@ SCOPES_DEFINE_TYPE(Concrete, Parameter, 
 SCOPES_DEFINE_TYPE(Concrete, Exception, TypedValue, ValueKind)
 #define TYPE_FIELDS_ArgumentList(T) T(type, Type) T(values, TypedValues)
 SCOPES_DEFINE_TYPE(Concrete, ArgumentList, TypedValue, ValueKind)
-#define TYPE_FIELDS_Block(T) T(type, Type) T(depth, SCOPES_i32) T(insert_index, SCOPES_i32) T(flags, BlockFlags) T(body, Instructions) T(terminator, Instruction) T(function, Function) T(valid, IDSet) T(owner, Instruction)
+#define TYPE_FIELDS_Block(T) T(type, Type) T(depth, SCOPES_i32) T(insert_index, SCOPES_i32) T(flags, BlockFlags) T(body, Instructions) T(terminator, SCOPES_OPTIONAL_ID_TYPE(Terminator)) T(function, Function) T(valid, IDSet) T(owner, Instruction)
 SCOPES_DEFINE_TYPE(Concrete, Block, TypedValue, ValueKind)
 #define TYPE_FIELDS_ExtractArgument(T) T(type, Type) T(value, TypedValue) T(index, SCOPES_i32)
 SCOPES_DEFINE_TYPE(Concrete, ExtractArgument, TypedValue, ValueKind)

          
@@ 647,17 647,14 @@ SCOPES_DEFINE_TYPE(Concrete, PureCast, P
 #define TYPE_FIELDS_Undef(T) T(type, Type)
 SCOPES_DEFINE_TYPE(Concrete, Undef, Pure, ValueKind)
 #define TYPE_FIELDS_Const(T) T(type, Type)
-#define TYPE_SUBTYPES_Const(T) T(Concrete, ConstNull) T(Abstract, ConstNumber) T(Concrete, ConstString) T(Concrete, ConstAggregate) T(Concrete, ConstPointer) T(Concrete, ConstValue)
+#define TYPE_SUBTYPES_Const(T) T(Concrete, ConstNull) T(Concrete, ConstInt) T(Concrete, ConstReal) T(Concrete, ConstString) T(Concrete, ConstAggregate) T(Concrete, ConstPointer) T(Concrete, ConstValue)
 SCOPES_DEFINE_TYPE(Abstract, Const, Pure, ValueKind)
 #define TYPE_FIELDS_ConstNull(T) T(type, Type)
 SCOPES_DEFINE_TYPE(Concrete, ConstNull, Const, ValueKind)
-#define TYPE_FIELDS_ConstNumber(T) T(type, Type)
-#define TYPE_SUBTYPES_ConstNumber(T) T(Concrete, ConstInt) T(Concrete, ConstReal)
-SCOPES_DEFINE_TYPE(Abstract, ConstNumber, Const, ValueKind)
 #define TYPE_FIELDS_ConstInt(T) T(type, Type) T(words, SCOPES_DARRAY_TYPE(SCOPES_u64))
-SCOPES_DEFINE_TYPE(Concrete, ConstInt, ConstNumber, ValueKind)
+SCOPES_DEFINE_TYPE(Concrete, ConstInt, Const, ValueKind)
 #define TYPE_FIELDS_ConstReal(T) T(type, Type) T(value, SCOPES_f64)
-SCOPES_DEFINE_TYPE(Concrete, ConstReal, ConstNumber, ValueKind)
+SCOPES_DEFINE_TYPE(Concrete, ConstReal, Const, ValueKind)
 #define TYPE_FIELDS_ConstString(T) T(type, Type) T(value, String)
 SCOPES_DEFINE_TYPE(Concrete, ConstString, Const, ValueKind)
 #define TYPE_FIELDS_ConstAggregate(T) T(type, Type) T(values, Consts)

          
@@ 667,7 664,7 @@ SCOPES_DEFINE_TYPE(Concrete, ConstPointe
 #define TYPE_FIELDS_ConstValue(T) T(type, Type) T(value, Value)
 SCOPES_DEFINE_TYPE(Concrete, ConstValue, Const, ValueKind)
 #define TYPE_FIELDS_Instruction(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block))
-#define TYPE_SUBTYPES_Instruction(T) T(Abstract, Label) T(Concrete, LoopLabel) T(Concrete, CondBr) T(Concrete, Switch) T(Concrete, Call) T(Concrete, Select) T(Concrete, ExtractValue) T(Concrete, InsertValue) T(Concrete, GetElementPtr) T(Concrete, ExtractElement) T(Concrete, InsertElement) T(Concrete, ShuffleVector) T(Concrete, Alloca) T(Concrete, Malloc) T(Concrete, Free) T(Concrete, Load) T(Concrete, Store) T(Abstract, AtomicRMW) T(Concrete, CmpXchg) T(Abstract, Barrier) T(Abstract, Cmp) T(Abstract, UnOp) T(Abstract, BinOp) T(Concrete, Annotate) T(Concrete, ExecutionMode) T(Abstract, Cast) T(Abstract, Terminator)
+#define TYPE_SUBTYPES_Instruction(T) T(Abstract, Label) T(Concrete, LoopLabel) T(Concrete, CondBr) T(Concrete, Switch) T(Concrete, Call) T(Concrete, Select) T(Concrete, ExtractValue) T(Concrete, InsertValue) T(Concrete, GetElementPtr) T(Concrete, ExtractElement) T(Concrete, InsertElement) T(Concrete, ShuffleVector) T(Concrete, Alloca) T(Concrete, Malloc) T(Concrete, Free) T(Concrete, Load) T(Concrete, Store) T(Abstract, AtomicRMW) T(Concrete, CmpXchg) T(Abstract, Barrier) T(Abstract, ICmp) T(Abstract, FCmp) T(Abstract, UnOp) T(Abstract, BinOp) T(Concrete, Annotate) T(Concrete, ExecutionMode) T(Abstract, Cast) T(Abstract, Terminator)
 SCOPES_DEFINE_TYPE(Abstract, Instruction, TypedValue, ValueKind)
 #define TYPE_FIELDS_Label(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(body, Block) T(merges, Merges) T(splitpoints, SCOPES_SET_TYPE(TypedValue))
 #define TYPE_SUBTYPES_Label(T) T(Concrete, UserLabel) T(Concrete, InlineLabel) T(Concrete, TryLabel) T(Concrete, ExceptLabel) T(Concrete, ExceptAllLabel) T(Concrete, ThenLabel) T(Concrete, BreakLabel) T(Concrete, BranchMergeLabel) T(Concrete, TypeOfLabel)

          
@@ 696,7 693,7 @@ SCOPES_DEFINE_TYPE(Concrete, LoopLabel, 
 SCOPES_DEFINE_TYPE(Concrete, CondBr, Instruction, ValueKind)
 #define TYPE_FIELDS_Switch(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(expr, TypedValue) T(cases, SCOPES_DARRAY_TYPE(SwitchCase))
 SCOPES_DEFINE_TYPE(Concrete, Switch, Instruction, ValueKind)
-#define TYPE_FIELDS_Call(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(callee, TypedValue) T(args, TypedValues) T(except, Exception) T(except_body, Block)
+#define TYPE_FIELDS_Call(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(callee, TypedValue) T(args, TypedValues) T(except, SCOPES_OPTIONAL_ID_TYPE(Exception)) T(except_body, SCOPES_OPTIONAL_ID_TYPE(Block))
 SCOPES_DEFINE_TYPE(Concrete, Call, Instruction, ValueKind)
 #define TYPE_FIELDS_Select(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(cond, TypedValue) T(value1, TypedValue) T(value2, TypedValue)
 SCOPES_DEFINE_TYPE(Concrete, Select, Instruction, ValueKind)

          
@@ 768,12 765,9 @@ SCOPES_DEFINE_TYPE(Concrete, BarrierMemo
 SCOPES_DEFINE_TYPE(Concrete, BarrierMemoryBuffer, Barrier, BarrierKind)
 #define TYPE_FIELDS_BarrierMemoryShared(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block))
 SCOPES_DEFINE_TYPE(Concrete, BarrierMemoryShared, Barrier, BarrierKind)
-#define TYPE_FIELDS_Cmp(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(value1, TypedValue) T(value2, TypedValue)
-#define TYPE_SUBTYPES_Cmp(T) T(Abstract, ICmp) T(Abstract, FCmp)
-SCOPES_DEFINE_TYPE(Abstract, Cmp, Instruction, ValueKind)
 #define TYPE_FIELDS_ICmp(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(value1, TypedValue) T(value2, TypedValue)
 #define TYPE_SUBTYPES_ICmp(T) T(Concrete, ICmpEQ) T(Concrete, ICmpNE) T(Concrete, ICmpUGT) T(Concrete, ICmpUGE) T(Concrete, ICmpULT) T(Concrete, ICmpULE) T(Concrete, ICmpSGT) T(Concrete, ICmpSGE) T(Concrete, ICmpSLT) T(Concrete, ICmpSLE)
-SCOPES_DEFINE_TYPE(Abstract, ICmp, Cmp, ICmpKind)
+SCOPES_DEFINE_TYPE(Abstract, ICmp, Instruction, ICmpKind)
 #define TYPE_FIELDS_ICmpEQ(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(value1, TypedValue) T(value2, TypedValue)
 SCOPES_DEFINE_TYPE(Concrete, ICmpEQ, ICmp, ICmpKind)
 #define TYPE_FIELDS_ICmpNE(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(value1, TypedValue) T(value2, TypedValue)

          
@@ 796,7 790,7 @@ SCOPES_DEFINE_TYPE(Concrete, ICmpSLT, IC
 SCOPES_DEFINE_TYPE(Concrete, ICmpSLE, ICmp, ICmpKind)
 #define TYPE_FIELDS_FCmp(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(value1, TypedValue) T(value2, TypedValue)
 #define TYPE_SUBTYPES_FCmp(T) T(Concrete, FCmpOEQ) T(Concrete, FCmpONE) T(Concrete, FCmpORD) T(Concrete, FCmpOGT) T(Concrete, FCmpOGE) T(Concrete, FCmpOLT) T(Concrete, FCmpOLE) T(Concrete, FCmpUEQ) T(Concrete, FCmpUNE) T(Concrete, FCmpUNO) T(Concrete, FCmpUGT) T(Concrete, FCmpUGE) T(Concrete, FCmpULT) T(Concrete, FCmpULE)
-SCOPES_DEFINE_TYPE(Abstract, FCmp, Cmp, FCmpKind)
+SCOPES_DEFINE_TYPE(Abstract, FCmp, Instruction, FCmpKind)
 #define TYPE_FIELDS_FCmpOEQ(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(value1, TypedValue) T(value2, TypedValue)
 SCOPES_DEFINE_TYPE(Concrete, FCmpOEQ, FCmp, FCmpKind)
 #define TYPE_FIELDS_FCmpONE(T) T(type, Type) T(name, Symbol) T(block, SCOPES_OPTIONAL_ID_TYPE(Block)) T(value1, TypedValue) T(value2, TypedValue)

          
@@ 995,7 989,6 @@ SCOPES_TYPEDEF(Types, SCOPES_DARRAY_TYPE
 SCOPES_TYPEDEF(Instructions, SCOPES_DARRAY_TYPE(Instruction))
 SCOPES_TYPEDEF(Parameters, SCOPES_DARRAY_TYPE(Parameter))
 SCOPES_TYPEDEF(ParameterTemplates, SCOPES_DARRAY_TYPE(ParameterTemplate))
-SCOPES_TYPEDEF(TypedValues, SCOPES_DARRAY_TYPE(TypedValue))
 SCOPES_TYPEDEF(Merges, SCOPES_DARRAY_TYPE(Merge))
 SCOPES_TYPEDEF(Returns, SCOPES_DARRAY_TYPE(Return))
 SCOPES_TYPEDEF(Raises, SCOPES_DARRAY_TYPE(Raise))

          
@@ 1004,6 997,7 @@ SCOPES_DEFINE_STRUCT(ValueIndex)
 #define STRUCT_FIELDS_UniqueInfo(T) T(value, ValueIndex)
 SCOPES_DEFINE_STRUCT(UniqueInfo)
 SCOPES_TYPEDEF(UniqueMap, SCOPES_MAP_TYPE(SCOPES_i32, UniqueInfo))
+SCOPES_TYPEDEF(TypedValues, SCOPES_DARRAY_TYPE(TypedValue))
 SCOPES_TYPEDEF(Values, SCOPES_DARRAY_TYPE(Value))
 SCOPES_TYPEDEF(Strings, SCOPES_DARRAY_TYPE(String))
 SCOPES_TYPEDEF(Symbols, SCOPES_DARRAY_TYPE(Symbol))

          
@@ 1114,7 1108,7 @@ SCOPES_IMPL_FIELDS(Concrete, FCmpOGT, FC
 SCOPES_IMPL_FIELDS(Concrete, FCmpORD, FCmp)
 SCOPES_IMPL_FIELDS(Concrete, FCmpONE, FCmp)
 SCOPES_IMPL_FIELDS(Concrete, FCmpOEQ, FCmp)
-SCOPES_IMPL_FIELDS(Abstract, FCmp, Cmp)
+SCOPES_IMPL_FIELDS(Abstract, FCmp, Instruction)
 SCOPES_IMPL_FIELDS(Concrete, ICmpSLE, ICmp)
 SCOPES_IMPL_FIELDS(Concrete, ICmpSLT, ICmp)
 SCOPES_IMPL_FIELDS(Concrete, ICmpSGE, ICmp)

          
@@ 1125,8 1119,7 @@ SCOPES_IMPL_FIELDS(Concrete, ICmpUGE, IC
 SCOPES_IMPL_FIELDS(Concrete, ICmpUGT, ICmp)
 SCOPES_IMPL_FIELDS(Concrete, ICmpNE, ICmp)
 SCOPES_IMPL_FIELDS(Concrete, ICmpEQ, ICmp)
-SCOPES_IMPL_FIELDS(Abstract, ICmp, Cmp)
-SCOPES_IMPL_FIELDS(Abstract, Cmp, Instruction)
+SCOPES_IMPL_FIELDS(Abstract, ICmp, Instruction)
 SCOPES_IMPL_FIELDS(Concrete, BarrierMemoryShared, Barrier)
 SCOPES_IMPL_FIELDS(Concrete, BarrierMemoryBuffer, Barrier)
 SCOPES_IMPL_FIELDS(Concrete, BarrierMemoryImage, Barrier)

          
@@ 1180,9 1173,8 @@ SCOPES_IMPL_FIELDS(Concrete, ConstValue,
 SCOPES_IMPL_FIELDS(Concrete, ConstPointer, Const)
 SCOPES_IMPL_FIELDS(Concrete, ConstAggregate, Const)
 SCOPES_IMPL_FIELDS(Concrete, ConstString, Const)
-SCOPES_IMPL_FIELDS(Concrete, ConstReal, ConstNumber)
-SCOPES_IMPL_FIELDS(Concrete, ConstInt, ConstNumber)
-SCOPES_IMPL_FIELDS(Abstract, ConstNumber, Const)
+SCOPES_IMPL_FIELDS(Concrete, ConstReal, Const)
+SCOPES_IMPL_FIELDS(Concrete, ConstInt, Const)
 SCOPES_IMPL_FIELDS(Concrete, ConstNull, Const)
 SCOPES_IMPL_FIELDS(Abstract, Const, Pure)
 SCOPES_IMPL_FIELDS(Concrete, Undef, Pure)