LLVMTargetRef radeon_llvm_get_r600_target(const char *triple) { LLVMTargetRef target = NULL; char *err_message = NULL; init_r600_target(); if (LLVMGetTargetFromTriple(triple, &target, &err_message)) { fprintf(stderr, "Cannot find target for triple %s ", triple); if (err_message) { fprintf(stderr, "%s\n", err_message); } LLVMDisposeMessage(err_message); return NULL; } return target; }
/** * Compile an LLVM module to machine code. * * @returns 0 for success, 1 for failure */ unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_llvm_binary *binary, const char * gpu_family, unsigned dump) { LLVMTargetRef target; LLVMTargetMachineRef tm; char cpu[CPU_STRING_LEN]; char fs[FS_STRING_LEN]; char *err; LLVMMemoryBufferRef out_buffer; unsigned buffer_size; const char *buffer_data; char triple[TRIPLE_STRING_LEN]; char *elf_buffer; Elf *elf; Elf_Scn *section = NULL; size_t section_str_index; LLVMBool r; init_r600_target(); target = get_r600_target(); if (!target) { return 1; } strncpy(cpu, gpu_family, CPU_STRING_LEN); memset(fs, 0, sizeof(fs)); if (dump) { LLVMDumpModule(M); strncpy(fs, "+DumpCode", FS_STRING_LEN); } strncpy(triple, "r600--", TRIPLE_STRING_LEN); tm = LLVMCreateTargetMachine(target, triple, cpu, fs, LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault); r = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err, &out_buffer); if (r) { fprintf(stderr, "%s", err); FREE(err); return 1; } buffer_size = LLVMGetBufferSize(out_buffer); buffer_data = LLVMGetBufferStart(out_buffer); /* One of the libelf implementations * (http://www.mr511.de/software/english.htm) requires calling * elf_version() before elf_memory(). */ elf_version(EV_CURRENT); elf_buffer = MALLOC(buffer_size); memcpy(elf_buffer, buffer_data, buffer_size); elf = elf_memory(elf_buffer, buffer_size); elf_getshdrstrndx(elf, §ion_str_index); binary->disassembled = 0; while ((section = elf_nextscn(elf, section))) { const char *name; Elf_Data *section_data = NULL; GElf_Shdr section_header; if (gelf_getshdr(section, §ion_header) != §ion_header) { fprintf(stderr, "Failed to read ELF section header\n"); return 1; } name = elf_strptr(elf, section_str_index, section_header.sh_name); if (!strcmp(name, ".text")) { section_data = elf_getdata(section, section_data); binary->code_size = section_data->d_size; binary->code = MALLOC(binary->code_size * sizeof(unsigned char)); memcpy(binary->code, section_data->d_buf, binary->code_size); } else if (!strcmp(name, ".AMDGPU.config")) { section_data = elf_getdata(section, section_data); binary->config_size = section_data->d_size; binary->config = MALLOC(binary->config_size * sizeof(unsigned char)); memcpy(binary->config, section_data->d_buf, binary->config_size); } else if (dump && !strcmp(name, ".AMDGPU.disasm")) { binary->disassembled = 1; section_data = elf_getdata(section, section_data); fprintf(stderr, "\nShader Disassembly:\n\n"); fprintf(stderr, "%.*s\n", (int)section_data->d_size, (char *)section_data->d_buf); } } LLVMDisposeMemoryBuffer(out_buffer); LLVMDisposeTargetMachine(tm); return 0; }