/** * Return the size of the LLVMType in bits. * XXX this function doesn't necessarily handle all LLVM types. */ unsigned lp_sizeof_llvm_type(LLVMTypeRef t) { LLVMTypeKind k = LLVMGetTypeKind(t); switch (k) { case LLVMIntegerTypeKind: return LLVMGetIntTypeWidth(t); case LLVMFloatTypeKind: return 8 * sizeof(float); case LLVMDoubleTypeKind: return 8 * sizeof(double); case LLVMVectorTypeKind: { LLVMTypeRef elem = LLVMGetElementType(t); unsigned len = LLVMGetVectorSize(t); return len * lp_sizeof_llvm_type(elem); } break; case LLVMArrayTypeKind: { LLVMTypeRef elem = LLVMGetElementType(t); unsigned len = LLVMGetArrayLength(t); return len * lp_sizeof_llvm_type(elem); } break; default: assert(0 && "Unexpected type in lp_get_llvm_type_size()"); return 0; } }
static int llvm_type_index(LLVMTypeRef type) { // LLVMDumpType(type); switch (LLVMGetTypeKind(type)) { case LLVMFloatTypeKind: return SCM_FOREIGN_TYPE_FLOAT; case LLVMDoubleTypeKind: return SCM_FOREIGN_TYPE_DOUBLE; case LLVMIntegerTypeKind: switch (LLVMGetIntTypeWidth(type)) { case 1: return SCM_FOREIGN_TYPE_BOOL; case 8: return SCM_FOREIGN_TYPE_INT8; case 16: return SCM_FOREIGN_TYPE_INT16; case 32: return SCM_FOREIGN_TYPE_INT32; case 64: return SCM_FOREIGN_TYPE_INT64; default: return SCM_FOREIGN_TYPE_VOID; }; default: return SCM_FOREIGN_TYPE_VOID; }; }
/** * Given the i32 or vNi32 \p type, generate the textual name (e.g. for use with * intrinsic names). */ void ac_build_type_name_for_intr(LLVMTypeRef type, char *buf, unsigned bufsize) { LLVMTypeRef elem_type = type; assert(bufsize >= 8); if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) { int ret = snprintf(buf, bufsize, "v%u", LLVMGetVectorSize(type)); if (ret < 0) { char *type_name = LLVMPrintTypeToString(type); fprintf(stderr, "Error building type name for: %s\n", type_name); return; } elem_type = LLVMGetElementType(type); buf += ret; bufsize -= ret; } switch (LLVMGetTypeKind(elem_type)) { default: break; case LLVMIntegerTypeKind: snprintf(buf, bufsize, "i%d", LLVMGetIntTypeWidth(elem_type)); break; case LLVMFloatTypeKind: snprintf(buf, bufsize, "f32"); break; case LLVMDoubleTypeKind: snprintf(buf, bufsize, "f64"); break; } }
/** * Print a LLVM value of any type */ LLVMValueRef lp_build_print_value(struct gallivm_state *gallivm, const char *msg, LLVMValueRef value) { LLVMBuilderRef builder = gallivm->builder; LLVMTypeKind type_kind; LLVMTypeRef type_ref; LLVMValueRef params[2 + LP_MAX_VECTOR_LENGTH]; char type_fmt[4] = " %x"; char format[2 + 3 * LP_MAX_VECTOR_LENGTH + 2] = "%s"; unsigned length; unsigned i; type_ref = LLVMTypeOf(value); type_kind = LLVMGetTypeKind(type_ref); if (type_kind == LLVMVectorTypeKind) { length = LLVMGetVectorSize(type_ref); type_ref = LLVMGetElementType(type_ref); type_kind = LLVMGetTypeKind(type_ref); } else { length = 1; } if (type_kind == LLVMFloatTypeKind || type_kind == LLVMDoubleTypeKind) { type_fmt[2] = 'f'; } else if (type_kind == LLVMIntegerTypeKind) { if (LLVMGetIntTypeWidth(type_ref) == 8) { type_fmt[2] = 'u'; } else { type_fmt[2] = 'i'; } } else { /* Unsupported type */ assert(0); } /* Create format string and arguments */ assert(strlen(format) + strlen(type_fmt) * length + 2 <= sizeof format); params[1] = lp_build_const_string(gallivm, msg); if (length == 1) { util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); params[2] = value; } else { for (i = 0; i < length; ++i) { util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); params[2 + i] = LLVMBuildExtractElement(builder, value, lp_build_const_int32(gallivm, i), ""); } } util_strncat(format, "\n", sizeof(format) - strlen(format) - 1); params[0] = lp_build_const_string(gallivm, format); return lp_build_print_args(gallivm, 2 + length, params); }
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; }
/** * Print an LLVMTypeRef. Like LLVMDumpValue(). For debugging. */ void lp_dump_llvmtype(LLVMTypeRef t) { LLVMTypeKind k = LLVMGetTypeKind(t); if (k == LLVMVectorTypeKind) { LLVMTypeRef te = LLVMGetElementType(t); LLVMTypeKind ke = LLVMGetTypeKind(te); unsigned len = LLVMGetVectorSize(t); if (ke == LLVMIntegerTypeKind) { unsigned b = LLVMGetIntTypeWidth(te); debug_printf("Vector [%u] of %u-bit Integer\n", len, b); } else { debug_printf("Vector [%u] of %s\n", len, lp_typekind_name(ke)); } } else if (k == LLVMArrayTypeKind) { LLVMTypeRef te = LLVMGetElementType(t); LLVMTypeKind ke = LLVMGetTypeKind(te); unsigned len = LLVMGetArrayLength(t); debug_printf("Array [%u] of %s\n", len, lp_typekind_name(ke)); } else if (k == LLVMIntegerTypeKind) { unsigned b = LLVMGetIntTypeWidth(t); debug_printf("%u-bit Integer\n", b); } else if (k == LLVMPointerTypeKind) { LLVMTypeRef te = LLVMGetElementType(t); debug_printf("Pointer to "); lp_dump_llvmtype(te); } else { debug_printf("%s\n", lp_typekind_name(k)); } }
/** * This function is a mirror of lp_build_elem_type() above. * * XXX: I'm not sure if it wouldn't be easier/efficient to just recreate the * type and check for identity. */ boolean lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type) { LLVMTypeKind elem_kind; assert(elem_type); if(!elem_type) return FALSE; elem_kind = LLVMGetTypeKind(elem_type); if (type.floating) { switch(type.width) { case 16: if(elem_kind != LLVMIntegerTypeKind) return FALSE; break; case 32: if(elem_kind != LLVMFloatTypeKind) return FALSE; break; case 64: if(elem_kind != LLVMDoubleTypeKind) return FALSE; break; default: assert(0); return FALSE; } } else { if(elem_kind != LLVMIntegerTypeKind) return FALSE; if(LLVMGetIntTypeWidth(elem_type) != type.width) return FALSE; } return TRUE; }
void lp_format_intrinsic(char *name, size_t size, const char *name_root, LLVMTypeRef type) { unsigned length = 0; unsigned width; char c; LLVMTypeKind kind = LLVMGetTypeKind(type); if (kind == LLVMVectorTypeKind) { length = LLVMGetVectorSize(type); type = LLVMGetElementType(type); kind = LLVMGetTypeKind(type); } switch (kind) { case LLVMIntegerTypeKind: c = 'i'; width = LLVMGetIntTypeWidth(type); break; case LLVMFloatTypeKind: c = 'f'; width = 32; break; case LLVMDoubleTypeKind: c = 'f'; width = 64; break; default: unreachable("unexpected LLVMTypeKind"); } if (length) { util_snprintf(name, size, "%s.v%u%c%u", name_root, length, c, width); } else { util_snprintf(name, size, "%s.%c%u", name_root, c, width); } }
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; }