Skip to content

Commit e5bd9da

Browse files
authored
Merge pull request #41928 from hyp/i/ref-ptm
[PrintAsClang] NFC, refactor primitive type mapping logic out from De…
2 parents b07b700 + 86f9162 commit e5bd9da

File tree

6 files changed

+191
-114
lines changed

6 files changed

+191
-114
lines changed

lib/PrintAsClang/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_swift_host_library(swiftPrintAsClang STATIC
33
CxxSynthesis.cpp
44
DeclAndTypePrinter.cpp
55
ModuleContentsWriter.cpp
6+
PrimitiveTypeMapping.cpp
67
PrintAsClang.cpp)
78
target_link_libraries(swiftPrintAsClang PRIVATE
89
swiftAST

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 4 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "DeclAndTypePrinter.h"
1414
#include "CxxSynthesis.h"
15+
#include "PrimitiveTypeMapping.h"
1516

1617
#include "swift/AST/ASTContext.h"
1718
#include "swift/AST/ASTMangler.h"
@@ -1442,7 +1443,7 @@ class DeclAndTypePrinter::Implementation
14421443
/// Otherwise returns null.
14431444
const ClassDecl *getObjCBridgedClass(const NominalTypeDecl *nominal) {
14441445
// Print known types as their unbridged type.
1445-
if (getKnownTypeInfo(nominal))
1446+
if (owningPrinter.typeMapping.getKnownObjCTypeInfo(nominal))
14461447
return nullptr;
14471448

14481449
// Print imported bridgeable decls as their unbridged type.
@@ -1546,102 +1547,6 @@ class DeclAndTypePrinter::Implementation
15461547
return false;
15471548
}
15481549

1549-
/// If \p typeDecl is one of the standard library types used to map in Clang
1550-
/// primitives and basic types, return the info in \c specialNames containing
1551-
/// the Clang name and whether it can be nullable in C.
1552-
Optional<CTypeInfo> getKnownTypeInfo(const TypeDecl *typeDecl) {
1553-
auto &specialNames = owningPrinter.specialNames;
1554-
if (specialNames.empty()) {
1555-
ASTContext &ctx = getASTContext();
1556-
#define MAP(SWIFT_NAME, CLANG_REPR, NEEDS_NULLABILITY) \
1557-
specialNames[{ctx.StdlibModuleName, ctx.getIdentifier(#SWIFT_NAME)}] = \
1558-
{ CLANG_REPR, NEEDS_NULLABILITY }
1559-
1560-
MAP(CBool, "bool", false);
1561-
1562-
MAP(CChar, "char", false);
1563-
MAP(CWideChar, "wchar_t", false);
1564-
MAP(CChar16, "char16_t", false);
1565-
MAP(CChar32, "char32_t", false);
1566-
1567-
MAP(CSignedChar, "signed char", false);
1568-
MAP(CShort, "short", false);
1569-
MAP(CInt, "int", false);
1570-
MAP(CLong, "long", false);
1571-
MAP(CLongLong, "long long", false);
1572-
1573-
MAP(CUnsignedChar, "unsigned char", false);
1574-
MAP(CUnsignedShort, "unsigned short", false);
1575-
MAP(CUnsignedInt, "unsigned int", false);
1576-
MAP(CUnsignedLong, "unsigned long", false);
1577-
MAP(CUnsignedLongLong, "unsigned long long", false);
1578-
1579-
MAP(CFloat, "float", false);
1580-
MAP(CDouble, "double", false);
1581-
1582-
MAP(Int8, "int8_t", false);
1583-
MAP(Int16, "int16_t", false);
1584-
MAP(Int32, "int32_t", false);
1585-
MAP(Int64, "int64_t", false);
1586-
MAP(UInt8, "uint8_t", false);
1587-
MAP(UInt16, "uint16_t", false);
1588-
MAP(UInt32, "uint32_t", false);
1589-
MAP(UInt64, "uint64_t", false);
1590-
1591-
MAP(Float, "float", false);
1592-
MAP(Double, "double", false);
1593-
MAP(Float32, "float", false);
1594-
MAP(Float64, "double", false);
1595-
1596-
MAP(Int, "NSInteger", false);
1597-
MAP(UInt, "NSUInteger", false);
1598-
MAP(Bool, "BOOL", false);
1599-
1600-
MAP(OpaquePointer, "void *", true);
1601-
MAP(UnsafeRawPointer, "void const *", true);
1602-
MAP(UnsafeMutableRawPointer, "void *", true);
1603-
1604-
Identifier ID_ObjectiveC = ctx.Id_ObjectiveC;
1605-
specialNames[{ID_ObjectiveC, ctx.getIdentifier("ObjCBool")}]
1606-
= { "BOOL", false};
1607-
specialNames[{ID_ObjectiveC, ctx.getIdentifier("Selector")}]
1608-
= { "SEL", true };
1609-
specialNames[{ID_ObjectiveC,
1610-
ctx.getIdentifier(
1611-
ctx.getSwiftName(KnownFoundationEntity::NSZone))}]
1612-
= { "struct _NSZone *", true };
1613-
1614-
specialNames[{ctx.Id_Darwin, ctx.getIdentifier("DarwinBoolean")}]
1615-
= { "Boolean", false};
1616-
1617-
specialNames[{ctx.Id_CoreGraphics, ctx.Id_CGFloat}]
1618-
= { "CGFloat", false };
1619-
1620-
specialNames[{ctx.Id_CoreFoundation, ctx.Id_CGFloat}]
1621-
= { "CGFloat", false };
1622-
1623-
// Use typedefs we set up for SIMD vector types.
1624-
#define MAP_SIMD_TYPE(BASENAME, _, __) \
1625-
specialNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "2")}] \
1626-
= { "swift_" #BASENAME "2", false }; \
1627-
specialNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "3")}] \
1628-
= { "swift_" #BASENAME "3", false }; \
1629-
specialNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "4")}] \
1630-
= { "swift_" #BASENAME "4", false };
1631-
#include "swift/ClangImporter/SIMDMappedTypes.def"
1632-
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
1633-
"must add or remove special name mappings if max number of "
1634-
"SIMD elements is changed");
1635-
}
1636-
1637-
Identifier moduleName = typeDecl->getModuleContext()->getName();
1638-
Identifier name = typeDecl->getName();
1639-
auto iter = specialNames.find({moduleName, name});
1640-
if (iter == specialNames.end())
1641-
return None;
1642-
return iter->second;
1643-
}
1644-
16451550
/// If \p typeDecl is one of the standard library types used to map in Clang
16461551
/// primitives and basic types, print out the appropriate spelling and
16471552
/// return true.
@@ -1650,7 +1555,8 @@ class DeclAndTypePrinter::Implementation
16501555
/// for interfacing with C and Objective-C.
16511556
bool printIfKnownSimpleType(const TypeDecl *typeDecl,
16521557
Optional<OptionalTypeKind> optionalKind) {
1653-
Optional<CTypeInfo> knownTypeInfo = getKnownTypeInfo(typeDecl);
1558+
auto knownTypeInfo =
1559+
owningPrinter.typeMapping.getKnownObjCTypeInfo(typeDecl);
16541560
if (!knownTypeInfo)
16551561
return false;
16561562
os << knownTypeInfo->name;

lib/PrintAsClang/DeclAndTypePrinter.h

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ namespace clang {
2525

2626
namespace swift {
2727

28+
class PrimitiveTypeMapping;
29+
2830
/// Responsible for printing a Swift Decl or Type in Objective-C, to be
2931
/// included in a Swift module's ObjC compatibility header.
3032
class DeclAndTypePrinter {
@@ -39,22 +41,10 @@ class DeclAndTypePrinter {
3941
raw_ostream &os;
4042
raw_ostream &prologueOS;
4143
const DelayedMemberSet &delayedMembers;
44+
PrimitiveTypeMapping &typeMapping;
4245
AccessLevel minRequiredAccess;
4346
OutputLanguageMode outputLang;
4447

45-
struct CTypeInfo {
46-
StringRef name;
47-
bool canBeNullable;
48-
};
49-
50-
/// A map from {Module, TypeName} pairs to {C name, C nullability} pairs.
51-
///
52-
/// This is populated on first use with a list of known Swift types that are
53-
/// translated directly by the ObjC printer instead of structurally, allowing
54-
/// it to do things like map 'Int' to 'NSInteger' and 'Float' to 'float'.
55-
/// In some sense it's the reverse of the ClangImporter's MappedTypes.def.
56-
llvm::DenseMap<std::pair<Identifier, Identifier>, CTypeInfo> specialNames;
57-
5848
/// The name 'CFTypeRef'.
5949
///
6050
/// Cached for convenience.
@@ -64,10 +54,12 @@ class DeclAndTypePrinter {
6454

6555
public:
6656
DeclAndTypePrinter(ModuleDecl &mod, raw_ostream &out, raw_ostream &prologueOS,
67-
DelayedMemberSet &delayed, AccessLevel access,
57+
DelayedMemberSet &delayed,
58+
PrimitiveTypeMapping &typeMapping, AccessLevel access,
6859
OutputLanguageMode outputLang)
6960
: M(mod), os(out), prologueOS(prologueOS), delayedMembers(delayed),
70-
minRequiredAccess(access), outputLang(outputLang) {}
61+
typeMapping(typeMapping), minRequiredAccess(access),
62+
outputLang(outputLang) {}
7163

7264
/// Returns true if \p VD should be included in a compatibility header for
7365
/// the options the printer was constructed with.

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "CxxSynthesis.h"
1616
#include "DeclAndTypePrinter.h"
1717
#include "OutputLanguageMode.h"
18+
#include "PrimitiveTypeMapping.h"
1819

1920
#include "swift/AST/ExistentialLayout.h"
2021
#include "swift/AST/Module.h"
@@ -123,6 +124,7 @@ class ModuleWriter {
123124
llvm::DenseMap<const TypeDecl *, std::pair<EmissionState, bool>> seenTypes;
124125
std::vector<const Decl *> declsToWrite;
125126
DelayedMemberSet delayedMembers;
127+
PrimitiveTypeMapping typeMapping;
126128
DeclAndTypePrinter printer;
127129
OutputLanguageMode outputLangMode;
128130

@@ -131,7 +133,8 @@ class ModuleWriter {
131133
llvm::SmallPtrSetImpl<ImportModuleTy> &imports, ModuleDecl &mod,
132134
AccessLevel access, OutputLanguageMode outputLang)
133135
: os(os), imports(imports), M(mod),
134-
printer(M, os, prologueOS, delayedMembers, access, outputLang),
136+
printer(M, os, prologueOS, delayedMembers, typeMapping, access,
137+
outputLang),
135138
outputLangMode(outputLang) {}
136139

137140
/// Returns true if we added the decl's module to the import set, false if
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//===--- PrimitiveTypeMapping.cpp - Mapping primitive types -----*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "PrimitiveTypeMapping.h"
14+
#include "swift/AST/ASTContext.h"
15+
#include "swift/AST/Decl.h"
16+
#include "swift/AST/Module.h"
17+
#include "swift/ClangImporter/ClangImporter.h"
18+
19+
using namespace swift;
20+
21+
void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
22+
assert(mappedTypeNames.empty() && "expected empty type map");
23+
#define MAP(SWIFT_NAME, CLANG_REPR, NEEDS_NULLABILITY) \
24+
mappedTypeNames[{ctx.StdlibModuleName, ctx.getIdentifier(#SWIFT_NAME)}] = { \
25+
CLANG_REPR, NEEDS_NULLABILITY}
26+
27+
MAP(CBool, "bool", false);
28+
29+
MAP(CChar, "char", false);
30+
MAP(CWideChar, "wchar_t", false);
31+
MAP(CChar16, "char16_t", false);
32+
MAP(CChar32, "char32_t", false);
33+
34+
MAP(CSignedChar, "signed char", false);
35+
MAP(CShort, "short", false);
36+
MAP(CInt, "int", false);
37+
MAP(CLong, "long", false);
38+
MAP(CLongLong, "long long", false);
39+
40+
MAP(CUnsignedChar, "unsigned char", false);
41+
MAP(CUnsignedShort, "unsigned short", false);
42+
MAP(CUnsignedInt, "unsigned int", false);
43+
MAP(CUnsignedLong, "unsigned long", false);
44+
MAP(CUnsignedLongLong, "unsigned long long", false);
45+
46+
MAP(CFloat, "float", false);
47+
MAP(CDouble, "double", false);
48+
49+
MAP(Int8, "int8_t", false);
50+
MAP(Int16, "int16_t", false);
51+
MAP(Int32, "int32_t", false);
52+
MAP(Int64, "int64_t", false);
53+
MAP(UInt8, "uint8_t", false);
54+
MAP(UInt16, "uint16_t", false);
55+
MAP(UInt32, "uint32_t", false);
56+
MAP(UInt64, "uint64_t", false);
57+
58+
MAP(Float, "float", false);
59+
MAP(Double, "double", false);
60+
MAP(Float32, "float", false);
61+
MAP(Float64, "double", false);
62+
63+
MAP(Int, "NSInteger", false);
64+
MAP(UInt, "NSUInteger", false);
65+
MAP(Bool, "BOOL", false);
66+
67+
MAP(OpaquePointer, "void *", true);
68+
MAP(UnsafeRawPointer, "void const *", true);
69+
MAP(UnsafeMutableRawPointer, "void *", true);
70+
71+
Identifier ID_ObjectiveC = ctx.Id_ObjectiveC;
72+
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier("ObjCBool")}] = {"BOOL",
73+
false};
74+
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier("Selector")}] = {"SEL",
75+
true};
76+
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier(ctx.getSwiftName(
77+
KnownFoundationEntity::NSZone))}] = {
78+
"struct _NSZone *", true};
79+
80+
mappedTypeNames[{ctx.Id_Darwin, ctx.getIdentifier("DarwinBoolean")}] = {
81+
"Boolean", false};
82+
83+
mappedTypeNames[{ctx.Id_CoreGraphics, ctx.Id_CGFloat}] = {"CGFloat", false};
84+
85+
mappedTypeNames[{ctx.Id_CoreFoundation, ctx.Id_CGFloat}] = {"CGFloat", false};
86+
87+
// Use typedefs we set up for SIMD vector types.
88+
#define MAP_SIMD_TYPE(BASENAME, _, __) \
89+
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "2")}] = { \
90+
"swift_" #BASENAME "2", false}; \
91+
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "3")}] = { \
92+
"swift_" #BASENAME "3", false}; \
93+
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "4")}] = { \
94+
"swift_" #BASENAME "4", false};
95+
#include "swift/ClangImporter/SIMDMappedTypes.def"
96+
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
97+
"must add or remove special name mappings if max number of "
98+
"SIMD elements is changed");
99+
}
100+
101+
Optional<PrimitiveTypeMapping::ObjCClangTypeInfo>
102+
PrimitiveTypeMapping::getKnownObjCTypeInfo(const TypeDecl *typeDecl) {
103+
if (mappedTypeNames.empty())
104+
initialize(typeDecl->getASTContext());
105+
106+
Identifier moduleName = typeDecl->getModuleContext()->getName();
107+
Identifier name = typeDecl->getName();
108+
auto iter = mappedTypeNames.find({moduleName, name});
109+
if (iter == mappedTypeNames.end())
110+
return None;
111+
return ObjCClangTypeInfo{iter->second.objcName, iter->second.canBeNullable};
112+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===--- PrimitiveTypeMapping.h - Mapping primitive types -------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_PRINTASCLANG_PRIMITIVETYPEMAPPING_H
14+
#define SWIFT_PRINTASCLANG_PRIMITIVETYPEMAPPING_H
15+
16+
#include "swift/AST/Identifier.h"
17+
#include "swift/Basic/LLVM.h"
18+
#include "llvm/ADT/DenseMap.h"
19+
20+
namespace swift {
21+
22+
class ASTContext;
23+
class TypeDecl;
24+
25+
/// Provides a mapping from Swift's primitive types to C / Objective-C / C++
26+
/// primitive types.
27+
///
28+
/// Certain types have mappings that differ in different language modes.
29+
/// For example, Swift's `Int` maps to `NSInteger` for Objective-C declarations,
30+
/// but to something like `intptr_t` or `swift::Int` for C and C++ declarations.
31+
class PrimitiveTypeMapping {
32+
public:
33+
struct ObjCClangTypeInfo {
34+
StringRef name;
35+
bool canBeNullable;
36+
};
37+
38+
/// Returns the Objective-C type name and nullability for the given Swift
39+
/// primitive type declaration, or \c None if no such type name exists.
40+
Optional<ObjCClangTypeInfo> getKnownObjCTypeInfo(const TypeDecl *typeDecl);
41+
42+
private:
43+
void initialize(ASTContext &ctx);
44+
45+
struct ClangTypeInfo {
46+
// The Objective-C name of the Swift type.
47+
StringRef objcName;
48+
bool canBeNullable;
49+
};
50+
51+
/// A map from {Module, TypeName} pairs to {C name, C nullability} pairs.
52+
///
53+
/// This is populated on first use with a list of known Swift types that are
54+
/// translated directly by the ObjC printer instead of structurally, allowing
55+
/// it to do things like map 'Int' to 'NSInteger' and 'Float' to 'float'.
56+
/// In some sense it's the reverse of the ClangImporter's MappedTypes.def.
57+
llvm::DenseMap<std::pair<Identifier, Identifier>, ClangTypeInfo>
58+
mappedTypeNames;
59+
};
60+
61+
} // end namespace swift
62+
63+
#endif

0 commit comments

Comments
 (0)