backport @addrSpaceCast to stage 1

This commit is contained in:
Robin Voetter 2022-09-17 01:24:13 +02:00
parent fb9a7dad17
commit 76ad9cb10e
No known key found for this signature in database
GPG Key ID: E755662F227CB468
7 changed files with 115 additions and 2 deletions

View File

@ -18181,7 +18181,6 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
const ptr = try sema.resolveInst(extra.rhs);
const ptr_ty = sema.typeOf(ptr);
// TODO in addition to pointers, this instruction is supposed to work for
// pointer-like optionals and slices.
try sema.checkPtrOperand(block, ptr_src, ptr_ty);

View File

@ -95,6 +95,11 @@ enum AddressSpace {
AddressSpaceGS,
AddressSpaceFS,
AddressSpaceSS,
AddressSpaceGlobal,
AddressSpaceConstant,
AddressSpaceParam,
AddressSpaceShared,
AddressSpaceLocal
};
// This one corresponds to the builtin.zig enum.
@ -1842,6 +1847,7 @@ enum BuiltinFnId {
BuiltinFnIdMaximum,
BuiltinFnIdMinimum,
BuiltinFnIdPrefetch,
BuiltinFnIdAddrSpaceCast,
};
struct BuiltinFnEntry {
@ -2673,6 +2679,7 @@ enum Stage1ZirInstId : uint8_t {
Stage1ZirInstIdWasmMemoryGrow,
Stage1ZirInstIdSrc,
Stage1ZirInstIdPrefetch,
Stage1ZirInstIdAddrSpaceCast,
};
// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
@ -4169,6 +4176,13 @@ struct Stage1AirInstAlignCast {
Stage1AirInst *target;
};
struct Stage1ZirInstAddrSpaceCast {
Stage1ZirInst base;
Stage1ZirInst *addrspace;
Stage1ZirInst *ptr;
};
struct Stage1ZirInstSetAlignStack {
Stage1ZirInst base;

View File

@ -1030,6 +1030,11 @@ const char *address_space_name(AddressSpace as) {
case AddressSpaceGS: return "gs";
case AddressSpaceFS: return "fs";
case AddressSpaceSS: return "ss";
case AddressSpaceGlobal: return "global";
case AddressSpaceConstant: return "constant";
case AddressSpaceParam: return "param";
case AddressSpaceShared: return "shared";
case AddressSpaceLocal: return "local";
}
zig_unreachable();
}

View File

@ -351,6 +351,8 @@ void destroy_instruction_src(Stage1ZirInst *inst) {
return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSrc *>(inst));
case Stage1ZirInstIdPrefetch:
return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPrefetch *>(inst));
case Stage1ZirInstIdAddrSpaceCast:
return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAddrSpaceCast *>(inst));
}
zig_unreachable();
}
@ -947,6 +949,10 @@ static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPrefetch *) {
return Stage1ZirInstIdPrefetch;
}
static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAddrSpaceCast *) {
return Stage1ZirInstIdAddrSpaceCast;
}
template<typename T>
static T *ir_create_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
T *special_instruction = heap::c_allocator.create<T>();
@ -2572,6 +2578,19 @@ static Stage1ZirInst *ir_build_align_cast_src(Stage1AstGen *ag, Scope *scope, As
return &instruction->base;
}
static Stage1ZirInst *ir_build_addrspace_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
Stage1ZirInst *addrspace, Stage1ZirInst *ptr)
{
Stage1ZirInstAddrSpaceCast *instruction = ir_build_instruction<Stage1ZirInstAddrSpaceCast>(ag, scope, source_node);
instruction->addrspace = addrspace;
instruction->ptr = ptr;
ir_ref_instruction(addrspace, ag->current_basic_block);
ir_ref_instruction(ptr, ag->current_basic_block);
return &instruction->base;
}
static Stage1ZirInst *ir_build_resolve_result(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
ResultLoc *result_loc, Stage1ZirInst *ty)
{
@ -5459,6 +5478,21 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast
Stage1ZirInst *ir_extern = ir_build_prefetch(ag, scope, node, ptr_value, casted_options_value);
return ir_lval_wrap(ag, scope, ir_extern, lval, result_loc);
}
case BuiltinFnIdAddrSpaceCast:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
if (arg0_value == ag->codegen->invalid_inst_src)
return arg0_value;
AstNode* arg1_node = node->data.fn_call_expr.params.at(1);
Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
if (arg1_value == ag->codegen->invalid_inst_src)
return arg1_value;
Stage1ZirInst *addrspace_cast = ir_build_addrspace_cast(ag, scope, node, arg0_value, arg1_value);
return ir_lval_wrap(ag, scope, addrspace_cast, lval, result_loc);
}
}
zig_unreachable();
}

View File

@ -4371,7 +4371,7 @@ static LLVMValueRef ir_render_binary_not(CodeGen *g, Stage1Air *executable,
static LLVMValueRef gen_soft_float_neg(CodeGen *g, ZigType *operand_type, LLVMValueRef operand) {
uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;
uint16_t num_bits = operand_type->id == ZigTypeIdVector ?
uint16_t num_bits = operand_type->id == ZigTypeIdVector ?
operand_type->data.vector.elem_type->data.floating.bit_count :
operand_type->data.floating.bit_count;
@ -10085,6 +10085,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdMaximum, "maximum", 2);
create_builtin_fn(g, BuiltinFnIdMinimum, "minimum", 2);
create_builtin_fn(g, BuiltinFnIdPrefetch, "prefetch", 2);
create_builtin_fn(g, BuiltinFnIdAddrSpaceCast, "addrSpaceCast", 2);
}
static const char *bool_to_str(bool b) {

View File

@ -23746,6 +23746,50 @@ static Stage1AirInst *ir_analyze_instruction_align_cast(IrAnalyze *ira, Stage1Zi
return result;
}
static bool ir_resolve_addrspace(IrAnalyze *ira, Stage1AirInst *value, AddressSpace *out) {
if (type_is_invalid(value->value->type))
return false;
ZigType *addrspace_type = get_builtin_type(ira->codegen, "AddressSpace");
Stage1AirInst *casted_value = ir_implicit_cast(ira, value, addrspace_type);
if (type_is_invalid(casted_value->value->type))
return false;
ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
if (!const_val)
return false;
*out = (AddressSpace)bigint_as_u32(&const_val->data.x_enum_tag);
return true;
}
static Stage1AirInst *ir_analyze_instruction_addrspace_cast(IrAnalyze *ira, Stage1ZirInstAddrSpaceCast *instruction) {
Stage1AirInst *ptr_inst = instruction->ptr->child;
ZigType *ptr_type = ptr_inst->value->type;
if (type_is_invalid(ptr_type))
return ira->codegen->invalid_inst_gen;
AddressSpace addrspace;
if (!ir_resolve_addrspace(ira, instruction->addrspace->child, &addrspace))
return ira->codegen->invalid_inst_gen;
if (addrspace != AddressSpaceGeneric) {
ir_add_error_node(ira, instruction->addrspace->source_node, buf_sprintf(
"address space '%s' not available in stage 1 compiler, must be .generic",
address_space_name(addrspace)));
return ira->codegen->invalid_inst_gen;
}
if (is_slice(ptr_type) || get_src_ptr_type(ptr_type) != nullptr) {
ir_add_error_node(ira, instruction->ptr->source_node,
buf_sprintf("expected pointer or slice, found '%s'", buf_ptr(&ptr_type->name)));
return ira->codegen->invalid_inst_gen;
}
return ptr_inst;
}
static Stage1AirInst *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, Stage1ZirInstSetAlignStack *instruction) {
uint32_t align_bytes;
Stage1AirInst *align_bytes_inst = instruction->align_bytes->child;
@ -25451,6 +25495,8 @@ static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst
return ir_analyze_instruction_src(ira, (Stage1ZirInstSrc *)instruction);
case Stage1ZirInstIdPrefetch:
return ir_analyze_instruction_prefetch(ira, (Stage1ZirInstPrefetch *)instruction);
case Stage1ZirInstIdAddrSpaceCast:
return ir_analyze_instruction_addrspace_cast(ira, (Stage1ZirInstAddrSpaceCast *)instruction);
}
zig_unreachable();
}
@ -25832,6 +25878,7 @@ bool ir_inst_src_has_side_effects(Stage1ZirInst *instruction) {
case Stage1ZirInstIdWasmMemorySize:
case Stage1ZirInstIdSrc:
case Stage1ZirInstIdReduce:
case Stage1ZirInstIdAddrSpaceCast:
return false;
case Stage1ZirInstIdAsm:

View File

@ -373,6 +373,8 @@ const char* ir_inst_src_type_str(Stage1ZirInstId id) {
return "SrcSrc";
case Stage1ZirInstIdPrefetch:
return "SrcPrefetch";
case Stage1ZirInstIdAddrSpaceCast:
return "SrcAddrSpaceCast";
}
zig_unreachable();
}
@ -2382,6 +2384,14 @@ static void ir_print_align_cast(IrPrintSrc *irp, Stage1ZirInstAlignCast *instruc
fprintf(irp->f, ")");
}
static void ir_print_addrspace_cast(IrPrintSrc *irp, Stage1ZirInstAddrSpaceCast *instruction) {
fprintf(irp->f, "@addrSpaceCast(");
ir_print_other_inst_src(irp, instruction->addrspace);
fprintf(irp->f, ",");
ir_print_other_inst_src(irp, instruction->ptr);
fprintf(irp->f, ")");
}
static void ir_print_align_cast(IrPrintGen *irp, Stage1AirInstAlignCast *instruction) {
fprintf(irp->f, "@alignCast(");
ir_print_other_inst_gen(irp, instruction->target);
@ -3127,6 +3137,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool
case Stage1ZirInstIdPrefetch:
ir_print_prefetch(irp, (Stage1ZirInstPrefetch *)instruction);
break;
case Stage1ZirInstIdAddrSpaceCast:
ir_print_addrspace_cast(irp, (Stage1ZirInstAddrSpaceCast *)instruction);
break;
}
fprintf(irp->f, "\n");
}