Skip to content

Commit bc7f2c8

Browse files
nbyavuzCommitfest Bot
authored andcommitted
meson: Add architecture for LLVM bitcode emission
This commit adds suport for bitcode emission for both normal and generated source files (processed by bison, flex, etc). These bitcode files are installed into $pkglibdir/bitcode/ directory if the LLVM is found. New variable `bitcode_modules` is introduced to generate bitcode files. All required information is gathered in this variable. Then, this variable is processed by the main meson LLVM bitcode emission scripts: src/backend/jit/llvm/bitcode/meson.build -> src/tools/irlink. An example of a possible structure of bitcode_modules is: ``` bitcode_modules = [ { 'name': '...', 'target': ..., 'srcfiles': [ '...', '...', ], 'additional_flags': [ '-I...', '-I...', ], 'gen_srcfiles': [ { 'srcfiles': [ <custom_target for ...>, <custom_target for ...>, ], 'additional_flags': [ '-I...', '-I...', ] } ] } ] ``` Author: Andres Freund <andres@anarazel.de> Author: Nazir Bilal Yavuz <byavuz81@gmail.com> Author: Diego Fronza <diego.fronza@percona.com> Reviewed-by: Diego Fronza <diego.fronza@percona.com> Discussion: https://postgr.es/m/206b001d-1884-4081-bd02-bed5c92f02ba%40eisentraut.org
1 parent 2991376 commit bc7f2c8

File tree

5 files changed

+141
-11
lines changed

5 files changed

+141
-11
lines changed

meson.build

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,8 @@ if add_languages('cpp', required: llvmopt, native: false)
820820
# Some distros put LLVM and clang in different paths, so fallback to
821821
# find via PATH, too.
822822
clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
823+
llvm_lto = find_program(llvm_binpath / 'llvm-lto', required: true)
824+
irlink = find_program('src/tools/irlink', native: true)
823825
endif
824826
elif llvmopt.auto()
825827
message('llvm requires a C++ compiler')
@@ -3056,6 +3058,11 @@ test_deps = []
30563058
tests = []
30573059
meson_extension_tests = []
30583060

3061+
# List of object files + source files to generated LLVM IR for inlining.
3062+
# Each element is a hash of:
3063+
# {'target': target, 'srcfiles': ..., 'additional_flags': ...}.
3064+
bitcode_modules = []
3065+
30593066

30603067
# Default options for targets
30613068

@@ -3378,6 +3385,11 @@ subdir('src/interfaces/ecpg/test')
33783385

33793386
subdir('doc/src/sgml')
33803387

3388+
# generate bitcode for JIT inlining after giving contrib modules etc a chance
3389+
# to add themselves to bitcode_modules[]
3390+
subdir('src/backend/jit/llvm/bitcode', if_found: llvm)
3391+
3392+
33813393
generated_sources_ac += {'': ['GNUmakefile']}
33823394

33833395
# After processing src/test, add test_install_libs to the testprep_targets
@@ -4000,6 +4012,15 @@ summary(
40004012
section: 'Programs',
40014013
)
40024014

4015+
if llvm.found()
4016+
summary(
4017+
{
4018+
'clang': clang,
4019+
},
4020+
section: 'Programs',
4021+
)
4022+
endif
4023+
40034024
summary(
40044025
{
40054026
'bonjour': bonjour,
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Copyright (c) 2022-2024, PostgreSQL Global Development Group
2+
#
3+
# emit LLVM bitcode for JIT inlining
4+
5+
assert(llvm.found())
6+
7+
foreach bitcode_module : bitcode_modules
8+
bitcode_targets = []
9+
bitcode_obj = bitcode_module['target']
10+
bitcode_cflags_local = bitcode_cflags + bitcode_module.get('additional_flags', [])
11+
bitcode_name = bitcode_module.get('name', bitcode_obj.name())
12+
13+
foreach srcfile : bitcode_module['srcfiles']
14+
if meson.version().version_compare('>=0.59')
15+
srcfilename = fs.parent(srcfile) / fs.name(srcfile)
16+
else
17+
srcfilename = '@0@'.format(srcfile)
18+
endif
19+
20+
targetname = '@0@_@1@.bc'.format(
21+
bitcode_name,
22+
srcfilename.underscorify(),
23+
)
24+
bitcode_targets += custom_target(
25+
targetname,
26+
depends: [bitcode_obj],
27+
input: [srcfile],
28+
output: targetname,
29+
command: [llvm_irgen_command, bitcode_cflags_local],
30+
install: true,
31+
install_dir: dir_bitcode,
32+
)
33+
endforeach
34+
35+
# Process generated sources, which may include custom compilation flags.
36+
foreach gen_sources: bitcode_module.get('gen_sources', [])
37+
bitcode_cflags_gen_local = bitcode_cflags_local + gen_sources.get('additional_flags', [])
38+
39+
foreach srcfile: gen_sources['srcfiles']
40+
# Generated sources are stored in some folder under meson.build_root()/**,
41+
# remove the build prefix from the string.
42+
srcfilename = srcfile.full_path().split(meson.build_root() + '/')[1]
43+
44+
targetname = '@0@_@1@.bc'.format(
45+
bitcode_name,
46+
srcfilename.underscorify(),
47+
)
48+
bitcode_targets += custom_target(
49+
targetname,
50+
depends: [bitcode_obj],
51+
input: [srcfile],
52+
output: targetname,
53+
command: [llvm_irgen_command, bitcode_cflags_gen_local],
54+
install: true,
55+
install_dir: dir_bitcode,
56+
)
57+
endforeach
58+
endforeach
59+
60+
index_name = '@0@.index.bc'.format(bitcode_name)
61+
bitcode_index = custom_target('@0@'.format(bitcode_name),
62+
output: index_name,
63+
input: bitcode_targets,
64+
command: [irlink, '--lto', llvm_lto, '--outdir', '@OUTDIR@', '--index', index_name, '@INPUT@'],
65+
install: true,
66+
install_dir: dir_bitcode,
67+
)
68+
backend_targets += bitcode_index
69+
endforeach

src/backend/jit/llvm/meson.build

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,22 @@ backend_targets += llvmjit
4242

4343
# Define a few bits and pieces used here and elsewhere to generate bitcode
4444

45-
llvm_irgen_args = [
46-
'-c', '-o', '@OUTPUT@', '@INPUT@',
45+
llvm_irgen_command = []
46+
if ccache.found()
47+
llvm_irgen_command += ccache
48+
endif
49+
50+
llvm_irgen_command += [
51+
clang,
52+
'-c', '-o', '@OUTPUT0@', '@INPUT0@',
4753
'-flto=thin', '-emit-llvm',
48-
'-MD', '-MQ', '@OUTPUT@', '-MF', '@DEPFILE@',
4954
'-O2',
5055
'-Wno-ignored-attributes',
5156
'-Wno-empty-body',
57+
'-Wno-unknown-warning-option',
58+
'-Wno-compound-token-split-by-macro',
5259
]
53-
54-
if ccache.found()
55-
llvm_irgen_command = ccache
56-
llvm_irgen_args = [clang.full_path()] + llvm_irgen_args
57-
else
58-
llvm_irgen_command = clang
59-
endif
60+
llvm_irgen_dep_args = ['-MD', '-MQ', '@OUTPUT0@', '-MF', '@DEPFILE@']
6061

6162

6263
# XXX: Need to determine proper version of the function cflags for clang
@@ -73,7 +74,7 @@ bitcode_cflags += '-I@SOURCE_ROOT@/src/include'
7374
# Note this is intentionally not installed to bitcodedir, as it's not for
7475
# inlining
7576
llvmjit_types = custom_target('llvmjit_types.bc',
76-
command: [llvm_irgen_command] + llvm_irgen_args + bitcode_cflags,
77+
command: llvm_irgen_command + llvm_irgen_dep_args + bitcode_cflags,
7778
input: 'llvmjit_types.c',
7879
output: 'llvmjit_types.bc',
7980
depends: [postgres],
@@ -82,3 +83,11 @@ llvmjit_types = custom_target('llvmjit_types.bc',
8283
depfile: '@BASENAME@.c.bc.d',
8384
)
8485
backend_targets += llvmjit_types
86+
87+
# Figure out -I's needed to build all postgres code, including all its
88+
# dependencies
89+
pkg_config = find_program(['pkg-config', 'pkgconf'], required: true)
90+
r = run_command(pkg_config,
91+
['--cflags-only-I', meson.build_root() / 'meson-uninstalled/postgresql-extension-uninstalled.pc'],
92+
check: true)
93+
bitcode_cflags += r.stdout().split()

src/backend/meson.build

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ postgres = executable('postgres',
140140

141141
backend_targets += postgres
142142

143+
bitcode_modules += {
144+
'name': 'postgres',
145+
'target': postgres_lib,
146+
'srcfiles': backend_sources,
147+
}
148+
143149
pg_mod_c_args = cflags_mod
144150
pg_mod_cpp_args = cxxflags_mod
145151
pg_mod_link_args = ldflags_sl + ldflags_mod

src/tools/irlink

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
import shutil
6+
import subprocess
7+
import sys
8+
9+
parser = argparse.ArgumentParser(
10+
description='generate PostgreSQL JIT IR module')
11+
12+
parser.add_argument('--index', type=str, required=True)
13+
parser.add_argument('--lto', type=str, required=True)
14+
parser.add_argument('--outdir', type=str, required=True)
15+
parser.add_argument('INPUT', type=str, nargs='+')
16+
17+
args = parser.parse_args()
18+
19+
file_names = [os.path.basename(f) for f in args.INPUT]
20+
command = [args.lto,
21+
'-thinlto', '-thinlto-action=thinlink',
22+
'-o', args.index] + file_names
23+
res = subprocess.run(command, cwd=args.outdir)
24+
25+
exit(res.returncode)

0 commit comments

Comments
 (0)