summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPer Nordlow <per.nordlow@autoliv.com>2016-09-28 18:12:01 +0200
committerJoel Rosdahl <joel@rosdahl.net>2016-10-18 23:12:20 +0200
commit66b96f6328f96408fdc5fa6c2a08430246df8e8c (patch)
treefce6d286afec373e7e5786fecd68573cc098e1e8
parentf253566db9d327bd51dfa648b7a3c5a4c88eac60 (diff)
downloadccache-66b96f6328f96408fdc5fa6c2a08430246df8e8c.tar.gz
Support caching of .su file generated by GCC flag -fstack-usage
-rw-r--r--ccache.c83
-rw-r--r--compopt.c1
-rwxr-xr-xtest.sh23
-rw-r--r--test/test_compopt.c5
4 files changed, 111 insertions, 1 deletions
diff --git a/ccache.c b/ccache.c
index 88e0ec5f..a008461a 100644
--- a/ccache.c
+++ b/ccache.c
@@ -96,6 +96,9 @@ static char *output_dep;
// The path to the coverage file (implicit when using -ftest-coverage).
static char *output_cov;
+// The path to the stack usage (implicit when using -fstack-usage).
+static char *output_su = NULL;
+
// Diagnostic generation information (clang). Contains pathname if not NULL.
static char *output_dia = NULL;
@@ -127,6 +130,10 @@ static char *cached_dep;
// (cachedir/a/b/cdef[...]-size.gcno).
static char *cached_cov;
+// Full path to the file containing the stack usage
+// (cachedir/a/b/cdef[...]-size.su).
+static char *cached_su;
+
// Full path to the file containing the diagnostic information (for clang)
// (cachedir/a/b/cdef[...]-size.dia).
static char *cached_dia;
@@ -171,6 +178,9 @@ static bool generating_dependencies;
// Is the compiler being asked to output coverage?
static bool generating_coverage;
+// Is the compiler being asked to output stack usage?
+static bool generating_stackusage;
+
// Relocating debuginfo in the format old=new.
static char *debug_prefix_map = NULL;
@@ -984,6 +994,7 @@ get_file_from_cache(const char *source, const char *dest)
x_unlink(cached_stderr);
x_unlink(cached_obj);
x_unlink(cached_dep);
+ x_unlink(cached_su);
x_unlink(cached_dia);
failed();
@@ -1053,6 +1064,21 @@ to_cache(struct args *args)
tmp_cov = NULL;
}
+ char *tmp_su;
+ if (generating_stackusage) {
+ char *tmp_aux;
+ // GCC has some funny rule about max extension length.
+ if (strlen(get_extension(output_obj)) < 6) {
+ tmp_aux = remove_extension(output_obj);
+ } else {
+ tmp_aux = x_strdup(output_obj);
+ }
+ tmp_su = format("%s.su", tmp_aux);
+ free(tmp_aux);
+ } else {
+ tmp_su = NULL;
+ }
+
// GCC (at least 4.8 and 4.9) forms the .dwo file name by removing everything
// after (and including) the last "." from the object file name and then
// appending ".dwo".
@@ -1097,6 +1123,9 @@ to_cache(struct args *args)
if (tmp_cov) {
tmp_unlink(tmp_cov);
}
+ if (tmp_su) {
+ tmp_unlink(tmp_su);
+ }
tmp_unlink(tmp_dwo);
failed();
}
@@ -1108,6 +1137,9 @@ to_cache(struct args *args)
if (tmp_cov) {
tmp_unlink(tmp_cov);
}
+ if (tmp_su) {
+ tmp_unlink(tmp_su);
+ }
tmp_unlink(tmp_dwo);
failed();
}
@@ -1169,6 +1201,9 @@ to_cache(struct args *args)
if (tmp_cov) {
tmp_unlink(tmp_cov);
}
+ if (tmp_su) {
+ tmp_unlink(tmp_su);
+ }
tmp_unlink(tmp_dwo);
failed();
@@ -1242,6 +1277,23 @@ to_cache(struct args *args)
}
}
+ if (generating_stackusage) {
+ // GCC won't generate notes if there is no code.
+ if (stat(tmp_su, &st) != 0 && errno == ENOENT) {
+ FILE *f = fopen(cached_su, "wb");
+ cc_log("Creating placeholder: %s", cached_su);
+ if (!f) {
+ cc_log("Failed to create %s: %s", cached_su, strerror(errno));
+ stats_update(STATS_ERROR);
+ failed();
+ }
+ fclose(f);
+ stats_update_size(0, 1);
+ } else {
+ put_file_in_cache(tmp_su, cached_su);
+ }
+ }
+
if (output_dia) {
if (x_stat(output_dia, &st) != 0) {
stats_update(STATS_ERROR);
@@ -1264,6 +1316,11 @@ to_cache(struct args *args)
use_relative_paths_in_depfile(output_dep);
put_file_in_cache(output_dep, cached_dep);
}
+
+ if (output_su) {
+ put_file_in_cache(output_su, cached_su);
+ }
+
stats_update(STATS_TOCACHE);
// Make sure we have a CACHEDIR.TAG in the cache part of cache_dir. This can
@@ -1295,6 +1352,7 @@ to_cache(struct args *args)
free(tmp_stderr);
free(tmp_stdout);
free(tmp_cov);
+ free(tmp_su);
free(tmp_dwo);
}
@@ -1413,6 +1471,7 @@ update_cached_result_globals(struct file_hash *hash)
cached_stderr = get_path_in_cache(object_name, ".stderr");
cached_dep = get_path_in_cache(object_name, ".d");
cached_cov = get_path_in_cache(object_name, ".gcno");
+ cached_su = get_path_in_cache(object_name, ".su");
cached_dia = get_path_in_cache(object_name, ".dia");
if (using_split_dwarf) {
@@ -1898,6 +1957,10 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest)
// The compiler won't generate notes if there is no code
get_file_from_cache(cached_cov, output_cov);
}
+ if (generating_stackusage && stat(cached_su, &st) == 0 && st.st_size > 0) {
+ // The compiler won't generate notes if there is no code
+ get_file_from_cache(cached_su, output_su);
+ }
if (output_dia) {
get_file_from_cache(cached_dia, output_dia);
}
@@ -1912,6 +1975,9 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest)
if (generating_coverage) {
update_mtime(cached_cov);
}
+ if (generating_stackusage) {
+ update_mtime(cached_su);
+ }
if (output_dia) {
update_mtime(cached_dia);
}
@@ -2394,6 +2460,11 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
args_add(stripped_args, argv[i]);
continue;
}
+ if (str_eq(argv[i], "-fstack-usage")) {
+ generating_stackusage = true;
+ args_add(stripped_args, argv[i]);
+ continue;
+ }
if (str_eq(argv[i], "--coverage") // = -fprofile-arcs -ftest-coverage
|| str_eq(argv[i], "-coverage")) { // Undocumented but still works.
profile_arcs = true;
@@ -2926,6 +2997,12 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
free(base_name);
output_cov = make_relative_path(x_strdup(default_covfile_name));
}
+ if (generating_stackusage) {
+ char *base_name = remove_extension(output_obj);
+ char *default_sufile_name = format("%s.su", base_name);
+ free(base_name);
+ output_su = make_relative_path(x_strdup(default_sufile_name));
+ }
*compiler_args = args_copy(stripped_args);
if (conf->run_second_cpp) {
@@ -3088,6 +3165,7 @@ cc_reset(void)
free(output_dwo); output_dwo = NULL;
free(output_dep); output_dep = NULL;
free(output_cov); output_cov = NULL;
+ free(output_su); output_su = NULL;
free(output_dia); output_dia = NULL;
free(cached_obj_hash); cached_obj_hash = NULL;
free(cached_obj); cached_obj = NULL;
@@ -3095,6 +3173,7 @@ cc_reset(void)
free(cached_stderr); cached_stderr = NULL;
free(cached_dep); cached_dep = NULL;
free(cached_cov); cached_cov = NULL;
+ free(cached_su); cached_su = NULL;
free(cached_dia); cached_dia = NULL;
free(manifest_path); manifest_path = NULL;
time_of_compilation = 0;
@@ -3111,6 +3190,7 @@ cc_reset(void)
generating_debuginfo = false;
generating_dependencies = false;
generating_coverage = false;
+ generating_stackusage = false;
profile_arcs = false;
free(profile_dir); profile_dir = NULL;
i_tmpfile = NULL;
@@ -3203,6 +3283,9 @@ ccache(int argc, char *argv[])
if (generating_coverage) {
cc_log("Coverage file: %s", output_cov);
}
+ if (generating_stackusage) {
+ cc_log("Stack usage file: %s", output_su);
+ }
if (output_dia) {
cc_log("Diagnostic file: %s", output_dia);
}
diff --git a/compopt.c b/compopt.c
index e5bee234..1d9a659f 100644
--- a/compopt.c
+++ b/compopt.c
@@ -60,7 +60,6 @@ static const struct compopt compopts[] = {
{"-fno-working-directory", AFFECTS_CPP},
{"-fplugin=libcc1plugin", TOO_HARD}, // interaction with GDB
{"-frepo", TOO_HARD},
- {"-fstack-usage", TOO_HARD},
{"-fworking-directory", AFFECTS_CPP},
{"-idirafter", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
{"-iframework", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
diff --git a/test.sh b/test.sh
index 3e041574..94a7173f 100755
--- a/test.sh
+++ b/test.sh
@@ -1697,6 +1697,29 @@ EOF
test -r code.gcno || test_failed "code.gcno missing"
# -------------------------------------------------------------------------
+ TEST "-fstack-usage"
+
+ cat <<EOF >code.c
+int test() { return 0; }
+EOF
+
+ if $COMPILER_TYPE_GCC; then
+ $CCACHE_COMPILE -c -fstack-usage code.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ test -r code.su || test_failed "code.su missing"
+
+ rm code.su
+
+ $CCACHE_COMPILE -c -fstack-usage code.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ test -r code.su || test_failed "code.su missing"
+ fi
+
+ # -------------------------------------------------------------------------
TEST "Direct mode on cache created by ccache without direct mode support"
CCACHE_NODIRECT=1 $CCACHE_COMPILE -c -MD test.c
diff --git a/test/test_compopt.c b/test/test_compopt.c
index dc1e74c1..be345aa2 100644
--- a/test/test_compopt.c
+++ b/test/test_compopt.c
@@ -70,6 +70,11 @@ TEST(dash_ftest_coverage_not_too_hard)
CHECK(!compopt_too_hard("-ftest-coverage"));
}
+TEST(dash_fstack_usage_not_too_hard)
+{
+ CHECK(!compopt_too_hard("-fstack-usage"));
+}
+
TEST(dash_doesnexist_not_too_hard)
{
CHECK(!compopt_too_hard("-doesntexist"));