diff --git a/self_hosted/typecheck.jou b/self_hosted/typecheck.jou index 27e64fce..2b9d18f5 100644 --- a/self_hosted/typecheck.jou +++ b/self_hosted/typecheck.jou @@ -1026,11 +1026,17 @@ class Stage3TypeChecker: snprintf(message, sizeof message[0], "value of type %s cannot be indexed", types->original_type->name) fail(pointer->location, message) - index_type = self->do_expression(index)->original_type - if not index_type->is_integer_type(): - snprintf(message, sizeof message[0], "the index inside [...] must be an integer, not %s", index_type->name) + index_types = self->do_expression(index) + assert index_types != NULL + + if not index_types->original_type->is_integer_type(): + snprintf(message, sizeof message[0], "the index inside [...] must be an integer, not %s", index_types->original_type->name) fail(index->location, message) + # LLVM assumes that indexes smaller than 64 bits are signed. + # https://github.com/Akuli/jou/issues/48 + index_types->do_implicit_cast(long_type, Location{}, NULL) + return pointer_type->value_type def do_expression_maybe_void(self, expression: AstExpression*) -> ExpressionTypes*: diff --git a/src/codegen.c b/src/codegen.c index 2a36a52f..313b5de4 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -336,15 +336,7 @@ static void codegen_instruction(const struct State *st, const CfInstruction *ins } break; case CF_PTR_ADD_INT: - { - LLVMValueRef index = getop(1); - if (ins->operands[1]->type->kind == TYPE_UNSIGNED_INTEGER) { - // https://github.com/Akuli/jou/issues/48 - // Apparently the default is to interpret indexes as signed. - index = LLVMBuildZExt(st->builder, index, LLVMInt64Type(), "ptr_add_int_implicit_cast"); - } - setdest(LLVMBuildGEP(st->builder, getop(0), &index, 1, "ptr_add_int")); - } + setdest(LLVMBuildGEP(st->builder, getop(0), (LLVMValueRef[]){getop(1)}, 1, "ptr_add_int")); break; case CF_NUM_CAST: { diff --git a/src/typecheck.c b/src/typecheck.c index 029d7fe4..2f3069c7 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -756,14 +756,18 @@ static const Type *typecheck_indexing( } assert(ptrtype->kind == TYPE_POINTER); - const Type *indextype = typecheck_expression_not_void(ft, indexexpr)->type; - if (!is_integer_type(indextype)) { + ExpressionTypes *indextypes = typecheck_expression_not_void(ft, indexexpr); + if (!is_integer_type(indextypes->type)) { fail_with_error( indexexpr->location, "the index inside [...] must be an integer, not %s", - indextype->name); + indextypes->type->name); } + // LLVM assumes that indexes smaller than 64 bits are signed. + // https://github.com/Akuli/jou/issues/48 + do_implicit_cast(indextypes, longType, (Location){0}, NULL); + return ptrtype->data.valuetype; }