1
- // ===--- SwiftTargetInfo.cpp --------------------------------------------* -===//
1
+ // ===--- SwiftTargetInfo.cpp --------------------------------------------- -===//
2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
19
19
#include " IRGenModule.h"
20
20
#include " llvm/ADT/Triple.h"
21
21
#include " llvm/IR/DataLayout.h"
22
- #include " swift/IRGen/Options.h"
22
+ #include " swift/ABI/System.h"
23
+ #include " swift/AST/IRGenOptions.h"
23
24
24
25
using namespace swift ;
25
26
using namespace irgen ;
26
27
27
- // / Creates a generic SwiftTargetInfo with conservative values that should
28
- // / be valid for any platform absent more specific information.
29
- static SwiftTargetInfo getGenericSwiftTargetInfo (IRGenModule &IGM) {
30
- auto pointerSize = IGM.DataLayout .getPointerSizeInBits ();
31
-
32
- // Assume no spare bits in pointers.
33
- llvm::BitVector pointerSpareBits (pointerSize, false );
34
- // Assume all bit patterns are reserved by the ObjC runtime.
35
- llvm::BitVector objcReservedBits (pointerSize, true );
36
- // Assume no special alignment of heap objects.
37
- Alignment heapObjectAlignment (1 );
38
- // Assume only zero is an invalid pointer.
39
- uint64_t leastValidPointerValue = 1 ;
40
-
41
- return SwiftTargetInfo (std::move (pointerSpareBits),
42
- std::move (objcReservedBits),
43
- heapObjectAlignment,
44
- leastValidPointerValue);
28
+ // / Initialize a bit vector to be equal to the given bit-mask.
29
+ static void setToMask (llvm::BitVector &bits, uint64_t mask) {
30
+ // This is a ridiculously inefficient way of doing this.
31
+ for (unsigned i = 0 , e = bits.size (); i != e; ++i) {
32
+ if (mask & (1ULL << i)) {
33
+ bits.set (i);
34
+ } else {
35
+ bits.reset (i);
36
+ }
37
+ }
45
38
}
46
39
47
- // / Creates SwiftTargetInfo for X86-64 platforms.
48
- static SwiftTargetInfo getX86_64SwiftTargetInfo (IRGenModule &IGM) {
49
- // User space only uses the low 47 bits of a pointer.
50
- // FIXME: In kernel mode, the highest bit is occupied.
51
- llvm::BitVector pointerSpareBits (47 , false );
52
- pointerSpareBits.resize (64 , true );
40
+ // / Configures target-specific information for arm64 platforms.
41
+ static void configureARM64 (IRGenModule &IGM, const llvm::Triple &triple,
42
+ SwiftTargetInfo &target) {
43
+ setToMask (target.PointerSpareBits ,
44
+ SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK);
45
+ setToMask (target.ObjCPointerReservedBits ,
46
+ SWIFT_ABI_ARM64_OBJC_RESERVED_BITS_MASK);
53
47
54
- // Objective-C reserves the lowest and highest bits for tagged pointers.
55
- llvm::BitVector objcReservedBits (64 , false );
56
- objcReservedBits[0 ] = true ;
57
- objcReservedBits[63 ] = true ;
48
+ if (triple.isOSDarwin ()) {
49
+ target.LeastValidPointerValue =
50
+ SWIFT_ABI_DARWIN_ARM64_LEAST_VALID_POINTER;
51
+ }
52
+
53
+ // CGPoint and CGRect are both returned in registers.
54
+ target.MaxScalarsForDirectResult = 4 ;
55
+
56
+ // arm64 has no special objc_msgSend variants, not even stret.
57
+ target.ObjCUseStret = false ;
58
+
59
+ // arm64 requires marker assembly for objc_retainAutoreleasedReturnValue.
60
+ target.ObjCRetainAutoreleasedReturnValueMarker =
61
+ " mov\t fp, fp\t\t ; marker for objc_retainAutoreleaseReturnValue" ;
62
+ }
63
+
64
+ // / Configures target-specific information for x86-64 platforms.
65
+ static void configureX86_64 (IRGenModule &IGM, const llvm::Triple &triple,
66
+ SwiftTargetInfo &target) {
67
+ setToMask (target.PointerSpareBits ,
68
+ SWIFT_ABI_X86_64_SWIFT_SPARE_BITS_MASK);
69
+ setToMask (target.ObjCPointerReservedBits ,
70
+ SWIFT_ABI_X86_64_OBJC_RESERVED_BITS_MASK);
58
71
59
- // Heap objects are 16-byte-aligned.
60
- Alignment heapObjectAlignment (16 );
72
+ if (triple.isOSDarwin ()) {
73
+ target.LeastValidPointerValue =
74
+ SWIFT_ABI_DARWIN_X86_64_LEAST_VALID_POINTER;
75
+ }
76
+
77
+ // On simulator targets, use null instead of &_objc_empty_vtable.
78
+ if (triple.isiOS ())
79
+ target.ObjCUseNullForEmptyVTable = true ;
61
80
62
- // The null 4K page is always unmapped.
63
- // FIXME: Are additional null pages always unmapped on some platforms?
64
- uint64_t leastValidPointerValue = 4096 ;
81
+ // x86-64 has every objc_msgSend variant known to humankind.
82
+ target.ObjCUseFPRet = true ;
83
+ target.ObjCUseFP2Ret = true ;
84
+ }
85
+
86
+ // / Configures target-specific information for 32-bit x86 platforms.
87
+ static void configureX86 (IRGenModule &IGM, const llvm::Triple &triple,
88
+ SwiftTargetInfo &target) {
89
+ // On simulator targets, use null instead of &_objc_empty_vtable.
90
+ if (triple.isiOS ())
91
+ target.ObjCUseNullForEmptyVTable = true ;
65
92
66
- return SwiftTargetInfo (std::move (pointerSpareBits),
67
- std::move (objcReservedBits),
68
- heapObjectAlignment,
69
- leastValidPointerValue);
93
+ // x86 uses objc_msgSend_fpret but not objc_msgSend_fp2ret.
94
+ target.ObjCUseFPRet = true ;
95
+ }
96
+
97
+ // / Configures target-specific information for 32-bit arm platforms.
98
+ static void configureARM (IRGenModule &IGM, const llvm::Triple &triple,
99
+ SwiftTargetInfo &target) {
100
+ // ARM requires marker assembly for objc_retainAutoreleasedReturnValue.
101
+ target.ObjCRetainAutoreleasedReturnValueMarker =
102
+ " mov\t r7, r7\t\t @ marker for objc_retainAutoreleaseReturnValue" ;
103
+ }
104
+
105
+ // / Configure a default target.
106
+ SwiftTargetInfo::SwiftTargetInfo (unsigned numPointerBits)
107
+ : PointerSpareBits(numPointerBits, false ),
108
+ ObjCPointerReservedBits(numPointerBits, true ),
109
+ HeapObjectAlignment(numPointerBits / 8 ),
110
+ LeastValidPointerValue(SWIFT_ABI_DEFAULT_LEAST_VALID_POINTER)
111
+ {
112
+ setToMask (PointerSpareBits,
113
+ SWIFT_ABI_DEFAULT_SWIFT_SPARE_BITS_MASK);
114
+ setToMask (ObjCPointerReservedBits,
115
+ SWIFT_ABI_DEFAULT_OBJC_RESERVED_BITS_MASK);
70
116
}
71
117
72
118
SwiftTargetInfo SwiftTargetInfo::get (IRGenModule &IGM) {
73
119
llvm::Triple triple (IGM.Opts .Triple );
120
+ auto pointerSize = IGM.DataLayout .getPointerSizeInBits ();
121
+
122
+ // / Prepare generic target information.
123
+ SwiftTargetInfo target (pointerSize);
74
124
75
125
switch (triple.getArch ()) {
76
126
case llvm::Triple::x86_64:
77
- return getX86_64SwiftTargetInfo (IGM);
127
+ configureX86_64 (IGM, triple, target);
128
+ break ;
129
+
130
+ case llvm::Triple::x86:
131
+ configureX86 (IGM, triple, target);
132
+ break ;
133
+
134
+ case llvm::Triple::arm:
135
+ configureARM (IGM, triple, target);
136
+ break ;
137
+
138
+ case llvm::Triple::arm64:
139
+ configureARM64 (IGM, triple, target);
140
+ break ;
141
+
78
142
default :
79
- return getGenericSwiftTargetInfo (IGM);
143
+ // FIXME: Complain here? Default target info is unlikely to be correct.
144
+ break ;
145
+ }
146
+
147
+ // The JIT does not support absolute symbols, so we have to use null
148
+ // for &objc_empty_vtable.
149
+ if (IGM.Opts .UseJIT ) {
150
+ target.ObjCUseNullForEmptyVTable = true ;
80
151
}
81
- }
152
+
153
+ return target;
154
+ }
155
+
0 commit comments