slice and array re-work plus some misc. changes

* `@truncate` builtin allows casting to the same size integer.
   It also performs two's complement casting between signed and
   unsigned integers.
 * The idiomatic way to convert between bytes and numbers is now
   `mem.readInt` and `mem.writeInt` instead of an unsafe cast.
   It works at compile time, is safer, and looks cleaner.
 * Implicitly casting an array to a slice is allowed only if the
   slice is const.
 * Constant pointer values know if their memory is from a compile-
   time constant value or a compile-time variable.
 * Cast from [N]u8 to []T no longer allowed, but [N]u8 to []const T
   still allowed.
 * Fix inability to pass a mutable pointer to comptime variable at
   compile-time to a function and have the function modify the
   memory pointed to by the pointer.
 * Add the `comptime T: type` parameter back to mem.eql. Prevents
   accidentally creating instantiations for arrays.
This commit is contained in:
Andrew Kelley
2017-02-12 17:22:35 -05:00
parent ca180d3f02
commit 6dba1f1c8e
24 changed files with 461 additions and 289 deletions

View File

@@ -1859,9 +1859,18 @@ static LLVMValueRef ir_render_div_exact(CodeGen *g, IrExecutable *executable, Ir
}
static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrInstructionTruncate *instruction) {
TypeTableEntry *dest_type = get_underlying_type(instruction->base.value.type);
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
return LLVMBuildTrunc(g->builder, target_val, dest_type->type_ref, "");
TypeTableEntry *dest_type = get_underlying_type(instruction->base.value.type);
TypeTableEntry *src_type = get_underlying_type(instruction->target->value.type);
if (dest_type == src_type) {
// no-op
return target_val;
} if (src_type->data.integral.bit_count == dest_type->data.integral.bit_count) {
return LLVMBuildBitCast(g->builder, target_val, dest_type->type_ref, "");
} else {
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
return LLVMBuildTrunc(g->builder, target_val, dest_type->type_ref, "");
}
}
static LLVMValueRef ir_render_alloca(CodeGen *g, IrExecutable *executable, IrInstructionAlloca *instruction) {
@@ -1945,10 +1954,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSlice *instruction) {
assert(instruction->tmp_ptr);
TypeTableEntry *array_type = get_underlying_type(instruction->ptr->value.type);
LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr);
TypeTableEntry *array_ptr_type = instruction->ptr->value.type;
assert(array_ptr_type->id == TypeTableEntryIdPointer);
bool is_volatile = array_ptr_type->data.pointer.is_volatile;
TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type;
LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, is_volatile);
LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;
LLVMValueRef array_ptr = ir_llvm_value(g, instruction->ptr);
bool want_debug_safety = instruction->safety_check_on && ir_want_debug_safety(g, &instruction->base);
@@ -2582,7 +2595,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
return LLVMGetUndef(canon_type->type_ref);
case ConstValSpecialStatic:
break;
}
switch (canon_type->id) {