+ if (fieldtype->m_vtype == TYPE_ARRAY) {
+ if (!ast_istype(fieldtype, ast_value)) {
+ compile_error(m_context, "internal error: ast_value required");
+ return false;
+ }
+ ast_value *array = reinterpret_cast<ast_value*>(fieldtype);
+
+ if (!checkArray(*array))
+ return false;
+
+ ast_expression *elemtype = array->m_next;
+ qc_type vtype = elemtype->m_vtype;
+
+ ir_value *v = ir->createField(m_name, vtype);
+ if (!v) {
+ compile_error(m_context, "ir_builder::createGlobal failed on `%s`", m_name);
+ return false;
+ }
+ v->m_context = m_context;
+ v->m_unique_life = true;
+ v->m_locked = true;
+ array->m_ir_v = m_ir_v = v;
+
+ if (m_flags & AST_FLAG_INCLUDE_DEF)
+ m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
+ if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
+ m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_v->m_flags |= IR_FLAG_NOREF;
+
+ const size_t namelen = m_name.length();
+ std::unique_ptr<char[]> name(new char[namelen+16]);
+ util_strncpy(name.get(), m_name.c_str(), namelen);
+
+ array->m_ir_values.resize(array->m_count);
+ array->m_ir_values[0] = v;
+ for (size_t ai = 1; ai < array->m_count; ++ai) {
+ util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai);
+ array->m_ir_values[ai] = ir->createField(name.get(), vtype);
+ if (!array->m_ir_values[ai]) {
+ compile_error(m_context, "ir_builder::createGlobal failed on `%s`", name.get());
+ return false;
+ }
+ array->m_ir_values[ai]->m_context = m_context;
+ array->m_ir_values[ai]->m_unique_life = true;
+ array->m_ir_values[ai]->m_locked = true;
+ if (m_flags & AST_FLAG_INCLUDE_DEF)
+ array->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
+ if (m_flags & AST_FLAG_NOREF)
+ array->m_ir_values[ai]->m_flags |= IR_FLAG_NOREF;
+ }
+ }
+ else
+ {
+ ir_value *v = ir->createField(m_name, m_next->m_vtype);
+ if (!v)
+ return false;
+ v->m_context = m_context;
+ m_ir_v = v;
+ if (m_flags & AST_FLAG_INCLUDE_DEF)
+ m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
+ if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
+ m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_v->m_flags |= IR_FLAG_NOREF;
+ }
+ return true;
+}
+
+ir_value *ast_value::prepareGlobalArray(ir_builder *ir)
+{
+ ast_expression *elemtype = m_next;
+ qc_type vtype = elemtype->m_vtype;
+
+ if (m_flags & AST_FLAG_ARRAY_INIT && !m_count) {
+ compile_error(m_context, "array `%s' has no size", m_name);
+ return nullptr;
+ }
+
+ /* same as with field arrays */
+ if (!checkArray(*this))
+ return nullptr;
+
+ ir_value *v = ir->createGlobal(m_name, vtype);
+ if (!v) {
+ compile_error(m_context, "ir_builder::createGlobal failed `%s`", m_name);
+ return nullptr;
+ }
+ v->m_context = m_context;
+ v->m_unique_life = true;
+ v->m_locked = true;
+
+ if (m_flags & AST_FLAG_INCLUDE_DEF)
+ v->m_flags |= IR_FLAG_INCLUDE_DEF;
+ if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
+ v->m_flags |= IR_FLAG_ERASABLE;
+ if (m_flags & AST_FLAG_NOREF)
+ v->m_flags |= IR_FLAG_NOREF;
+
+ const size_t namelen = m_name.length();
+ std::unique_ptr<char[]> name(new char[namelen+16]);
+ util_strncpy(name.get(), m_name.c_str(), namelen);
+
+ m_ir_values.resize(m_count);
+ m_ir_values[0] = v;
+ for (size_t ai = 1; ai < m_count; ++ai) {
+ util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai);
+ m_ir_values[ai] = ir->createGlobal(name.get(), vtype);
+ if (!m_ir_values[ai]) {
+ compile_error(m_context, "ir_builder::createGlobal failed `%s`", name.get());
+ return nullptr;
+ }
+ m_ir_values[ai]->m_context = m_context;
+ m_ir_values[ai]->m_unique_life = true;
+ m_ir_values[ai]->m_locked = true;
+ if (m_flags & AST_FLAG_INCLUDE_DEF)
+ m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_values[ai]->m_flags |= IR_FLAG_NOREF;
+ }
+
+ return v;
+}
+
+bool ast_value::generateLocal(ir_function *func, bool param)
+{
+ if (m_vtype == TYPE_NIL) {
+ compile_error(m_context, "internal error: trying to generate a variable of TYPE_NIL");
+ return false;
+ }
+
+ if (m_hasvalue && m_vtype == TYPE_FUNCTION)