[Compiler] Help IR gen in targetting MSVC

Hi all,

I found a bug in my port for MSVC and Cygwin.

The C function swift_stdlib_readLine_stdin() is mapped to 'Int' type in
Swift, but it generates i32 in LLVM if I specify the target as MSVC. If I
give the target as Cygwin, it generates i64.

With the target options, the Cygwin ported swiftc.exe has the same output.

I know that the one of the differences between MSVC and Cygwin is the size
of 'long' type. But I don't know even if it is related to this problem.

I don't know where to I start with.

BEGIN OF tt.swift ---
import SwiftShims

var linePtr: UnsafeMutablePointer<CChar>? = nil
var readBytes = swift_stdlib_readLine_stdin(&linePtr)
print(readBytes)
END OF tt.swift -----

C:\temp>swiftc -emit-ir tt.swift -target x86_64-pc-windows-msvc | findstr
stdlib
  %4 = call i32 @swift_stdlib_readLine_stdin(i8** bitcast (%Sq*
@_Tv2tt7linePtrGSqGSpVs4Int8__ to i8**))
declare i32 @swift_stdlib_readLine_stdin(i8**) #0

C:\temp>swiftc -emit-ir tt.swift -target x86_64-unknown-windows-cygnus |
findstr stdlib
  %4 = call i64 @swift_stdlib_readLine_stdin(i8** bitcast (%Sq*
@_Tv2tt7linePtrGSqGSpVs4Int8__ to i8**))
declare i64 @swift_stdlib_readLine_stdin(i8**) #0

- Han Sangjin

Hi all,

I found a bug in my port for MSVC and Cygwin.

The C function swift_stdlib_readLine_stdin() is mapped to 'Int' type in Swift, but it generates i32 in LLVM if I specify the target as MSVC. If I give the target as Cygwin, it generates i64.

With the target options, the Cygwin ported swiftc.exe has the same output.

I know that the one of the differences between MSVC and Cygwin is the size of 'long' type. But I don't know even if it is related to this problem.

I don't know where to I start with.

The problem is probably the unconditional line
  public typealias CLong = Int
in CTypes.swift. That is generally true for Unix platforms (LP32 / LP64) but not MSVC (LLP64).

You will need to conditionalize that line.

John.

···

On Apr 25, 2016, at 7:54 PM, Sangjin Han via swift-dev <swift-dev@swift.org> wrote:

BEGIN OF tt.swift ---
import SwiftShims

var linePtr: UnsafeMutablePointer<CChar>? = nil
var readBytes = swift_stdlib_readLine_stdin(&linePtr)
print(readBytes)
END OF tt.swift -----

C:\temp>swiftc -emit-ir tt.swift -target x86_64-pc-windows-msvc | findstr stdlib
  %4 = call i32 @swift_stdlib_readLine_stdin(i8** bitcast (%Sq* @_Tv2tt7linePtrGSqGSpVs4Int8__ to i8**))
declare i32 @swift_stdlib_readLine_stdin(i8**) #0

C:\temp>swiftc -emit-ir tt.swift -target x86_64-unknown-windows-cygnus | findstr stdlib
  %4 = call i64 @swift_stdlib_readLine_stdin(i8** bitcast (%Sq* @_Tv2tt7linePtrGSqGSpVs4Int8__ to i8**))
declare i64 @swift_stdlib_readLine_stdin(i8**) #0

- Han Sangjin

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

The problem can be solved by modifying that code. Thanks you. I thought
that code will affect only to the CLong type not Int.

But I meet another problem to fix it. I couldn't find the conditional
method to distinct x86_64-*-windows-msvc with x86_64-*-windows-cygnus in
Swift source.

"if os(Windows)" can not distinct MSVC from Cygwin.

Should I add new condition 'env()' for the environment?

- Han Sangjin

···

2016-04-26 14:39 GMT+09:00 John McCall <rjmccall@apple.com>:

> On Apr 25, 2016, at 7:54 PM, Sangjin Han via swift-dev < > swift-dev@swift.org> wrote:
> Hi all,
>
> I found a bug in my port for MSVC and Cygwin.
>
> The C function swift_stdlib_readLine_stdin() is mapped to 'Int' type in
Swift, but it generates i32 in LLVM if I specify the target as MSVC. If I
give the target as Cygwin, it generates i64.
>
> With the target options, the Cygwin ported swiftc.exe has the same
output.
>
> I know that the one of the differences between MSVC and Cygwin is the
size of 'long' type. But I don't know even if it is related to this problem.
>
> I don't know where to I start with.

The problem is probably the unconditional line
  public typealias CLong = Int
in CTypes.swift. That is generally true for Unix platforms (LP32 / LP64)
but not MSVC (LLP64).

You will need to conditionalize that line.

John.

>
> BEGIN OF tt.swift ---
> import SwiftShims
>
> var linePtr: UnsafeMutablePointer<CChar>? = nil
> var readBytes = swift_stdlib_readLine_stdin(&linePtr)
> print(readBytes)
> END OF tt.swift -----
>
> C:\temp>swiftc -emit-ir tt.swift -target x86_64-pc-windows-msvc |
findstr stdlib
> %4 = call i32 @swift_stdlib_readLine_stdin(i8** bitcast (%Sq*
@_Tv2tt7linePtrGSqGSpVs4Int8__ to i8**))
> declare i32 @swift_stdlib_readLine_stdin(i8**) #0
>
> C:\temp>swiftc -emit-ir tt.swift -target x86_64-unknown-windows-cygnus |
findstr stdlib
> %4 = call i64 @swift_stdlib_readLine_stdin(i8** bitcast (%Sq*
@_Tv2tt7linePtrGSqGSpVs4Int8__ to i8**))
> declare i64 @swift_stdlib_readLine_stdin(i8**) #0
>
>
> - Han Sangjin
>
> _______________________________________________
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

The problem can be solved by modifying that code. Thanks you. I thought that code will affect only to the CLong type not Int.

It changes what 'long' gets imported as. If there's a Windows API defined using 'long' (rather than some more meaningful typedef like 'size_t'), it's important for it to be imported as Int32 rather than Int, since 'long' is always 32 bits under MSVC.

But I meet another problem to fix it. I couldn't find the conditional method to distinct x86_64-*-windows-msvc with x86_64-*-windows-cygnus in Swift source.

"if os(Windows)" can not distinct MSVC from Cygwin.

Should I add new condition 'env()' for the environment?

That is an excellent question.

My understanding / memory is that, as far as their programming interfaces goes, Cygwin and MSVC are very, very different environments. Maybe it's useful to have a condition that's true for both environments — although I'm not sure why it would — but I don't think it deserves to be as prominent as os(Windows). So my gut reaction is that, rather than adding a #env, we ought to just reserve os(Windows) for MSVC compatibility and make a new os(Cygwin) for Cygwin.

This needs to be raised on swift-evolution, though. CC'ing that list.

John.

···

On Apr 26, 2016, at 1:03 PM, Sangjin Han <tinysun.net@gmail.com> wrote:

- Han Sangjin

2016-04-26 14:39 GMT+09:00 John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>>:
> On Apr 25, 2016, at 7:54 PM, Sangjin Han via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
> Hi all,
>
> I found a bug in my port for MSVC and Cygwin.
>
> The C function swift_stdlib_readLine_stdin() is mapped to 'Int' type in Swift, but it generates i32 in LLVM if I specify the target as MSVC. If I give the target as Cygwin, it generates i64.
>
> With the target options, the Cygwin ported swiftc.exe has the same output.
>
> I know that the one of the differences between MSVC and Cygwin is the size of 'long' type. But I don't know even if it is related to this problem.
>
> I don't know where to I start with.

The problem is probably the unconditional line
  public typealias CLong = Int
in CTypes.swift. That is generally true for Unix platforms (LP32 / LP64) but not MSVC (LLP64).

You will need to conditionalize that line.

John.

>
> BEGIN OF tt.swift ---
> import SwiftShims
>
> var linePtr: UnsafeMutablePointer<CChar>? = nil
> var readBytes = swift_stdlib_readLine_stdin(&linePtr)
> print(readBytes)
> END OF tt.swift -----
>
> C:\temp>swiftc -emit-ir tt.swift -target x86_64-pc-windows-msvc | findstr stdlib
> %4 = call i32 @swift_stdlib_readLine_stdin(i8** bitcast (%Sq* @_Tv2tt7linePtrGSqGSpVs4Int8__ to i8**))
> declare i32 @swift_stdlib_readLine_stdin(i8**) #0
>
> C:\temp>swiftc -emit-ir tt.swift -target x86_64-unknown-windows-cygnus | findstr stdlib
> %4 = call i64 @swift_stdlib_readLine_stdin(i8** bitcast (%Sq* @_Tv2tt7linePtrGSqGSpVs4Int8__ to i8**))
> declare i64 @swift_stdlib_readLine_stdin(i8**) #0
>
>
> - Han Sangjin
>
> _______________________________________________
> swift-dev mailing list
> swift-dev@swift.org <mailto:swift-dev@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-dev

It's an interesting question. Mingw, Cygwin, and MSVC definitely vary greatly in ABI and C language level behavior, but the underlying Win32 system libraries remain the same. I think it makes sense to consider them different os(...) environments, but it would also make sense IMO to have a broader platform check for Win32. Along similar lines, Linux, FreeBSD, and Darwin are different OSes, but all also share a POSIX environment.

-Joe

···

On Apr 26, 2016, at 1:24 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 26, 2016, at 1:03 PM, Sangjin Han <tinysun.net@gmail.com> wrote:
The problem can be solved by modifying that code. Thanks you. I thought that code will affect only to the CLong type not Int.

It changes what 'long' gets imported as. If there's a Windows API defined using 'long' (rather than some more meaningful typedef like 'size_t'), it's important for it to be imported as Int32 rather than Int, since 'long' is always 32 bits under MSVC.

But I meet another problem to fix it. I couldn't find the conditional method to distinct x86_64-*-windows-msvc with x86_64-*-windows-cygnus in Swift source.

"if os(Windows)" can not distinct MSVC from Cygwin.

Should I add new condition 'env()' for the environment?

That is an excellent question.

My understanding / memory is that, as far as their programming interfaces goes, Cygwin and MSVC are very, very different environments. Maybe it's useful to have a condition that's true for both environments — although I'm not sure why it would — but I don't think it deserves to be as prominent as os(Windows). So my gut reaction is that, rather than adding a #env, we ought to just reserve os(Windows) for MSVC compatibility and make a new os(Cygwin) for Cygwin.

This needs to be raised on swift-evolution, though. CC'ing that list.

If, after import and however much magic, they both end up exposing a similarly-typed set of system APIs, I agree that it makes sense to have a condition that says "yes, the target has those APIs". It certainly seems like a worthwhile goal for Swift to present them with the same imported types.

John.

···

On Apr 26, 2016, at 1:39 PM, Joe Groff <jgroff@apple.com> wrote:

On Apr 26, 2016, at 1:24 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 26, 2016, at 1:03 PM, Sangjin Han <tinysun.net@gmail.com> wrote:
The problem can be solved by modifying that code. Thanks you. I thought that code will affect only to the CLong type not Int.

It changes what 'long' gets imported as. If there's a Windows API defined using 'long' (rather than some more meaningful typedef like 'size_t'), it's important for it to be imported as Int32 rather than Int, since 'long' is always 32 bits under MSVC.

But I meet another problem to fix it. I couldn't find the conditional method to distinct x86_64-*-windows-msvc with x86_64-*-windows-cygnus in Swift source.

"if os(Windows)" can not distinct MSVC from Cygwin.

Should I add new condition 'env()' for the environment?

That is an excellent question.

My understanding / memory is that, as far as their programming interfaces goes, Cygwin and MSVC are very, very different environments. Maybe it's useful to have a condition that's true for both environments — although I'm not sure why it would — but I don't think it deserves to be as prominent as os(Windows). So my gut reaction is that, rather than adding a #env, we ought to just reserve os(Windows) for MSVC compatibility and make a new os(Cygwin) for Cygwin.

This needs to be raised on swift-evolution, though. CC'ing that list.

It's an interesting question. Mingw, Cygwin, and MSVC definitely vary greatly in ABI and C language level behavior, but the underlying Win32 system libraries remain the same. I think it makes sense to consider them different os(...) environments, but it would also make sense IMO to have a broader platform check for Win32.

I made a PR [Compiler] Cygwin is identified by os(Cygwin) instead of os(Windows) by tinysun212 · Pull Request #2351 · apple/swift · GitHub introducing os(Cygwin).

···

2016-04-27 5:54 GMT+09:00 John McCall <rjmccall@apple.com>:

> On Apr 26, 2016, at 1:39 PM, Joe Groff <jgroff@apple.com> wrote:
>> On Apr 26, 2016, at 1:24 PM, John McCall via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>>> On Apr 26, 2016, at 1:03 PM, Sangjin Han <tinysun.net@gmail.com> > wrote:
>>> The problem can be solved by modifying that code. Thanks you. I
thought that code will affect only to the CLong type not Int.
>>
>> It changes what 'long' gets imported as. If there's a Windows API
defined using 'long' (rather than some more meaningful typedef like
'size_t'), it's important for it to be imported as Int32 rather than Int,
since 'long' is always 32 bits under MSVC.
>>
>>> But I meet another problem to fix it. I couldn't find the conditional
method to distinct x86_64-*-windows-msvc with x86_64-*-windows-cygnus in
Swift source.
>>>
>>> "if os(Windows)" can not distinct MSVC from Cygwin.
>>>
>>> Should I add new condition 'env()' for the environment?
>>
>> That is an excellent question.
>>
>> My understanding / memory is that, as far as their programming
interfaces goes, Cygwin and MSVC are very, very different environments.
Maybe it's useful to have a condition that's true for both environments —
although I'm not sure why it would — but I don't think it deserves to be as
prominent as os(Windows). So my gut reaction is that, rather than adding a
#env, we ought to just reserve os(Windows) for MSVC compatibility and make
a new os(Cygwin) for Cygwin.
>>
>> This needs to be raised on swift-evolution, though. CC'ing that list.
>
> It's an interesting question. Mingw, Cygwin, and MSVC definitely vary
greatly in ABI and C language level behavior, but the underlying Win32
system libraries remain the same. I think it makes sense to consider them
different os(...) environments, but it would also make sense IMO to have a
broader platform check for Win32.

If, after import and however much magic, they both end up exposing a
similarly-typed set of system APIs, I agree that it makes sense to have a
condition that says "yes, the target has those APIs". It certainly seems
like a worthwhile goal for Swift to present them with the same imported
types.

John.