Skip to content

Commit 0553d29

Browse files
vecchiot-awsadpaco-aws
authored andcommitted
Symbol table transformer (#321)
Adds a recursive visitor pattern which can be used to transform goto symbol tables, as well as a default (identity transform) implementation.
1 parent 8001520 commit 0553d29

21 files changed

Lines changed: 1321 additions & 23 deletions

File tree

compiler/rustc_codegen_llvm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.0.0"
44
edition = "2018"
55

66
[lib]
7-
test = false
7+
test = true
88
doctest = false
99

1010
[dependencies]

compiler/rustc_codegen_llvm/src/gotoc/cbmc/goto_program/expr.rs

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ impl Expr {
584584
// Check that each formal field has an value
585585
assert!(
586586
fields.iter().zip(values.iter()).all(|(f, v)| f.typ() == *v.typ()),
587-
"Error in struct_expr\n\t{:?}\n\t{:?}",
587+
"Error in struct_expr; value type does not match field type.\n\t{:?}\n\t{:?}",
588588
typ,
589589
values
590590
);
@@ -593,20 +593,25 @@ impl Expr {
593593

594594
/// Struct initializer
595595
/// `struct foo the_foo = >>> {.field1 = val1, .field2 = val2, ... } <<<`
596-
/// Note that only the NON padding fields should be explicitiy given.
596+
/// Note that only the NON padding fields should be explicitly given.
597597
/// Padding fields are automatically inserted using the type from the `SymbolTable`
598598
pub fn struct_expr(
599599
typ: Type,
600600
mut components: BTreeMap<String, Expr>,
601601
symbol_table: &SymbolTable,
602602
) -> Self {
603-
assert!(typ.is_struct_tag(), "Error in struct_expr\n\t{:?}\n\t{:?}", typ, components);
603+
assert!(
604+
typ.is_struct_tag(),
605+
"Error in struct_expr; must be given a struct_tag.\n\t{:?}\n\t{:?}",
606+
typ,
607+
components
608+
);
604609
let fields = symbol_table.lookup_fields_in_type(&typ).unwrap();
605610
let non_padding_fields: Vec<_> = fields.iter().filter(|x| !x.is_padding()).collect();
606611
assert_eq!(
607612
non_padding_fields.len(),
608613
components.len(),
609-
"Error in struct_expr\n\t{:?}\n\t{:?}",
614+
"Error in struct_expr; mismatch in number of fields and components.\n\t{:?}\n\t{:?}",
610615
typ,
611616
components
612617
);
@@ -658,7 +663,7 @@ impl Expr {
658663

659664
/// Struct initializer
660665
/// `struct foo the_foo = >>> {field1, field2, ... } <<<`
661-
/// Note that only the NON padding fields should be explicitiy given.
666+
/// Note that only the NON padding fields should be explicitly given.
662667
/// Padding fields are automatically inserted using the type from the `SymbolTable`
663668
pub fn struct_expr_from_values(
664669
typ: Type,
@@ -667,7 +672,7 @@ impl Expr {
667672
) -> Self {
668673
assert!(
669674
typ.is_struct_tag(),
670-
"Error in struct_expr\n\t{:?}\n\t{:?}",
675+
"Error in struct_expr; must be given struct_tag.\n\t{:?}\n\t{:?}",
671676
typ,
672677
non_padding_values
673678
);
@@ -676,7 +681,7 @@ impl Expr {
676681
assert_eq!(
677682
non_padding_fields.len(),
678683
non_padding_values.len(),
679-
"Error in struct_expr\n\t{:?}\n\t{:?}",
684+
"Error in struct_expr; mismatch in number of fields and values.\n\t{:?}\n\t{:?}",
680685
typ,
681686
non_padding_values
682687
);
@@ -685,7 +690,7 @@ impl Expr {
685690
.iter()
686691
.zip(non_padding_values.iter())
687692
.all(|(f, v)| f.field_typ().unwrap() == v.typ()),
688-
"Error in struct_expr\n\t{:?}\n\t{:?}",
693+
"Error in struct_expr; value type does not match field type.\n\t{:?}\n\t{:?}",
689694
typ,
690695
non_padding_values
691696
);
@@ -698,6 +703,40 @@ impl Expr {
698703
Expr::struct_expr_with_explicit_padding(typ, fields, values)
699704
}
700705

706+
/// Struct initializer
707+
/// `struct foo the_foo = >>> {field1, padding2, field3, ... } <<<`
708+
/// Note that padding fields should be explicitly given.
709+
/// This would be used when the values and padding have already been combined,
710+
/// e.g. when extracting the values out of an existing struct expr (see transformer.rs)
711+
pub fn struct_expr_from_padded_values(
712+
typ: Type,
713+
values: Vec<Expr>,
714+
symbol_table: &SymbolTable,
715+
) -> Self {
716+
assert!(
717+
typ.is_struct_tag(),
718+
"Error in struct_expr; must be given struct_tag.\n\t{:?}\n\t{:?}",
719+
typ,
720+
values
721+
);
722+
let fields = symbol_table.lookup_fields_in_type(&typ).unwrap();
723+
assert_eq!(
724+
fields.len(),
725+
values.len(),
726+
"Error in struct_expr; mismatch in number of padded fields and padded values.\n\t{:?}\n\t{:?}",
727+
typ,
728+
values
729+
);
730+
assert!(
731+
fields.iter().zip(values.iter()).all(|(f, v)| &f.typ() == v.typ()),
732+
"Error in struct_expr; value type does not match field type.\n\t{:?}\n\t{:?}",
733+
typ,
734+
values
735+
);
736+
737+
Expr::struct_expr_with_explicit_padding(typ, fields, values)
738+
}
739+
701740
/// `identifier`
702741
pub fn symbol_expression(identifier: String, typ: Type) -> Self {
703742
expr!(Symbol { identifier }, typ)
@@ -1205,6 +1244,12 @@ impl Expr {
12051244
res.overflowed.ternary(saturating_val, res.result)
12061245
}
12071246

1247+
/// `"s"`
1248+
/// only to be used when manually wrapped in `.array_to_ptr()`
1249+
pub fn raw_string_constant(s: &str) -> Self {
1250+
expr!(StringConstant { s: s.to_string() }, Type::c_char().array_of(s.len() + 1))
1251+
}
1252+
12081253
/// `"s"`
12091254
pub fn string_constant(s: &str) -> Self {
12101255
// Internally, CBMC distinguishes between the string constant, and the pointer to it.

compiler/rustc_codegen_llvm/src/gotoc/cbmc/goto_program/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod location;
88
mod stmt;
99
mod symbol;
1010
mod symbol_table;
11+
pub mod symtab_transformer;
1112
mod typ;
1213

1314
pub use builtin::BuiltinFn;

compiler/rustc_codegen_llvm/src/gotoc/cbmc/goto_program/symbol_table.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::collections::BTreeMap;
66
/// This is a typesafe implementation of the CBMC symbol table, based on the CBMC code at:
77
/// https://github.com/diffblue/cbmc/blob/develop/src/util/symbol_table.h
88
/// Since the field is kept private, with only immutable references handed out, elements can only
9-
#[derive(Debug)]
9+
#[derive(Clone, Debug)]
1010
pub struct SymbolTable {
1111
symbol_table: BTreeMap<String, Symbol>,
1212
machine_model: MachineModel,

0 commit comments

Comments
 (0)