Skip to content

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

Merged
merged 2 commits into from
Dec 2, 2016
Merged

Port swift/basic to Windows using MSVC #5949

merged 2 commits into from
Dec 2, 2016

Conversation

hughbe
Copy link
Contributor

@hughbe hughbe commented Nov 28, 2016

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.

@@ -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)
Copy link
Member

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?

Copy link
Contributor Author

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?

Copy link
Member

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?

Copy link
Contributor Author

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

Copy link
Contributor Author

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__))

Copy link
Contributor Author

@hughbe hughbe Nov 30, 2016

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))
Copy link
Member

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?

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

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!

Copy link
Contributor

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>
Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the whitespace changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleanliness and consistency

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right - will revert.

@jckarter
Copy link
Contributor

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
Copy link
Contributor Author

hughbe commented Nov 28, 2016

Interesting @jckarter... I've opened SR-3285 to track this. I've filed it as a starter bug. I'm hideously busy atm due so I hope you don't mind that I'm not addressing that in this PR?

@jckarter
Copy link
Contributor

@hughbe Sure, no problem.

@compnerd
Copy link
Member

@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
Copy link
Contributor

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.)

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

@hughbe hughbe Nov 30, 2016

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
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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)
Copy link
Contributor

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.

Copy link
Contributor

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.)

Copy link
Contributor Author

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 {
Copy link
Contributor

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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stray endif() here?

Copy link
Contributor Author

@hughbe hughbe Dec 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, dammit

@jrose-apple
Copy link
Contributor

@swift-ci Please smoke test and merge

@hughbe
Copy link
Contributor Author

hughbe commented Dec 2, 2016

Also this one didn't merge although tests passed

@jrose-apple jrose-apple merged commit a184057 into swiftlang:master Dec 2, 2016
@jrose-apple
Copy link
Contributor

sigh

@hughbe hughbe deleted the basic-win-msvc branch December 9, 2016 14:11
@@ -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;
Copy link
Contributor Author

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>;
Copy link
Contributor Author

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;
Copy link
Contributor Author

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

Copy link
Contributor

@jckarter jckarter Dec 15, 2016

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.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants