diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-04-18 02:28:05 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-04-18 02:28:05 -0400 |
| commit | a791417552f200911e534aebe312ab3c527b1a2b (patch) | |
| tree | 365c97b3f139de892893427ea14e34c8045eb2f9 /src/codegen.cpp | |
| parent | 407916cd2f3f4931de29fd87b8c9ae3faeba8452 (diff) | |
| download | zig-a791417552f200911e534aebe312ab3c527b1a2b.tar.gz zig-a791417552f200911e534aebe312ab3c527b1a2b.zip | |
add `@fieldParentPtr` builtin function
closes #320
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 7222cd3fc8..d5f1cfe4f6 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2261,6 +2261,34 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable return LLVMBuildInBoundsGEP(g->builder, enum_tag_type->data.enum_tag.name_table, indices, 2, ""); } +static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable, + IrInstructionFieldParentPtr *instruction) +{ + TypeTableEntry *container_ptr_type = instruction->base.value.type; + assert(container_ptr_type->id == TypeTableEntryIdPointer); + + TypeTableEntry *container_type = container_ptr_type->data.pointer.child_type; + + size_t byte_offset = LLVMOffsetOfElement(g->target_data_ref, + container_type->type_ref, instruction->field->gen_index); + + LLVMValueRef field_ptr_val = ir_llvm_value(g, instruction->field_ptr); + + if (byte_offset == 0) { + return LLVMBuildBitCast(g->builder, field_ptr_val, container_ptr_type->type_ref, ""); + } else { + TypeTableEntry *usize = g->builtin_types.entry_usize; + + LLVMValueRef field_ptr_int = LLVMBuildPtrToInt(g->builder, field_ptr_val, + usize->type_ref, ""); + + LLVMValueRef base_ptr_int = LLVMBuildNUWSub(g->builder, field_ptr_int, + LLVMConstInt(usize->type_ref, byte_offset, false), ""); + + return LLVMBuildIntToPtr(g->builder, base_ptr_int, container_ptr_type->type_ref, ""); + } +} + static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { switch (atomic_order) { @@ -2963,6 +2991,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_panic(g, executable, (IrInstructionPanic *)instruction); case IrInstructionIdEnumTagName: return ir_render_enum_tag_name(g, executable, (IrInstructionEnumTagName *)instruction); + case IrInstructionIdFieldParentPtr: + return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction); } zig_unreachable(); } @@ -4509,6 +4539,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrcast", 2); create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2); create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1); + create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3); } static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) { |
