ICG exclude of class member variables now defines incorrect memory offsets in io_src #311

This changes back the default behavior to not use offsetof in io_src code.
Added a flag to ICG, -c or --compat15, to globally generate offsetof statements.
Added an ENV variable that can be used to generate offsetof statements by file or directory.
Added in a warning if classes parsed at ICG time are different in size than at runtime.
This commit is contained in:
Alex Lin 2016-10-21 09:30:55 -05:00
parent 5484e39f11
commit f1cbacd646
13 changed files with 233 additions and 125 deletions

View File

@ -193,7 +193,7 @@ endif
# header files.
.PHONY: icg_sim_serv
icg_sim_serv: $(ICG_EXE)
${TRICK_HOME}/bin/trick-ICG -s -m -n ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_HOME}/include/trick/files_to_ICG.hh
${TRICK_HOME}/bin/trick-ICG -s -m ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_HOME}/include/trick/files_to_ICG.hh
# 1.1.1.4.1 Build the Interface Code Generator (ICG) executable.
$(ICG_EXE) :

View File

@ -0,0 +1,101 @@
/**
* Provides a map of class/struct name and calculated size difference between ICG and runtime
*/
#ifndef CLASSSIZECHECK_HH
#define CLASSSIZECHECK_HH
#include <map>
#include <string>
#include <iostream>
#include "trick/attributes.h"
#include "trick/AttributesMap.hh"
namespace Trick {
/**
* These maps stores all the attributes by class/struct/enum name
* So these 2 classes could inherit from a template or something fancy, but
* they are so simple I decided to leave them separate.
*/
struct ClassSizeDiffInfo {
int diff ;
std::string file_name ;
ClassSizeDiffInfo( int in_diff , std::string in_file_name ) :
diff(in_diff) , file_name(in_file_name) {}
} ;
class ClassSizeCheck {
public:
/**
* Returns a pointer to the singleton Trick::ClassSizeCheck instance.
* @return A pointer to Trick::ClassSizeCheck
*/
static ClassSizeCheck * class_size_check() {
if ( pInstance == NULL ) {
pInstance = new Trick::ClassSizeCheck() ;
}
return pInstance ;
}
static void reset_instance() {
delete pInstance ;
pInstance = NULL ;
}
ClassSizeCheck() {} ;
~ClassSizeCheck() {} ;
/**
* Adds a type and the corresponding attributes
* @param type The name of the type.
* @param attr Pointer to the attributes.
*/
void add_diff( std::string type , ClassSizeDiffInfo diff_info ) {
name_to_diff.insert(std::pair<std::string,ClassSizeDiffInfo>(type,diff_info)) ;
}
/**
* Prints all the types that have a difference in size
*/
void print_nonzero_diffs() {
std::map<std::string, ClassSizeDiffInfo>::iterator it ;
for ( it = name_to_diff.begin() ; it != name_to_diff.end() ; it++ ) {
int curr_diff = it->second.diff ;
ATTRIBUTES * attr = Trick::AttributesMap::attributes_map()->get_attr(it->first) ;
unsigned int ii ;
for ( ii = 0 ; attr[ii].name[0] != '\0'; ii++ ) {
// Look for structured types that are not pointers
std::map<std::string, ClassSizeDiffInfo>::iterator search_it ;
if ( (attr[ii].type == TRICK_STRUCTURED) and
((attr[ii].num_index == 0) or (attr[ii].index[attr[ii].num_index-1].size != 0)) and
((search_it = name_to_diff.find(attr[ii].type_name)) != name_to_diff.end())
) {
int num = 1 ;
int jj ;
// Calculate total number of structs in the variable
for ( jj = 0 ; jj < attr[ii].num_index ; jj++ ) {
num *= attr[ii].index[jj].size ;
}
// Subtract the combined difference
curr_diff -= num * search_it->second.diff ;
}
}
if ( curr_diff != 0 ) {
std::cerr << it->first << " ICG size and runtime size do not match" << std::endl ;
std::cerr << "Search for \"#ifndef TRICK_ICG\" within " << it->second.file_name << std::endl ;
}
}
}
private:
std::map<std::string, ClassSizeDiffInfo> name_to_diff ;
static ClassSizeCheck * pInstance ;
} ;
}
#endif

View File

@ -88,6 +88,7 @@ sub gte (@) {
$def{"TRICK_HOME"} = "$trick_home" ;
$def{"TRICK_HOST_CPU_USER_SUFFIX"} = "" ;
$def{"TRICK_ICGFLAGS"} = "" ;
$def{"TRICK_ICG_COMPAT15"} = "" ;
$def{"TRICK_ICG_NOCOMMENT"} = "" ;
$def{"TRICK_ICG_EXCLUDE"} = "" ;
$def{"TRICK_SWIG_EXCLUDE"} = "" ;

View File

@ -52,6 +52,7 @@ PURPOSE:
#include \"trick/attributes.h\"
#include \"trick/populate_attribute_maps.hh\"
#include \"trick/ClassSizeCheck.hh\"
#include \"trick/SimObject.hh\"
#include \"trick/JobData.hh\"
@ -178,6 +179,8 @@ PURPOSE:
#---------------------------
# Memory Init
print S_SOURCE "Trick::ClassSizeCheck * Trick::ClassSizeCheck::pInstance = NULL ;\n" ;
print S_SOURCE "\n/* Memory Init */\n" ,
"void memory_init( void ) {\n\n" ;
@ -220,6 +223,8 @@ PURPOSE:
print S_SOURCE $$sim_ref{create_connections} ;
print S_SOURCE "\n" ,
" " x 4 , "Trick::ClassSizeCheck::class_size_check()->print_nonzero_diffs() ;\n" ,
" " x 4 , "Trick::ClassSizeCheck::reset_instance() ;\n" ,
" " x 4 , "return ;\n" ,
"}\n\n" ;

View File

@ -40,6 +40,7 @@ export TRICK_CXXFLAGS
export TRICK_LDFLAGS
export TRICK_SFLAGS
export TRICK_EXCLUDE
export TRICK_ICG_COMPAT15
export TRICK_ICG_EXCLUDE
export TRICK_ICG_NOCOMMENT
export TRICK_SWIG_EXCLUDE

View File

@ -8,7 +8,7 @@
#ifdef __APPLE__
#include "llvm/Support/CommandLine.h"
extern llvm::cl::opt< bool > no_offset_of ;
extern llvm::cl::opt< bool > global_compat15 ;
#endif
ClassValues::ClassValues() :
@ -16,7 +16,8 @@ ClassValues::ClassValues() :
is_pod(false) ,
is_abstract(false) ,
has_default_constructor(false) ,
has_public_destructor(false)
has_public_destructor(false),
compat15(false)
{}
ClassValues::~ClassValues() {
@ -30,7 +31,7 @@ void ClassValues::addFieldDescription(FieldDescription * in_fdes) {
field_descripts.push_back(in_fdes) ;
#ifdef __APPLE__
if ( no_offset_of ) {
if ( !global_compat15 and !compat15 ) {
#else
{
#endif
@ -57,7 +58,7 @@ void ClassValues::addInheritedFieldDescriptions(std::vector<FieldDescription *>
std::vector<FieldDescription *>::iterator fdit ;
// Loop through the incoming inherited variable names
#ifdef __APPLE__
if ( no_offset_of ) {
if ( !global_compat15 and !compat15 ) {
#else
{
#endif
@ -203,6 +204,14 @@ bool ClassValues::isPOD() {
return is_pod ;
}
void ClassValues::setSize(unsigned int in_size) {
size = in_size ;
}
unsigned int ClassValues::getSize() {
return size ;
}
void ClassValues::setAbstract(bool in_val) {
is_abstract = in_val ;
}
@ -266,6 +275,14 @@ std::string ClassValues::getFullyQualifiedMangledTypeName() {
return oss.str() ;
}
void ClassValues::setCompat15(bool in_val) {
compat15 = in_val ;
}
bool ClassValues::isCompat15() {
return compat15 ;
}
void ClassValues::print_namespaces(std::ostream & os, const char * delimiter) {
unsigned int ii ;
for ( ii = 0 ; ii < namespaces.size() ; ii++ ) {

View File

@ -68,6 +68,8 @@ class ClassValues : public ConstructValues {
bool getHasInitAttrFriend() ;
void setPOD(bool in_val) ;
bool isPOD() ;
void setSize(unsigned int size) ;
unsigned int getSize() ;
void setAbstract(bool in_val) ;
bool isAbstract() ;
void setHasDefaultConstructor(bool in_val) ;
@ -78,6 +80,8 @@ class ClassValues : public ConstructValues {
void setMangledTypeName( std::string in_val ) ;
std::string getMangledTypeName() ;
std::string getFullyQualifiedMangledTypeName() ;
void setCompat15(bool in_val) ;
bool isCompat15() ;
void print_namespaces(std::ostream & os, const char * delimiter) ;
@ -102,6 +106,9 @@ class ClassValues : public ConstructValues {
/** Is this class plain old data? */
bool is_pod ;
/** Size of class in bytes */
unsigned int size ;
/** Is this class abstract? */
bool is_abstract ;
@ -113,6 +120,10 @@ class ClassValues : public ConstructValues {
/** Mangled type name. Templates will have a mangled_type_name. */
std::string mangled_type_name ;
/** Generate Trick 15 compatible io_src code */
bool compat15 ;
} ;
#endif

View File

@ -158,6 +158,8 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) {
cs.hasICGNo(header_file_name) ) {
return false ;
}
cval.setCompat15(hsd.isPathInCompat15(rp)) ;
free(rp) ;
// If this class needs a default constructor, then the complier will generate one and we can call it.
if ( rec->needsImplicitDefaultConstructor() ) {
@ -183,6 +185,8 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) {
cval.setName(rec->getNameAsString()) ;
cval.setPOD(rec->isPOD()) ;
cval.setSize(rec->getASTContext().getASTRecordLayout(rec).getSize().getQuantity()) ;
clang::CXXRecordDecl::base_class_iterator bcii ;
//std::cout << "parsing " << cval.getName() << std::endl ;

View File

@ -139,12 +139,12 @@ void HeaderSearchDirs::AddTrickSearchDirs () {
}
}
void HeaderSearchDirs::AddICGExcludeDirs () {
void HeaderSearchDirs::AddDirsAndFiles(std::string env_var, std::vector<std::string> & var_list) {
char * trick_icg_exclude = getenv("TRICK_ICG_EXCLUDE") ;
char * env_var_contents = getenv(env_var.c_str()) ;
if( trick_icg_exclude != NULL ) {
std::string s = std::string(trick_icg_exclude) ;
if( env_var_contents != NULL ) {
std::string s = std::string(env_var_contents) ;
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, ':')) {
@ -155,84 +155,13 @@ void HeaderSearchDirs::AddICGExcludeDirs () {
std::ifstream file_or_dir(resolved_path) ;
file_or_dir.seekg(0, std::ios::end) ;
if ( !file_or_dir.good()) {
icg_exclude_dirs.push_back(std::string(resolved_path) + std::string("/"));
var_list.push_back(std::string(resolved_path) + std::string("/"));
} else {
icg_exclude_dirs.push_back(std::string(resolved_path));
var_list.push_back(std::string(resolved_path));
}
} else {
std::cout << bold(color(WARNING, "Warning")) << " Cannot find TRICK_ICG_EXCLUDE directory " << quote(bold(item)) << std::endl ;
}
}
}
}
}
void HeaderSearchDirs::AddExcludeDirs () {
char * trick_exclude = getenv("TRICK_EXCLUDE") ;
if( trick_exclude != NULL ) {
std::string s = std::string(trick_exclude) ;
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, ':')) {
item = trim(item) ;
if ( ! item.empty() ) {
char * resolved_path = realpath(item.c_str(), NULL) ;
if ( resolved_path ) {
std::ifstream file_or_dir(resolved_path) ;
file_or_dir.seekg(0, std::ios::end) ;
if ( !file_or_dir.good()) {
exclude_dirs.push_back(std::string(resolved_path) + std::string("/"));
} else {
exclude_dirs.push_back(std::string(resolved_path));
}
} else {
std::cout << bold(color(WARNING, "Warning")) << " Cannot find TRICK_EXCLUDE directory " << quote(bold(item)) << std::endl ;
}
}
}
}
}
void HeaderSearchDirs::AddExtLibDirs () {
char * trick_ext_lib_dirs = getenv("TRICK_EXT_LIB_DIRS") ;
if( trick_ext_lib_dirs != NULL ) {
std::string s = std::string(trick_ext_lib_dirs) ;
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, ':')) {
item = trim(item) ;
if ( ! item.empty() ) {
char * resolved_path = realpath(item.c_str(), NULL) ;
if ( resolved_path ) {
ext_lib_dirs.push_back(std::string(resolved_path) + std::string("/"));
} else {
std::cout << bold(color(WARNING, "Warning")) << " Cannot find TRICK_EXT_LIB_DIRS directory " << quote(bold(item)) << std::endl ;
}
}
}
}
}
void HeaderSearchDirs::AddICGNoCommentDirs () {
char * trick_icg_nocomment = getenv("TRICK_ICG_NOCOMMENT") ;
if( trick_icg_nocomment != NULL ) {
std::string s = std::string(trick_icg_nocomment) ;
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, ':')) {
item = trim(item) ;
if ( ! item.empty() ) {
char * resolved_path = realpath(item.c_str(), NULL) ;
if ( resolved_path ) {
icg_nocomment_dirs.push_back(std::string(resolved_path) + std::string("/"));
} else {
std::cout << bold(color(WARNING, "Warning")) << " Cannot find TRICK_ICG_NOCOMMENT directory " << quote(bold(item)) << std::endl ;
std::cout << bold(color(WARNING, "Warning")) << " Cannot find " <<
env_var << " directory " << quote(bold(item)) << std::endl ;
}
}
}
@ -260,11 +189,22 @@ void HeaderSearchDirs::addSearchDirs ( std::vector<std::string> & include_dirs )
AddUserSearchDirs( include_dirs ) ;
AddTrickSearchDirs() ;
AddCompilerBuiltInSearchDirs() ;
AddExcludeDirs() ;
AddICGExcludeDirs() ;
AddExtLibDirs() ;
AddICGNoCommentDirs() ;
ApplyHeaderSearchOptions() ;
AddDirsAndFiles("TRICK_ICG_EXCLUDE", icg_exclude_dirs) ;
AddDirsAndFiles("TRICK_EXCLUDE", exclude_dirs) ;
AddDirsAndFiles("TRICK_EXT_LIB_DIRS", ext_lib_dirs) ;
AddDirsAndFiles("TRICK_ICG_NOCOMMENT", icg_nocomment_dirs) ;
char * compat15_contents = getenv("TRICK_ICG_COMPAT15") ;
if ( compat15_contents != NULL ) {
std::string s(compat15_contents) ;
if ( s.length() > 0 ) {
s += std::string(":./S_source.hh") ;
setenv("TRICK_ICG_COMPAT15",s.c_str(),1) ;
}
}
AddDirsAndFiles("TRICK_ICG_COMPAT15", compat15_dirs) ;
}
bool HeaderSearchDirs::isPathInUserDir (const std::string& in_dir ) {
@ -357,6 +297,18 @@ bool HeaderSearchDirs::isPathInICGNoComment (const std::string& in_file ) {
return false ;
}
bool HeaderSearchDirs::isPathInCompat15 (const std::string& in_dir ) {
std::vector<std::string>::iterator vit ;
for ( vit = compat15_dirs.begin() ; vit != compat15_dirs.end() ; vit++ ) {
if ( ! in_dir.compare(0, (*vit).size(), (*vit))) {
return true ;
}
}
return false ;
}
std::string HeaderSearchDirs::getPathInExclude (const std::string& in_dir ) {
std::vector<std::string>::iterator vit ;

View File

@ -75,6 +75,13 @@ class HeaderSearchDirs {
*/
bool isPathInICGNoComment (const std::string& path) ;
/** Returns true if directory is a subdirectory of a compatible 15 directory
in the TRICK_ICG_COMPAT15 environment variable.
@param path = directory path to be checked
@return true = path is in a system directory, false = not in system directory.
*/
bool isPathInCompat15 (const std::string& path) ;
/** Returns the TRICK_EXCLUDE directory that contains the path argument.
@param path = path to be checked
@return string from TRICK_EXCLUDE that contains the path.
@ -126,17 +133,8 @@ class HeaderSearchDirs {
/** Adds ${TRICK_HOME}/trick_source to the search directories */
void AddTrickSearchDirs () ;
/** Create list of EXCLUDE directories */
void AddExcludeDirs () ;
/** Create list of ICG_EXCLUDE directories */
void AddICGExcludeDirs () ;
/** Create list of EXT_LIB_DIRS directories */
void AddExtLibDirs () ;
/** Create list of ICG_NOCOMMENT directories */
void AddICGNoCommentDirs () ;
/** Create list of directories */
void AddDirsAndFiles(std::string env_var, std::vector<std::string> & var_list ) ;
/** Apply all search directories to the preprocessor. */
void ApplyHeaderSearchOptions () ;
@ -153,6 +151,9 @@ class HeaderSearchDirs {
/** List of directoris to exclude comments from the TRICK_ICG_NOCOMMENT environment variable */
std::vector<std::string> icg_nocomment_dirs ;
/** List of directoris to write offsetof lines compatible with Trick 15 and earlier */
std::vector<std::string> compat15_dirs ;
/** Map of file names to in icg_nocomment_dir used as a cache */
std::map< std::string , bool > icg_nocomment_files ;
} ;

View File

@ -7,7 +7,7 @@
#include "EnumValues.hh"
#include "Utilities.hh"
extern llvm::cl::opt< bool > no_offset_of ;
extern llvm::cl::opt< bool > global_compat15 ;
PrintFileContents10::PrintFileContents10() {}
@ -35,6 +35,7 @@ void PrintFileContents10::printIOHeader(std::ostream & ostream , std::string hea
"#include \"trick/MemoryManager.hh\"\n"
"#include \"trick/attributes.h\"\n"
"#include \"trick/parameter_types.h\"\n"
"#include \"trick/ClassSizeCheck.hh\"\n"
"#include \"trick/UnitsMap.hh\"\n"
"#include \"trick/checkpoint_stl.hh\"\n"
"#include \"" << header_file_name << "\"\n"
@ -149,17 +150,7 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ostream & ostream ,
ClassValues * cv , unsigned int index ) {
// For static variables replace the offset field with the address of the static variable
if ( no_offset_of ) {
if ( fdes->isStatic() ) {
ostream << " attr" ;
printNamespaces( ostream, cv , "__" ) ;
printContainerClasses( ostream, cv , "__" ) ;
ostream << cv->getMangledTypeName() << "[" << index << "].offset = (long)(void *)&" ;
printNamespaces( ostream, cv , "::" ) ;
printContainerClasses( ostream, cv , "::" ) ;
ostream << cv->getName() << "::" << fdes->getName() << " ;\n" ;
}
} else {
if ( global_compat15 or cv->isCompat15()) {
if ( fdes->isStatic() ) {
// print a special offsetof statement if this is a static
ostream << " attr" ;
@ -206,6 +197,16 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ostream & ostream ,
printContainerClasses( ostream, cv , "::" ) ;
ostream << cv->getMangledTypeName() << "," << fdes->getName() << ") ;\n" ;
}
} else {
if ( fdes->isStatic() ) {
ostream << " attr" ;
printNamespaces( ostream, cv , "__" ) ;
printContainerClasses( ostream, cv , "__" ) ;
ostream << cv->getMangledTypeName() << "[" << index << "].offset = (long)(void *)&" ;
printNamespaces( ostream, cv , "::" ) ;
printContainerClasses( ostream, cv , "::" ) ;
ostream << cv->getName() << "::" << fdes->getName() << " ;\n" ;
}
}
if ( fdes->isSTL()) {
@ -299,6 +300,21 @@ void PrintFileContents10::print_init_attr_func( std::ostream & ostream , ClassVa
ostream << " typedef " << cv->getName() << " " << cv->getMangledTypeName() << " ;\n\n" ;
}
if ( !global_compat15 and !cv->isCompat15()) {
ostream << " if ( sizeof(" ;
printNamespaces( ostream, cv , "::" ) ;
printContainerClasses( ostream, cv , "::" ) ;
ostream << cv->getName() << ") > " << cv->getSize() << ") {\n" ;
ostream << " Trick::ClassSizeCheck::class_size_check()->add_diff(\"" ;
printNamespaces( ostream, cv , "::" ) ;
printContainerClasses( ostream, cv , "::" ) ;
ostream << cv->getName() << "\" , Trick::ClassSizeDiffInfo((sizeof(" ;
printNamespaces( ostream, cv , "::" ) ;
printContainerClasses( ostream, cv , "::" ) ;
ostream << cv->getName() << ") - " << cv->getSize() << ") , \"" << cv->getFileName() << "\")) ;\n" ;
ostream << " }\n" ;
}
unsigned int ii = 0 ;
for ( fit = cv->field_begin() ; fit != cv->field_end() ; fit++ ) {
if ( determinePrintAttr(cv , *fit) ) {

View File

@ -12,7 +12,7 @@
#include "ClassValues.hh"
#include "EnumValues.hh"
extern llvm::cl::opt< bool > no_offset_of ;
extern llvm::cl::opt< bool > global_compat15 ;
PrintFileContentsBase::PrintFileContentsBase() {}
@ -77,7 +77,15 @@ void PrintFileContentsBase::print_close_extern_c(std::ostream & ostream) {
*/
bool PrintFileContentsBase::determinePrintAttr( ClassValues * c , FieldDescription * fdes ) {
if ( fdes->getTypeName().compare("void") and fdes->getIO() != 0 and fdes->getEnumString().compare("TRICK_VOID")) {
if ( no_offset_of ) {
if ( global_compat15 or c->isCompat15()) {
if ( fdes->isInherited() ) {
return ((c->getHasInitAttrFriend() && fdes->getAccess() == clang::AS_protected)
|| (fdes->getAccess() == clang::AS_public)) ;
} else {
return (c->getHasInitAttrFriend()
|| (fdes->getAccess() == clang::AS_public)) ;
}
} else {
if ( fdes->isStatic() ) {
if ( fdes->isInherited() ) {
return ((c->getHasInitAttrFriend() && fdes->getAccess() == clang::AS_protected)
@ -89,14 +97,7 @@ bool PrintFileContentsBase::determinePrintAttr( ClassValues * c , FieldDescripti
} else {
return true ;
}
} else {
if ( fdes->isInherited() ) {
return ((c->getHasInitAttrFriend() && fdes->getAccess() == clang::AS_protected)
|| (fdes->getAccess() == clang::AS_public)) ;
} else {
return (c->getHasInitAttrFriend()
|| (fdes->getAccess() == clang::AS_public)) ;
}
}
}
return false ;

View File

@ -44,10 +44,8 @@ llvm::cl::list< std::string > sink(llvm::cl::Sink, llvm::cl::ZeroOrMore) ;
llvm::cl::list< std::string > pre_compiled_headers("include", llvm::cl::Prefix, llvm::cl::desc("pre-compiled headers"),
llvm::cl::value_desc("pre_compiled_headers")) ;
llvm::cl::opt< bool > no_offset_of ("n", llvm::cl::desc("Do not print the offsetof calculations in attributes")) ;
llvm::cl::alias no_offset_of_alias ("no-offset-of" , llvm::cl::desc("Alias for -n") , llvm::cl::aliasopt(no_offset_of)) ;
//llvm::cl::opt< bool > show_units ("u", llvm::cl::desc("List recognized units")) ;
llvm::cl::opt< bool > global_compat15 ("c", llvm::cl::desc("Print the offsetof calculations in attributes")) ;
llvm::cl::alias compat15_alias ("compat15" , llvm::cl::desc("Alias for -c") , llvm::cl::aliasopt(global_compat15)) ;
void ICG_version() {
std::cout << "Trick Interface Code Generator (trick-ICG) " << TRICK_VERSION << std::endl ;