|
8 | 8 |
|
9 | 9 | #include "language.h"
|
10 | 10 | #include "expr.h"
|
| 11 | +#include <util/symbol.h> |
| 12 | +#include <util/symbol_table.h> |
| 13 | +#include <util/prefix.h> |
| 14 | +#include <util/cprover_prefix.h> |
| 15 | +#include <util/std_types.h> |
11 | 16 |
|
12 | 17 | /*******************************************************************\
|
13 | 18 |
|
@@ -125,3 +130,183 @@ bool languaget::type_to_name(
|
125 | 130 | name=type.pretty();
|
126 | 131 | return false;
|
127 | 132 | }
|
| 133 | + |
| 134 | +/*******************************************************************\ |
| 135 | +
|
| 136 | +Function: languaget::generate_opaque_method_stubs |
| 137 | +
|
| 138 | + Inputs: |
| 139 | + symbol_table - the symbol table for the program |
| 140 | +
|
| 141 | + Outputs: |
| 142 | +
|
| 143 | + Purpose: When there are opaque methods (e.g. ones where we don't |
| 144 | + have a body), we create a stub function in the goto |
| 145 | + program and mark it as opaque so the interpreter fills in |
| 146 | + appropriate values for it. |
| 147 | +
|
| 148 | +\*******************************************************************/ |
| 149 | + |
| 150 | +void languaget::generate_opaque_method_stubs(symbol_tablet &symbol_table) |
| 151 | +{ |
| 152 | + for(auto &symbol_entry : symbol_table.symbols) |
| 153 | + { |
| 154 | + if(is_symbol_opaque_function(symbol_entry.second)) |
| 155 | + { |
| 156 | + symbolt &symbol=symbol_entry.second; |
| 157 | + |
| 158 | + generate_opaque_parameter_symbols(symbol, symbol_table); |
| 159 | + |
| 160 | + irep_idt return_symbol_id = generate_opaque_stub_body( |
| 161 | + symbol, |
| 162 | + symbol_table); |
| 163 | + |
| 164 | + if(return_symbol_id!=ID_nil) |
| 165 | + { |
| 166 | + symbol.type.set("opaque_method_capture_symbol", return_symbol_id); |
| 167 | + } |
| 168 | + } |
| 169 | + } |
| 170 | +} |
| 171 | + |
| 172 | +/*******************************************************************\ |
| 173 | +
|
| 174 | +Function: languaget::generate_opaque_stub_body |
| 175 | +
|
| 176 | + Inputs: |
| 177 | + symbol - the function symbol which is opaque |
| 178 | + symbol_table - the symbol table |
| 179 | +
|
| 180 | + Outputs: The identifier of the return variable. ID_nil if the function |
| 181 | + doesn't return anything. |
| 182 | +
|
| 183 | + Purpose: To generate the stub function for the opaque function in |
| 184 | + question. The identifier is used in the flag to the interpreter |
| 185 | + that the function is opaque. This function should be implemented |
| 186 | + in the languages. |
| 187 | +
|
| 188 | +\*******************************************************************/ |
| 189 | + |
| 190 | +irep_idt languaget::generate_opaque_stub_body( |
| 191 | + symbolt &symbol, |
| 192 | + symbol_tablet &symbol_table) |
| 193 | +{ |
| 194 | + return ID_nil; |
| 195 | +} |
| 196 | + |
| 197 | +/*******************************************************************\ |
| 198 | +
|
| 199 | +Function: languaget::build_stub_parameter_symbol |
| 200 | +
|
| 201 | + Inputs: |
| 202 | + function_symbol - the symbol of an opaque function |
| 203 | + parameter_index - the index of the parameter within the |
| 204 | + the parameter list |
| 205 | + parameter_type - the type of the parameter |
| 206 | +
|
| 207 | + Outputs: A named symbol to be added to the symbol table representing |
| 208 | + one of the parameters in this opaque function. |
| 209 | +
|
| 210 | + Purpose: To build the parameter symbol and choose its name. This should |
| 211 | + be implemented in each language. |
| 212 | +
|
| 213 | +\*******************************************************************/ |
| 214 | + |
| 215 | +parameter_symbolt languaget::build_stub_parameter_symbol( |
| 216 | + const symbolt &function_symbol, |
| 217 | + size_t parameter_index, |
| 218 | + const code_typet::parametert ¶meter) |
| 219 | +{ |
| 220 | + error() << "language " << id() |
| 221 | + << " doesn't implement build_stub_parameter_symbol. " |
| 222 | + << "This means cannot use opaque functions." << eom; |
| 223 | + |
| 224 | + return parameter_symbolt(); |
| 225 | +} |
| 226 | + |
| 227 | +/*******************************************************************\ |
| 228 | +
|
| 229 | +Function: languaget::get_stub_return_symbol_name |
| 230 | +
|
| 231 | + Inputs: |
| 232 | + function_id - the function that has a return value |
| 233 | +
|
| 234 | + Outputs: the identifier to use for the symbol that will store the |
| 235 | + return value of this function. |
| 236 | +
|
| 237 | + Purpose: To get the name of the symbol to be used for the return value |
| 238 | + of the function. Generates a name like to_return_function_name |
| 239 | +
|
| 240 | +\*******************************************************************/ |
| 241 | + |
| 242 | +irep_idt languaget::get_stub_return_symbol_name(const irep_idt &function_id) |
| 243 | +{ |
| 244 | + std::ostringstream return_symbol_name_builder; |
| 245 | + return_symbol_name_builder << "to_return_" << function_id; |
| 246 | + return return_symbol_name_builder.str(); |
| 247 | +} |
| 248 | + |
| 249 | + |
| 250 | +/*******************************************************************\ |
| 251 | +
|
| 252 | +Function: languaget::is_symbol_opaque_function |
| 253 | +
|
| 254 | + Inputs: |
| 255 | + symbol - the symbol to be checked |
| 256 | +
|
| 257 | + Outputs: True if the symbol is an opaque (e.g. non-bodied) function |
| 258 | +
|
| 259 | + Purpose: To identify if a given symbol is an opaque function and |
| 260 | + hence needs to be stubbed. We explicitly exclude CPROVER |
| 261 | + functions, if they have no body it is because we haven't |
| 262 | + generated it yet. |
| 263 | +
|
| 264 | +\*******************************************************************/ |
| 265 | + |
| 266 | +bool languaget::is_symbol_opaque_function(const symbolt &symbol) |
| 267 | +{ |
| 268 | + // Explictly exclude CPROVER functions since these aren't opaque |
| 269 | + std::string variable_id_str(symbol.name.c_str()); |
| 270 | + bool is_cprover_function = has_prefix(variable_id_str, CPROVER_PREFIX); |
| 271 | + |
| 272 | + return !symbol.is_type && |
| 273 | + symbol.value.id()==ID_nil && |
| 274 | + symbol.type.id()==ID_code && |
| 275 | + !is_cprover_function; |
| 276 | +} |
| 277 | + |
| 278 | +/*******************************************************************\ |
| 279 | +
|
| 280 | +Function: languaget::generate_opaque_parameter_symbols |
| 281 | +
|
| 282 | + Inputs: |
| 283 | + function_symbol - the symbol of an opaque function |
| 284 | + symbol_table - the symbol table to add the new parameter |
| 285 | + symbols into |
| 286 | +
|
| 287 | + Outputs: |
| 288 | +
|
| 289 | + Purpose: To create stub parameter symbols for each parameter the |
| 290 | + function has and assign their IDs into the parameters |
| 291 | + identifier. |
| 292 | +
|
| 293 | +\*******************************************************************/ |
| 294 | + |
| 295 | +void languaget::generate_opaque_parameter_symbols( |
| 296 | + symbolt &function_symbol, |
| 297 | + symbol_tablet &symbol_table) |
| 298 | +{ |
| 299 | + code_typet &function_type = to_code_type(function_symbol.type); |
| 300 | + code_typet::parameterst ¶meters=function_type.parameters(); |
| 301 | + for(std::size_t i=0; i<parameters.size(); ++i) |
| 302 | + { |
| 303 | + code_typet::parametert ¶m=parameters[i]; |
| 304 | + const parameter_symbolt ¶m_symbol= |
| 305 | + build_stub_parameter_symbol(function_symbol, i, param); |
| 306 | + |
| 307 | + param.set_base_name(param_symbol.base_name); |
| 308 | + param.set_identifier(param_symbol.name); |
| 309 | + |
| 310 | + symbol_table.add(param_symbol); |
| 311 | + } |
| 312 | +} |
0 commit comments