summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/llvm-utils.c31
-rw-r--r--tools/perf/util/llvm-utils.h9
2 files changed, 38 insertions, 2 deletions
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 5e94857dfca2..19262f98cd4e 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -22,12 +22,14 @@
"$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \
"-Wno-unused-value -Wno-pointer-sign " \
"-working-directory $WORKING_DIR " \
- "-c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
+ "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
struct llvm_param llvm_param = {
.clang_path = "clang",
+ .llc_path = "llc",
.clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE,
.clang_opt = NULL,
+ .opts = NULL,
.kbuild_dir = NULL,
.kbuild_opts = NULL,
.user_set_param = false,
@@ -51,6 +53,8 @@ int perf_llvm_config(const char *var, const char *value)
llvm_param.kbuild_opts = strdup(value);
else if (!strcmp(var, "dump-obj"))
llvm_param.dump_obj = !!perf_config_bool(var, value);
+ else if (!strcmp(var, "opts"))
+ llvm_param.opts = strdup(value);
else {
pr_debug("Invalid LLVM config option: %s\n", value);
return -1;
@@ -430,11 +434,13 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
unsigned int kernel_version;
char linux_version_code_str[64];
const char *clang_opt = llvm_param.clang_opt;
- char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
+ char clang_path[PATH_MAX], llc_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
char serr[STRERR_BUFSIZE];
char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
*perf_bpf_include_opts = NULL;
const char *template = llvm_param.clang_bpf_cmd_template;
+ char *pipe_template = NULL;
+ const char *opts = llvm_param.opts;
char *command_echo = NULL, *command_out;
char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
@@ -484,6 +490,26 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
force_set_env("WORKING_DIR", kbuild_dir ? : ".");
+ if (opts) {
+ err = search_program(llvm_param.llc_path, "llc", llc_path);
+ if (err) {
+ pr_err("ERROR:\tunable to find llc.\n"
+ "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
+ " \tand 'llc-path' option in [llvm] section of ~/.perfconfig.\n");
+ version_notice();
+ goto errout;
+ }
+
+ if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
+ template, llc_path, opts) < 0) {
+ pr_err("ERROR:\tnot enough memory to setup command line\n");
+ goto errout;
+ }
+
+ template = pipe_template;
+
+ }
+
/*
* Since we may reset clang's working dir, path of source file
* should be transferred into absolute path, except we want
@@ -535,6 +561,7 @@ errout:
free(obj_buf);
free(perf_bpf_include_opts);
free(perf_include_dir);
+ free(pipe_template);
if (p_obj_buf)
*p_obj_buf = NULL;
if (p_obj_buf_sz)
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index d3ad8deb5db4..bf3f3f4c4fe2 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -11,6 +11,8 @@
struct llvm_param {
/* Path of clang executable */
const char *clang_path;
+ /* Path of llc executable */
+ const char *llc_path;
/*
* Template of clang bpf compiling. 5 env variables
* can be used:
@@ -23,6 +25,13 @@ struct llvm_param {
const char *clang_bpf_cmd_template;
/* Will be filled in $CLANG_OPTIONS */
const char *clang_opt;
+ /*
+ * If present it'll add -emit-llvm to $CLANG_OPTIONS to pipe
+ * the clang output to llc, useful for new llvm options not
+ * yet selectable via 'clang -mllvm option', such as -mattr=dwarfris
+ * in clang 6.0/llvm 7
+ */
+ const char *opts;
/* Where to find kbuild system */
const char *kbuild_dir;
/*