aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-07-10 14:03:03 -0400
committerAndrew Kelley <superjoe30@gmail.com>2018-07-10 14:03:03 -0400
commitcfaebb20d8906d31cedc59e39e6a9286967a931a (patch)
tree33d0c3994bfb658937e2e692a946bc8a2eca4fe5 /src/codegen.cpp
parentb5d07297dec61a3993dfe91ceee2c87672db1e8e (diff)
parent0ce6934e2631eb3beca817d3bce12ecb13aafa13 (diff)
downloadzig-cfaebb20d8906d31cedc59e39e6a9286967a931a.tar.gz
zig-cfaebb20d8906d31cedc59e39e6a9286967a931a.zip
Merge remote-tracking branch 'origin/master' into llvm7
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp45
1 files changed, 38 insertions, 7 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index bfc20cb1d2..1d51629002 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2927,18 +2927,26 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");
} else if (array_type->id == TypeTableEntryIdStruct) {
assert(array_type->data.structure.is_slice);
+ if (!type_has_bits(instruction->base.value.type)) {
+ if (safety_check_on) {
+ assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);
+ add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, array_ptr);
+ }
+ return nullptr;
+ }
+
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
if (safety_check_on) {
- size_t len_index = array_type->data.structure.fields[1].gen_index;
+ size_t len_index = array_type->data.structure.fields[slice_len_index].gen_index;
assert(len_index != SIZE_MAX);
LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");
LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, "");
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
}
- size_t ptr_index = array_type->data.structure.fields[0].gen_index;
+ size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
assert(ptr_index != SIZE_MAX);
LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, "");
LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, "");
@@ -3353,14 +3361,22 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, BuiltinFnId fn_id) {
ZigLLVMFnKey key = {};
const char *fn_name;
+ uint32_t n_args;
if (fn_id == BuiltinFnIdCtz) {
fn_name = "cttz";
+ n_args = 2;
key.id = ZigLLVMFnIdCtz;
key.data.ctz.bit_count = (uint32_t)int_type->data.integral.bit_count;
} else if (fn_id == BuiltinFnIdClz) {
fn_name = "ctlz";
+ n_args = 2;
key.id = ZigLLVMFnIdClz;
key.data.clz.bit_count = (uint32_t)int_type->data.integral.bit_count;
+ } else if (fn_id == BuiltinFnIdPopCount) {
+ fn_name = "ctpop";
+ n_args = 1;
+ key.id = ZigLLVMFnIdPopCount;
+ key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
} else {
zig_unreachable();
}
@@ -3375,7 +3391,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, Bui
int_type->type_ref,
LLVMInt1Type(),
};
- LLVMTypeRef fn_type = LLVMFunctionType(int_type->type_ref, param_types, 2, false);
+ LLVMTypeRef fn_type = LLVMFunctionType(int_type->type_ref, param_types, n_args, false);
LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type);
assert(LLVMGetIntrinsicID(fn_val));
@@ -3408,6 +3424,14 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru
return gen_widen_or_shorten(g, false, int_type, instruction->base.value.type, wrong_size_int);
}
+static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
+ TypeTableEntry *int_type = instruction->value->value.type;
+ LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
+ LLVMValueRef operand = ir_llvm_value(g, instruction->value);
+ LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, &operand, 1, "");
+ return gen_widen_or_shorten(g, false, int_type, instruction->base.value.type, wrong_size_int);
+}
+
static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, IrInstructionSwitchBr *instruction) {
LLVMValueRef target_value = ir_llvm_value(g, instruction->target_value);
LLVMBasicBlockRef else_block = instruction->else_block->llvm_block;
@@ -3894,11 +3918,15 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
}
- LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
- LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
- gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
+ if (type_has_bits(array_type)) {
+ size_t gen_ptr_index = instruction->base.value.type->data.structure.fields[slice_ptr_index].gen_index;
+ LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");
+ LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
+ gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
+ }
- LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
+ size_t gen_len_index = instruction->base.value.type->data.structure.fields[slice_len_index].gen_index;
+ LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, "");
LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
@@ -4730,6 +4758,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
case IrInstructionIdCtz:
return ir_render_ctz(g, executable, (IrInstructionCtz *)instruction);
+ case IrInstructionIdPopCount:
+ return ir_render_pop_count(g, executable, (IrInstructionPopCount *)instruction);
case IrInstructionIdSwitchBr:
return ir_render_switch_br(g, executable, (IrInstructionSwitchBr *)instruction);
case IrInstructionIdPhi:
@@ -6241,6 +6271,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdCUndef, "cUndef", 1);
create_builtin_fn(g, BuiltinFnIdCtz, "ctz", 1);
create_builtin_fn(g, BuiltinFnIdClz, "clz", 1);
+ create_builtin_fn(g, BuiltinFnIdPopCount, "popCount", 1);
create_builtin_fn(g, BuiltinFnIdImport, "import", 1);
create_builtin_fn(g, BuiltinFnIdCImport, "cImport", 1);
create_builtin_fn(g, BuiltinFnIdErrName, "errorName", 1);