Conversation
|
Thanks for your pull request and interest in making D better, @rikkimax! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + dmd#22824" |
|
|
|
This looks like something that could be handled with no language support if there was a drtbeg.o/drtend.o object that the compiler passes to the linker to make section boundaries for declared |
No, the sections themselves are user-provided. You don't know what exists with multi-step compilation which is the norm for D. |
|
Also start + end symbols only need to exist for Windows, the rest are all special ones that don't require actual global variables associated with them. They can be emitted wherever the iteration is. So they are a non-issue. Given the constraints on mutability, types, |
|
import core.stdc.stdio;
import core.attribute;
template getSectionStart(string name)
{
@section(name ~ "$A") __gshared int specialStart = 1; // moved into .data by dmd
void* getSectionStart()
{
return &specialStart;
}
}
void* getSectionEnd(string name)()
{
@section(name ~ "$Z") __gshared int specialEnd; // moved into .bss by dmd
return &specialEnd;
}
@section(".special$B") __gshared int specialGlobal;
void* foo()
{
@section(".special$B") __gshared int specialFoo;
return &specialFoo;
}
void main()
{
@section(".special$B") __gshared int specialMain;
printf("specialStart @ %p\n", getSectionStart!".special");
printf("specialGlobal @ %p\n", &specialGlobal);
printf("specialFoo @ %p\n", foo());
printf("specialMain @ %p\n", &specialMain);
printf("specialEnd @ %p\n", getSectionEnd!".special");
}It does not work with dmd from master, though. AFAICT |
I implemented the section attribute in dmd. Yes it works in templates, however this does not do what is being wanted here, nor does it give the reliability. I also want to emphasise, I want to be able to append to the list using CTFE, and have it end up in the appropriete root module. |
Not in this example. The section is created, but the variables are still in data/bss:
What do you mean by "CTFE appending"? Can it do more than Can you add a test case (or provide a use case) that does something that is not possible yet. |
It should be working: dmd/compiler/test/runnable/sectiondefs.d Line 46 in ca244ef The code isn't checking for things like templates. And yes I was doing objdump to verify symbols going into sections, and they are iterating correctly.
Yes. You are not limited to one per declaration. It works in loops as a statement. But most importantly, anyone can use this and get it right. You don't need to know any platform specific details (which there are a bunch). There are fun stuff like only pointers can go into a linker list, I can hide all these awful details.
Note: no tests are implemented yet, for this PR its not going to be fun to actually get it into the test runner. I have test code locally running on Windows. import second;
import third;
@MyUDA(2)
@MyUDA(9)
@MyUDA(1)
void main() {
import core.stdc.stdio;
foreach(ref v; myInts) {
printf("I got: %d\n", v);
v++;
}
foreach(v; myInts) {
printf("I mutated: %d\n", v);
}
foreach(v; myObjects) {
printf("got object %p\n", v);
}
foreach(v; myIntefaces) {
printf("got interface %p\n", v);
}
}
static assert(() { myInts ~= 6; return true; }());
static assert(() { myObjects ~= new Object; return true; }());
static assert(() { myIntefaces ~= new CI; return true; }());module second;
import third;
struct MyUDA {
this(int val) {
if (__ctfe)
myInts ~= val;
}
}module third;
import core.attribute;
__linkerlist!int myInts;
__linkerlist!Object myObjects;
__linkerlist!I myIntefaces;
interface I {}
class CI : I {}I've had 12 years to think this feature over, this is the feature I needed when I was working on a web service framework. |
|
So I guess your main use case is generating runtime data from UDAs. Modifying global state by CTFE is unprecedented in D, though, and likely to cause trouble (evaluation order, speculative compilation, etc). Good luck getting this approved. With a few things fixed with section emission (segment overwritten by .bss/.data in COMDATs, section name length > 8 working differently), this adds data for each UDA: import core.stdc.stdio;
import core.attribute;
template sectionStart(string name)
{
@section(name ~ "$A") __gshared int sectionStart = 0; // should be COMDAT
}
template sectionEnd(string name)
{
@section(name ~ "$Z") __gshared int sectionEnd = 0; // should be COMDAT
}
@section(".spec$B") __gshared int specialGlobal = 11;
struct MyUda(int n, string mod = __MODULE__, int line = __LINE__)
{
@section(".spec$B") __gshared static int value = n; // a COMDAT with LDC, but not with DMD
}
@MyUda!2()
@MyUda!9()
@MyUda!1()
void main()
{
@section(".spec$B") __gshared int specialMain = 12;
auto start = §ionStart!".spec";
auto end = §ionEnd!".spec";
for (auto p = start; p <= end; p++)
printf("%p = %x\n", p, *p);
}Output: It would be good to allow specifying whether the section is a COMDAT or not, both have their application. LDC and DMD seem to disagree when inside a template. |
Yes it is runtime data from UDA's. It basically gives us the ability to create our own reflection mechanisms. As for CTFE, this isn't actually global state, due to it not being readable at CT. Evaluation order shouldn't matter, there is no guarantee on ordering, or even that the entries are in contiguous memory. Thank you Microsoft. Speculative compilation again, shouldn't matter too much, the point is to trigger registration of information about symbols that exist. If a symbol doesn't exist, we don't care about it.
I need to go back and fix section name length > 8, right now it just creates new sections each time, which isn't ideal.
I've disabled COMDAT's for sections, both attribute and linker list. P.S. Enjoy: https://devblogs.microsoft.com/oldnewthing/20190114-00/?p=100695 https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165 |
Requires DIP, changelog and test.
I can't be bothered to do it atm.
Uses sections for within binary appending of symbols with CTFE appending.
I want to emphasise that, if a user were to attempt to do this, they will very likely fail.
Being a compiler feature allows us to ensure it is correct codegen and brings us in line with the capabilities of application VM languages.