Changeset f1791a4


Ignore:
Timestamp:
Oct 15, 2020, 9:41:31 PM (4 years ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
afe2939
Parents:
0b18db7
Message:

Expanding earlier #182 fix to another case of the same issue. Fixes #224?

There is now a reusable helper function addDataSectonAttribute that applies the fix to an ObjectDecl? when we realize it needs it. Test const-init is expanded with case of #224.

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixGlobalInit.cc

    r0b18db7 rf1791a4  
    112112                        } // if
    113113                        if ( Statement * ctor = ctorInit->ctor ) {
    114                                 // Translation 1: Add this attribute on the global declaration:
    115                                 //    __attribute__((section (".data#")))
    116                                 // which makes gcc put the global in the data section,
    117                                 // so that the global is writeable (via a const cast) in the init function.
    118                                 // The trailing # is an injected assembly comment, to suppress the "a" in
    119                                 //    .section .data,"a"
    120                                 //    .section .data#,"a"
    121                                 // to avoid assembler warning "ignoring changed section attributes for .data"
    122                                 Type *strLitT = new PointerType( Type::Qualifiers( ),
    123                                         new BasicType( Type::Qualifiers( ), BasicType::Char ) );
    124                                 std::list< Expression * > attr_params;
    125                                 attr_params.push_back(
    126                                         new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
    127                                 objDecl->attributes.push_back(new Attribute("section", attr_params));
    128                                 // Translation 2: Move the initizliation off the global declaration,
    129                                 // into the startup function.
     114                                addDataSectonAttribute( objDecl );
    130115                                initStatements.push_back( ctor );
    131116                                objDecl->init = nullptr;
  • src/InitTweak/FixInit.cc

    r0b18db7 rf1791a4  
    802802                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    803803                                        if ( objDecl->get_storageClasses().is_static ) {
     804
     805                                                // The ojbect needs to go in the data section, regardless of dtor complexity below.
     806                                                // The attribute works, and is meant to apply, both for leaving the static local alone,
     807                                                // and for hoisting it out as a static global.
     808                                                addDataSectonAttribute( objDecl );
     809
    804810                                                // originally wanted to take advantage of gcc nested functions, but
    805811                                                // we get memory errors with this approach. To remedy this, the static
  • src/InitTweak/InitTweak.cc

    r0b18db7 rf1791a4  
    10551055                return isCopyFunction( decl, "?{}" );
    10561056        }
     1057
     1058        void addDataSectonAttribute( ObjectDecl * objDecl ) {
     1059                Type *strLitT = new PointerType( Type::Qualifiers( ),
     1060                        new BasicType( Type::Qualifiers( ), BasicType::Char ) );
     1061                std::list< Expression * > attr_params;
     1062                attr_params.push_back(
     1063                        new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
     1064                objDecl->attributes.push_back(new Attribute("section", attr_params));
     1065        }
     1066
    10571067}
  • src/InitTweak/InitTweak.h

    r0b18db7 rf1791a4  
    103103        bool isConstExpr( Initializer * init );
    104104
     105        /// Modifies objDecl to have:
     106        ///    __attribute__((section (".data#")))
     107        /// which makes gcc put the declared variable in the data section,
     108        /// which is helpful for global constants on newer gcc versions,
     109        /// so that CFA's generated initialization won't segfault when writing it via a const cast.
     110        /// The trailing # is an injected assembly comment, to suppress the "a" in
     111        ///    .section .data,"a"
     112        ///    .section .data#,"a"
     113        /// to avoid assembler warning "ignoring changed section attributes for .data"
     114        void addDataSectonAttribute( ObjectDecl * objDecl );
     115
    105116        class InitExpander_old {
    106117        public:
  • tests/.expect/const-init.txt

    r0b18db7 rf1791a4  
    1 done
     1almost done
     2dtor
  • tests/const-init.cfa

    r0b18db7 rf1791a4  
    1616/*
    1717
    18 This test shows non-crashing of generated code for constants with interesting initizers.
     18These tests show non-crashing of generated code for constants with interesting initializers.
    1919The potential for these to crash is compiler dependent.
    2020
    2121There are two cases:
    22 1. static constants in one compilation unit (tested here)
     221. static constants in one compilation unit (tested here, in a few sub-cases)
    23232. extern constants across compilation units (tested by libcfa being loadable, specifically
    24    the constant declarations in libcfa/src/limits.cfa, which almost every test exercises,
     24   the constant definitions in libcfa/src/limits.cfa, which almost every test exercises,
    2525   including "hello;" but notably, the "limits" test does not exercise it because that test
    2626   is compile-only)
     
    3737GCC-10 on Ubuntu 20.04    Has crashed      Has crashed
    3838
    39 For this test case to fail, with most other tests passing, would be a situation only ever
     39For this test to fail, with most other tests passing, would be a situation only ever
    4040observed with GCC-8.
    4141
    4242*/
    4343
     44// initailized by generated function, called before main
    4445static const char foo = -1;
    4546
     47struct thing{};
     48void ^?{}( thing & ) { printf("dtor\n"); }
     49
    4650int main() {
    47     printf("done\n");
     51    // foo is already initialized
     52
     53    // no dtor => stays a (static) local, initialized here
     54    static const char bar = -1;
     55
     56    // has dtor => becomes a global, ctor called here, dtor called at exit
     57    static const thing it;
     58
     59    printf("almost done\n");
    4860}
Note: See TracChangeset for help on using the changeset viewer.