mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
IR: pass intToPtrCast test
This commit is contained in:
parent
aee7ad3de2
commit
735cdbfdac
@ -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,
|
||||
|
||||
@ -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:
|
||||
|
||||
88
src/ir.cpp
88
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:
|
||||
{
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user