-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Tools] Add a library to build specialized generic metadata out of process. #70900
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
[Tools] Add a library to build specialized generic metadata out of process. #70900
Conversation
0ca8dec
to
632ee03
Compare
@swift-ci please test |
613974c
to
30e17f9
Compare
@swift-ci please test |
30e17f9
to
54f6b3f
Compare
@swift-ci please test |
54f6b3f
to
599e9f0
Compare
@swift-ci please test |
599e9f0
to
13af9a2
Compare
@swift-ci please test |
13af9a2
to
6ac4da3
Compare
@swift-ci please test |
6ac4da3
to
15f471c
Compare
@swift-ci please test windows platform |
15f471c
to
6171779
Compare
@swift-ci please test |
6171779
to
ef41fbb
Compare
@swift-ci please test |
ef41fbb
to
9bca2a8
Compare
@swift-ci please test |
9bca2a8
to
db61333
Compare
@swift-ci please test |
db61333
to
f62bbd5
Compare
@swift-ci please test |
struct SwiftExternalMetadataBuilder *); | ||
|
||
// Returns an error string if the dylib could not be added | ||
// The builder owns the string, so the caller does not have to free it |
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.
Is it just the last error string that's valid? (Maybe the comment should say something about that?)
if (!VWT_Bi8_) | ||
return *VWT_Bi8_.getError(); |
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.
Should be VWT_Bi16_
.
if (!VWT_Bi8_) | |
return *VWT_Bi8_.getError(); | |
if (!VWT_Bi16_) | |
return *VWT_Bi16_.getError(); |
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.
Ouch, major copy/pasta fail there. Good catch.
if (!VWT_Bi8_) | ||
return *VWT_Bi8_.getError(); |
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.
Should be VWT_Bi32_
.
if (!VWT_Bi8_) | |
return *VWT_Bi8_.getError(); | |
if (!VWT_Bi32_) | |
return *VWT_Bi32_.getError(); |
if (!VWT_Bi8_) | ||
return *VWT_Bi8_.getError(); |
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.
Should be VWT_Bi64_
.
if (!VWT_Bi8_) | |
return *VWT_Bi8_.getError(); | |
if (!VWT_Bi64_) | |
return *VWT_Bi64_.getError(); |
if (!VWT_Bi8_) | ||
return *VWT_Bi8_.getError(); |
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.
Should be VWT_Bi128_
.
if (!VWT_Bi8_) | |
return *VWT_Bi8_.getError(); | |
if (!VWT_Bi128_) | |
return *VWT_Bi128_.getError(); |
auto contents = section.getContents(); | ||
if (!contents) { | ||
consumeError(contents.takeError()); | ||
continue; |
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 wonder whether we should expose the error that occurred here somehow? Even just mentioning it in the message below might be useful if it happens, e.g.
if (hadErrors) {
return BuilderError("Pointer %p is in file %s but is not in any section (we had errors fetching section contents)",
ptr, file->path.c_str());
}
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.
That's a good idea. The MachO implementation can never return an error, but it'll be good in case of future expansion to other formats.
while (cursor) { | ||
switch (cursor->getKind()) { | ||
case Node::Kind::BoundGenericClass: | ||
case Node::Kind::BoundGenericStructure: | ||
case Node::Kind::BoundGenericEnum: | ||
case Node::Kind::BoundGenericProtocol: | ||
case Node::Kind::BoundGenericTypeAlias: | ||
case Node::Kind::BoundGenericFunction: | ||
case Node::Kind::BoundGenericOtherNominalType: | ||
if (foundDepth == depth) { | ||
auto typeList = cursor->getChild(1); | ||
if (!typeList) | ||
return BuilderError( | ||
"Requested generic parameter at depth=%" PRIu64 | ||
" index=%" PRIu64 | ||
", BoundGeneric node does not have two children", | ||
depth, index); | ||
if (typeList->getKind() != Node::Kind::TypeList) | ||
return BuilderError( | ||
"Requested generic parameter at depth=%" PRIu64 | ||
" index=%" PRIu64 | ||
", child 1 of BoundGeneric is %s, not TypeList", | ||
depth, index, nodeKindString(typeList->getKind())); | ||
|
||
auto child = typeList->getChild(index); | ||
if (!child) | ||
return BuilderError( | ||
"Requested generic parameter at depth=%" PRIu64 | ||
" index=%" PRIu64 | ||
", but bound generic TypeList only has %zu children", | ||
depth, index, typeList->getNumChildren()); | ||
|
||
return child; | ||
} | ||
foundDepth++; | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
} |
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.
This loop doesn't appear to advance cursor
at all.
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.
Oops. Looks like we don't yet have enough support for nested types for this to matter. I added code to walk the tree here, and we'll end up testing it as part of testing expanded support for nested types.
ExternalGenericMetadataBuilderContext<Runtime>::addImagesInPath( | ||
std::string path) { | ||
auto forEachFile = [&](std::string filepath) { | ||
auto error = addImageAtPath(filepath); |
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.
Should we check the file extension at least, to avoid trying to load everything in sight? Or maybe only generate the warning about not being able to read a dylib if the extension is .dylib
, .so
or empty? (We expect something with the extension .txt
to fail, after all, and in some ways it'd be more interesting if it didn't.)
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 sure what the right approach is here. It doesn't matter too much, as swift_externalMetadataBuilder_addDylib
is intended to be the primary interface, and this is a convenience. For the convenience interface, I'd rather it try load everything in sight rather than have it potentially skip something we want to keep if somebody puts a weird extension on their dylib.
if (command.C.cmd == llvm::MachO::LC_LOAD_DYLIB || | ||
command.C.cmd == llvm::MachO::LC_LOAD_WEAK_DYLIB || | ||
command.C.cmd == llvm::MachO::LC_REEXPORT_DYLIB || | ||
command.C.cmd == llvm::MachO::LC_LOAD_UPWARD_DYLIB) { |
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.
Do we need LC_LAZY_LOAD_DYLIB
?
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.
It seems not. LC_LAZY_LOAD_DYLIB
seems to be obsolete, and this matches the behavior of dyld.
let readJSONError = readJSONErrorCStr.map { String(cString: $0) } | ||
expectNil(readJSONError) | ||
|
||
// Find libswiftCore dynamically since we don't know where we might have loaded it from. |
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.
swift_getRuntimeLibraryPath()
will tell you this, FWIW.
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.
Thanks, that's much nicer.
f62bbd5
to
ad253bb
Compare
Addressed review feedback and moved the code to |
@swift-ci please test |
ad253bb
to
9f54982
Compare
@swift-ci please test |
@swift-ci please clean test Windows platform |
…ocess. This library uses GenericMetadataBuilder with a ReaderWriter that can read data and resolve pointers from MachO files, and emit a JSON representation of a dylib containing the built metadata. We use LLVM's binary file readers to parse the MachO files and resolve fixups so we can follow pointers. This code is somewhat MachO specific, but could be generalized to other formats that LLVM supports. rdar://116592577
9f54982
to
4341102
Compare
@swift-ci please test |
@swift-ci please test macos platform |
This library uses GenericMetadataBuilder with a ReaderWriter that can read data and resolve pointers from MachO files, and emit a JSON representation of a dylib containing the built metadata.
We use LLVM's binary file readers to parse the MachO files and resolve fixups so we can follow pointers. This code is somewhat MachO specific, but could be generalized to other formats that LLVM supports.
rdar://116592577