Пример #1
0
LLVMModuleRef radeon_llvm_parse_bitcode(LLVMContextRef ctx,
							const char * bitcode, unsigned bitcode_len)
{
	LLVMMemoryBufferRef buf;
	LLVMModuleRef module;

	buf = LLVMCreateMemoryBufferWithMemoryRangeCopy((const char*)bitcode,
							bitcode_len, "radeon");
	LLVMParseBitcodeInContext(ctx, buf, &module, NULL);
	LLVMDisposeMemoryBuffer(buf);
	return module;
}
Пример #2
0
static LLVMModuleRef load_module(bool Lazy, bool New) {
  LLVMMemoryBufferRef MB;
  LLVMModuleRef M;
  char *msg = NULL;

  if (LLVMCreateMemoryBufferWithSTDIN(&MB, &msg)) {
    fprintf(stderr, "Error reading file: %s\n", msg);
    exit(1);
  }

  LLVMBool Ret;
  if (New) {
    LLVMContextRef C = LLVMGetGlobalContext();
    LLVMContextSetDiagnosticHandler(C, diagnosticHandler, NULL);
    if (Lazy)
      Ret = LLVMGetBitcodeModule2(MB, &M);
    else
      Ret = LLVMParseBitcode2(MB, &M);
  } else {
    if (Lazy)
      Ret = LLVMGetBitcodeModule(MB, &M, &msg);
    else
      Ret = LLVMParseBitcode(MB, &M, &msg);
  }

  if (Ret) {
    fprintf(stderr, "Error parsing bitcode: %s\n", msg);
    LLVMDisposeMemoryBuffer(MB);
    exit(1);
  }

  if (!Lazy)
    LLVMDisposeMemoryBuffer(MB);

  return M;
}
Пример #3
0
Файл: jit.c Проект: a4a881d4/nvc
static void jit_init_llvm(const char *path)
{
   char *error;
   LLVMMemoryBufferRef buf;
   if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &error))
      fatal("error reading bitcode from %s: %s", path, error);

   if (LLVMParseBitcode(buf, &module, &error))
      fatal("error parsing bitcode: %s", error);

   LLVMDisposeMemoryBuffer(buf);

   LLVMInitializeNativeTarget();
   LLVMLinkInJIT();

   if (LLVMCreateExecutionEngineForModule(&exec_engine, module, &error))
      fatal("error creating execution engine: %s", error);
}
Пример #4
0
/**
 * Compile an LLVM module to machine code.
 *
 * @returns 0 for success, 1 for failure
 */
unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary,
			  const char *gpu_family, unsigned dump, LLVMTargetMachineRef tm)
{

	char cpu[CPU_STRING_LEN];
	char fs[FS_STRING_LEN];
	char *err;
	bool dispose_tm = false;
	LLVMContextRef llvm_ctx;
	unsigned rval = 0;
	LLVMMemoryBufferRef out_buffer;
	unsigned buffer_size;
	const char *buffer_data;
	char triple[TRIPLE_STRING_LEN];
	LLVMBool mem_err;

	if (!tm) {
		strncpy(triple, "r600--", TRIPLE_STRING_LEN);
		LLVMTargetRef target = radeon_llvm_get_r600_target(triple);
		if (!target) {
			return 1;
		}
		strncpy(cpu, gpu_family, CPU_STRING_LEN);
		memset(fs, 0, sizeof(fs));
		if (dump) {
			strncpy(fs, "+DumpCode", FS_STRING_LEN);
		}
		tm = LLVMCreateTargetMachine(target, triple, cpu, fs,
				  LLVMCodeGenLevelDefault, LLVMRelocDefault,
						  LLVMCodeModelDefault);
		dispose_tm = true;
	}
	if (dump) {
		LLVMDumpModule(M);
	}
	/* Setup Diagnostic Handler*/
	llvm_ctx = LLVMGetModuleContext(M);

#if HAVE_LLVM >= 0x0305
	LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &rval);
#endif
	rval = 0;

	/* Compile IR*/
	mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err,
								 &out_buffer);

	/* Process Errors/Warnings */
	if (mem_err) {
		fprintf(stderr, "%s: %s", __FUNCTION__, err);
		FREE(err);
		LLVMDisposeTargetMachine(tm);
		return 1;
	}

	if (0 != rval) {
		fprintf(stderr, "%s: Processing Diag Flag\n", __FUNCTION__);
	}

	/* Extract Shader Code*/
	buffer_size = LLVMGetBufferSize(out_buffer);
	buffer_data = LLVMGetBufferStart(out_buffer);

	radeon_elf_read(buffer_data, buffer_size, binary, dump);

	/* Clean up */
	LLVMDisposeMemoryBuffer(out_buffer);

	if (dispose_tm) {
		LLVMDisposeTargetMachine(tm);
	}
	return rval;
}
Пример #5
0
/**
 * 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, &section_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, &section_header) != &section_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;
}
Пример #6
0
int main(int c, char **v)
{
    LLVMContextRef *contexts;
    LLVMModuleRef *modules;
    char *error;
    const char *mode = "opt";
    const char **filenames;
    unsigned numFiles;
    unsigned i;
    bool moreOptions;
    static int verboseFlag = 0;
    static int timingFlag = 0;
    static int disassembleFlag = 0;
    bool manyContexts = true;
    double beforeAll;
    
    if (c == 1)
        usage();
    
    moreOptions = true;
    while (moreOptions) {
        static struct option longOptions[] = {
            {"verbose", no_argument, &verboseFlag, 1},
            {"timing", no_argument, &timingFlag, 1},
            {"disassemble", no_argument, &disassembleFlag, 1},
            {"mode", required_argument, 0, 0},
            {"contexts", required_argument, 0, 0},
            {"help", no_argument, 0, 0}
        };
        
        int optionIndex;
        int optionValue;
        
        optionValue = getopt_long(c, v, "", longOptions, &optionIndex);
        
        switch (optionValue) {
        case -1:
            moreOptions = false;
            break;
            
        case 0: {
            const char* thisOption = longOptions[optionIndex].name;
            if (!strcmp(thisOption, "help"))
                usage();
            if (!strcmp(thisOption, "contexts")) {
                if (!strcasecmp(optarg, "one"))
                    manyContexts = false;
                else if (!strcasecmp(optarg, "many"))
                    manyContexts = true;
                else {
                    fprintf(stderr, "Invalid argument for --contexts.\n");
                    exit(1);
                }
                break;
            }
            if (!strcmp(thisOption, "mode")) {
                mode = strdup(optarg);
                break;
            }
            break;
        }
            
        case '?':
            exit(0);
            break;
            
        default:
            printf("optionValue = %d\n", optionValue);
            abort();
            break;
        }
    }
    
    LLVMLinkInMCJIT();
    LLVMInitializeNativeTarget();
    LLVMInitializeX86AsmPrinter();
    LLVMInitializeX86Disassembler();

    filenames = (const char **)(v + optind);
    numFiles = c - optind;
    
    contexts = malloc(sizeof(LLVMContextRef) * numFiles);
    modules = malloc(sizeof(LLVMModuleRef) * numFiles);
    
    if (manyContexts) {
        for (i = 0; i < numFiles; ++i)
            contexts[i] = LLVMContextCreate();
    } else {
        LLVMContextRef context = LLVMContextCreate();
        for (i = 0; i < numFiles; ++i)
            contexts[i] = context;
    }
    
    for (i = 0; i < numFiles; ++i) {
        LLVMMemoryBufferRef buffer;
        const char* filename = filenames[i];
        
        if (LLVMCreateMemoryBufferWithContentsOfFile(filename, &buffer, &error)) {
            fprintf(stderr, "Error reading file %s: %s\n", filename, error);
            exit(1);
        }
        
        if (LLVMParseBitcodeInContext(contexts[i], buffer, modules + i, &error)) {
            fprintf(stderr, "Error parsing file %s: %s\n", filename, error);
            exit(1);
        }
        
        LLVMDisposeMemoryBuffer(buffer);
        
        if (verboseFlag) {
            printf("Module #%u (%s) after parsing:\n", i, filename);
            LLVMDumpModule(modules[i]);
        }
    }

    if (verboseFlag)
        printf("Generating code for modules...\n");
    
    if (timingFlag)
        beforeAll = currentTime();
    for (i = 0; i < numFiles; ++i) {
        LLVMModuleRef module;
        LLVMExecutionEngineRef engine;
        struct LLVMMCJITCompilerOptions options;
        LLVMValueRef value;
        LLVMPassManagerRef functionPasses = 0;
        LLVMPassManagerRef modulePasses = 0;
        
        double before;
        
        if (timingFlag)
            before = currentTime();
        
        module = modules[i];

        LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
        options.OptLevel = 2;
        options.EnableFastISel = 0;
        options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
            0, mmAllocateCodeSection, mmAllocateDataSection, mmApplyPermissions, mmDestroy);
    
        if (LLVMCreateMCJITCompilerForModule(&engine, module, &options, sizeof(options), &error)) {
            fprintf(stderr, "Error building MCJIT: %s\n", error);
            exit(1);
        }
    
        if (!strcasecmp(mode, "simple")) {
            modulePasses = LLVMCreatePassManager();
            LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses);
            LLVMAddConstantPropagationPass(modulePasses);
            LLVMAddInstructionCombiningPass(modulePasses);
            LLVMAddPromoteMemoryToRegisterPass(modulePasses);
            LLVMAddBasicAliasAnalysisPass(modulePasses);
            LLVMAddTypeBasedAliasAnalysisPass(modulePasses);
            LLVMAddGVNPass(modulePasses);
            LLVMAddCFGSimplificationPass(modulePasses);
            LLVMRunPassManager(modulePasses, module);
        } else if (!strcasecmp(mode, "opt")) {
            LLVMPassManagerBuilderRef passBuilder;

            passBuilder = LLVMPassManagerBuilderCreate();
            LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
            LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
        
            functionPasses = LLVMCreateFunctionPassManagerForModule(module);
            modulePasses = LLVMCreatePassManager();
        
            LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses);
        
            LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, functionPasses);
            LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
        
            LLVMPassManagerBuilderDispose(passBuilder);
        
            LLVMInitializeFunctionPassManager(functionPasses);
            for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value))
                LLVMRunFunctionPassManager(functionPasses, value);
            LLVMFinalizeFunctionPassManager(functionPasses);
        
            LLVMRunPassManager(modulePasses, module);
        } else {
            fprintf(stderr, "Bad optimization mode: %s.\n", mode);
            fprintf(stderr, "Valid modes are: \"simple\" or \"opt\".\n");
            exit(1);
        }

        if (verboseFlag) {
            printf("Module #%d (%s) after optimization:\n", i, filenames[i]);
            LLVMDumpModule(module);
        }
    
        for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value)) {
            if (LLVMIsDeclaration(value))
                continue;
            LLVMGetPointerToGlobal(engine, value);
        }

        if (functionPasses)
            LLVMDisposePassManager(functionPasses);
        if (modulePasses)
            LLVMDisposePassManager(modulePasses);
    
        LLVMDisposeExecutionEngine(engine);
        
        if (timingFlag) {
            double after = currentTime();
            printf("Module #%d (%s) took %lf ms.\n", i, filenames[i], (after - before) * 1000);
        }
    }
    if (timingFlag) {
        double after = currentTime();
        printf("Compilation took a total of %lf ms.\n", (after - beforeAll) * 1000);
    }
    
    if (disassembleFlag) {
        LLVMDisasmContextRef disassembler;
        struct MemorySection *section;
        
        disassembler = LLVMCreateDisasm("x86_64-apple-darwin", 0, 0, 0, symbolLookupCallback);
        if (!disassembler) {
            fprintf(stderr, "Error building disassembler.\n");
            exit(1);
        }
    
        for (section = sectionHead; section; section = section->next) {
            printf("Disassembly for section %p:\n", section);
        
            char pcString[20];
            char instructionString[1000];
            uint8_t *pc;
            uint8_t *end;
        
            pc = section->start;
            end = pc + section->size;
        
            while (pc < end) {
                snprintf(
                    pcString, sizeof(pcString), "0x%lx",
                    (unsigned long)(uintptr_t)pc);
            
                size_t instructionSize = LLVMDisasmInstruction(
                    disassembler, pc, end - pc, (uintptr_t)pc,
                    instructionString, sizeof(instructionString));
            
                if (!instructionSize)
                    snprintf(instructionString, sizeof(instructionString), ".byte 0x%02x", *pc++);
                else
                    pc += instructionSize;
            
                printf("    %16s: %s\n", pcString, instructionString);
            }
        }
    }
    
    return 0;
}
Пример #7
0
/**
 * Compile an LLVM module to machine code.
 *
 * @returns 0 for success, 1 for failure
 */
unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary,
			     const char *gpu_family,
			     LLVMTargetMachineRef tm,
			     struct pipe_debug_callback *debug)
{
	struct radeon_llvm_diagnostics diag;
	char cpu[CPU_STRING_LEN];
	char fs[FS_STRING_LEN];
	char *err;
	bool dispose_tm = false;
	LLVMContextRef llvm_ctx;
	LLVMMemoryBufferRef out_buffer;
	unsigned buffer_size;
	const char *buffer_data;
	char triple[TRIPLE_STRING_LEN];
	LLVMBool mem_err;

	diag.debug = debug;
	diag.retval = 0;

	if (!tm) {
		strncpy(triple, "r600--", TRIPLE_STRING_LEN);
		LLVMTargetRef target = radeon_llvm_get_r600_target(triple);
		if (!target) {
			return 1;
		}
		strncpy(cpu, gpu_family, CPU_STRING_LEN);
		memset(fs, 0, sizeof(fs));
		strncpy(fs, "+DumpCode", FS_STRING_LEN);
		tm = LLVMCreateTargetMachine(target, triple, cpu, fs,
				  LLVMCodeGenLevelDefault, LLVMRelocDefault,
						  LLVMCodeModelDefault);
		dispose_tm = true;
	}

	/* Setup Diagnostic Handler*/
	llvm_ctx = LLVMGetModuleContext(M);

	LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &diag);

	/* Compile IR*/
	mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err,
								 &out_buffer);

	/* Process Errors/Warnings */
	if (mem_err) {
		fprintf(stderr, "%s: %s", __FUNCTION__, err);
		pipe_debug_message(debug, SHADER_INFO,
				   "LLVM emit error: %s", err);
		FREE(err);
		diag.retval = 1;
		goto out;
	}

	/* Extract Shader Code*/
	buffer_size = LLVMGetBufferSize(out_buffer);
	buffer_data = LLVMGetBufferStart(out_buffer);

	radeon_elf_read(buffer_data, buffer_size, binary);

	/* Clean up */
	LLVMDisposeMemoryBuffer(out_buffer);

out:
	if (dispose_tm) {
		LLVMDisposeTargetMachine(tm);
	}
	if (diag.retval != 0)
		pipe_debug_message(debug, SHADER_INFO, "LLVM compile failed");
	return diag.retval;
}