Skip to content

Commit 3411b22

Browse files
author
Remi Delmas
committed
Allow to force-load symbols from the cprover library even if they are
not already found in the symbol table and ensure they survive `remove_internal_symbols`.
1 parent 8699438 commit 3411b22

6 files changed

+89
-13
lines changed

src/ansi-c/ansi_c_language.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ bool ansi_c_languaget::typecheck(
104104
symbol_tablet &symbol_table,
105105
const std::string &module,
106106
const bool keep_file_local)
107+
{
108+
return typecheck(symbol_table, module, keep_file_local, {});
109+
}
110+
111+
bool ansi_c_languaget::typecheck(
112+
symbol_tablet &symbol_table,
113+
const std::string &module,
114+
const bool keep_file_local,
115+
const std::set<irep_idt> &keep)
107116
{
108117
symbol_tablet new_symbol_table;
109118

@@ -117,7 +126,7 @@ bool ansi_c_languaget::typecheck(
117126
}
118127

119128
remove_internal_symbols(
120-
new_symbol_table, this->get_message_handler(), keep_file_local);
129+
new_symbol_table, this->get_message_handler(), keep_file_local, keep);
121130

122131
if(linking(symbol_table, new_symbol_table, get_message_handler()))
123132
return true;

src/ansi-c/ansi_c_language.h

+6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ class ansi_c_languaget:public languaget
5656
const std::string &module,
5757
const bool keep_file_local) override;
5858

59+
bool typecheck(
60+
symbol_tablet &symbol_table,
61+
const std::string &module,
62+
const bool keep_file_local,
63+
const std::set<irep_idt> &keep);
64+
5965
bool can_keep_file_local() override
6066
{
6167
return true;

src/ansi-c/cprover_library.cpp

+23-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Author: Daniel Kroening, [email protected]
1717

1818
static std::string get_cprover_library_text(
1919
const std::set<irep_idt> &functions,
20-
const symbol_tablet &symbol_table)
20+
const symbol_tablet &symbol_table,
21+
const bool force_load)
2122
{
2223
std::ostringstream library_text;
2324

@@ -52,14 +53,15 @@ static std::string get_cprover_library_text(
5253
/// \endcond
5354

5455
return get_cprover_library_text(
55-
functions, symbol_table, cprover_library, library_text.str());
56+
functions, symbol_table, cprover_library, library_text.str(), force_load);
5657
}
5758

5859
std::string get_cprover_library_text(
5960
const std::set<irep_idt> &functions,
6061
const symbol_tablet &symbol_table,
6162
const struct cprover_library_entryt cprover_library[],
62-
const std::string &prologue)
63+
const std::string &prologue,
64+
const bool force_load)
6365
{
6466
// the default mode is ios_base::out which means subsequent write to the
6567
// stream will overwrite the original content
@@ -77,8 +79,9 @@ std::string get_cprover_library_text(
7779
symbol_tablet::symbolst::const_iterator old=
7880
symbol_table.symbols.find(id);
7981

80-
if(old!=symbol_table.symbols.end() &&
81-
old->second.value.is_nil())
82+
if(
83+
force_load ||
84+
(old != symbol_table.symbols.end() && old->second.value.is_nil()))
8285
{
8386
count++;
8487
library_text << e->model << '\n';
@@ -100,17 +103,17 @@ void cprover_c_library_factory(
100103
if(config.ansi_c.lib==configt::ansi_ct::libt::LIB_NONE)
101104
return;
102105

103-
std::string library_text;
104-
105-
library_text=get_cprover_library_text(functions, symbol_table);
106+
std::string library_text =
107+
get_cprover_library_text(functions, symbol_table, false);
106108

107109
add_library(library_text, symbol_table, message_handler);
108110
}
109111

110112
void add_library(
111113
const std::string &src,
112114
symbol_tablet &symbol_table,
113-
message_handlert &message_handler)
115+
message_handlert &message_handler,
116+
const std::set<irep_idt> &keep)
114117
{
115118
if(src.empty())
116119
return;
@@ -121,5 +124,15 @@ void add_library(
121124
ansi_c_language.set_message_handler(message_handler);
122125
ansi_c_language.parse(in, "");
123126

124-
ansi_c_language.typecheck(symbol_table, "<built-in-library>");
127+
ansi_c_language.typecheck(symbol_table, "<built-in-library>", true, keep);
128+
}
129+
130+
void cprover_c_library_factory_force_load(
131+
const std::set<irep_idt> &functions,
132+
symbol_tablet &symbol_table,
133+
message_handlert &message_handler)
134+
{
135+
std::string library_text =
136+
get_cprover_library_text(functions, symbol_table, true);
137+
add_library(library_text, symbol_table, message_handler, functions);
125138
}

src/ansi-c/cprover_library.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,28 @@ std::string get_cprover_library_text(
2727
const std::set<irep_idt> &functions,
2828
const symbol_tablet &,
2929
const struct cprover_library_entryt[],
30-
const std::string &prologue);
30+
const std::string &prologue,
31+
const bool force_load = false);
3132

33+
/// Parses and typechecks the given src and adds its contents to the
34+
/// symbol table. Symbols with names found in `keep` will survive
35+
/// the symbol table cleanup pass and be found in the symbol_table.
3236
void add_library(
3337
const std::string &src,
3438
symbol_tablet &,
35-
message_handlert &);
39+
message_handlert &,
40+
const std::set<irep_idt> &keep = {});
3641

3742
void cprover_c_library_factory(
3843
const std::set<irep_idt> &functions,
3944
symbol_tablet &,
4045
message_handlert &);
4146

47+
/// Load the requested function symbols from the cprover library
48+
/// and add them to the symbol table regardless of
49+
/// the library config flags and usage.
50+
void cprover_c_library_factory_force_load(
51+
const std::set<irep_idt> &functions,
52+
symbol_tablet &symbol_table,
53+
message_handlert &message_handler);
4254
#endif // CPROVER_ANSI_C_CPROVER_LIBRARY_H

src/linking/remove_internal_symbols.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,30 @@ void remove_internal_symbols(
108108
symbol_tablet &symbol_table,
109109
message_handlert &mh,
110110
const bool keep_file_local)
111+
{
112+
remove_internal_symbols(symbol_table, mh, keep_file_local, {});
113+
}
114+
115+
/// Removes internal symbols from a symbol table
116+
/// A symbol is EXPORTED if it is a
117+
/// * non-static function with body that is not extern inline
118+
/// * symbol used in an EXPORTED symbol
119+
/// * type used in an EXPORTED symbol
120+
///
121+
/// Read
122+
/// http://gcc.gnu.org/ml/gcc/2006-11/msg00006.html
123+
/// on "extern inline"
124+
/// \param symbol_table: symbol table to clean up
125+
/// \param mh: log handler
126+
/// \param keep_file_local: keep file-local functions with bodies even if we
127+
/// would otherwise remove them
128+
/// \param keep: set of symbol names to keep in the symbol table regardless
129+
/// of usage or kind
130+
void remove_internal_symbols(
131+
symbol_tablet &symbol_table,
132+
message_handlert &mh,
133+
const bool keep_file_local,
134+
const std::set<irep_idt> &keep)
111135
{
112136
namespacet ns(symbol_table);
113137
find_symbols_sett exported;
@@ -130,6 +154,8 @@ void remove_internal_symbols(
130154
special.insert("__placement_new_array");
131155
special.insert("__delete");
132156
special.insert("__delete_array");
157+
// plus any extra symbols we wish to keep
158+
special.insert(keep.begin(), keep.end());
133159

134160
for(symbol_tablet::symbolst::const_iterator
135161
it=symbol_table.symbols.begin();

src/linking/remove_internal_symbols.h

+10
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,21 @@ Author: Daniel Kroening
1212
#ifndef CPROVER_LINKING_REMOVE_INTERNAL_SYMBOLS_H
1313
#define CPROVER_LINKING_REMOVE_INTERNAL_SYMBOLS_H
1414

15+
#include <util/irep.h>
16+
17+
#include <set>
18+
1519
class message_handlert;
1620

1721
void remove_internal_symbols(
1822
class symbol_tablet &symbol_table,
1923
message_handlert &,
2024
const bool);
2125

26+
void remove_internal_symbols(
27+
class symbol_tablet &symbol_table,
28+
message_handlert &,
29+
const bool keep_file_local,
30+
const std::set<irep_idt> &keep);
31+
2232
#endif // CPROVER_LINKING_REMOVE_INTERNAL_SYMBOLS_H

0 commit comments

Comments
 (0)