LLVMValueRef gen_digestof(compile_t* c, ast_t* ast) { ast_t* expr = ast_child(ast); LLVMValueRef value = gen_expr(c, expr); ast_t* type = deferred_reify(c->frame->reify, ast_type(expr), c->opt); LLVMValueRef ret = gen_digestof_value(c, type, value); ast_free_unattached(type); return ret; }
static LLVMValueRef gen_digestof_value(compile_t* c, LLVMValueRef value) { LLVMTypeRef type = LLVMTypeOf(value); switch(LLVMGetTypeKind(type)) { case LLVMFloatTypeKind: value = LLVMBuildBitCast(c->builder, value, c->i32, ""); return LLVMBuildZExt(c->builder, value, c->i64, ""); case LLVMDoubleTypeKind: return LLVMBuildBitCast(c->builder, value, c->i64, ""); case LLVMIntegerTypeKind: { uint32_t width = LLVMGetIntTypeWidth(type); if(width < 64) { value = LLVMBuildZExt(c->builder, value, c->i64, ""); } else if(width == 128) { LLVMValueRef shift = LLVMConstInt(c->i128, 64, false); LLVMValueRef high = LLVMBuildLShr(c->builder, value, shift, ""); high = LLVMBuildTrunc(c->builder, high, c->i64, ""); value = LLVMBuildTrunc(c->builder, value, c->i64, ""); value = LLVMBuildXor(c->builder, value, high, ""); } return value; } case LLVMStructTypeKind: { uint32_t count = LLVMCountStructElementTypes(type); LLVMValueRef result = LLVMConstInt(c->i64, 0, false); for(uint32_t i = 0; i < count; i++) { LLVMValueRef elem = LLVMBuildExtractValue(c->builder, value, i, ""); elem = gen_digestof_value(c, elem); result = LLVMBuildXor(c->builder, result, elem, ""); } return result; } case LLVMPointerTypeKind: return LLVMBuildPtrToInt(c->builder, value, c->i64, ""); default: {} } assert(0); return NULL; }
void gen_digestof_fun(compile_t* c, reach_type_t* t) { pony_assert(t->can_be_boxed); reach_method_t* m = reach_method(t, TK_BOX, stringtab("__digestof"), NULL); if(m == NULL) return; compile_type_t* c_t = (compile_type_t*)t->c_type; compile_method_t* c_m = (compile_method_t*)m->c_method; c_m->func_type = LLVMFunctionType(c->intptr, &c_t->structure_ptr, 1, false); c_m->func = codegen_addfun(c, m->full_name, c_m->func_type, true); codegen_startfun(c, c_m->func, NULL, NULL, NULL, false); LLVMValueRef value = LLVMGetParam(codegen_fun(c), 0); value = gen_unbox(c, t->ast_cap, value); LLVMBuildRet(c->builder, gen_digestof_value(c, t->ast_cap, value)); codegen_finishfun(c); }
static LLVMValueRef gen_digestof_value(compile_t* c, ast_t* type, LLVMValueRef value) { LLVMTypeRef impl_type = LLVMTypeOf(value); switch(LLVMGetTypeKind(impl_type)) { case LLVMFloatTypeKind: value = LLVMBuildBitCast(c->builder, value, c->i32, ""); return LLVMBuildZExt(c->builder, value, c->intptr, ""); case LLVMDoubleTypeKind: value = LLVMBuildBitCast(c->builder, value, c->i64, ""); return gen_digestof_int64(c, value); case LLVMIntegerTypeKind: { uint32_t width = LLVMGetIntTypeWidth(impl_type); if(width < 64) { return LLVMBuildZExt(c->builder, value, c->intptr, ""); } else if(width == 64) { return gen_digestof_int64(c, value); } else if(width == 128) { LLVMValueRef shift = LLVMConstInt(c->i128, 64, false); LLVMValueRef high = LLVMBuildLShr(c->builder, value, shift, ""); high = LLVMBuildTrunc(c->builder, high, c->i64, ""); value = LLVMBuildTrunc(c->builder, value, c->i64, ""); high = gen_digestof_int64(c, high); value = gen_digestof_int64(c, value); return LLVMBuildXor(c->builder, value, high, ""); } break; } case LLVMStructTypeKind: { uint32_t count = LLVMCountStructElementTypes(impl_type); LLVMValueRef result = LLVMConstInt(c->intptr, 0, false); ast_t* child = ast_child(type); for(uint32_t i = 0; i < count; i++) { LLVMValueRef elem = LLVMBuildExtractValue(c->builder, value, i, ""); elem = gen_digestof_value(c, child, elem); result = LLVMBuildXor(c->builder, result, elem, ""); child = ast_sibling(child); } pony_assert(child == NULL); return result; } case LLVMPointerTypeKind: if(!is_known(type)) { reach_type_t* t = reach_type(c->reach, type); int sub_kind = subtype_kind(t); if((sub_kind & SUBTYPE_KIND_BOXED) != 0) return gen_digestof_box(c, t, value, sub_kind); } return LLVMBuildPtrToInt(c->builder, value, c->intptr, ""); default: {} } pony_assert(0); return NULL; }
LLVMValueRef gen_digestof(compile_t* c, ast_t* ast) { ast_t* expr = ast_child(ast); LLVMValueRef value = gen_expr(c, expr); return gen_digestof_value(c, value); }