@@ -17,6 +17,8 @@ Date: December 2014
17
17
18
18
#include < util/c_types.h>
19
19
#include < util/pointer_expr.h>
20
+ #include < util/prefix.h>
21
+ #include < util/range.h>
20
22
#include < util/std_code.h>
21
23
#include < util/string_constant.h>
22
24
@@ -36,22 +38,26 @@ class remove_asmt
36
38
void operator ()()
37
39
{
38
40
for (auto &f : goto_functions.function_map )
39
- process_function (f.second );
41
+ process_function (f.first , f. second );
40
42
}
41
43
42
44
protected:
43
45
symbol_tablet &symbol_table;
44
46
goto_functionst &goto_functions;
45
47
46
- void process_function (goto_functionst::goto_functiont &);
48
+ void process_function (const irep_idt &, goto_functionst::goto_functiont &);
47
49
48
50
void process_instruction (
51
+ const irep_idt &function_id,
49
52
goto_programt::instructiont &instruction,
50
53
goto_programt &dest);
51
54
52
55
void process_instruction_gcc (const code_asm_gcct &, goto_programt &dest);
53
56
54
- void process_instruction_msc (const code_asmt &, goto_programt &dest);
57
+ void process_instruction_msc (
58
+ const irep_idt &,
59
+ const code_asmt &,
60
+ goto_programt &dest);
55
61
56
62
void gcc_asm_function_call (
57
63
const irep_idt &function_base_name,
@@ -60,6 +66,7 @@ class remove_asmt
60
66
61
67
void msc_asm_function_call (
62
68
const irep_idt &function_base_name,
69
+ const exprt::operandst &operands,
63
70
const code_asmt &code,
64
71
goto_programt &dest);
65
72
};
@@ -102,7 +109,10 @@ void remove_asmt::gcc_asm_function_call(
102
109
}
103
110
}
104
111
105
- code_typet fkt_type ({}, empty_typet ());
112
+ code_typet fkt_type{
113
+ code_typet::parameterst{
114
+ arguments.size (), code_typet::parametert{void_pointer}},
115
+ empty_typet ()};
106
116
107
117
symbol_exprt fkt (function_identifier, fkt_type);
108
118
@@ -138,23 +148,33 @@ void remove_asmt::gcc_asm_function_call(
138
148
// / assembly statement
139
149
// /
140
150
// / \param function_base_name: Name of the function to call
151
+ // / \param operands: Arguments to be passed to function
141
152
// / \param code: msc-style inline assembly statement to translate to function
142
153
// / call
143
154
// / \param dest: Goto program to append the function call to
144
155
void remove_asmt::msc_asm_function_call (
145
156
const irep_idt &function_base_name,
157
+ const exprt::operandst &operands,
146
158
const code_asmt &code,
147
159
goto_programt &dest)
148
160
{
149
161
irep_idt function_identifier = function_base_name;
150
162
163
+ code_function_callt::argumentst arguments;
164
+
151
165
const typet void_pointer = pointer_type (empty_typet ());
152
166
153
- code_typet fkt_type ({}, empty_typet ());
167
+ for (const auto &op : operands)
168
+ arguments.push_back (typecast_exprt::conditional_cast (op, void_pointer));
169
+
170
+ code_typet fkt_type{
171
+ code_typet::parameterst{
172
+ arguments.size (), code_typet::parametert{void_pointer}},
173
+ empty_typet ()};
154
174
155
175
symbol_exprt fkt (function_identifier, fkt_type);
156
176
157
- code_function_callt function_call (fkt);
177
+ code_function_callt function_call (std::move ( fkt), std::move (arguments) );
158
178
159
179
dest.add (
160
180
goto_programt::make_function_call (function_call, code.source_location ()));
@@ -185,10 +205,12 @@ void remove_asmt::msc_asm_function_call(
185
205
// / Translates the given inline assembly code (which must be in either gcc or
186
206
// / msc style) to non-assembly goto program instructions
187
207
// /
208
+ // / \param function_id: Name of function being processed
188
209
// / \param instruction: The goto program instruction containing the inline
189
210
// / assembly statements
190
211
// / \param dest: The goto program to append the new instructions to
191
212
void remove_asmt::process_instruction (
213
+ const irep_idt &function_id,
192
214
goto_programt::instructiont &instruction,
193
215
goto_programt &dest)
194
216
{
@@ -199,7 +221,7 @@ void remove_asmt::process_instruction(
199
221
if (flavor == ID_gcc)
200
222
process_instruction_gcc (to_code_asm_gcc (code), dest);
201
223
else if (flavor == ID_msc)
202
- process_instruction_msc (code, dest);
224
+ process_instruction_msc (function_id, code, dest);
203
225
else
204
226
DATA_INVARIANT (false , " unexpected assembler flavor" );
205
227
}
@@ -376,9 +398,11 @@ void remove_asmt::process_instruction_gcc(
376
398
// / Translates the given inline assembly code (in msc style) to non-assembly
377
399
// / goto program instructions
378
400
// /
401
+ // / \param function_id: Name of function being processed
379
402
// / \param code: The inline assembly code statement to translate
380
403
// / \param dest: The goto program to append the new instructions to
381
404
void remove_asmt::process_instruction_msc (
405
+ const irep_idt &function_id,
382
406
const code_asmt &code,
383
407
goto_programt &dest)
384
408
{
@@ -450,12 +474,35 @@ void remove_asmt::process_instruction_msc(
450
474
451
475
if (command == " fstcw" || command == " fnstcw" || command == " fldcw" ) // x86
452
476
{
453
- msc_asm_function_call (" __asm_" + id2string (command), code, tmp_dest);
477
+ exprt::operandst args{null_pointer_exprt{pointer_type (empty_typet{})}};
478
+ // try to typecheck the argument
479
+ if (pos != instruction.size () && instruction[pos].id () == ID_symbol)
480
+ {
481
+ const irep_idt &name = instruction[pos].get (ID_identifier);
482
+ for (const auto &entry : equal_range (symbol_table.symbol_base_map , name))
483
+ {
484
+ // global scope symbol, don't replace a local one
485
+ if (entry.second == name && args[0 ].id () != ID_address_of)
486
+ {
487
+ args[0 ] =
488
+ address_of_exprt{symbol_table.lookup_ref (name).symbol_expr ()};
489
+ }
490
+ // parameter or symbol in local scope
491
+ else if (has_prefix (
492
+ id2string (entry.second ), id2string (function_id) + " ::" ))
493
+ {
494
+ args[0 ] = address_of_exprt{
495
+ symbol_table.lookup_ref (entry.second ).symbol_expr ()};
496
+ }
497
+ }
498
+ }
499
+ msc_asm_function_call (
500
+ " __asm_" + id2string (command), args, code, tmp_dest);
454
501
}
455
502
else if (
456
503
command == " mfence" || command == " lfence" || command == " sfence" ) // x86
457
504
{
458
- msc_asm_function_call (" __asm_" + id2string (command), code, tmp_dest);
505
+ msc_asm_function_call (" __asm_" + id2string (command), {}, code, tmp_dest);
459
506
}
460
507
else
461
508
unknown = true ; // give up
@@ -479,8 +526,10 @@ void remove_asmt::process_instruction_msc(
479
526
// / Replaces inline assembly instructions in the goto function by non-assembly
480
527
// / goto program instructions
481
528
// /
529
+ // / \param function_id: Name of function being processed
482
530
// / \param goto_function: The goto function
483
531
void remove_asmt::process_function (
532
+ const irep_idt &function_id,
484
533
goto_functionst::goto_functiont &goto_function)
485
534
{
486
535
bool did_something = false ;
@@ -490,7 +539,7 @@ void remove_asmt::process_function(
490
539
if (it->is_other () && it->get_other ().get_statement () == ID_asm)
491
540
{
492
541
goto_programt tmp_dest;
493
- process_instruction (*it, tmp_dest);
542
+ process_instruction (function_id, *it, tmp_dest);
494
543
it->turn_into_skip ();
495
544
did_something = true ;
496
545
0 commit comments