Skip to content

Commit d074475

Browse files
authored
[SPIR-V][Headers] Enable programs that include system headers on Windows for SPIRV32 and SPIRV64 targets (#13548)
This is text from OpenCL SPIR Spec 2.0 (https://registry.khronos.org/SPIR/specs/spir_spec-2.0.pdf) The OpenCL size_t, ptrdiff_t,uintptr_t, intptr_t, atomic_size_t, atomic_ptrdiff_t, atomic_uintptr_t and atomic_intptr_t data types are mapped to LLVM i32 when the device address width is equal to 32 bits and to LLVM i64 when the device address width is equal 64 bits. After some analysis though, I see that the windows os based customizations made for the SPIR target (#325) are necessary for successful compilation on windows. Also, they do not seem to be violating the spec. It's just that 'long' and 'long long' mean different things on windows and linux. On 64-bit linux, long type has 8 bytes, but on 64-bit windows, long type has 4 bytes. Hence, I have extended the SPIR target changes to the SPIR-V target as well. This PR extends those changes for SPIRV32 and SPIRV64 targets and added appropriate tests as well. We would eventually want to submit this (and PR #325) upstream. Thanks --------- Signed-off-by: Arvind Sudarsanam <[email protected]>
1 parent f770f69 commit d074475

File tree

7 files changed

+151
-7
lines changed

7 files changed

+151
-7
lines changed

clang/lib/Basic/Targets.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -698,15 +698,39 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
698698
if (os != llvm::Triple::UnknownOS ||
699699
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
700700
return nullptr;
701-
return std::make_unique<SPIRV32TargetInfo>(Triple, Opts);
701+
llvm::Triple HT(Opts.HostTriple);
702+
switch (HT.getOS()) {
703+
case llvm::Triple::Win32:
704+
switch (HT.getEnvironment()) {
705+
default: // Assume MSVC for unknown environments
706+
case llvm::Triple::MSVC:
707+
assert(HT.getArch() == llvm::Triple::x86 &&
708+
"Unsupported host architecture");
709+
return std::make_unique<MicrosoftX86_32SPIRV32TargetInfo>(Triple, Opts);
710+
}
711+
default:
712+
return std::make_unique<SPIRV32TargetInfo>(Triple, Opts);
713+
}
702714
}
703715
case llvm::Triple::spirv64: {
704716
if (os != llvm::Triple::UnknownOS ||
705717
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
706718
return nullptr;
707-
return std::make_unique<SPIRV64TargetInfo>(Triple, Opts);
719+
llvm::Triple HT(Opts.HostTriple);
720+
switch (HT.getOS()) {
721+
case llvm::Triple::Win32:
722+
switch (HT.getEnvironment()) {
723+
default: // Assume MSVC for unknown environments
724+
case llvm::Triple::MSVC:
725+
assert(HT.getArch() == llvm::Triple::x86_64 &&
726+
"Unsupported host architecture");
727+
return std::make_unique<MicrosoftX86_64_SPIRV64TargetInfo>(Triple,
728+
Opts);
729+
}
730+
default:
731+
return std::make_unique<SPIRV64TargetInfo>(Triple, Opts);
732+
}
708733
}
709-
710734
case llvm::Triple::wasm32:
711735
if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
712736
Triple.getVendor() != llvm::Triple::UnknownVendor ||

clang/lib/Basic/Targets/SPIR.h

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,96 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo {
475475
MacroBuilder &Builder) const override;
476476
};
477477

478+
// x86-32 SPIRV32 Windows target
479+
class LLVM_LIBRARY_VISIBILITY WindowsX86_32SPIRV32TargetInfo
480+
: public WindowsTargetInfo<SPIRV32TargetInfo> {
481+
public:
482+
WindowsX86_32SPIRV32TargetInfo(const llvm::Triple &Triple,
483+
const TargetOptions &Opts)
484+
: WindowsTargetInfo<SPIRV32TargetInfo>(Triple, Opts) {
485+
DoubleAlign = LongLongAlign = 64;
486+
WCharType = UnsignedShort;
487+
}
488+
489+
BuiltinVaListKind getBuiltinVaListKind() const override {
490+
return TargetInfo::CharPtrBuiltinVaList;
491+
}
492+
493+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
494+
if (CC == CC_X86VectorCall)
495+
// Permit CC_X86VectorCall which is used in Microsoft headers
496+
return CCCR_OK;
497+
return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
498+
: CCCR_Warning;
499+
}
500+
};
501+
502+
// x86-32 SPIRV32 Windows Visual Studio target
503+
class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32SPIRV32TargetInfo
504+
: public WindowsX86_32SPIRV32TargetInfo {
505+
public:
506+
MicrosoftX86_32SPIRV32TargetInfo(const llvm::Triple &Triple,
507+
const TargetOptions &Opts)
508+
: WindowsX86_32SPIRV32TargetInfo(Triple, Opts) {}
509+
510+
void getTargetDefines(const LangOptions &Opts,
511+
MacroBuilder &Builder) const override {
512+
WindowsX86_32SPIRV32TargetInfo::getTargetDefines(Opts, Builder);
513+
// The value of the following reflects processor type.
514+
// 300=386, 400=486, 500=Pentium, 600=Blend (default)
515+
// We lost the original triple, so we use the default.
516+
Builder.defineMacro("_M_IX86", "600");
517+
}
518+
};
519+
520+
// x86-64 SPIRV64 Windows target
521+
class LLVM_LIBRARY_VISIBILITY WindowsX86_64_SPIRV64TargetInfo
522+
: public WindowsTargetInfo<SPIRV64TargetInfo> {
523+
public:
524+
WindowsX86_64_SPIRV64TargetInfo(const llvm::Triple &Triple,
525+
const TargetOptions &Opts)
526+
: WindowsTargetInfo<SPIRV64TargetInfo>(Triple, Opts) {
527+
LongWidth = LongAlign = 32;
528+
DoubleAlign = LongLongAlign = 64;
529+
IntMaxType = SignedLongLong;
530+
Int64Type = SignedLongLong;
531+
SizeType = UnsignedLongLong;
532+
PtrDiffType = SignedLongLong;
533+
IntPtrType = SignedLongLong;
534+
WCharType = UnsignedShort;
535+
}
536+
537+
BuiltinVaListKind getBuiltinVaListKind() const override {
538+
return TargetInfo::CharPtrBuiltinVaList;
539+
}
540+
541+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
542+
if (CC == CC_X86VectorCall || CC == CC_X86RegCall)
543+
// Permit CC_X86VectorCall which is used in Microsoft headers
544+
// Permit CC_X86RegCall which is used to mark external functions with
545+
// explicit simd or structure type arguments to pass them via registers.
546+
return CCCR_OK;
547+
return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
548+
: CCCR_Warning;
549+
}
550+
};
551+
552+
// x86-64 SPIRV64 Windows Visual Studio target
553+
class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64_SPIRV64TargetInfo
554+
: public WindowsX86_64_SPIRV64TargetInfo {
555+
public:
556+
MicrosoftX86_64_SPIRV64TargetInfo(const llvm::Triple &Triple,
557+
const TargetOptions &Opts)
558+
: WindowsX86_64_SPIRV64TargetInfo(Triple, Opts) {}
559+
560+
void getTargetDefines(const LangOptions &Opts,
561+
MacroBuilder &Builder) const override {
562+
WindowsX86_64_SPIRV64TargetInfo::getTargetDefines(Opts, Builder);
563+
Builder.defineMacro("_M_X64", "100");
564+
Builder.defineMacro("_M_AMD64", "100");
565+
}
566+
};
567+
478568
} // namespace targets
479569
} // namespace clang
480570
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H

clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// destructor, copy constructor or move constructor defined by user.
33

44
// RUN: %clang -emit-llvm --cuda-device-only --offload=spirv32 \
5-
// RUN: -nocudalib -nocudainc %s -o %t.bc -c 2>&1
5+
// RUN: --target=i386-pc-windows-msvc -nocudalib -nocudainc %s -o %t.bc -c 2>&1
66
// RUN: llvm-dis %t.bc -o %t.ll
77
// RUN: FileCheck %s --input-file=%t.ll
88

clang/test/CodeGenCUDASPIRV/kernel-argument.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
// RUN: %clang -emit-llvm --cuda-device-only --offload=spirv32 \
5-
// RUN: -nocudalib -nocudainc %s -o %t.bc -c 2>&1
5+
// RUN: --target=i386-pc-windows-msvc -nocudalib -nocudainc %s -o %t.bc -c 2>&1
66
// RUN: llvm-dis %t.bc -o %t.ll
77
// RUN: FileCheck %s --input-file=%t.ll
88

clang/test/SemaSYCL/mangle-kernel.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown -aux-triple x86_64-pc-windows-msvc -I %S/../Headers/Inputs/include/ -ast-dump %s | FileCheck %s --check-prefix=CHECK-64-WIN
22
// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown -aux-triple x86_64-unknown-linux-gnu -I %S/../Headers/Inputs/include/ -ast-dump %s | FileCheck %s --check-prefix=CHECK-64-LIN
33
// RUN: %clang_cc1 -fsycl-is-device -triple spir-unknown-linux -I %S/../Headers/Inputs/include/ -ast-dump %s | FileCheck %s --check-prefix=CHECK-32
4+
// RUN: %clang_cc1 -fsycl-is-device -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc -I %S/../Headers/Inputs/include/ -ast-dump %s | FileCheck %s --check-prefix=CHECK-64-WIN
5+
// RUN: %clang_cc1 -fsycl-is-device -triple spirv64-unknown-unknown -aux-triple x86_64-unknown-linux-gnu -I %S/../Headers/Inputs/include/ -ast-dump %s | FileCheck %s --check-prefix=CHECK-64-LIN
6+
// RUN: %clang_cc1 -fsycl-is-device -triple spirv32-unknown-unknown -I %S/../Headers/Inputs/include/ -ast-dump %s | FileCheck %s --check-prefix=CHECK-32
47
#include "Inputs/sycl.hpp"
58
#include <stdlib.h>
69

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// This test verifies that the correct macros are predefined.
2+
// This test verifies that __builtin_va_list is processed without errors.
3+
// RUN: %clang_cc1 -fsycl-is-device -triple spir-unknown-unknown -aux-triple i386-pc-windows-msvc -fsyntax-only -E -dM -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64
4+
// RUN: %clang_cc1 -fsycl-is-device -triple spirv32-unknown-unknown -aux-triple i386-pc-windows-msvc -fsyntax-only -E -dM -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64
5+
// CHECK-MS64: #define _M_IX86 600
6+
void foo(__builtin_va_list bvl) {
7+
char * VaList = bvl;
8+
}

clang/test/SemaSYCL/msvc-fixes.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
1+
// This test verifies that the correct macros are predefined.
2+
// This test checks that sizes of different types are as expected.
3+
// This test verifies that __builtin_va_list is processed without errors.
4+
//
15
// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-windows -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
6+
// RUN: %clang_cc1 -fsycl-is-device -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
27
// expected-no-diagnostics
3-
8+
// RUN: %clang_cc1 -fsycl-is-device -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc -fsyntax-only -E -dM -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64
9+
// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown -aux-triple x86_64-pc-windows-msvc -fsyntax-only -E -dM -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64
10+
// CHECK-MS64: #define _M_AMD64 100
11+
// CHECK-MS64: #define _M_X64 100
12+
typedef __PTRDIFF_TYPE__ ptrdiff_t;
13+
typedef __SIZE_TYPE__ size_t;
14+
typedef __INT64_TYPE__ int64_t;
15+
typedef __INTMAX_TYPE__ intmax_t;
416
void foo(__builtin_va_list bvl) {
517
char * VaList = bvl;
6-
static_assert(sizeof(wchar_t) == 2, "sizeof wchar is 2 on Windows");
18+
static_assert(sizeof(long) == 4, "sizeof long is 4 on Windows (x86_64)");
19+
static_assert(sizeof(double) == 8, "sizeof double is 8 on Windows (x86_64)");
20+
static_assert(sizeof(intmax_t) == 8, "sizeof intmax_t is 8 on Windows (x86_64)");
21+
static_assert(sizeof(int64_t) == 8, "sizeof int64_t is 8 on Windows (x86_64)");
22+
static_assert(sizeof(size_t) == 8, "sizeof size_t is 8 on Windows (x86_64)");
23+
static_assert(sizeof(ptrdiff_t) == 8, "sizeof ptrdiff_t is 8 on Windows (x86_64)");
24+
static_assert(sizeof(int *) == 8, "sizeof IntPtr is 8 on Windows (x86_64)");
25+
static_assert(sizeof(wchar_t) == 2, "sizeof wchar is 2 on Windows (x86_64)");
726
}

0 commit comments

Comments
 (0)