static void pocl_parse_event_filter () { const char *trace_filter; char *tmp_str, *save_ptr, *token; trace_filter = pocl_get_string_option ("POCL_TRACE_EVENT_FILTER", NULL); if (trace_filter == NULL) return; tmp_str = strdup (trace_filter); if (tmp_str == NULL) return; event_trace_filter = 0; while (1) { token = strtok_r (tmp_str, ",", &save_ptr); if (token == NULL) goto PARSE_OUT; if (strcmp (token, "queued") == 0) event_trace_filter |= (1 << CL_QUEUED); else if (strcmp (token, "submitted") == 0) event_trace_filter |= (1 << CL_SUBMITTED); else if (strcmp (token, "running") == 0) event_trace_filter |= (1 << CL_RUNNING); else if (strcmp (token, "complete") == 0) event_trace_filter |= (1 << CL_COMPLETE); tmp_str = NULL; } PARSE_OUT: free (tmp_str); }
void pocl_event_tracing_init () { const char *trace_env; unsigned i; if (tracing_initialized) return; trace_env = pocl_get_string_option ("POCL_TRACE_EVENT", NULL); if (trace_env == NULL) goto EVENT_INIT_OUT; /* Check if a tracer has a name matching the supplied one */ for (i = 0; i < POCL_TRACER_COUNT; i++) { if (strcmp (trace_env, pocl_event_tracers[i]->name) == 0) { event_tracer = pocl_event_tracers[i]; break; } } if (event_tracer == NULL) goto EVENT_INIT_OUT; pocl_parse_event_filter (); event_tracer->init (); EVENT_INIT_OUT: tracing_initialized = 1; }
void pocl_cache_init_topdir() { if (cache_topdir_initialized) return; const char *tmp_path = pocl_get_string_option("POCL_CACHE_DIR", NULL); int needed; if (tmp_path && (pocl_exists(tmp_path))) { needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "%s", tmp_path); } else { #ifdef POCL_ANDROID char* process_name = pocl_get_process_name(); needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "/data/data/%s/cache/", process_name); free(process_name); if (!pocl_exists(cache_topdir)) needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "/sdcard/pocl/kcache"); #elif defined(_MSC_VER) || defined(__MINGW32__) tmp_path = getenv("LOCALAPPDATA"); if (!tmp_path) tmp_path = getenv("TEMP"); assert(tmp_path); needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "%s\\pocl", tmp_path); #else // "If $XDG_CACHE_HOME is either not set or empty, a default equal to // $HOME/.cache should be used." // http://standards.freedesktop.org/basedir-spec/latest/ tmp_path = getenv("XDG_CACHE_HOME"); if (tmp_path && tmp_path[0] != '\0') { needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "%s/pocl/kcache", tmp_path); } else if ((tmp_path = getenv("HOME")) != NULL) { needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "%s/.cache/pocl/kcache", tmp_path); } else { needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "/tmp/pocl/kcache"); } #endif } if (needed >= POCL_FILENAME_LENGTH) { POCL_ABORT("pocl: cache path longer than maximum filename length"); } assert(strlen(cache_topdir) > 0); if (pocl_mkdir_p(cache_topdir)) POCL_ABORT("Could not create topdir for cache"); cache_topdir_initialized = 1; }
static void text_tracer_init () { const char *text_tracer_output; text_tracer_output = pocl_get_string_option ("POCL_TRACE_EVENT_OPT", "pocl_trace_events.log"); text_tracer_file = fopen (text_tracer_output, "w"); if (!text_tracer_file) POCL_ABORT ("Failed to open text tracer output\n"); }
static inline void build_program_compute_hash(cl_program program) { SHA1_CTX hash_ctx; int total_binary_size, i; pocl_SHA1_Init(&hash_ctx); if (program->source) { pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->source, strlen(program->source)); } else /* Program was created with clCreateProgramWithBinary() */ { total_binary_size = 0; for (i = 0; i < program->num_devices; ++i) total_binary_size += program->binary_sizes[i]; /* Binaries are stored in continuous chunk of memory starting from binaries[0] */ pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->binaries[0], total_binary_size); } if (program->compiler_options) pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->compiler_options, strlen(program->compiler_options)); /* The kernel compiler work-group function method affects the produced binary heavily. */ const char *wg_method = pocl_get_string_option ("POCL_WORK_GROUP_METHOD", ""); pocl_SHA1_Update (&hash_ctx, (uint8_t*) wg_method, strlen (wg_method)); pocl_SHA1_Update (&hash_ctx, (uint8_t*) PACKAGE_VERSION, strlen (PACKAGE_VERSION)); pocl_SHA1_Update (&hash_ctx, (uint8_t*) LLVM_VERSION, strlen (LLVM_VERSION)); pocl_SHA1_Update (&hash_ctx, (uint8_t*) POCL_BUILD_TIMESTAMP, strlen (POCL_BUILD_TIMESTAMP)); /*devices may include their own information to hash */ for (i = 0; i < program->num_devices; ++i) { if (program->devices[i]->ops->build_hash) program->devices[i]->ops->build_hash (program->devices[i]->data, &hash_ctx); } pocl_SHA1_Final(&hash_ctx, program->build_hash); }
cl_int compile_and_link_program(int compile_program, int link_program, cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, cl_uint num_input_headers, const cl_program *input_headers, const char **header_include_names, cl_uint num_input_programs, const cl_program *input_programs, void (CL_CALLBACK *pfn_notify) (cl_program program, void *user_data), void *user_data) { char program_bc_path[POCL_FILENAME_LENGTH]; char link_options[512]; int errcode, error; int create_library = 0; int requires_cr_sqrt_div = 0; int spir_build = 0; unsigned flush_denorms = 0; uint64_t fsize; cl_device_id *unique_devlist = NULL; char *binary = NULL; unsigned device_i = 0, actually_built = 0; size_t i, j; char *temp_options = NULL; const char *extra_build_options = pocl_get_string_option ("POCL_EXTRA_BUILD_FLAGS", NULL); int build_error_code = (link_program ? CL_BUILD_PROGRAM_FAILURE : CL_COMPILE_PROGRAM_FAILURE); POCL_GOTO_LABEL_COND (PFN_NOTIFY, (program == NULL), CL_INVALID_PROGRAM); POCL_GOTO_LABEL_COND (PFN_NOTIFY, (num_devices > 0 && device_list == NULL), CL_INVALID_VALUE); POCL_GOTO_LABEL_COND (PFN_NOTIFY, (num_devices == 0 && device_list != NULL), CL_INVALID_VALUE); POCL_GOTO_LABEL_COND (PFN_NOTIFY, (pfn_notify == NULL && user_data != NULL), CL_INVALID_VALUE); POCL_GOTO_LABEL_ON (PFN_NOTIFY, program->kernels, CL_INVALID_OPERATION, "Program already has kernels\n"); POCL_GOTO_LABEL_ON (PFN_NOTIFY, (program->source == NULL && program->binaries == NULL), CL_INVALID_PROGRAM, "Program doesn't have sources or binaries! You need " "to call clCreateProgramWith{Binary|Source} first\n"); POCL_GOTO_LABEL_ON (PFN_NOTIFY, ((program->source == NULL) && (link_program == 0)), CL_INVALID_OPERATION, "Cannot clCompileProgram when program has no source\n"); POCL_LOCK_OBJ (program); program->main_build_log[0] = 0; /* TODO this should be somehow utilized at linking */ POCL_MEM_FREE (program->compiler_options); if (extra_build_options) { size_t len = (options != NULL) ? strlen (options) : 0; len += strlen (extra_build_options) + 2; temp_options = (char *)malloc (len); temp_options[0] = 0; if (options != NULL) { strcpy (temp_options, options); strcat (temp_options, " "); } strcat (temp_options, extra_build_options); } else temp_options = (char*) options; if (temp_options) { i = strlen (temp_options); size_t size = i + 512; /* add some space for pocl-added options */ program->compiler_options = (char *)malloc (size); errcode = process_options (temp_options, program->compiler_options, link_options, program, compile_program, link_program, &create_library, &flush_denorms, &requires_cr_sqrt_div, &spir_build, size); if (errcode != CL_SUCCESS) goto ERROR_CLEAN_OPTIONS; } POCL_MSG_PRINT_LLVM ("building program with options %s\n", program->compiler_options); program->flush_denorms = flush_denorms; #if !(defined(__x86_64__) && defined(__GNUC__)) if (flush_denorms) { POCL_MSG_WARN ("flush to zero is currently only implemented for " "x86-64 & gcc/clang, ignoring flag\n"); } #endif /* DEVICE LIST */ if (num_devices == 0) { num_devices = program->num_devices; device_list = program->devices; } else { // convert subdevices to devices and remove duplicates cl_uint real_num_devices = 0; unique_devlist = pocl_unique_device_list (device_list, num_devices, &real_num_devices); num_devices = real_num_devices; device_list = unique_devlist; } clean_program_on_rebuild (program); /* Build the fully linked non-parallel bitcode for all devices. */ for (device_i = 0; device_i < program->num_devices; ++device_i) { cl_device_id device = program->devices[device_i]; /* find the device in the supplied devices-to-build-for list */ int found = 0; for (i = 0; i < num_devices; ++i) if (device_list[i] == device) found = 1; if (!found) continue; if (requires_cr_sqrt_div && !(device->single_fp_config & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT)) { APPEND_TO_MAIN_BUILD_LOG (REQUIRES_CR_SQRT_DIV_ERR); POCL_GOTO_ERROR_ON (1, build_error_code, REQUIRES_CR_SQRT_DIV_ERR " %s\n", device->short_name); } actually_built++; /* clCreateProgramWithSource */ if (program->source) { #ifdef OCS_AVAILABLE if (device->compiler_available == CL_TRUE) { POCL_MSG_PRINT_INFO ("building from sources for device %d\n", device_i); error = pocl_llvm_build_program ( program, device_i, program->compiler_options, program_bc_path, num_input_headers, input_headers, header_include_names, (create_library ? 0 : link_program)); POCL_GOTO_ERROR_ON ((error != 0), build_error_code, "pocl_llvm_build_program() failed\n"); } else #endif { APPEND_TO_MAIN_BUILD_LOG ( "Cannot build a program from sources with pocl " "that does not have online compiler support\n"); POCL_GOTO_ERROR_ON (1, CL_COMPILER_NOT_AVAILABLE, "%s", program->main_build_log); } } /* clCreateProgramWithBinaries */ else if (program->binaries[device_i] && (program->pocl_binaries[device_i] == NULL)) { #ifdef OCS_AVAILABLE /* bitcode is now either plain LLVM IR or SPIR IR */ int spir_binary = bitcode_is_spir ((char*)program->binaries[device_i], program->binary_sizes[device_i]); if (spir_binary) POCL_MSG_PRINT_LLVM ("LLVM-SPIR binary detected\n"); else POCL_MSG_PRINT_LLVM ("building from a BC binary for device %d\n", device_i); if (spir_binary) { #ifdef ENABLE_SPIR if (!strstr (device->extensions, "cl_khr_spir")) { APPEND_TO_MAIN_BUILD_LOG (REQUIRES_SPIR_SUPPORT); POCL_GOTO_ERROR_ON (1, build_error_code, REQUIRES_SPIR_SUPPORT " %s\n", device->short_name); } if (!spir_build) POCL_MSG_WARN ( "SPIR binary provided, but no spir in build options\n"); /* SPIR binaries need to be explicitly linked to the kernel * library. for non-SPIR binaries this happens as part of build * process when program.bc is generated. */ error = pocl_llvm_link_program (program, device_i, program_bc_path, 0, NULL, NULL, NULL, 0, 1); POCL_GOTO_ERROR_ON (error, CL_LINK_PROGRAM_FAILURE, "Failed to link SPIR program.bc\n"); #else APPEND_TO_MAIN_BUILD_LOG (REQUIRES_SPIR_SUPPORT); POCL_GOTO_ERROR_ON (1, build_error_code, REQUIRES_SPIR_SUPPORT " %s\n", device->short_name); #endif } #else APPEND_TO_MAIN_BUILD_LOG ( "Cannot build program from LLVM IR binaries with " "pocl that does not have online compiler support\n"); POCL_GOTO_ERROR_ON (1, CL_COMPILER_NOT_AVAILABLE, "%s", program->main_build_log); #endif } else if (program->pocl_binaries[device_i]) { POCL_MSG_PRINT_INFO("having a poclbinary for device %d\n", device_i); #ifdef OCS_AVAILABLE if (program->binaries[device_i] == NULL) { POCL_MSG_WARN ( "pocl-binary for this device doesn't contain " "program.bc - you won't be able to rebuild/link it\n"); /* do not try to read program.bc or LLVM IRs * TODO maybe read LLVM IRs ?*/ continue; } #else continue; #endif } else if (link_program && (num_input_programs > 0)) { #ifdef OCS_AVAILABLE /* just link binaries. */ unsigned char *cur_device_binaries[num_input_programs]; size_t cur_device_binary_sizes[num_input_programs]; void *cur_llvm_irs[num_input_programs]; for (j = 0; j < num_input_programs; j++) { assert (device == input_programs[j]->devices[device_i]); cur_device_binaries[j] = input_programs[j]->binaries[device_i]; assert (cur_device_binaries[j]); cur_device_binary_sizes[j] = input_programs[j]->binary_sizes[device_i]; if (input_programs[j]->llvm_irs[device_i] == NULL) pocl_update_program_llvm_irs (input_programs[j], device_i); cur_llvm_irs[j] = input_programs[j]->llvm_irs[device_i]; assert (cur_llvm_irs[j]); } error = pocl_llvm_link_program ( program, device_i, program_bc_path, num_input_programs, cur_device_binaries, cur_device_binary_sizes, cur_llvm_irs, create_library, 0); POCL_GOTO_ERROR_ON ((error != CL_SUCCESS), CL_LINK_PROGRAM_FAILURE, "pocl_llvm_link_program() failed\n"); #else POCL_GOTO_ERROR_ON ((1), CL_LINK_PROGRAM_FAILURE, "clCompileProgram/clLinkProgram/clBuildProgram" " require a pocl built with LLVM\n"); #endif } else { POCL_GOTO_ERROR_ON (1, CL_INVALID_BINARY, "No sources nor binaries for device %s - can't " "build the program\n", device->short_name); } #ifdef OCS_AVAILABLE /* Read binaries from program.bc to memory */ if (program->binaries[device_i] == NULL) { errcode = pocl_read_file(program_bc_path, &binary, &fsize); POCL_GOTO_ERROR_ON(errcode, CL_BUILD_ERROR, "Failed to read binaries from program.bc to " "memory: %s\n", program_bc_path); program->binary_sizes[device_i] = (size_t)fsize; program->binaries[device_i] = (unsigned char *)binary; } if (program->llvm_irs[device_i] == NULL) { pocl_update_program_llvm_irs(program, device_i); } /* Maintain a 'last_accessed' file in every program's * cache directory. Will be useful for cache pruning script * that flushes old directories based on LRU */ pocl_cache_update_program_last_access(program, device_i); #endif } POCL_GOTO_ERROR_ON ((actually_built < num_devices), build_error_code, "Some of the devices on the argument-supplied list are" "not available for the program, or do not exist\n"); program->build_status = CL_BUILD_SUCCESS; program->binary_type = CL_PROGRAM_BINARY_TYPE_EXECUTABLE; /* if program will be compiled using clCompileProgram its binary_type * will be set to CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT. * * if program was created by clLinkProgram which is called * with the –createlibrary link option its binary_type will be set to * CL_PROGRAM_BINARY_TYPE_LIBRARY. */ if (create_library) program->binary_type = CL_PROGRAM_BINARY_TYPE_LIBRARY; if (compile_program && !link_program) program->binary_type = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT; assert(program->num_kernels == 0); /* get non-device-specific kernel metadata. We can stop after finding * the first method that works.*/ for (device_i = 0; device_i < program->num_devices; device_i++) { #ifdef OCS_AVAILABLE if (program->binaries[device_i]) { program->num_kernels = pocl_llvm_get_kernel_count (program, device_i); if (program->num_kernels) { program->kernel_meta = calloc (program->num_kernels, sizeof (pocl_kernel_metadata_t)); pocl_llvm_get_kernels_metadata (program, device_i); } break; } #endif if (program->pocl_binaries[device_i]) { program->num_kernels = pocl_binary_get_kernel_count (program, device_i); if (program->num_kernels) { program->kernel_meta = calloc (program->num_kernels, sizeof (pocl_kernel_metadata_t)); pocl_binary_get_kernels_metadata (program, device_i); } break; } } POCL_GOTO_ERROR_ON ((device_i >= program->num_devices), CL_INVALID_BINARY, "Could find kernel metadata in the built program\n"); /* calculate device-specific kernel hashes. */ for (j = 0; j < program->num_kernels; ++j) { program->kernel_meta[j].build_hash = calloc (program->num_devices, sizeof (pocl_kernel_hash_t)); for (device_i = 0; device_i < program->num_devices; device_i++) { pocl_calculate_kernel_hash (program, j, device_i); } } errcode = CL_SUCCESS; goto FINISH; ERROR: free_meta (program); program->kernels = NULL; for (device_i = 0; device_i < program->num_devices; device_i++) { if (program->source) { POCL_MEM_FREE (program->binaries[device_i]); program->binary_sizes[device_i] = 0; } } ERROR_CLEAN_OPTIONS: if (temp_options != options) free (temp_options); program->build_status = CL_BUILD_ERROR; FINISH: POCL_UNLOCK_OBJ (program); POCL_MEM_FREE (unique_devlist); PFN_NOTIFY: if (pfn_notify) pfn_notify (program, user_data); return errcode; }
void pocl_cuda_init (cl_device_id device, const char *parameters) { CUresult result; result = cuInit (0); CUDA_CHECK (result, "cuInit"); if (device->data) return; pocl_cuda_device_data_t *data = malloc (sizeof (pocl_cuda_device_data_t)); result = cuDeviceGet (&data->device, 0); CUDA_CHECK (result, "cuDeviceGet"); // Get specific device name device->long_name = device->short_name = malloc (256 * sizeof (char)); cuDeviceGetName (device->long_name, 256, data->device); // Get other device properties cuDeviceGetAttribute ((int *)&device->max_work_group_size, CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK, data->device); cuDeviceGetAttribute ((int *)(device->max_work_item_sizes + 0), CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_X, data->device); cuDeviceGetAttribute ((int *)(device->max_work_item_sizes + 1), CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Y, data->device); cuDeviceGetAttribute ((int *)(device->max_work_item_sizes + 2), CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Z, data->device); cuDeviceGetAttribute ( (int *)&device->local_mem_size, CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_MULTIPROCESSOR, data->device); cuDeviceGetAttribute ((int *)&device->max_compute_units, CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT, data->device); cuDeviceGetAttribute ((int *)&device->max_clock_frequency, CU_DEVICE_ATTRIBUTE_CLOCK_RATE, data->device); cuDeviceGetAttribute ((int *)&device->error_correction_support, CU_DEVICE_ATTRIBUTE_ECC_ENABLED, data->device); cuDeviceGetAttribute ((int *)&device->host_unified_memory, CU_DEVICE_ATTRIBUTE_INTEGRATED, data->device); cuDeviceGetAttribute ((int *)&device->max_constant_buffer_size, CU_DEVICE_ATTRIBUTE_TOTAL_CONSTANT_MEMORY, data->device); device->preferred_vector_width_char = 1; device->preferred_vector_width_short = 1; device->preferred_vector_width_int = 1; device->preferred_vector_width_long = 1; device->preferred_vector_width_float = 1; device->preferred_vector_width_double = 1; device->preferred_vector_width_half = 0; device->native_vector_width_char = 1; device->native_vector_width_short = 1; device->native_vector_width_int = 1; device->native_vector_width_long = 1; device->native_vector_width_float = 1; device->native_vector_width_double = 1; device->native_vector_width_half = 0; device->single_fp_config = CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_FMA | CL_FP_INF_NAN | CL_FP_DENORM; device->double_fp_config = CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_FMA | CL_FP_INF_NAN | CL_FP_DENORM; device->local_mem_type = CL_LOCAL; device->host_unified_memory = 0; // Get GPU architecture name int sm_maj, sm_min; cuDeviceGetAttribute (&sm_maj, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, data->device); cuDeviceGetAttribute (&sm_min, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, data->device); char *gpu_arch = malloc (16 * sizeof (char)); snprintf (gpu_arch, 16, "sm_%d%d", sm_maj, sm_min); device->llvm_cpu = pocl_get_string_option ("POCL_CUDA_GPU_ARCH", gpu_arch); POCL_MSG_PRINT_INFO ("[CUDA] GPU architecture = %s\n", device->llvm_cpu); // Create context result = cuCtxCreate (&data->context, CU_CTX_MAP_HOST, data->device); CUDA_CHECK (result, "cuCtxCreate"); // Get global memory size size_t memfree, memtotal; result = cuMemGetInfo (&memfree, &memtotal); device->max_mem_alloc_size = max (memtotal / 4, 128 * 1024 * 1024); device->global_mem_size = memtotal; device->data = data; }
/** * Generate code from the final bitcode using the LLVM * tools. * * Uses an existing (cached) one, if available. * * @param tmpdir The directory of the work-group function bitcode. * @param return the generated binary filename. */ const char* llvm_codegen (const char* tmpdir, cl_kernel kernel, cl_device_id device) { const char* pocl_verbose_ptr = pocl_get_string_option("POCL_VERBOSE", (char*)NULL); int pocl_verbose = pocl_verbose_ptr && *pocl_verbose_ptr; char command[COMMAND_LENGTH]; char bytecode[POCL_FILENAME_LENGTH]; char objfile[POCL_FILENAME_LENGTH]; char* module = (char*) malloc(min(POCL_FILENAME_LENGTH, strlen(tmpdir) + strlen(kernel->function_name) + 5)); // strlen of / .so 4+1 int error; cl_program program = kernel->program; error = snprintf (module, POCL_FILENAME_LENGTH, "%s/%s.so", tmpdir, kernel->function_name); assert (error >= 0); error = snprintf (objfile, POCL_FILENAME_LENGTH, "%s/%s.so.o", tmpdir, kernel->function_name); assert (error >= 0); if (access (module, F_OK) != 0) { error = snprintf (bytecode, POCL_FILENAME_LENGTH, "%s/%s", tmpdir, POCL_PARALLEL_BC_FILENAME); assert (error >= 0); error = pocl_llvm_codegen( kernel, device, bytecode, objfile); assert (error == 0); // clang is used as the linker driver in LINK_CMD error = snprintf (command, COMMAND_LENGTH, #ifndef ANDROID LINK_CMD " " HOST_CLANG_FLAGS " " HOST_LD_FLAGS " -o %s %s", #else ANDROID_POCL_PREFIX"/bin/ld " HOST_LD_FLAGS " -o %s %s " " /system/lib/crtend_so.o /system/lib/crtbegin_so.o -ldl -lc ", #endif module, objfile); assert (error >= 0); if (pocl_verbose) { fprintf(stderr, "[pocl] executing [%s]\n", command); fflush(stderr); } error = system (command); assert (error == 0); /* Save space in kernel cache */ if (!pocl_get_bool_option("POCL_LEAVE_KERNEL_COMPILER_TEMP_FILES", 0)) { pocl_remove_file(objfile); pocl_remove_file(bytecode); } } return module; }
static inline void build_program_compute_hash(cl_program program, unsigned device_i, const char* preprocessed_source, size_t source_len) { SHA1_CTX hash_ctx; unsigned i; cl_device_id device = program->devices[device_i]; pocl_SHA1_Init(&hash_ctx); if (program->source) { assert(preprocessed_source); assert(source_len > 0); pocl_SHA1_Update(&hash_ctx, (uint8_t*)preprocessed_source, source_len); } else { /* Program was created with clCreateProgramWithBinary() */ assert(program->binaries[device_i]); pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->binaries[device_i], program->binary_sizes[device_i]); } if (program->compiler_options) pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->compiler_options, strlen(program->compiler_options)); /* The kernel compiler work-group function method affects the produced binary heavily. */ const char *wg_method= pocl_get_string_option("POCL_WORK_GROUP_METHOD", ""); pocl_SHA1_Update(&hash_ctx, (uint8_t*) wg_method, strlen(wg_method)); pocl_SHA1_Update(&hash_ctx, (uint8_t*) PACKAGE_VERSION, strlen(PACKAGE_VERSION)); pocl_SHA1_Update(&hash_ctx, (uint8_t*) LLVM_VERSION, strlen(LLVM_VERSION)); pocl_SHA1_Update(&hash_ctx, (uint8_t*) POCL_BUILD_TIMESTAMP, strlen(POCL_BUILD_TIMESTAMP)); pocl_SHA1_Update(&hash_ctx, (const uint8_t *)POCL_KERNELLIB_SHA1, strlen(POCL_KERNELLIB_SHA1)); /*devices may include their own information to hash */ if (device->ops->build_hash) device->ops->build_hash(device->data, &hash_ctx); uint8_t digest[SHA1_DIGEST_SIZE]; pocl_SHA1_Final(&hash_ctx, digest); unsigned char* hashstr = program->build_hash[device_i]; for (i=0; i < SHA1_DIGEST_SIZE; i++) { *hashstr++ = (digest[i] & 0x0F) + 65; *hashstr++ = ((digest[i] & 0xF0) >> 4) + 65; } *hashstr = 0; program->build_hash[device_i][2] = '/'; }