remove @alignOf and add @cAbiAlignOf and @preferredAlignOf

See #396
This commit is contained in:
Andrew Kelley 2017-08-26 13:29:24 -04:00
parent 3a4ea41fe8
commit e726925e80
5 changed files with 174 additions and 35 deletions

View File

@ -1184,7 +1184,8 @@ enum BuiltinFnId {
BuiltinFnIdMemcpy,
BuiltinFnIdMemset,
BuiltinFnIdSizeof,
BuiltinFnIdAlignof,
BuiltinFnIdPreferredAlignOf,
BuiltinFnIdAbiAlignOf,
BuiltinFnIdMaxValue,
BuiltinFnIdMinValue,
BuiltinFnIdMemberCount,
@ -1805,7 +1806,8 @@ enum IrInstructionId {
IrInstructionIdBreakpoint,
IrInstructionIdReturnAddress,
IrInstructionIdFrameAddress,
IrInstructionIdAlignOf,
IrInstructionIdPreferredAlignOf,
IrInstructionIdAbiAlignOf,
IrInstructionIdOverflowOp,
IrInstructionIdTestErr,
IrInstructionIdUnwrapErrCode,
@ -2389,7 +2391,13 @@ struct IrInstructionOverflowOp {
TypeTableEntry *result_ptr_type;
};
struct IrInstructionAlignOf {
struct IrInstructionPreferredAlignOf {
IrInstruction base;
IrInstruction *type_value;
};
struct IrInstructionAbiAlignOf {
IrInstruction base;
IrInstruction *type_value;

View File

@ -3233,7 +3233,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdEmbedFile:
case IrInstructionIdIntType:
case IrInstructionIdMemberCount:
case IrInstructionIdAlignOf:
case IrInstructionIdPreferredAlignOf:
case IrInstructionIdAbiAlignOf:
case IrInstructionIdFnProto:
case IrInstructionIdTestComptime:
case IrInstructionIdCheckSwitchProngs:
@ -4594,7 +4595,8 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);
create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3);
create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1);
create_builtin_fn(g, BuiltinFnIdAlignof, "alignOf", 1);
create_builtin_fn(g, BuiltinFnIdPreferredAlignOf, "preferredAlignOf", 1);
create_builtin_fn(g, BuiltinFnIdAbiAlignOf, "cAbiAlignOf", 1);
create_builtin_fn(g, BuiltinFnIdMaxValue, "maxValue", 1);
create_builtin_fn(g, BuiltinFnIdMinValue, "minValue", 1);
create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1);

View File

@ -422,8 +422,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *)
return IrInstructionIdFrameAddress;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
return IrInstructionIdAlignOf;
static constexpr IrInstructionId ir_instruction_id(IrInstructionPreferredAlignOf *) {
return IrInstructionIdPreferredAlignOf;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionAbiAlignOf *) {
return IrInstructionIdAbiAlignOf;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {
@ -1806,8 +1810,17 @@ static IrInstruction *ir_build_overflow_op_from(IrBuilder *irb, IrInstruction *o
return new_instruction;
}
static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {
IrInstructionAlignOf *instruction = ir_build_instruction<IrInstructionAlignOf>(irb, scope, source_node);
static IrInstruction *ir_build_preferred_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {
IrInstructionPreferredAlignOf *instruction = ir_build_instruction<IrInstructionPreferredAlignOf>(irb, scope, source_node);
instruction->type_value = type_value;
ir_ref_instruction(type_value, irb->current_basic_block);
return &instruction->base;
}
static IrInstruction *ir_build_abi_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {
IrInstructionAbiAlignOf *instruction = ir_build_instruction<IrInstructionAbiAlignOf>(irb, scope, source_node);
instruction->type_value = type_value;
ir_ref_instruction(type_value, irb->current_basic_block);
@ -2658,7 +2671,14 @@ static IrInstruction *ir_instruction_frameaddress_get_dep(IrInstructionFrameAddr
return nullptr;
}
static IrInstruction *ir_instruction_alignof_get_dep(IrInstructionAlignOf *instruction, size_t index) {
static IrInstruction *ir_instruction_preferredalignof_get_dep(IrInstructionPreferredAlignOf *instruction, size_t index) {
switch (index) {
case 0: return instruction->type_value;
default: return nullptr;
}
}
static IrInstruction *ir_instruction_abialignof_get_dep(IrInstructionAbiAlignOf *instruction, size_t index) {
switch (index) {
case 0: return instruction->type_value;
default: return nullptr;
@ -3036,8 +3056,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
return ir_instruction_returnaddress_get_dep((IrInstructionReturnAddress *) instruction, index);
case IrInstructionIdFrameAddress:
return ir_instruction_frameaddress_get_dep((IrInstructionFrameAddress *) instruction, index);
case IrInstructionIdAlignOf:
return ir_instruction_alignof_get_dep((IrInstructionAlignOf *) instruction, index);
case IrInstructionIdPreferredAlignOf:
return ir_instruction_preferredalignof_get_dep((IrInstructionPreferredAlignOf *) instruction, index);
case IrInstructionIdAbiAlignOf:
return ir_instruction_abialignof_get_dep((IrInstructionAbiAlignOf *) instruction, index);
case IrInstructionIdOverflowOp:
return ir_instruction_overflowop_get_dep((IrInstructionOverflowOp *) instruction, index);
case IrInstructionIdTestErr:
@ -4264,14 +4286,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_build_return_address(irb, scope, node);
case BuiltinFnIdFrameAddress:
return ir_build_frame_address(irb, scope, node);
case BuiltinFnIdAlignof:
case BuiltinFnIdPreferredAlignOf:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
return ir_build_alignof(irb, scope, node, arg0_value);
return ir_build_preferred_align_of(irb, scope, node, arg0_value);
}
case BuiltinFnIdAbiAlignOf:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
return ir_build_abi_align_of(irb, scope, node, arg0_value);
}
case BuiltinFnIdAddWithOverflow:
return ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd);
@ -13829,25 +13860,108 @@ static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIn
return u8_ptr_const;
}
static TypeTableEntry *ir_analyze_instruction_alignof(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
static TypeTableEntry *ir_analyze_instruction_preferred_align_of(IrAnalyze *ira, IrInstructionPreferredAlignOf *instruction) {
IrInstruction *type_value = instruction->type_value->other;
if (type_is_invalid(type_value->value.type))
return ira->codegen->builtin_types.entry_invalid;
TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
ensure_complete_type(ira->codegen, type_entry);
if (type_is_invalid(type_entry)) {
if (type_is_invalid(type_entry))
return ira->codegen->builtin_types.entry_invalid;
} else if (type_entry->id == TypeTableEntryIdUnreachable) {
ir_add_error(ira, instruction->type_value,
buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->builtin_types.entry_invalid;
} else {
uint64_t align_in_bytes = LLVMABIAlignmentOfType(ira->codegen->target_data_ref, type_entry->type_ref);
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes);
return ira->codegen->builtin_types.entry_num_lit_int;
switch (type_entry->id) {
case TypeTableEntryIdInvalid:
case TypeTableEntryIdVar:
zig_unreachable();
case TypeTableEntryIdMetaType:
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdNumLitFloat:
case TypeTableEntryIdNumLitInt:
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdArgTuple:
ir_add_error(ira, instruction->type_value,
buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->builtin_types.entry_invalid;
case TypeTableEntryIdVoid:
case TypeTableEntryIdBool:
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdPureError:
case TypeTableEntryIdEnum:
case TypeTableEntryIdEnumTag:
case TypeTableEntryIdUnion:
case TypeTableEntryIdFn:
case TypeTableEntryIdOpaque:
{
uint64_t align_in_bytes = LLVMPreferredAlignmentOfType(ira->codegen->target_data_ref, type_entry->type_ref);
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes);
return ira->codegen->builtin_types.entry_num_lit_int;
}
}
zig_unreachable();
}
static TypeTableEntry *ir_analyze_instruction_abi_align_of(IrAnalyze *ira, IrInstructionAbiAlignOf *instruction) {
IrInstruction *type_value = instruction->type_value->other;
if (type_is_invalid(type_value->value.type))
return ira->codegen->builtin_types.entry_invalid;
TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
ensure_complete_type(ira->codegen, type_entry);
if (type_is_invalid(type_entry))
return ira->codegen->builtin_types.entry_invalid;
switch (type_entry->id) {
case TypeTableEntryIdInvalid:
case TypeTableEntryIdVar:
zig_unreachable();
case TypeTableEntryIdMetaType:
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdNumLitFloat:
case TypeTableEntryIdNumLitInt:
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdArgTuple:
ir_add_error(ira, instruction->type_value,
buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->builtin_types.entry_invalid;
case TypeTableEntryIdVoid:
case TypeTableEntryIdBool:
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdPureError:
case TypeTableEntryIdEnum:
case TypeTableEntryIdEnumTag:
case TypeTableEntryIdUnion:
case TypeTableEntryIdFn:
case TypeTableEntryIdOpaque:
{
uint64_t align_in_bytes = LLVMABIAlignmentOfType(ira->codegen->target_data_ref, type_entry->type_ref);
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes);
return ira->codegen->builtin_types.entry_num_lit_int;
}
}
zig_unreachable();
}
static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
@ -14838,8 +14952,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction);
case IrInstructionIdFrameAddress:
return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction);
case IrInstructionIdAlignOf:
return ir_analyze_instruction_alignof(ira, (IrInstructionAlignOf *)instruction);
case IrInstructionIdPreferredAlignOf:
return ir_analyze_instruction_preferred_align_of(ira, (IrInstructionPreferredAlignOf *)instruction);
case IrInstructionIdAbiAlignOf:
return ir_analyze_instruction_abi_align_of(ira, (IrInstructionAbiAlignOf *)instruction);
case IrInstructionIdOverflowOp:
return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction);
case IrInstructionIdTestErr:
@ -15035,7 +15151,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdBoolNot:
case IrInstructionIdSlice:
case IrInstructionIdMemberCount:
case IrInstructionIdAlignOf:
case IrInstructionIdPreferredAlignOf:
case IrInstructionIdAbiAlignOf:
case IrInstructionIdReturnAddress:
case IrInstructionIdFrameAddress:
case IrInstructionIdTestErr:

View File

@ -664,8 +664,14 @@ static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *in
fprintf(irp->f, "@returnAddress()");
}
static void ir_print_alignof(IrPrint *irp, IrInstructionAlignOf *instruction) {
fprintf(irp->f, "@alignOf(");
static void ir_print_preferred_align_of(IrPrint *irp, IrInstructionPreferredAlignOf *instruction) {
fprintf(irp->f, "@preferredAlignOf(");
ir_print_other_instruction(irp, instruction->type_value);
fprintf(irp->f, ")");
}
static void ir_print_abi_align_of(IrPrint *irp, IrInstructionAbiAlignOf *instruction) {
fprintf(irp->f, "@abiAlignOf(");
ir_print_other_instruction(irp, instruction->type_value);
fprintf(irp->f, ")");
}
@ -1110,8 +1116,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdFrameAddress:
ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction);
break;
case IrInstructionIdAlignOf:
ir_print_alignof(irp, (IrInstructionAlignOf *)instruction);
case IrInstructionIdPreferredAlignOf:
ir_print_preferred_align_of(irp, (IrInstructionPreferredAlignOf *)instruction);
break;
case IrInstructionIdAbiAlignOf:
ir_print_abi_align_of(irp, (IrInstructionAbiAlignOf *)instruction);
break;
case IrInstructionIdOverflowOp:
ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);

View File

@ -3,9 +3,12 @@ const builtin = @import("builtin");
const Foo = struct { x: u32, y: u32, z: u32, };
test "@alignOf(T) before referencing T" {
comptime assert(@alignOf(Foo) != @maxValue(usize));
test "@abiAlignOf(T) before referencing T" {
comptime assert(@cAbiAlignOf(Foo) != @maxValue(usize));
if (builtin.arch == builtin.Arch.x86_64) {
comptime assert(@alignOf(Foo) == 4);
comptime {
assert(@cAbiAlignOf(Foo) == 4);
assert(@preferredAlignOf(Foo) == 8);
}
}
}