PiJoules wrote:

> I'm not sure we can just unconditionally call the destructor. We need to 
> ensure the constructor runs first. If a constructor throws an exception or 
> calls exit(), not all constructors will run before we start cleaning up. This 
> works out naturally with atexit... but if you use global_dtors, I think you 
> end up calling the destructor on an uninitialized object.

Ah yeah you're right. I didn't consider this. Since we're willing to make ABI 
changes, my colleague @mysterymath came up with another idea that might help 
address this:

1. Instrument in a dso_local global counter that indicates how many ctors we 
successfully called.
2. After each successful ctor call for each global, increment the counter by 1.
3. Inside the function that would be added to `llvm.global_dtors` and would 
invoke all the dtors, have a global switch that jumps to the appropriate case 
based on the number of correctly initialized globals. This would be akin to 
Duff's device.

```
// Given globals:
//
//   A first;
//   A second;
//   A third;

static int SuccessfulInits = 0;

void module_ctor() {
  construct_A(&first);
  SuccessfulInits++;

  construct_A(&second);
  SuccessfulInits++;

  construct_A(&third);
  SuccessfulInits++;
}

void module_dtor() {
  switch (SuccessfulInits) {
    case 3: destruct_A(&third);  // fallthrough
    case 2: destruct_A(&second);  // falthrough
    case 1: destruct_A(&first);  // fallthrough
    case 0: break;  // No destructors invoked
  }
}
```

An alternative approach might be using a lookup table with a decrementing 
pointer:

```
void __dtor_first() {
  destruct_A(&first);
}

void __dtor_second() {
  destruct_A(&second);
}


void __dtor_third() {
  destruct_A(&third);
}

void (*dtor_list[])() = {__dtor_first, __dtor_second, __dtor_third};
void (*dtor_ptr)() = dtor_list;

void module_ctor() {
  construct_A(&first);
  dtor_ptr++;

  construct_A(&second);
  dtor_ptr++;

  construct_A(&third);
  dtor_ptr++;
}

void module_dtor() {
  while (dtor_ptr != dtor_list) {
    (--dtor_ptr)();  // Invoke one of the functions in dtor_list
  }
}
```

I probably won't implement these here or continue with the patch, but these are 
some ideas we had.


> Also, I'm not sure objects are destroyed in the correct order.

Do you mean for the test case I added? I think they should be destroyed in 
reverse order.

https://github.com/llvm/llvm-project/pull/115788
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to