-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support bindings for literal defines #50
Conversation
cc24b1b
to
458aa66
Compare
458aa66
to
1ce2e45
Compare
I decided that literals will be places directly to Scala code, so their values will be known by a programmer without looking into header file (see Support Bindings for Defines Design Doc) This commit will be only about literals. Currently there are following issues:
|
Last commit is incorrect, I'll fix it tomorrow |
llvm::errs() << "IR is not empty. Please use new instance of " | ||
"ScalaFrontendActionFactory.\n"; | ||
llvm::errs().flush(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I guess this is pointless now.
bindgen/Main.cpp
Outdated
|
||
DefineFinderActionFactory defineFinderActionFactory(ir); | ||
Tool.run(&defineFinderActionFactory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's check the returned result code
bindgen/defines/DefineFinder.cpp
Outdated
llvm::errs().flush(); | ||
} | ||
} else if (finalToken->isAnyIdentifier()) { | ||
// TODO: save identifier and get its type in ScalaFrontendAction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to use while (token->isAnyIdentifier())
in getFinalIdentifier()
so this branch never happens?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because finalToken
might still be anyIdentifier
, since not all defines have literal values.
So the loop may never end. But I can reorganize the code so it will be a bit more clear
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need this branch because we want to find defines that are aliases for variables.
bindgen/defines/DefineFinder.cpp
Outdated
} | ||
|
||
const clang::Token * | ||
DefineFinder::getFinalIdentifier(const clang::Token &token) const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with the AST but I suggest renaming this method to resolveIdentifier()
and recursively call it on a token until we resolve it to a literal or something we don't handle. Maybe I misunderstood something here though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name is good
It should be called recursively until the identifier is not an another define, but the problem is that defines may contain multiple tokens:
extern int a;
#define MY_A a
#define MY_A_PTR MY_A * // two tokens, one of them is another define
So the function might get too complicated. I'll try to find clang function that will resolve value of define for us
bindgen/defines/DefineFinder.cpp
Outdated
: ir(ir), compiler(compiler), pp(pp) {} | ||
|
||
void DefineFinder::MacroDefined(const clang::Token &MacroNameTok, | ||
const clang::MacroDirective *MD) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From a style point of view I find it confusing to have variable names starting with upper. We don't do it for ir
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The names are from the overriden methods, but they can be renamed
tests/samples/Define.h
Outdated
|
||
extern int a; | ||
#define MY_A a // unsupported | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#define wait_for_it(cond) do { sleep (1000); } while (!cond)
bindgen/ir/IR.h
Outdated
@@ -28,6 +29,11 @@ class IR { | |||
void addUnion(std::string name, std::vector<Field> fields, | |||
uint64_t maxSize); | |||
|
|||
void addLiteralDefine(std::string name, std::string literal); | |||
|
|||
void addLiteralDefine(std::string name, std::string literal, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can type have a default value to reduce this to one method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LiteralDefine
always have a type now, so I can simply delete the method without a type
c0bbf73
to
c8c7543
Compare
I couldn't find a function that would expand a define. #define INT 42
#define INT_2 INT But I think it shouldn't be a big problem to write the implementation that handles more difficult cases. Once we expand a define we need to process it. If it is a literal then there is no problems to embed it in the Scala code, but if it's not then we need to find a way to check if it's a variable of data type or of pointer type (or something else). Currently I don't know how to do that. |
Tests in a container fail because clang API changed since version 4.0 |
To check is a define is an alias for a variable maybe it is a good idea to generate C code that includes the header and uses the value, feed it into FrontendAction and see if there will be errors |
7b81274
to
5a67df5
Compare
5a67df5
to
fad3366
Compare
fad3366
to
e288ac9
Compare
I think saving all floating point numbers as |
Maybe some of C literals are not valid literals in Scala, so it also has to be checked |
We can test against LLVM 4 if you want. It would however be nice to support more recent versions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I suggest to wait with merging this until 0.1 has been tagged. |
0537917
to
41585a3
Compare
41585a3
to
2db8071
Compare
Part of #4
Currently the code only finds defines and does not generate any code for it.
I think it would be better to implement end-to-end testing before moving to this one #51