+void
+gallivm_destroy(struct gallivm_state *gallivm)
+{
+ gallivm_free_ir(gallivm);
+ gallivm_free_code(gallivm);
+ FREE(gallivm);
+}
+
+
+/**
+ * Validate a function.
+ * Verification is only done with debug builds.
+ */
+void
+gallivm_verify_function(struct gallivm_state *gallivm,
+ LLVMValueRef func)
+{
+ /* Verify the LLVM IR. If invalid, dump and abort */
+#ifdef DEBUG
+ if (LLVMVerifyFunction(func, LLVMPrintMessageAction)) {
+ lp_debug_dump_value(func);
+ assert(0);
+ return;
+ }
+#endif
+
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
+ /* Print the LLVM IR to stderr */
+ lp_debug_dump_value(func);
+ debug_printf("\n");
+ }
+}
+
+
+/**
+ * Compile a module.
+ * This does IR optimization on all functions in the module.
+ */
+void
+gallivm_compile_module(struct gallivm_state *gallivm)
+{
+ LLVMValueRef func;
+ int64_t time_begin = 0;
+
+ assert(!gallivm->compiled);
+
+ if (gallivm->builder) {
+ LLVMDisposeBuilder(gallivm->builder);
+ gallivm->builder = NULL;
+ }
+
+ if (gallivm_debug & GALLIVM_DEBUG_PERF)
+ time_begin = os_time_get();
+
+ /* Run optimization passes */
+ LLVMInitializeFunctionPassManager(gallivm->passmgr);
+ func = LLVMGetFirstFunction(gallivm->module);
+ while (func) {
+ if (0) {
+ debug_printf("optimizing func %s...\n", LLVMGetValueName(func));
+ }
+
+ /* Disable frame pointer omission on debug/profile builds */
+ /* XXX: And workaround http://llvm.org/PR21435 */
+#if HAVE_LLVM >= 0x0307 && \
+ (defined(DEBUG) || defined(PROFILE) || \
+ defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64))
+ LLVMAddTargetDependentFunctionAttr(func, "no-frame-pointer-elim", "true");
+ LLVMAddTargetDependentFunctionAttr(func, "no-frame-pointer-elim-non-leaf", "true");
+#endif
+
+ LLVMRunFunctionPassManager(gallivm->passmgr, func);
+ func = LLVMGetNextFunction(func);
+ }
+ LLVMFinalizeFunctionPassManager(gallivm->passmgr);
+
+ if (gallivm_debug & GALLIVM_DEBUG_PERF) {
+ int64_t time_end = os_time_get();
+ int time_msec = (int)(time_end - time_begin) / 1000;
+ assert(gallivm->module_name);
+ debug_printf("optimizing module %s took %d msec\n",
+ gallivm->module_name, time_msec);
+ }
+
+ /* Dump byte code to a file */
+ if (gallivm_debug & GALLIVM_DEBUG_DUMP_BC) {
+ char filename[256];
+ assert(gallivm->module_name);
+ util_snprintf(filename, sizeof(filename), "ir_%s.bc", gallivm->module_name);
+ LLVMWriteBitcodeToFile(gallivm->module, filename);
+ debug_printf("%s written\n", filename);
+ debug_printf("Invoke as \"llc %s%s -o - %s\"\n",
+ (HAVE_LLVM >= 0x0305) ? "[-mcpu=<-mcpu option] " : "",
+ "[-mattr=<-mattr option(s)>]",
+ filename);
+ }
+
+ if (use_mcjit) {
+ assert(!gallivm->engine);
+ if (!init_gallivm_engine(gallivm)) {
+ assert(0);
+ }
+ }
+ assert(gallivm->engine);
+
+ ++gallivm->compiled;
+
+ if (gallivm_debug & GALLIVM_DEBUG_ASM) {
+ LLVMValueRef llvm_func = LLVMGetFirstFunction(gallivm->module);
+
+ while (llvm_func) {
+ /*
+ * Need to filter out functions which don't have an implementation,
+ * such as the intrinsics. May not be sufficient in case of IPO?
+ * LLVMGetPointerToGlobal() will abort otherwise.
+ */
+ if (!LLVMIsDeclaration(llvm_func)) {
+ void *func_code = LLVMGetPointerToGlobal(gallivm->engine, llvm_func);
+ lp_disassemble(llvm_func, func_code);
+ }
+ llvm_func = LLVMGetNextFunction(llvm_func);
+ }
+ }
+
+#if defined(PROFILE)
+ {
+ LLVMValueRef llvm_func = LLVMGetFirstFunction(gallivm->module);
+
+ while (llvm_func) {
+ if (!LLVMIsDeclaration(llvm_func)) {
+ void *func_code = LLVMGetPointerToGlobal(gallivm->engine, llvm_func);
+ lp_profile(llvm_func, func_code);
+ }
+ llvm_func = LLVMGetNextFunction(llvm_func);
+ }
+ }