|
17 | 17 |
|
18 | 18 | using namespace swift;
|
19 | 19 |
|
| 20 | +/// We could use a higher bit. But by reusing the first bit, we just save a |
| 21 | +/// little bit of code. |
| 22 | +/// |
| 23 | +/// $valueToShift << (((sizeof(Word) - 1) << 3) + 4) |
| 24 | +/// |
| 25 | +/// Mathematicaly this is $valueToShift * 2**((sizeof(Word) - 1)*8 + 4) |
| 26 | +/// |
| 27 | +/// On 64 bit this is 60. This works since we want to use the bottom two bits of |
| 28 | +/// the top nibble of the TBI bits. |
| 29 | +static SILValue getTBIBits(SILBuilder &b, SILLocation loc, |
| 30 | + unsigned valueToShift = 1) { |
| 31 | + auto &ctx = b.getASTContext(); |
| 32 | + auto silWordType = SILType::getBuiltinWordType(ctx); |
| 33 | + |
| 34 | + auto id = ctx.getIdentifier(getBuiltinName(BuiltinValueKind::Sizeof)); |
| 35 | + auto *builtin = cast<FuncDecl>(getBuiltinValueDecl(ctx, id)); |
| 36 | + auto wordType = BuiltinIntegerType::getWordType(ctx)->getCanonicalType(); |
| 37 | + auto metatypeTy = SILType::getPrimitiveObjectType(CanMetatypeType::get( |
| 38 | + wordType->getCanonicalType(), MetatypeRepresentation::Thin)); |
| 39 | + auto metatypeVal = b.createMetatype(loc, metatypeTy); |
| 40 | + |
| 41 | + auto sizeOfWord = |
| 42 | + b.createBuiltin(loc, id, silWordType, |
| 43 | + SubstitutionMap::get(builtin->getGenericSignature(), |
| 44 | + ArrayRef<Type>{wordType}, |
| 45 | + LookUpConformanceInModule()), |
| 46 | + {metatypeVal}); |
| 47 | + auto one = b.createIntegerLiteral(loc, silWordType, 1); |
| 48 | + auto three = b.createIntegerLiteral(loc, silWordType, 3); |
| 49 | + auto four = b.createIntegerLiteral(loc, silWordType, 4); |
| 50 | + auto valueToShiftLit = b.createIntegerLiteral(loc, silWordType, valueToShift); |
| 51 | + |
| 52 | + // sizeof(Word) - 1 |
| 53 | + auto sub = b.createBuiltinBinaryFunction(loc, "sub", silWordType, silWordType, |
| 54 | + {sizeOfWord, one}); |
| 55 | + // (sizeof(Word) - 1) << 3 |
| 56 | + auto innerShift = b.createBuiltinBinaryFunction(loc, "shl", silWordType, |
| 57 | + silWordType, {sub, three}); |
| 58 | + // ((sizeof(Word) - 1) << 3) + 4 |
| 59 | + auto innerShiftOffset = b.createBuiltinBinaryFunction( |
| 60 | + loc, "add", silWordType, silWordType, {innerShift, four}); |
| 61 | + auto outerShift = |
| 62 | + b.createBuiltinBinaryFunction(loc, "shl", silWordType, silWordType, |
| 63 | + {valueToShiftLit, innerShiftOffset}); |
| 64 | + return outerShift; |
| 65 | +} |
| 66 | + |
| 67 | +/// Construct the TBI mask in a platform independent way that works on all |
| 68 | +/// platforms. |
| 69 | +/// |
| 70 | +/// We compute: |
| 71 | +/// |
| 72 | +/// mask = (0x3 << (((sizeof(Word) - 1) << 3) + 4)) ^ -1 |
| 73 | +static SILValue getTBIClearMask(SILBuilder &b, SILLocation loc) { |
| 74 | + auto &ctx = b.getASTContext(); |
| 75 | + auto silWordType = SILType::getBuiltinWordType(ctx); |
| 76 | + auto negBits = b.createIntegerLiteral(loc, silWordType, -1); |
| 77 | + |
| 78 | + return b.createBuiltinBinaryFunction(loc, "xor", silWordType, silWordType, |
| 79 | + {getTBIBits(b, loc, 3), negBits}); |
| 80 | +} |
| 81 | + |
| 82 | +static SILValue transformTupleElts( |
| 83 | + SILBuilder &b, SILLocation loc, SILValue mv, SILType finalType, |
| 84 | + llvm::function_ref<SILValue(ArrayRef<SILValue> destructureValues)> func) { |
| 85 | + auto &ctx = b.getASTContext(); |
| 86 | + auto silWordType = SILType::getBuiltinWordType(ctx); |
| 87 | + auto tupleType = |
| 88 | + SILType::getTupleType(b.getASTContext(), {silWordType, silWordType}); |
| 89 | + auto cast = b.emitUncheckedValueCast(loc, mv, tupleType); |
| 90 | + SmallVector<SILValue, 2> destructureValues; |
| 91 | + b.emitDestructureOperation(loc, cast, destructureValues); |
| 92 | + SILValue reformedValue = func(destructureValues); |
| 93 | + auto reformedPointer = |
| 94 | + b.emitUncheckedValueCast(loc, reformedValue, finalType); |
| 95 | + |
| 96 | + // NOTE: Our reformed pointer is actually has none ownership here. Our value |
| 97 | + // gains guaranteed ownership by the merging the guaranteedness of mv (the |
| 98 | + // mark dependence base). |
| 99 | + // |
| 100 | + // DISCUSSION: This is important since we allows for us to avoid needing to |
| 101 | + // insert end_borrows on the reformed value in our caller which would be |
| 102 | + // required if we used an unchecked_ownership_conversion. The author |
| 103 | + // originally did that thinking it would be safer but hit problems in |
| 104 | + // SILGenApply since even if we inserted an end_borrow for the |
| 105 | + // unchecked_ownership_conversion, we failed to insert the end_borrow along |
| 106 | + // error paths of try_apply due to the way SILGenApply is setup. After some |
| 107 | + // thought, it became clear we could safely just rely on mark_dependence to |
| 108 | + // mixin the guaranteedness and get the semantics that we cared about (tieing |
| 109 | + // the reformed value to the lifetime of the original value in a guaranteed |
| 110 | + // way). |
| 111 | + return b.emitMarkDependence(loc, reformedPointer, mv, |
| 112 | + MarkDependenceKind::NonEscaping); |
| 113 | +} |
| 114 | + |
20 | 115 | SILValue swift::clearImplicitIsolationActorBits(SILBuilder &b, SILLocation loc,
|
21 | 116 | SILValue value,
|
22 | 117 | SILType finalType) {
|
23 | 118 | if (!finalType)
|
24 | 119 | finalType =
|
25 | 120 | SILType::getBuiltinImplicitIsolationActorType(b.getASTContext());
|
26 |
| - if (value->getType() == finalType) |
27 |
| - return value; |
28 |
| - return b.emitUncheckedValueCast(loc, value, finalType); |
| 121 | + |
| 122 | + auto &ctx = b.getASTContext(); |
| 123 | + |
| 124 | + return transformTupleElts( |
| 125 | + b, loc, value, finalType, [&](ArrayRef<SILValue> tupleElts) { |
| 126 | + auto silWordType = SILType::getBuiltinWordType(ctx); |
| 127 | + SILValue bitMask = ctx.LangOpts.HasAArch64TBI |
| 128 | + ? getTBIClearMask(b, loc) |
| 129 | + : b.createIntegerLiteral(loc, silWordType, -4); |
| 130 | + |
| 131 | + auto result = b.createBuiltinBinaryFunction( |
| 132 | + loc, "and", silWordType, silWordType, {tupleElts[1], bitMask}); |
| 133 | + return b.createTuple(loc, {tupleElts[0], result}); |
| 134 | + }); |
29 | 135 | }
|
30 | 136 |
|
31 | 137 | SILValue swift::setImplicitIsolationActorBits(SILBuilder &b, SILLocation loc,
|
32 | 138 | SILValue value) {
|
33 |
| - return value; |
| 139 | + auto &ctx = b.getASTContext(); |
| 140 | + |
| 141 | + return transformTupleElts( |
| 142 | + b, loc, value, value->getType(), [&](ArrayRef<SILValue> tupleElts) { |
| 143 | + auto silWordType = SILType::getBuiltinWordType(ctx); |
| 144 | + SILValue bitMask = ctx.LangOpts.HasAArch64TBI |
| 145 | + ? getTBIBits(b, loc) |
| 146 | + : b.createIntegerLiteral(loc, silWordType, 1); |
| 147 | + |
| 148 | + auto result = b.createBuiltinBinaryFunction( |
| 149 | + loc, "or", silWordType, silWordType, {tupleElts[1], bitMask}); |
| 150 | + return b.createTuple(loc, {tupleElts[0], result}); |
| 151 | + }); |
34 | 152 | }
|
0 commit comments