Commit 735cdbfdac
Changed files (7)
src/all_types.hpp
@@ -90,6 +90,11 @@ enum ConstPtrSpecial {
// This means that the pointer points to inline memory, so attempting
// to write a non-compile-time known value is an error
ConstPtrSpecialInline,
+ // This means that we did a compile-time pointer reinterpret and we cannot
+ // understand the value of pointee at compile time. However, we will still
+ // emit a binary with a compile time known address.
+ // In this case index is the numeric address value.
+ ConstPtrSpecialRuntime,
};
struct ConstPtrValue {
@@ -427,8 +432,6 @@ struct AstNodeUnwrapErrorExpr {
enum CastOp {
CastOpNoCast, // signifies the function call expression is not a cast
CastOpNoop, // fn call expr is a cast, but does nothing
- CastOpPtrToInt,
- CastOpIntToPtr,
CastOpErrToInt,
CastOpIntToFloat,
CastOpFloatToInt,
@@ -1453,6 +1456,8 @@ enum IrInstructionId {
IrInstructionIdInitEnum,
IrInstructionIdPointerReinterpret,
IrInstructionIdWidenOrShorten,
+ IrInstructionIdIntToPtr,
+ IrInstructionIdPtrToInt,
};
struct IrInstruction {
@@ -2101,6 +2106,18 @@ struct IrInstructionWidenOrShorten {
IrInstruction *target;
};
+struct IrInstructionPtrToInt {
+ IrInstruction base;
+
+ IrInstruction *target;
+};
+
+struct IrInstructionIntToPtr {
+ IrInstruction base;
+
+ IrInstruction *target;
+};
+
enum LValPurpose {
LValPurposeNone,
LValPurposeAssign,
src/codegen.cpp
@@ -969,10 +969,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
} else {
zig_panic("TODO");
}
- case CastOpPtrToInt:
- return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
- case CastOpIntToPtr:
- return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
case CastOpResizeSlice:
{
assert(cast_instruction->tmp_ptr);
@@ -1114,6 +1110,18 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
instruction->base.value.type, target_val);
}
+static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, IrInstructionIntToPtr *instruction) {
+ TypeTableEntry *wanted_type = instruction->base.value.type;
+ LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
+ return LLVMBuildIntToPtr(g->builder, target_val, wanted_type->type_ref, "");
+}
+
+static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, IrInstructionPtrToInt *instruction) {
+ TypeTableEntry *wanted_type = instruction->base.value.type;
+ LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
+ return LLVMBuildPtrToInt(g->builder, target_val, wanted_type->type_ref, "");
+}
+
static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
IrInstructionUnreachable *unreachable_instruction)
{
@@ -2347,6 +2355,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);
case IrInstructionIdWidenOrShorten:
return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
+ case IrInstructionIdPtrToInt:
+ return ir_render_ptr_to_int(g, executable, (IrInstructionPtrToInt *)instruction);
+ case IrInstructionIdIntToPtr:
+ return ir_render_int_to_ptr(g, executable, (IrInstructionIntToPtr *)instruction);
case IrInstructionIdContainerInitList:
return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
case IrInstructionIdSwitchVar:
src/ir.cpp
@@ -52,6 +52,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {
assert(const_val->special == ConstValSpecialStatic);
+ assert(const_val->data.x_ptr.special != ConstPtrSpecialRuntime);
ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
size_t index = const_val->data.x_ptr.index;
@@ -459,6 +460,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *
return IrInstructionIdWidenOrShorten;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrToInt *) {
+ return IrInstructionIdPtrToInt;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToPtr *) {
+ return IrInstructionIdIntToPtr;
+}
+
template<typename T>
static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -1899,6 +1908,30 @@ static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, As
return &instruction->base;
}
+static IrInstruction *ir_build_int_to_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *target)
+{
+ IrInstructionIntToPtr *instruction = ir_build_instruction<IrInstructionIntToPtr>(
+ irb, scope, source_node);
+ instruction->target = target;
+
+ ir_ref_instruction(target);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *target)
+{
+ IrInstructionPtrToInt *instruction = ir_build_instruction<IrInstructionPtrToInt>(
+ irb, scope, source_node);
+ instruction->target = target;
+
+ ir_ref_instruction(target);
+
+ return &instruction->base;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -4657,8 +4690,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
*const_val = *other_val;
const_val->type = new_type;
break;
- case CastOpPtrToInt:
- case CastOpIntToPtr:
case CastOpResizeSlice:
case CastOpBytesToSlice:
// can't do it
@@ -5234,6 +5265,51 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
return result;
}
+static IrInstruction *ir_analyze_ptr_to_int(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *target, TypeTableEntry *wanted_type)
+{
+ assert(wanted_type->id == TypeTableEntryIdInt);
+
+ if (instr_is_comptime(target)) {
+ ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+ if (val->data.x_ptr.special == ConstPtrSpecialRuntime) {
+ IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, wanted_type, val->depends_on_compile_var);
+ bignum_init_unsigned(&result->value.data.x_bignum, val->data.x_ptr.index);
+ return result;
+ }
+ }
+
+ IrInstruction *result = ir_build_ptr_to_int(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, target);
+ result->value.type = wanted_type;
+ return result;
+}
+
+static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *target, TypeTableEntry *wanted_type)
+{
+ assert(wanted_type->id == TypeTableEntryIdPointer);
+
+ if (instr_is_comptime(target)) {
+ ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+ IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, wanted_type, val->depends_on_compile_var);
+ result->value.data.x_ptr.base_ptr = nullptr;
+ result->value.data.x_ptr.index = bignum_to_twos_complement(&val->data.x_bignum);
+ result->value.data.x_ptr.special = ConstPtrSpecialRuntime;
+ return result;
+ }
+
+ IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, target);
+ result->value.type = wanted_type;
+ return result;
+}
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
TypeTableEntry *wanted_type, IrInstruction *value)
@@ -5270,7 +5346,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) &&
type_is_codegen_pointer(actual_type_canon))
{
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpPtrToInt, false);
+ return ir_analyze_ptr_to_int(ira, source_instr, value, wanted_type);
}
@@ -5278,7 +5354,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (wanted_type_canon->id == TypeTableEntryIdPointer &&
(actual_type_canon == isize_type || actual_type_canon == usize_type))
{
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToPtr, false);
+ return ir_analyze_int_to_ptr(ira, source_instr, value, wanted_type);
}
// explicit widening or shortening cast
@@ -9937,6 +10013,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
case IrInstructionIdInvalid:
case IrInstructionIdPointerReinterpret:
case IrInstructionIdWidenOrShorten:
+ case IrInstructionIdIntToPtr:
+ case IrInstructionIdPtrToInt:
case IrInstructionIdStructInit:
case IrInstructionIdStructFieldPtr:
case IrInstructionIdEnumFieldPtr:
@@ -10244,6 +10322,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdInitEnum:
case IrInstructionIdPointerReinterpret:
case IrInstructionIdWidenOrShorten:
+ case IrInstructionIdPtrToInt:
+ case IrInstructionIdIntToPtr:
return false;
case IrInstructionIdAsm:
{
src/ir_print.cpp
@@ -98,7 +98,11 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {
}
case TypeTableEntryIdPointer:
fprintf(irp->f, "&");
- ir_print_const_value(irp, const_ptr_pointee(const_val));
+ if (const_val->data.x_ptr.special == ConstPtrSpecialRuntime) {
+ fprintf(irp->f, "(runtime pointer value)");
+ } else {
+ ir_print_const_value(irp, const_ptr_pointee(const_val));
+ }
return;
case TypeTableEntryIdFn:
{
@@ -934,6 +938,18 @@ static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten
fprintf(irp->f, ")");
}
+static void ir_print_ptr_to_int(IrPrint *irp, IrInstructionPtrToInt *instruction) {
+ fprintf(irp->f, "@ptrToInt(");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction) {
+ fprintf(irp->f, "@intToPtr(");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -1179,6 +1195,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdWidenOrShorten:
ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
break;
+ case IrInstructionIdPtrToInt:
+ ir_print_ptr_to_int(irp, (IrInstructionPtrToInt *)instruction);
+ break;
+ case IrInstructionIdIntToPtr:
+ ir_print_int_to_ptr(irp, (IrInstructionIntToPtr *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
src/parseh.cpp
@@ -1203,7 +1203,7 @@ static void process_symbol_macros(Context *c) {
if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) {
TypeTableEntry *child_type = var_type->data.maybe.child_type;
if (child_type->id == TypeTableEntryIdFn) {
- zig_panic("TODO");
+ zig_panic("TODO macro alias of function pointer in .h file");
//Tld *fn_tld = create_inline_fn_alias(c, ms.name, tld_var->var);
//c->macro_table.put(ms.name, fn_tld);
continue;
test/cases/misc.zig
@@ -414,6 +414,14 @@ fn testTakeAddressOfParameter(f: f32) {
}
+fn intToPtrCast() {
+ @setFnTest(this);
+
+ const x = isize(13);
+ const y = (&u8)(x);
+ const z = usize(y);
+ assert(z == 13);
+}
test/self_hosted.zig
@@ -11,16 +11,6 @@ fn getFirstByte(inline T: type, mem: []T) -> u8 {
}
-// TODO not passing
-fn intToPtrCast() {
- @setFnTest(this);
-
- const x = isize(13);
- const y = (&u8)(x);
- const z = usize(y);
- assert(z == 13);
-}
-
// TODO not passing
fn pointerToVoidReturnType() {
@setFnTest(this);