[SAoC] 'DPP with Linux kernel headers' Project Thread
Cristian Becerescu
cristian.becerescu at yahoo.com
Thu Oct 10 20:28:20 UTC 2019
It's time for a new update, so here we go. Sorry for those long
posts :)
This past week I've dived deeper into the 3rd problem mentioned
in the last update.
There were multiple problems when trying to generate and compile
a D program from this DPP:
// foo.dpp
#include <linux/namei.h>
void main()
{
}
Problem #1 - Clang errors
Even though compiling a C program which included the same kernel
header with clang worked, compiling it through dpp didn't. I've
managed to find out that this happens because dpp appends some
include directories by default, the problem being related to
'/usr/include/' in particular (which is set through the function
call systemPaths() from the D libclang [1]). Clang complains
about undeclared identifiers and expected closed parenthesis, but
I still have to investigate why including that directory to the
include directories messes things up.
-------------------------------------------------
Problem #2 - Multi-line macro definition w/ casts
Consider this code from kernel.h:
#define u64_to_user_ptr(x) ( \
{ \
typecheck(u64, x); \
(void __user *)(uintptr_t)x; \
} \
)
In dpp, when translating this into D code, we also check for
pairs of open and closed parenthesis [2]. When finding a '(', we
increment the index of the tokens array until we find a matching
')'. If the C code is valid (and in the above example it is),
this should work well, but it doesn't, resulting in a fatal
error: range violation. The reason is, as seen in [2], we only
check for tokens with the ')' spelling, when, in reality, the
last parenthesis of the macro is not spelled ')', but '\\\n)'
('\' character, followed by newline, followed by the actual
parenthesis).
-------------------------------------------------
Problem #3 - Aggregates with name being a D keyword
I'll give you an example:
// test.h
struct module;
void f(struct module *);
struct module {
int a;
int b;
};
Generating a D file from a DPP one which includes the above
header will look like this:
// test.d, generated from test.dpp through the last version of
d++ from github
// ...
extern(C)
{
void f(module*) @nogc nothrow;
struct module__
{
int a;
int b;
}
}
struct module;
void main() {}
// ...
Clearly there are multiple wrong things here:
- the module struct should be named module_ and not module__
(this is what dpp should do internally)
- even though the struct is renamed, the parameter types are not
- we are declaring the same structure again (with the original C
spelling) outside of the extern(C) block because dpp thinks
module was an undeclared structure
- compilation of this D program clearly doesn't work
The reasons for those bugs are a bit subtler, so I'm not going
over them as it would make this post quite big.
-------------------------------------------------
I have implemented working solutions for all the above problems.
They pass all the unit tests and I can also successfully generate
an executable file from a .dpp which contains the linux/namei.h
kernel header. I just have to clean some things and start making
pull requests and maybe get some feedback.
Problem #1 is "solved" by not including that directory in the
paths (just a workaround for the moment), but as I will
investigate this further, I will try to see what the underlying
problem really is (probably some collisions with other files).
Going from here, I will investigate if my changes impact other
non-unit-tested C cases. Also, I will try running dpp with other
kernel and non-kernel headers as well, making sure there are no
other bugs or untreated edge cases.
Cristi
[1] https://code.dlang.org/packages/libclang
[2]
https://github.com/atilaneves/dpp/blob/master/source/dpp/translation/macro_.d#L326
More information about the Digitalmars-d
mailing list