Skip to content

Commit f5158cd

Browse files
author
Daniel Kroening
authored
Merge pull request #50 from tautschnig/gcc-asm-labels
Gcc asm labels and attribute "alias" support
2 parents dc3a655 + 39677b6 commit f5158cd

17 files changed

+313
-46
lines changed

regression/ansi-c/asm3/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
other.c
44
^EXIT=0$
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <assert.h>
2+
3+
int foo(int a)
4+
{
5+
return a;
6+
}
7+
8+
// this is a GCC extension
9+
10+
int bar(int b) __attribute__((alias("foo")));
11+
12+
__typeof__(foo) bar2 __attribute__((alias("foo")));
13+
14+
int main()
15+
{
16+
#ifdef __GNUC__
17+
assert(bar(42)==42);
18+
assert(bar2(42)==42);
19+
#endif
20+
return 0;
21+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$

src/ansi-c/ansi_c_convert_type.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,11 @@ void ansi_c_convert_typet::read_rec(const typet &type)
7272
c_qualifiers.is_ptr64=true;
7373
else if(type.id()==ID_volatile)
7474
c_qualifiers.is_volatile=true;
75-
else if(type.id()==ID_asm)
75+
else if(type.id()==ID_asm &&
76+
type.has_subtype() &&
77+
type.subtype().id()==ID_string_constant)
7678
{
77-
// These are called 'asm labels' by GCC.
78-
// ignore for now
79+
c_storage_spec.asm_label=type.subtype().get(ID_value);
7980
}
8081
else if(type.id()==ID_const)
8182
c_qualifiers.is_constant=true;
@@ -233,6 +234,12 @@ void ansi_c_convert_typet::read_rec(const typet &type)
233234
constructor=true;
234235
else if(type.id()==ID_destructor)
235236
destructor=true;
237+
else if(type.id()==ID_alias &&
238+
type.has_subtype() &&
239+
type.subtype().id()==ID_string_constant)
240+
{
241+
c_storage_spec.alias=type.subtype().get(ID_value);
242+
}
236243
else
237244
other.push_back(type);
238245
}

src/ansi-c/c_storage_spec.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,16 @@ void c_storage_spect::read(const typet &type)
5555
if(it->id()==ID_thread)
5656
is_thread_local=true;
5757
}
58+
else if(type.id()==ID_alias &&
59+
type.has_subtype() &&
60+
type.subtype().id()==ID_string_constant)
61+
{
62+
alias=type.subtype().get(ID_value);
63+
}
64+
else if(type.id()==ID_asm &&
65+
type.has_subtype() &&
66+
type.subtype().id()==ID_string_constant)
67+
{
68+
asm_label=type.subtype().get(ID_value);
69+
}
5870
}

src/ansi-c/c_storage_spec.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,18 @@ class c_storage_spect
3434
is_register=false;
3535
is_inline=false;
3636
is_weak=false;
37+
alias.clear();
38+
asm_label.clear();
3739
}
3840

3941
bool is_typedef, is_extern, is_static, is_register,
4042
is_inline, is_thread_local, is_weak;
43+
44+
// __attribute__((alias("foo")))
45+
irep_idt alias;
46+
47+
// GCC asm labels __asm__("foo") - these change the symbol name
48+
irep_idt asm_label;
4149

4250
friend bool operator == (
4351
const c_storage_spect &a,
@@ -49,7 +57,9 @@ class c_storage_spect
4957
a.is_register==b.is_register &&
5058
a.is_thread_local==b.is_thread_local &&
5159
a.is_inline==b.is_inline &&
52-
a.is_weak==b.is_weak;
60+
a.is_weak==b.is_weak &&
61+
a.alias==b.alias &&
62+
a.asm_label==b.asm_label;
5363
}
5464

5565
friend bool operator != (
@@ -70,6 +80,8 @@ class c_storage_spect
7080
a.is_inline |=b.is_inline;
7181
a.is_thread_local |=b.is_thread_local;
7282
a.is_weak |=b.is_weak;
83+
if(!b.alias.empty()) a.alias=b.alias;
84+
if(!b.asm_label.empty()) a.asm_label=b.asm_label;
7385

7486
return a;
7587
}

src/ansi-c/c_typecheck_base.cpp

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ void c_typecheck_baset::typecheck_new_symbol(symbolt &symbol)
195195

196196
if(symbol.type.id()==ID_code)
197197
{
198-
if(symbol.value.is_not_nil())
198+
if(symbol.value.is_not_nil() &&
199+
!symbol.is_macro)
199200
typecheck_function_body(symbol);
200201
else
201202
{
@@ -361,7 +362,8 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
361362
}
362363

363364
// do initializer, this may change the type
364-
if(follow(new_symbol.type).id()!=ID_code)
365+
if(follow(new_symbol.type).id()!=ID_code &&
366+
!new_symbol.is_macro)
365367
do_initializer(new_symbol);
366368

367369
const typet &final_new=follow(new_symbol.type);
@@ -464,7 +466,10 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
464466
old_symbol.is_weak=true;
465467
}
466468

467-
typecheck_function_body(new_symbol);
469+
if(new_symbol.is_macro)
470+
old_symbol.is_macro=true;
471+
else
472+
typecheck_function_body(new_symbol);
468473

469474
// overwrite location
470475
old_symbol.location=new_symbol.location;
@@ -592,6 +597,7 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
592597
{
593598
old_symbol.value=new_symbol.value;
594599
old_symbol.type=new_symbol.type;
600+
old_symbol.is_macro=new_symbol.is_macro;
595601
}
596602
}
597603

@@ -690,6 +696,89 @@ void c_typecheck_baset::typecheck_function_body(symbolt &symbol)
690696

691697
/*******************************************************************\
692698
699+
Function: c_typecheck_baset::apply_asm_label
700+
701+
Inputs:
702+
703+
Outputs:
704+
705+
Purpose:
706+
707+
\*******************************************************************/
708+
709+
void c_typecheck_baset::apply_asm_label(
710+
const irep_idt &asm_label,
711+
symbolt &symbol)
712+
{
713+
const irep_idt orig_name=symbol.name;
714+
715+
// restrict renaming to functions and global variables;
716+
// procedure-local ones would require fixing the scope, as we
717+
// do for parameters below
718+
if(!asm_label.empty() &&
719+
!symbol.is_type &&
720+
(symbol.type.id()==ID_code || symbol.is_static_lifetime))
721+
{
722+
symbol.name=asm_label;
723+
symbol.base_name=asm_label;
724+
}
725+
726+
if(symbol.name!=orig_name)
727+
{
728+
if(!asm_label_map.insert(
729+
std::make_pair(orig_name, asm_label)).second)
730+
{
731+
err_location(symbol.location);
732+
if(asm_label_map[orig_name]==asm_label)
733+
{
734+
str << "duplicate (consistent) asm renaming";
735+
warning_msg();
736+
}
737+
else
738+
{
739+
str << "error: conflicting asm renaming";
740+
throw 0;
741+
}
742+
}
743+
}
744+
else if(asm_label.empty())
745+
{
746+
asm_label_mapt::const_iterator entry=
747+
asm_label_map.find(symbol.name);
748+
if(entry!=asm_label_map.end())
749+
{
750+
symbol.name=entry->second;
751+
symbol.base_name=entry->second;
752+
}
753+
}
754+
755+
if(symbol.name!=orig_name &&
756+
symbol.type.id()==ID_code &&
757+
symbol.value.is_not_nil() && !symbol.is_macro)
758+
{
759+
const code_typet &code_type=to_code_type(symbol.type);
760+
761+
for(code_typet::parameterst::const_iterator
762+
p_it=code_type.parameters().begin();
763+
p_it!=code_type.parameters().end();
764+
++p_it)
765+
{
766+
const irep_idt &p_bn=p_it->get_base_name();
767+
if(p_bn.empty())
768+
continue;
769+
770+
irep_idt p_id=id2string(orig_name)+"::"+id2string(p_bn);
771+
irep_idt p_new_id=id2string(symbol.name)+"::"+id2string(p_bn);
772+
773+
if(!asm_label_map.insert(
774+
std::make_pair(p_id, p_new_id)).second)
775+
assert(asm_label_map[p_id]==p_new_id);
776+
}
777+
}
778+
}
779+
780+
/*******************************************************************\
781+
693782
Function: c_typecheck_baset::typecheck_declaration
694783
695784
Inputs:
@@ -751,11 +840,24 @@ void c_typecheck_baset::typecheck_declaration(
751840

752841
symbolt symbol;
753842
declaration.to_symbol(*d_it, symbol);
754-
irep_idt identifier=symbol.name;
755843

756844
// now check other half of type
757845
typecheck_type(symbol.type);
758846

847+
if(!full_spec.alias.empty())
848+
{
849+
if(symbol.value.is_not_nil())
850+
throw "alias attribute cannot be used with a body";
851+
852+
// alias function need not have been declared yet, thus
853+
// can't lookup
854+
symbol.value=symbol_exprt(full_spec.alias);
855+
symbol.is_macro=true;
856+
}
857+
858+
apply_asm_label(full_spec.asm_label, symbol);
859+
irep_idt identifier=symbol.name;
860+
759861
typecheck_symbol(symbol);
760862

761863
// add code contract (if any); we typecheck this after the

src/ansi-c/c_typecheck_base.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@ class c_typecheck_baset:
244244
src.id()==ID_c_enum_tag ||
245245
src.id()==ID_c_bit_field;
246246
}
247+
248+
typedef hash_map_cont<irep_idt, irep_idt, irep_id_hash> asm_label_mapt;
249+
asm_label_mapt asm_label_map;
250+
251+
void apply_asm_label(const irep_idt &asm_label, symbolt &symbol);
247252
};
248253

249254
#endif

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ Function: c_typecheck_baset::typecheck_expr_symbol
799799

800800
void c_typecheck_baset::typecheck_expr_symbol(exprt &expr)
801801
{
802-
const irep_idt &identifier=to_symbol_expr(expr).get_identifier();
802+
irep_idt identifier=to_symbol_expr(expr).get_identifier();
803803

804804
// Is it a parameter? We do this while checking parameter lists.
805805
id_type_mapt::const_iterator p_it=parameter_map.find(identifier);
@@ -811,6 +811,15 @@ void c_typecheck_baset::typecheck_expr_symbol(exprt &expr)
811811
return;
812812
}
813813

814+
// renaming via GCC asm label
815+
asm_label_mapt::const_iterator entry=
816+
asm_label_map.find(identifier);
817+
if(entry!=asm_label_map.end())
818+
{
819+
identifier=entry->second;
820+
to_symbol_expr(expr).set_identifier(identifier);
821+
}
822+
814823
// look it up
815824
const symbolt *symbol_ptr;
816825
if(lookup(identifier, symbol_ptr))
@@ -839,11 +848,13 @@ void c_typecheck_baset::typecheck_expr_symbol(exprt &expr)
839848
// preserve enum key
840849
irep_idt base_name=expr.get(ID_C_base_name);
841850

842-
expr=symbol.value;
851+
follow_macros(expr);
843852

844853
if(expr.id()==ID_constant &&
845854
!base_name.empty())
846855
expr.set(ID_C_cformat, base_name);
856+
else
857+
typecheck_expr(expr);
847858

848859
// preserve location
849860
expr.add_source_location()=source_location;
@@ -2149,8 +2160,12 @@ void c_typecheck_baset::typecheck_side_effect_function_call(
21492160

21502161
if(f_op.id()==ID_symbol)
21512162
{
2152-
const irep_idt &identifier=
2153-
to_symbol_expr(f_op).get_identifier();
2163+
irep_idt identifier=to_symbol_expr(f_op).get_identifier();
2164+
2165+
asm_label_mapt::const_iterator entry=
2166+
asm_label_map.find(identifier);
2167+
if(entry!=asm_label_map.end())
2168+
identifier=entry->second;
21542169

21552170
if(symbol_table.symbols.find(identifier)==symbol_table.symbols.end())
21562171
{

0 commit comments

Comments
 (0)