-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Port swift/basic to Windows using MSVC #5949
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
Conversation
@@ -29,7 +29,7 @@ namespace swift { | |||
/// is not intended to be specialized. | |||
template<typename T> | |||
struct IsTriviallyCopyable { | |||
#if _LIBCPP_VERSION | |||
#if _LIBCPP_VERSION || defined(_MSC_VER) |
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.
What if you are using msvcprt with clang-cl?
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.
Right, that was my concern. Would || (defined(_MSC_VER) && !defined(__clang__)
work? I dunno how to detect clang-cl!
Maybe its a version thing - we should check _MSC_VER >= X
?
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 value for _MSC_VER will be the same across clang and clang-cl. What exactly are you trying to protect against?
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.
Well if we don't have this check, I get a fatal error saying "not implemented" at compile time. We need this, but need to figure out how to detect msvcprt
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.
Okay - I've addressed this by changing it to:
#if _LIBCPP_VERSION || (defined(_MSC_VER) && !defined(__clang__))
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 works, since this works __has_feature(is_trivially_copyable)
with clang-cl
@@ -53,7 +53,7 @@ struct IsTriviallyConstructible { | |||
|
|||
template<typename T> | |||
struct IsTriviallyDestructible { | |||
#if _LIBCPP_VERSION | |||
#if _LIBCPP_VERSION || (defined(_MSC_VER) && defined(_WIN32)) |
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.
Why the additional _WIN32
check?
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 idea, I'll remove when we get a better idea about the other stuff
// _attribute__((used) is not defined in MSVC | ||
#if !defined(_MSC_VER) | ||
__attribute__((used)) | ||
#endif |
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.
Hmm, I wonder if there is a better way to handle this. Something like using a __pragma(warning(supress:????))))
. In that case, we could have a SWIFT_USED
macro.
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 is the only place __attribute((used))
is used in the entire library I think, so I'm not sure its worth the effort!
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.
What does LLVM_ATTRIBUTE_USED do?
// WIN32 doesn't natively support <uuid/uuid.h>. Instead, we use Win32 APIs | ||
// class | ||
#if defined(_WIN32) | ||
#include <rpc.h> |
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.
Might be nice to #define WIN32_LEAN_AND_MEAN
here.
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.
will do
#endif | ||
#if __has_include("SwiftRevision.inc") | ||
# include "SwiftRevision.inc" | ||
#include "SwiftRevision.inc" | ||
#endif |
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.
Why the whitespace changes?
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.
cleanliness and consistency
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 old way is meant to show #if
nesting.
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.
right - will revert.
I believe that the only place we use UUIDs in the compiler is to print "opened archetypes" in SIL in a way that lets them be reliably parsed back as unique types. We could probably use a better uniquing scheme in SIL printing now that we have better tracking of opened type uses in SIL, and kill the UUID dependency. |
@hughbe Sure, no problem. |
@jckarter what exactly did you have in mind for replacing the naming scheme with? It sounds simple enough that I might be able to take that on. |
@@ -112,7 +112,8 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode { | |||
return *LowerBound == Ptr; | |||
} | |||
|
|||
using iterator = typename decltype(Data)::iterator; | |||
// Ideally we would use decltype(Data)::iterator, but MSVC reports an error |
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.
Nitpick: comments should end with periods. (Although I don't really think you need this one; the alternate formulation isn't so bad that anyone would be tempted to change 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.
Removed the comment as suggested.
@@ -24,7 +24,9 @@ void SourceManager::verifyAllBuffers() const { | |||
}; | |||
|
|||
// FIXME: This depends on the buffer IDs chosen by llvm::SourceMgr. | |||
__attribute__((used)) static char arbitraryTotal = 0; | |||
// _attribute__((used) is not defined in MSVC |
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 need for the comment here.
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.
Removed, thanks
// convert the memory of a 128 bit unsigned char array to a ::UUID. | ||
// We also can't expose <rpc.h> in any headers, as it imports <windows.h> which | ||
// defines macros that conflict with many definitions (e.g. ERROR, std::max) | ||
union Conversion { |
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.
memcpy already takes a void *, so you don't need this.
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 I can entirely remove this. We use this conversion union in methods such as UUIDCompare
and UUIDToString
that require a UUID passed. I have removed all the conversions from memcpy though as you suggested.
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.
Either ::UUID is a POD type, in which case you can just memcpy into one directly, or it's not, in which case the union isn't safe either.
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 had no idea you can just memcpy like that - you learn something new everyday:
This works, and the file builds, so we're good:
#include <rpc.h>
int main()
{
::UUID uuid1;
unsigned char data[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
memcpy(&uuid1, data, 16);
// uuid1 = {04030201-0605-0807-090A-0B0C0D0E0F10}
return 0;
}
@@ -43,6 +43,12 @@ | |||
SWIFT_MAKE_VERSION_STRING(SWIFT_VERSION_MAJOR, SWIFT_VERSION_MINOR) | |||
#endif | |||
|
|||
// MSVC doesn't support __has_include |
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.
Hm. This isn't 100% correct, then, because these files won't exist when the source root isn't a Git or SVN repo. Maybe we should just have CMake generate empty files in those cases?
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.
Strange - I see lines in the build log on Windows saying "Generating LLVMRevision.inc" etc. etc. for each file. Seems like CMake already does this and has already generated these files by the time Version.cpp is built.
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 only does that if you're in a checkout of a Git or SVN repo.
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.
Ah I understand now. I've modified lib/Basic/CMakeLists.txt
file to generate an empty file if these files are not found. I've made it a seperate commit because its not necessarily Windows/MSVC specific.
@@ -57,8 +57,10 @@ class TaskQueue { | |||
|
|||
// TODO: remove once -Wdocumentation stops warning for \param, \returns on | |||
// std::function (<rdar://problem/15665132>). | |||
#if !defined(_MSC_VER) |
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.
These shouldn't be necessary now, since we decided to allow unknown pragmas.
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.
(If we did have them, we should check for Clang instead of for !MSVC.)
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 removed the ifs
// convert the memory of a 128 bit unsigned char array to a ::UUID. | ||
// We also can't expose <rpc.h> in any headers, as it imports <windows.h> which | ||
// defines macros that conflict with many definitions (e.g. ERROR, std::max) | ||
union Conversion { |
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.
Either ::UUID is a POD type, in which case you can just memcpy into one directly, or it's not, in which case the union isn't safe either.
set_source_files_properties("${revision_inc}" | ||
PROPERTIES GENERATED TRUE | ||
HEADER_FILE_ONLY TRUE) | ||
set(${revision_inc_var} ${revision_inc} PARENT_SCOPE) | ||
endif() |
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.
Stray endif()
here?
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.
Ah, dammit
@swift-ci Please smoke test and merge |
Also this one didn't merge although tests passed |
sigh |
@@ -112,7 +112,7 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode { | |||
return *LowerBound == Ptr; | |||
} | |||
|
|||
using iterator = typename decltype(Data)::iterator; | |||
using iterator = typename ArrayRef<PtrTy>::iterator; |
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.
static const size_t Size = (sizeof(void*) - 1) / sizeof(Chunk); | ||
static const size_t ActualSize = max<size_t>(Size, 1); | ||
|
||
using MapBase = PrefixMap<Chunk, ValueType, ActualSize>; |
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.
MapBase TheMap; | ||
|
||
public: | ||
using SequenceIterator = EncodedSequence::iterator; | ||
using SequenceIterator = typename EncodedSequence::iterator; |
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 seems to be a Clang deficiency rather than an MSVC deficiency
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.
Agreed, typename
ought to be required by the standard. (Assuming EncodedSequence
is dependent, of course.)
The UUID stuff is the heart of this PR, and relies on linking rpcrt4.lib, found in #5904. We can merge these PRs in any order, however.
The only limitation is that we can't generate a UUID based on the current time, but this isn't terrible.