Skip to content

Commit 2be0696

Browse files
authored
Merge pull request #1389 from diffblue/smv-word-constants
SMV: word constants
2 parents a5a43bc + 38db215 commit 2be0696

File tree

7 files changed

+170
-1
lines changed

7 files changed

+170
-1
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# EBMC 5.9
2+
3+
* SMV: word constants
4+
15
# EBMC 5.8
26

37
* AIG/netlist engine: fix for conversion of extract bits operator
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
word_constants1.smv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
MODULE main
2+
3+
SPEC uwconst(123, 8) = 0d8_123;
4+
SPEC uwconst(123, 8) = 0ud8_123;
5+
SPEC uwconst(123, 8) = 0h_7b;
6+
SPEC uwconst(123, 8) = 0uh_7b;
7+
SPEC uwconst(123, 8) = 0o8_173;
8+
SPEC uwconst(123, 8) = 0uo8_173;
9+
SPEC uwconst(123, 8) = 0b_01111011;
10+
SPEC uwconst(123, 8) = 0ub_01111011;
11+
SPEC uwconst(123, 8) = 0b8_1111011;
12+
SPEC uwconst(123, 8) = 0ub8_1111011;
13+
14+
SPEC swconst(123, 8) = 0sd8_123;
15+
SPEC swconst(123, 8) = 0sh_7b;
16+
SPEC swconst(123, 8) = 0so8_173;
17+
SPEC swconst(123, 8) = 0sb_01111011;
18+
SPEC swconst(123, 8) = 0sb8_1111011;

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ IREP_ID_ONE(smv_union)
4141
IREP_ID_ONE(smv_unsigned_cast)
4242
IREP_ID_ONE(smv_uwconst)
4343
IREP_ID_ONE(smv_word1)
44+
IREP_ID_ONE(smv_word_constant)
4445
IREP_ID_ONE(smv_H)
4546
IREP_ID_ONE(smv_bounded_H)
4647
IREP_ID_ONE(smv_O)

src/smvlang/parser.y

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,9 @@ static smv_parse_treet::modulet &new_module(YYSTYPE &module_name)
320320

321321
%token IDENTIFIER_Token "identifier"
322322
%token QIDENTIFIER_Token "quoted identifier"
323-
%token STRING_Token "quoted string"
323+
%token STRING_Token "quoted string"
324324
%token NUMBER_Token "number"
325+
%token WORD_CONSTANT_Token "word constant"
325326

326327
/* operator precedence, low to high */
327328
%right IMPLIES_Token
@@ -815,6 +816,7 @@ formula : basic_expr
815816

816817
constant : boolean_constant
817818
| integer_constant
819+
| word_constant
818820
;
819821

820822
boolean_constant:
@@ -841,6 +843,15 @@ integer_constant:
841843
}
842844
;
843845

846+
word_constant:
847+
WORD_CONSTANT_Token
848+
{
849+
init($$, ID_constant);
850+
stack_expr($$).set(ID_value, stack_expr($1).id());
851+
stack_expr($$).type() = typet{ID_smv_word_constant};
852+
}
853+
;
854+
844855
basic_expr : constant
845856
| identifier
846857
{

src/smvlang/scanner.l

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ void newlocation(YYSTYPE &x)
188188
stack_expr(yysmvlval).id(yytext);
189189
return NUMBER_Token;
190190
}
191+
0[us]?[bBoOdDhH][0-9]*_[0-9a-fA-F][_0-9a-fA-F]* {
192+
newstack(yysmvlval);
193+
stack_expr(yysmvlval).id(yytext);
194+
return WORD_CONSTANT_Token;
195+
}
191196
\"[^\"]*\" {
192197
newstack(yysmvlval);
193198
std::string tmp(yytext);

src/smvlang/smv_typecheck.cpp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class smv_typecheckt:public typecheckt
9090
void typecheck(smv_parse_treet::modulet::itemt &);
9191
void typecheck_expr_rec(exprt &, modet);
9292
void convert_expr_to(exprt &, const typet &dest);
93+
exprt convert_word_constant(const constant_exprt &);
9394

9495
smv_parse_treet::modulet *modulep;
9596

@@ -582,6 +583,123 @@ void smv_typecheckt::typecheck(exprt &expr, modet mode)
582583

583584
/*******************************************************************\
584585
586+
Function: convert_word_constant
587+
588+
Inputs:
589+
590+
Outputs:
591+
592+
Purpose:
593+
594+
\*******************************************************************/
595+
596+
exprt smv_typecheckt::convert_word_constant(const constant_exprt &src_expr)
597+
{
598+
auto &src = id2string(src_expr.get_value());
599+
600+
DATA_INVARIANT(src[0] == '0', "word constant grammar");
601+
602+
std::size_t index = 1;
603+
bool is_signed = false;
604+
605+
DATA_INVARIANT(index < src.size(), "word constant length");
606+
607+
switch(src[index])
608+
{
609+
case 's':
610+
case 'S':
611+
is_signed = true;
612+
index++;
613+
break;
614+
615+
case 'u':
616+
case 'U':
617+
// this is the default
618+
index++;
619+
break;
620+
621+
default:;
622+
}
623+
624+
DATA_INVARIANT(index < src.size(), "word constant length");
625+
626+
unsigned base;
627+
switch(src[index])
628+
{
629+
case 'd':
630+
case 'D':
631+
base = 10;
632+
break;
633+
634+
case 'h':
635+
case 'H':
636+
base = 16;
637+
break;
638+
639+
case 'b':
640+
case 'B':
641+
base = 2;
642+
break;
643+
644+
case 'o':
645+
case 'O':
646+
base = 8;
647+
break;
648+
649+
default:
650+
DATA_INVARIANT(false, "word constant base");
651+
}
652+
653+
index++;
654+
655+
DATA_INVARIANT(index < src.size(), "word constant length");
656+
657+
std::optional<mp_integer> bits = {};
658+
659+
// optional number of bits
660+
if(isdigit(src[index]))
661+
{
662+
std::string bits_str;
663+
for(; index < src.size() && isdigit(src[index]); index++)
664+
{
665+
bits_str += src[index];
666+
}
667+
668+
bits = string2integer(bits_str);
669+
}
670+
671+
std::string digits;
672+
digits.reserve(src.size());
673+
674+
for(; index < src.size(); index++)
675+
{
676+
if(src[index] != '_')
677+
digits.push_back(src[index]);
678+
}
679+
680+
if(!bits.has_value())
681+
{
682+
if(base == 10)
683+
throw errort{}.with_location(src_expr.source_location())
684+
<< "decimal word constant without width";
685+
else if(base == 2)
686+
bits = digits.size();
687+
else if(base == 8)
688+
bits = digits.size() * 3;
689+
else if(base == 16)
690+
bits = digits.size() * 4;
691+
}
692+
693+
auto digits_int = string2integer(digits, base);
694+
695+
auto type =
696+
bitvector_typet{is_signed ? ID_signedbv : ID_unsignedbv, bits.value()};
697+
698+
return from_integer(digits_int, type).with_source_location(src_expr);
699+
}
700+
701+
/*******************************************************************\
702+
585703
Function: smv_typecheckt::typecheck_expr_rec
586704
587705
Inputs:
@@ -845,6 +963,11 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
845963
{
846964
// good as is
847965
}
966+
else if(type.id() == ID_smv_word_constant)
967+
{
968+
// turn into signedbv/unsignedbv
969+
expr = convert_word_constant(to_constant_expr(expr));
970+
}
848971
else
849972
{
850973
PRECONDITION(false);

0 commit comments

Comments
 (0)