From ae07b2624317cad71aa9818c1b9f7dd42a0e4dbf Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Fri, 16 Sep 2016 08:39:37 -0500 Subject: [PATCH] ICG exclude of class member variables now defines incorrect memory offsets in io_src #311 Added back the code that set the offset of variables with the offsetof function. This code is running by default. Any code that includes #ifndef TRICK_ICG in classes/structures will want this on. Added a flag to ICG that allows us to turn off writing of these lines. If the flag is present, ICG may write out io_src code for private/protected variables that it could not reach if an offsetof function was required. Code cannot have any #ifndef TRICK_ICG present in classes/structures for this to work. --- .../Interface_Code_Gen/ClassValues.cpp | 5 +- .../codegen/Interface_Code_Gen/ClassValues.hh | 3 +- .../Interface_Code_Gen/ClassVisitor.cpp | 4 +- .../Interface_Code_Gen/FieldDescription.cpp | 18 +++++ .../Interface_Code_Gen/FieldDescription.hh | 10 +++ .../PrintFileContents10.cpp | 67 ++++++++++++++++--- .../PrintFileContentsBase.cpp | 20 +++++- .../codegen/Interface_Code_Gen/main.cpp | 4 ++ 8 files changed, 116 insertions(+), 15 deletions(-) diff --git a/trick_source/codegen/Interface_Code_Gen/ClassValues.cpp b/trick_source/codegen/Interface_Code_Gen/ClassValues.cpp index 6d0e07b0..3b54233c 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassValues.cpp +++ b/trick_source/codegen/Interface_Code_Gen/ClassValues.cpp @@ -38,7 +38,8 @@ void ClassValues::addFieldDescription(FieldDescription * in_fdes) { field_name_to_info_map[in_fdes->getName()] = in_fdes ; } -void ClassValues::addInheritedFieldDescriptions(std::vector in_fdes, unsigned int class_offset ) { +void ClassValues::addInheritedFieldDescriptions(std::vector in_fdes, + unsigned int class_offset, bool virtual_inherited ) { // Make a copy of all of the FieldDescription variables. field_descripts.insert(field_descripts.end(), in_fdes.begin() , in_fdes.end()) ; @@ -46,7 +47,9 @@ void ClassValues::addInheritedFieldDescriptions(std::vector // Loop through the incoming inherited variable names for ( fdit = in_fdes.begin() ; fdit != in_fdes.end() ; fdit++ ) { + (*fdit)->setBaseClassOffset( class_offset ) ; (*fdit)->setInherited( true ) ; + (*fdit)->setVirtualInherited( virtual_inherited ) ; // Adds the class offset to the field offset giving the total offset to the inherited variable // The offset is stored in bits so multiply class_offset by 8. (*fdit)->addOffset( class_offset * 8 ) ; diff --git a/trick_source/codegen/Interface_Code_Gen/ClassValues.hh b/trick_source/codegen/Interface_Code_Gen/ClassValues.hh index 4fbf8d57..39234dbe 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassValues.hh +++ b/trick_source/codegen/Interface_Code_Gen/ClassValues.hh @@ -36,7 +36,8 @@ class ClassValues : public ConstructValues { /** Appends a vector of fields to field_descripts. A vector comes from adding all inherited fields at once */ - void addInheritedFieldDescriptions(std::vector, unsigned int class_offset) ; + void addInheritedFieldDescriptions(std::vector, + unsigned int class_offset, bool virtual_inherited) ; /** Gets the list of fields in this class */ std::vector getFieldDescription() ; diff --git a/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp index 31e01ff6..8bff6573 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp @@ -207,7 +207,7 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) { CXXRecordVisitor inherit_cvis(ci , cs, hsd , pa, false) ; inherit_cvis.TraverseCXXRecordDecl(static_cast(rd)) ; cval.addInheritedFieldDescriptions(inherit_cvis.get_class_data()->getFieldDescription(), - inherit_class_offset) ; + inherit_class_offset, false) ; // clear the field list in the inherited class so they are not freed when inherit_cvis // goes out of scope. inherit_cvis.get_class_data()->clearFieldDescription() ; @@ -257,7 +257,7 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) { //std::cout << " " << getFileName(ci , rd->getRBraceLoc(), hsd) << "" << std::endl ; CXXRecordVisitor inherit_cvis(ci , cs, hsd , pa, false) ; inherit_cvis.TraverseCXXRecordDecl(static_cast(rd)) ; - cval.addInheritedFieldDescriptions(inherit_cvis.get_class_data()->getFieldDescription(), inherit_class_offset) ; + cval.addInheritedFieldDescriptions(inherit_cvis.get_class_data()->getFieldDescription(), inherit_class_offset, true) ; // clear the field list in the inherited class so they are not freed when inherit_cvis goes out of scope. inherit_cvis.get_class_data()->clearFieldDescription() ; // If we are inheriting from a template specialization, don't save the inherited class. This list diff --git a/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp b/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp index 733a9148..fa8d76a0 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp +++ b/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp @@ -37,9 +37,11 @@ ut_system * FieldDescription::u_system = get_u_system() ; FieldDescription::FieldDescription( std::string in_container_class ) : container_class(in_container_class) , + base_class_offset(0) , field_offset(0) , field_width(0) , inherited(false) , + virtual_inherited(false) , units("1") , is_dashdash(false) , line_no(0) , @@ -314,6 +316,14 @@ void FieldDescription::setContainerClass(std::string in_name ) { container_class = in_name ; } +void FieldDescription::setBaseClassOffset(unsigned int in_offset) { + base_class_offset = in_offset ; +} + +unsigned int FieldDescription::getBaseClassOffset() { + return base_class_offset ; +} + void FieldDescription::setFieldOffset(unsigned int in_offset) { field_offset = in_offset ; } @@ -393,6 +403,14 @@ bool FieldDescription::isInherited() { return inherited ; } +void FieldDescription::setVirtualInherited(bool in_inherited) { + virtual_inherited = in_inherited ; +} + +bool FieldDescription::isVirtualInherited() { + return virtual_inherited ; +} + void FieldDescription::setAccess( clang::AccessSpecifier in_val ) { access = in_val ; } diff --git a/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh b/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh index 5e74fcbc..0f2a68ef 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh +++ b/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh @@ -39,6 +39,7 @@ class FieldDescription : public ConstructValues { /* Accessor functions to the data of the class */ std::string getContainerClass() ; void setContainerClass( std::string in_name ) ; + void setBaseClassOffset( unsigned int in_offset ) ; unsigned int getBaseClassOffset() ; void setFieldOffset( unsigned int in_offset ) ; unsigned int getFieldOffset() ; @@ -80,6 +81,8 @@ class FieldDescription : public ConstructValues { bool isStatic() ; void setInherited( bool yes_no ) ; bool isInherited() ; + void setVirtualInherited( bool yes_no ) ; + bool isVirtualInherited() ; void setAccess( clang::AccessSpecifier in_val ) ; clang::AccessSpecifier getAccess() ; void addOffset( unsigned int offset ) ; @@ -97,6 +100,10 @@ class FieldDescription : public ConstructValues { /** Name of the class this field is in */ std::string container_class ; + /** This is copied from the current class we are processing. It is the class offset to + be added to field offset */ + unsigned int base_class_offset ; + /** The total offset to the current field in bits */ unsigned int field_offset ; @@ -151,6 +158,9 @@ class FieldDescription : public ConstructValues { /** is this field inherited from parent class */ bool inherited ; + /** is this field virtual inherited from parent class */ + bool virtual_inherited ; + /** is an enumeration */ bool is_enum ; diff --git a/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp b/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp index 8adc2b28..076e7888 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp @@ -9,6 +9,8 @@ #include "EnumValues.hh" #include "Utilities.hh" +extern llvm::cl::opt< bool > no_offset_of ; + PrintFileContents10::PrintFileContents10() {} /** Prints the io_src header information */ @@ -157,14 +159,63 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , ClassValues * cv , unsigned int index ) { // For static variables replace the offset field with the address of the static variable - if ( fdes->isStatic() ) { - outfile << " attr" ; - printNamespaces( outfile, cv , "__" ) ; - printContainerClasses( outfile, cv , "__" ) ; - outfile << cv->getMangledTypeName() << "[" << index << "].offset = (long)(void *)&" ; - printNamespaces( outfile, cv , "::" ) ; - printContainerClasses( outfile, cv , "::" ) ; - outfile << cv->getName() << "::" << fdes->getName() << " ;\n" ; + if ( no_offset_of ) { + if ( fdes->isStatic() ) { + outfile << " attr" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; + outfile << cv->getMangledTypeName() << "[" << index << "].offset = (long)(void *)&" ; + printNamespaces( outfile, cv , "::" ) ; + printContainerClasses( outfile, cv , "::" ) ; + outfile << cv->getName() << "::" << fdes->getName() << " ;\n" ; + } + } else { + if ( fdes->isStatic() ) { + // print a special offsetof statement if this is a static + outfile << " attr" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; + outfile << cv->getMangledTypeName() << "[" << index << "].offset = (long)(void *)&" ; + printNamespaces( outfile, cv , "::" ) ; + printContainerClasses( outfile, cv , "::" ) ; + outfile << cv->getName() << "::" << fdes->getName() << " ;\n" ; + } else if ( fdes->isBitField() ) { + // else if this is a bitfield + outfile << " attr" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; + outfile << cv->getMangledTypeName() << "[" << index << "].offset = " ; + outfile << fdes->getBitFieldByteOffset() << " ;\n" ; + // All bitfield offsets are in terms of unsigned ints. + outfile << " attr" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; + outfile << cv->getMangledTypeName() << "[" << index << "].size = sizeof(unsigned int) ;\n" ; + } else if ( fdes->isVirtualInherited() ) { + // else if we have a virtually inherited class. + outfile << " attr" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; + outfile << cv->getMangledTypeName() << "[" << index << "].offset = " << fdes->getBaseClassOffset() ; + outfile << " + offsetof(" ; + outfile << fdes->getContainerClass() << "," << fdes->getName() << ") ;\n" ; + } else if ( cv->getMangledTypeName() != cv->getName() ) { + // else if we have a template type where mangled_type_name is different then name. + outfile << " attr" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; + outfile << cv->getMangledTypeName() << "[" << index << "].offset = offsetof(" ; + outfile << cv->getMangledTypeName() << "," << fdes->getName() << ") ;\n" ; + } else { + // else print an offsetof statement if this is not a special case + outfile << " attr" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; + outfile << cv->getMangledTypeName() << "[" << index << "].offset = offsetof(" ; + printNamespaces( outfile, cv , "::" ) ; + printContainerClasses( outfile, cv , "::" ) ; + outfile << cv->getMangledTypeName() << "," << fdes->getName() << ") ;\n" ; + } } if ( fdes->isSTL()) { diff --git a/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp b/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp index 8095c4e8..1f9b6764 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp @@ -6,11 +6,15 @@ #include #include +#include "llvm/Support/CommandLine.h" + #include "PrintFileContentsBase.hh" #include "FieldDescription.hh" #include "ClassValues.hh" #include "EnumValues.hh" +extern llvm::cl::opt< bool > no_offset_of ; + PrintFileContentsBase::PrintFileContentsBase() {} // provide empty default implementation of these routines. @@ -74,7 +78,19 @@ void PrintFileContentsBase::print_close_extern_c(std::ofstream & outfile) { */ bool PrintFileContentsBase::determinePrintAttr( ClassValues * c , FieldDescription * fdes ) { if ( fdes->getTypeName().compare("void") and fdes->getIO() != 0 and fdes->getEnumString().compare("TRICK_VOID")) { - if ( fdes->isStatic() ) { + if ( no_offset_of ) { + if ( fdes->isStatic() ) { + 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 { + return true ; + } + } else { if ( fdes->isInherited() ) { return ((c->getHasInitAttrFriend() && fdes->getAccess() == clang::AS_protected) || (fdes->getAccess() == clang::AS_public)) ; @@ -82,8 +98,6 @@ bool PrintFileContentsBase::determinePrintAttr( ClassValues * c , FieldDescripti return (c->getHasInitAttrFriend() || (fdes->getAccess() == clang::AS_public)) ; } - } else { - return true ; } } return false ; diff --git a/trick_source/codegen/Interface_Code_Gen/main.cpp b/trick_source/codegen/Interface_Code_Gen/main.cpp index a93292ac..c236d553 100644 --- a/trick_source/codegen/Interface_Code_Gen/main.cpp +++ b/trick_source/codegen/Interface_Code_Gen/main.cpp @@ -43,6 +43,10 @@ llvm::cl::list< std::string > input_file_names(llvm::cl::Positional, llvm::cl::d 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")) ; void ICG_version() {