@@ -17,6 +17,8 @@ Date: December 2014
1717
1818#include < util/c_types.h>
1919#include < util/pointer_expr.h>
20+ #include < util/prefix.h>
21+ #include < util/range.h>
2022#include < util/std_code.h>
2123#include < util/string_constant.h>
2224
@@ -36,22 +38,26 @@ class remove_asmt
3638 void operator ()()
3739 {
3840 for (auto &f : goto_functions.function_map )
39- process_function (f.second );
41+ process_function (f.first , f. second );
4042 }
4143
4244protected:
4345 symbol_tablet &symbol_table;
4446 goto_functionst &goto_functions;
4547
46- void process_function (goto_functionst::goto_functiont &);
48+ void process_function (const irep_idt &, goto_functionst::goto_functiont &);
4749
4850 void process_instruction (
51+ const irep_idt &function_id,
4952 goto_programt::instructiont &instruction,
5053 goto_programt &dest);
5154
5255 void process_instruction_gcc (const code_asm_gcct &, goto_programt &dest);
5356
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);
5561
5662 void gcc_asm_function_call (
5763 const irep_idt &function_base_name,
@@ -60,6 +66,7 @@ class remove_asmt
6066
6167 void msc_asm_function_call (
6268 const irep_idt &function_base_name,
69+ const exprt::operandst &operands,
6370 const code_asmt &code,
6471 goto_programt &dest);
6572};
@@ -102,7 +109,10 @@ void remove_asmt::gcc_asm_function_call(
102109 }
103110 }
104111
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 ()};
106116
107117 symbol_exprt fkt (function_identifier, fkt_type);
108118
@@ -138,23 +148,33 @@ void remove_asmt::gcc_asm_function_call(
138148// / assembly statement
139149// /
140150// / \param function_base_name: Name of the function to call
151+ // / \param operands: Arguments to be passed to function
141152// / \param code: msc-style inline assembly statement to translate to function
142153// / call
143154// / \param dest: Goto program to append the function call to
144155void remove_asmt::msc_asm_function_call (
145156 const irep_idt &function_base_name,
157+ const exprt::operandst &operands,
146158 const code_asmt &code,
147159 goto_programt &dest)
148160{
149161 irep_idt function_identifier = function_base_name;
150162
163+ code_function_callt::argumentst arguments;
164+
151165 const typet void_pointer = pointer_type (empty_typet ());
152166
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 ()};
154174
155175 symbol_exprt fkt (function_identifier, fkt_type);
156176
157- code_function_callt function_call (fkt);
177+ code_function_callt function_call (std::move ( fkt), std::move (arguments) );
158178
159179 dest.add (
160180 goto_programt::make_function_call (function_call, code.source_location ()));
@@ -185,10 +205,12 @@ void remove_asmt::msc_asm_function_call(
185205// / Translates the given inline assembly code (which must be in either gcc or
186206// / msc style) to non-assembly goto program instructions
187207// /
208+ // / \param function_id: Name of function being processed
188209// / \param instruction: The goto program instruction containing the inline
189210// / assembly statements
190211// / \param dest: The goto program to append the new instructions to
191212void remove_asmt::process_instruction (
213+ const irep_idt &function_id,
192214 goto_programt::instructiont &instruction,
193215 goto_programt &dest)
194216{
@@ -199,7 +221,7 @@ void remove_asmt::process_instruction(
199221 if (flavor == ID_gcc)
200222 process_instruction_gcc (to_code_asm_gcc (code), dest);
201223 else if (flavor == ID_msc)
202- process_instruction_msc (code, dest);
224+ process_instruction_msc (function_id, code, dest);
203225 else
204226 DATA_INVARIANT (false , " unexpected assembler flavor" );
205227}
@@ -376,9 +398,11 @@ void remove_asmt::process_instruction_gcc(
376398// / Translates the given inline assembly code (in msc style) to non-assembly
377399// / goto program instructions
378400// /
401+ // / \param function_id: Name of function being processed
379402// / \param code: The inline assembly code statement to translate
380403// / \param dest: The goto program to append the new instructions to
381404void remove_asmt::process_instruction_msc (
405+ const irep_idt &function_id,
382406 const code_asmt &code,
383407 goto_programt &dest)
384408{
@@ -450,12 +474,35 @@ void remove_asmt::process_instruction_msc(
450474
451475 if (command == " fstcw" || command == " fnstcw" || command == " fldcw" ) // x86
452476 {
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);
454501 }
455502 else if (
456503 command == " mfence" || command == " lfence" || command == " sfence" ) // x86
457504 {
458- msc_asm_function_call (" __asm_" + id2string (command), code, tmp_dest);
505+ msc_asm_function_call (" __asm_" + id2string (command), {}, code, tmp_dest);
459506 }
460507 else
461508 unknown = true ; // give up
@@ -479,8 +526,10 @@ void remove_asmt::process_instruction_msc(
479526// / Replaces inline assembly instructions in the goto function by non-assembly
480527// / goto program instructions
481528// /
529+ // / \param function_id: Name of function being processed
482530// / \param goto_function: The goto function
483531void remove_asmt::process_function (
532+ const irep_idt &function_id,
484533 goto_functionst::goto_functiont &goto_function)
485534{
486535 bool did_something = false ;
@@ -490,7 +539,7 @@ void remove_asmt::process_function(
490539 if (it->is_other () && it->get_other ().get_statement () == ID_asm)
491540 {
492541 goto_programt tmp_dest;
493- process_instruction (*it, tmp_dest);
542+ process_instruction (function_id, *it, tmp_dest);
494543 it->turn_into_skip ();
495544 did_something = true ;
496545
0 commit comments