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;
}
Example #2
0
/* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */
CAMLprim value llvm_parse_bitcode(LLVMContextRef C,
                                  LLVMMemoryBufferRef MemBuf) {
  CAMLparam0();
  CAMLlocal2(Variant, MessageVal);
  LLVMModuleRef M;
  char *Message;
  
  if (LLVMParseBitcodeInContext(C, MemBuf, &M, &Message))
    llvm_raise(llvm_bitreader_error_exn, Message);
  
  CAMLreturn((value) M);
}
Example #3
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;
}