-typedef struct ir_builder_s
-{
- char *name;
- MEM_VECTOR_MAKE(ir_function*, functions);
- MEM_VECTOR_MAKE(ir_value*, globals);
- MEM_VECTOR_MAKE(ir_value*, fields);
-} ir_builder;
-
-ir_builder* ir_builder_new(const char *modulename);
-void ir_builder_delete(ir_builder*);
-
-bool ir_builder_set_name(ir_builder *self, const char *name);
-
-MEM_VECTOR_PROTO(ir_builder, ir_function*, functions);
-MEM_VECTOR_PROTO(ir_builder, ir_value*, globals);
-MEM_VECTOR_PROTO(ir_builder, ir_value*, fields);
-
-ir_function* ir_builder_get_function(ir_builder*, const char *fun);
-ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype);
+#define IR_HT_SIZE 1024
+#define IR_MAX_VINSTR_TEMPS 1
+
+struct ir_builder {
+ void* operator new(std::size_t);
+ void operator delete(void*);
+ ir_builder(const std::string& modulename);
+ ~ir_builder();
+
+ std::string name;
+ std::vector<std::unique_ptr<ir_function>> functions;
+ std::vector<std::unique_ptr<ir_value>> globals;
+ std::vector<std::unique_ptr<ir_value>> fields;
+ // for reusing them in vector-splits, TODO: sort this or use a radix-tree
+ std::vector<ir_value*> const_floats;
+
+ ht htfunctions;
+ ht htglobals;
+ ht htfields;
+
+ // extparams' ir_values reference the ones from extparam_protos
+ std::vector<std::unique_ptr<ir_value>> extparam_protos;
+ std::vector<ir_value*> extparams;
+
+ // the highest func->allocated_locals
+ size_t max_locals = 0;
+ size_t max_globaltemps = 0;
+ uint32_t first_common_local = 0;
+ uint32_t first_common_globaltemp = 0;
+
+ std::vector<const char*> filenames;
+ std::vector<qcint_t> filestrings;
+
+ // we cache the #IMMEDIATE string here
+ qcint_t str_immediate = 0;
+
+ // there should just be this one nil
+ ir_value *nil;
+ ir_value *reserved_va_count = nullptr;
+ ir_value *coverage_func = nullptr;
+
+ /* some virtual instructions require temps, and their code is isolated
+ * so that we don't need to keep track of their liveness.
+ */
+ ir_value *vinstr_temp[IR_MAX_VINSTR_TEMPS];