static void write_const(CTX *ctx, struct ir_const_val v) { char *s = const_unparse(NULL, v); if (TEST_UNION(IR_TYPE, tarray, &v.type)) { fprintf(ctx->f, "{%s}", s); } else if (type_is_integer(v.type)) { // Get rid of annoying-but-correct gcc warning. This happens because we // negate a value not representable in intmax_t, even though the result // is representable, i.e. the only case is INT64_MIN. if (type_equals(v.type, type_integer(true, 64)) && *GET_UNION(VALUE, vuint64, &v.value) == INT64_MIN) { fprintf(ctx->f, "INT64_MIN"); } else { fprintf(ctx->f, "%s(%s)", int_const(v.type), s); } } else if (TEST_UNION(IR_TYPE, tslice, &v.type)) { if (TEST_UNION0(VALUE, vempty, &v.value)) { fprintf(ctx->f, "{0}"); } else if (type_equals(v.type, TYPE_STRING)) { char *raw = *GET_UNION(VALUE, vstring, &v.value); fprintf(ctx->f, "{ %s, %zd }", s, raw ? strlen(raw) : 0); } else { assert(false); } } else { fprintf(ctx->f, "%s", s); } talloc_free(s); }
bool type_is_integer(type_t t) { assert(t != NULL); if (t->kind == T_SUBTYPE) return type_is_integer(type_base(t)); else return (t->kind == T_INTEGER); }
void UnionTree::parse(Parser *parser) { if (parser->cur()->type() != '<') { log_expect(parser->cur()->loc(), "'<'"); } parser->eat(); ptr<Token> token = parser->cur(); if (!token->is_iden()) { log_expect(token->loc(), "identifier"); } parser->eat(); ptr<Tree> tree = _struct->getItem(token->text(), false); if (!tree) { log_error(token->loc(), "unknown key field '%s'", token->text()); } if (tree->type() != TREE_STRUCT_ITEM) { log_error(token->loc(), "key field must is integer type", token->text()); } if (!type_is_integer(tree.cast<StructItemTree>()->type()->type())) { log_error(token->loc(), "key field must is integer type", token->text()); } _key = tree.cast<StructItemTree>(); if (parser->cur()->type() != '>') { log_expect(parser->cur()->loc(), "'>'"); } parser->eat(); if (parser->cur()->type() != '{') { log_expect(parser->cur()->loc(), "'{'"); } parser->eat(); while (1) { switch (parser->cur()->type()) { case '}': do { parser->eat(); ptr<Token> token = parser->cur(); if (token->is_iden()) { parser->eat(); _name = token; token = parser->cur(); } if (token->type() == ';') { parser->eat(); return; } else { log_expect(token->loc(), "identifier or ';'"); } return; } while (0); default: do { object<UnionItemTree> item; item->parse(parser); for (auto sym : _symbols) { if (item->index()->value()->vint() == sym->index()->value()->vint()) { log_error(item->index()->loc, "dup union item index"); } if (item->decl()->name()->text() == sym->decl()->name()->text()) { log_error(item->decl()->name()->loc(), "dup union item name"); } } _symbols.push_back(item); } while (0); } } }