From 3e93a32d8b50435546654ea23a52b07bc13164dc Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 24 Aug 2022 19:58:45 -0700
Subject: [PATCH v13 18/20] meson: Add LLVM bitcode emission

This needs a bit more love before being ready...
---
 src/backend/jit/llvm/meson.build | 21 +++++++++++++++
 src/backend/meson.build          | 46 ++++++++++++++++++++++++++++++++
 meson.build                      |  2 ++
 src/tools/irlink                 | 43 +++++++++++++++++++++++++++++
 4 files changed, 112 insertions(+)
 create mode 100644 src/tools/irlink

diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build
index de2e624ab58..ede51503377 100644
--- a/src/backend/jit/llvm/meson.build
+++ b/src/backend/jit/llvm/meson.build
@@ -48,6 +48,19 @@ else
   llvm_irgen_command = clang
 endif
 
+llvm_irlink_kw = {
+  'command': [
+    irlink,
+    '--name', 'postgres',
+    '--lto', llvm_lto,
+    '--outdir', '@OUTPUT0@',
+    '--privdir', '@PRIVATE_DIR@',
+    '@INPUT@',
+  ],
+  'install': true,
+  'install_dir': dir_lib_pkg,
+}
+
 
 # XXX: Need to determine proper version of the function cflags for clang
 bitcode_cflags = ['-fno-strict-aliasing', '-fwrapv']
@@ -71,3 +84,11 @@ llvmjit_types = custom_target('llvmjit_types.bc',
   depfile: '@BASENAME@.c.bc.d',
 )
 backend_targets += llvmjit_types
+
+# Figure out -I's needed to build all postgres code, including all its
+# dependencies
+pkg_config = find_program(['pkg-config', 'pkgconf'], required: true)
+r = run_command(pkg_config,
+  ['--cflags-only-I', meson.build_root() / 'meson-uninstalled/postgresql-extension-uninstalled.pc'],
+  check: true)
+bitcode_cflags += r.stdout().split()
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 0598085a240..3f5e9883c0c 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -284,3 +284,49 @@ subdir('replication/libpqwalreceiver')
 subdir('replication/pgoutput')
 subdir('snowball')
 subdir('utils/mb/conversion_procs')
+
+
+
+###############################################################
+# emit LLVM bitcode of backend code for JIT inlining
+###############################################################
+
+if llvm.found()
+
+  # custom_target() insists on targetting files into the current
+  # directory. But we have files with the same name in different
+  # subdirectories.  generators() don't have that problem, but their results
+  # are not installable. The irlink command copies the files for us.
+  #
+  # FIXME: this needs to be in a central place
+  #
+  # generators don't accept CustomTargetIndex as input or 'depends', nor do
+  # they like targets with more than one output. However, a custom target
+  # accepts them as input without a problem. So we have the below transitive
+  # target :(
+
+  transitive_depend_target = custom_target('stamp',
+    input: generated_headers + generated_backend_headers + generated_backend_sources,
+    output: 'stamp',
+    command: [touch, '@OUTPUT@'],
+    install: false)
+
+  llvm_gen = generator(llvm_irgen_command,
+    arguments: llvm_irgen_args + bitcode_cflags,
+    depends: transitive_depend_target,
+    depfile: '@BASENAME@.c.bc.d',
+    output: '@PLAINNAME@.bc',
+  )
+
+  bc_backend_sources = llvm_gen.process(backend_sources,
+    preserve_path_from: meson.current_source_dir())
+
+  postgres_llvm = custom_target('bitcode',
+    output: ['bitcode'],
+    input: bc_backend_sources,
+    kwargs: llvm_irlink_kw,
+  )
+
+  backend_targets += postgres_llvm
+
+endif
diff --git a/meson.build b/meson.build
index 31c7dbe0ea0..a56af6ccb0e 100644
--- a/meson.build
+++ b/meson.build
@@ -684,6 +684,8 @@ if not llvmopt.disabled()
 
     ccache = find_program('ccache', native: true, required: false)
     clang = find_program(llvm_binpath / 'clang', required: true)
+    llvm_lto = find_program(llvm_binpath / 'llvm-lto', required: true)
+    irlink = find_program('src/tools/irlink', native: true)
   endif
 else
   llvm = not_found_dep
diff --git a/src/tools/irlink b/src/tools/irlink
new file mode 100644
index 00000000000..813bbf13398
--- /dev/null
+++ b/src/tools/irlink
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+
+import os
+import shutil
+import subprocess
+import sys
+import argparse
+
+parser = argparse.ArgumentParser(
+    description='generate PostgreSQL JIT IR module')
+
+parser.add_argument('--name', type=str, required=True)
+parser.add_argument('--lto', type=str, required=True)
+parser.add_argument('--privdir', type=str, required=True)
+parser.add_argument('--outdir', type=str, required=True)
+parser.add_argument('INPUT', type=str, nargs='+')
+
+args = parser.parse_args()
+
+outdir = os.path.realpath(args.outdir)
+privdir = os.path.realpath(args.privdir)
+
+index = '{0}/{1}.index.bc'.format(outdir, args.name)
+destdir = '{0}/{1}'.format(outdir, args.name)
+
+# Remove old contents if exist
+if os.path.exists(destdir):
+    shutil.rmtree(destdir)
+
+shutil.copytree(privdir, destdir)
+
+# Change working directory for irlink to link correctly
+os.chdir(args.outdir)
+
+file_names = []
+for input in args.INPUT:
+    file_names += [args.name + input.replace(args.privdir, '')]
+
+command = [args.lto, '-thinlto', '-thinlto-action=thinlink',
+           '-o', index] + file_names
+res = subprocess.run(command)
+
+exit(res.returncode)
-- 
2.37.3.542.gdd3f6c4cae

