|
24 | 24 | #include "llvm/Support/raw_ostream.h"
|
25 | 25 | #include "llvm/IR/DerivedTypes.h"
|
26 | 26 |
|
| 27 | +#include "FixedTypeInfo.h" |
27 | 28 | #include "IRGenFunction.h"
|
28 | 29 | #include "IRGenModule.h"
|
29 | 30 | #include "ProtocolInfo.h"
|
@@ -948,41 +949,161 @@ void irgen::emitDestroyCall(IRGenFunction &IGF, llvm::Value *metadata,
|
948 | 949 |
|
949 | 950 | Address irgen::emitAllocateValueInBuffer(IRGenFunction &IGF, SILType type,
|
950 | 951 | Address buffer) {
|
951 |
| - auto *size = emitLoadOfSize(IGF, type); |
952 |
| - auto *alignMask = emitLoadOfAlignmentMask(IGF, type); |
953 |
| - // TODO: check whether we fit in the inline value buffer. |
954 |
| - auto valueAddr = IGF.emitAllocRawCall(size, alignMask, "outline.ValueBuffer"); |
955 |
| - IGF.Builder.CreateStore( |
956 |
| - valueAddr, |
957 |
| - Address(IGF.Builder.CreateBitCast(buffer.getAddress(), |
958 |
| - valueAddr->getType()->getPointerTo()), |
959 |
| - Alignment(1))); |
960 |
| - valueAddr = |
961 |
| - IGF.Builder.CreateBitCast(valueAddr, IGF.IGM.getStoragePointerType(type)); |
962 |
| - return Address(valueAddr, Alignment(1)); |
963 |
| - |
964 |
| -} |
965 |
| - |
966 |
| -Address irgen::emitProjectValueInBuffer(IRGenFunction &IGF, |
967 |
| - SILType type, |
968 |
| - Address buffer) { |
969 |
| - // TODO: check whether we fit in the inline value buffer. |
970 |
| - auto ptr = IGF.Builder.CreateLoad(Address( |
971 |
| - IGF.Builder.CreateBitCast(buffer.getAddress(), IGF.IGM.Int8PtrPtrTy), |
972 |
| - Alignment(1))); |
973 |
| - auto valueAddr = |
974 |
| - IGF.Builder.CreateBitCast(ptr, IGF.IGM.getStoragePointerType(type)); |
975 |
| - return Address(valueAddr, Alignment(1)); |
| 952 | + // Handle FixedSize types. |
| 953 | + auto &IGM = IGF.IGM; |
| 954 | + auto storagePtrTy = IGM.getStoragePointerType(type); |
| 955 | + if (auto *fixedTI = dyn_cast<FixedTypeInfo>(&IGF.getTypeInfo(type))) { |
| 956 | + auto packing = fixedTI->getFixedPacking(IGM); |
| 957 | + |
| 958 | + // Inline representation. |
| 959 | + if (packing == FixedPacking::OffsetZero) { |
| 960 | + return Address( |
| 961 | + IGF.Builder.CreateBitCast(buffer.getAddress(), storagePtrTy), |
| 962 | + buffer.getAlignment()); |
| 963 | + } |
| 964 | + |
| 965 | + // Outline representation. |
| 966 | + assert(packing == FixedPacking::Allocate && "Expect non dynamic packing"); |
| 967 | + auto size = fixedTI->getStaticSize(IGM); |
| 968 | + auto alignMask = fixedTI->getStaticAlignmentMask(IGM); |
| 969 | + auto valueAddr = |
| 970 | + IGF.emitAllocRawCall(size, alignMask, "outline.ValueBuffer"); |
| 971 | + IGF.Builder.CreateStore( |
| 972 | + valueAddr, |
| 973 | + Address(IGF.Builder.CreateBitCast(buffer.getAddress(), |
| 974 | + valueAddr->getType()->getPointerTo()), |
| 975 | + buffer.getAlignment())); |
| 976 | + return Address(IGF.Builder.CreateBitCast(valueAddr, storagePtrTy), |
| 977 | + buffer.getAlignment()); |
| 978 | + } |
| 979 | + |
| 980 | + // Dynamic packing. |
| 981 | + llvm::Value *isInline = emitLoadOfIsInline(IGF, type); |
| 982 | + auto *outlineBB = IGF.createBasicBlock("outline.allocateValueInBuffer"); |
| 983 | + auto *doneBB = IGF.createBasicBlock("done"); |
| 984 | + llvm::Value *addressInline, *addressOutline; |
| 985 | + auto *origBB = IGF.Builder.GetInsertBlock(); |
| 986 | + addressInline = IGF.Builder.CreateBitCast(buffer.getAddress(), storagePtrTy); |
| 987 | + IGF.Builder.CreateCondBr(isInline, doneBB, outlineBB); |
| 988 | + |
| 989 | + IGF.Builder.emitBlock(outlineBB); |
| 990 | + { |
| 991 | + ConditionalDominanceScope scope(IGF); |
| 992 | + auto *size = emitLoadOfSize(IGF, type); |
| 993 | + auto *alignMask = emitLoadOfAlignmentMask(IGF, type); |
| 994 | + auto valueAddr = |
| 995 | + IGF.emitAllocRawCall(size, alignMask, "outline.ValueBuffer"); |
| 996 | + IGF.Builder.CreateStore( |
| 997 | + valueAddr, |
| 998 | + Address(IGF.Builder.CreateBitCast(buffer.getAddress(), |
| 999 | + valueAddr->getType()->getPointerTo()), |
| 1000 | + Alignment(1))); |
| 1001 | + addressOutline = IGF.Builder.CreateBitCast(valueAddr, storagePtrTy); |
| 1002 | + IGF.Builder.CreateBr(doneBB); |
| 1003 | + } |
| 1004 | + |
| 1005 | + IGF.Builder.emitBlock(doneBB); |
| 1006 | + auto *addressOfValue = IGF.Builder.CreatePHI(storagePtrTy, 2); |
| 1007 | + addressOfValue->addIncoming(addressInline, origBB); |
| 1008 | + addressOfValue->addIncoming(addressOutline, outlineBB); |
| 1009 | + |
| 1010 | + return Address(addressOfValue, Alignment(1)); |
| 1011 | +} |
| 1012 | + |
| 1013 | +Address irgen::emitProjectValueInBuffer(IRGenFunction &IGF, SILType type, |
| 1014 | + Address buffer) { |
| 1015 | + // Handle FixedSize types. |
| 1016 | + auto &IGM = IGF.IGM; |
| 1017 | + auto storagePtrTy = IGM.getStoragePointerType(type); |
| 1018 | + if (auto *fixedTI = dyn_cast<FixedTypeInfo>(&IGF.getTypeInfo(type))) { |
| 1019 | + auto packing = fixedTI->getFixedPacking(IGM); |
| 1020 | + |
| 1021 | + // Inline representation. |
| 1022 | + if (packing == FixedPacking::OffsetZero) { |
| 1023 | + return Address( |
| 1024 | + IGF.Builder.CreateBitCast(buffer.getAddress(), storagePtrTy), |
| 1025 | + buffer.getAlignment()); |
| 1026 | + } |
| 1027 | + |
| 1028 | + // Outline representation. |
| 1029 | + assert(packing == FixedPacking::Allocate && "Expect non dynamic packing"); |
| 1030 | + auto valueAddr = IGF.Builder.CreateLoad( |
| 1031 | + Address(IGF.Builder.CreateBitCast(buffer.getAddress(), |
| 1032 | + storagePtrTy->getPointerTo()), |
| 1033 | + buffer.getAlignment())); |
| 1034 | + return Address(IGF.Builder.CreateBitCast(valueAddr, storagePtrTy), |
| 1035 | + buffer.getAlignment()); |
| 1036 | + } |
| 1037 | + |
| 1038 | + // Dynamic packing. |
| 1039 | + llvm::Value *isInline = emitLoadOfIsInline(IGF, type); |
| 1040 | + auto *outlineBB = IGF.createBasicBlock("outline.projectValueInBuffer"); |
| 1041 | + auto *doneBB = IGF.createBasicBlock("done"); |
| 1042 | + llvm::Value *addressInline, *addressOutline; |
| 1043 | + auto *origBB = IGF.Builder.GetInsertBlock(); |
| 1044 | + addressInline = IGF.Builder.CreateBitCast(buffer.getAddress(), storagePtrTy); |
| 1045 | + |
| 1046 | + IGF.Builder.CreateCondBr(isInline, doneBB, outlineBB); |
| 1047 | + |
| 1048 | + IGF.Builder.emitBlock(outlineBB); |
| 1049 | + { |
| 1050 | + auto ptr = IGF.Builder.CreateLoad( |
| 1051 | + Address(IGF.Builder.CreateBitCast(buffer.getAddress(), |
| 1052 | + storagePtrTy->getPointerTo()), |
| 1053 | + Alignment(1))); |
| 1054 | + addressOutline = IGF.Builder.CreateBitCast(ptr, storagePtrTy); |
| 1055 | + IGF.Builder.CreateBr(doneBB); |
| 1056 | + } |
| 1057 | + |
| 1058 | + IGF.Builder.emitBlock(doneBB); |
| 1059 | + auto *addressOfValue = IGF.Builder.CreatePHI(storagePtrTy, 2); |
| 1060 | + addressOfValue->addIncoming(addressInline, origBB); |
| 1061 | + addressOfValue->addIncoming(addressOutline, outlineBB); |
| 1062 | + |
| 1063 | + return Address(addressOfValue, Alignment(1)); |
976 | 1064 | }
|
977 | 1065 |
|
978 | 1066 | void irgen::emitDeallocateValueInBuffer(IRGenFunction &IGF,
|
979 | 1067 | SILType type,
|
980 | 1068 | Address buffer) {
|
981 |
| - auto *size = emitLoadOfSize(IGF, type); |
982 |
| - auto *alignMask = emitLoadOfAlignmentMask(IGF, type); |
983 |
| - auto *ptr = IGF.Builder.CreateLoad(Address( |
984 |
| - IGF.Builder.CreateBitCast(buffer.getAddress(), IGF.IGM.Int8PtrPtrTy), |
985 |
| - Alignment(1))); |
986 |
| - // TODO: check whether we fit in the inline value buffer. |
987 |
| - IGF.emitDeallocRawCall(ptr, size, alignMask); |
| 1069 | + // Handle FixedSize types. |
| 1070 | + auto &IGM = IGF.IGM; |
| 1071 | + if (auto *fixedTI = dyn_cast<FixedTypeInfo>(&IGF.getTypeInfo(type))) { |
| 1072 | + auto packing = fixedTI->getFixedPacking(IGM); |
| 1073 | + |
| 1074 | + // Inline representation. |
| 1075 | + if (packing == FixedPacking::OffsetZero) |
| 1076 | + return; |
| 1077 | + |
| 1078 | + // Outline representation. |
| 1079 | + assert(packing == FixedPacking::Allocate && "Expect non dynamic packing"); |
| 1080 | + auto size = fixedTI->getStaticSize(IGM); |
| 1081 | + auto alignMask = fixedTI->getStaticAlignmentMask(IGM); |
| 1082 | + auto *ptr = IGF.Builder.CreateLoad(Address( |
| 1083 | + IGF.Builder.CreateBitCast(buffer.getAddress(), IGM.Int8PtrPtrTy), |
| 1084 | + buffer.getAlignment())); |
| 1085 | + IGF.emitDeallocRawCall(ptr, size, alignMask); |
| 1086 | + return; |
| 1087 | + } |
| 1088 | + |
| 1089 | + // Dynamic packing. |
| 1090 | + llvm::Value *isInline = emitLoadOfIsInline(IGF, type); |
| 1091 | + auto *outlineBB = IGF.createBasicBlock("outline.projectValueInBuffer"); |
| 1092 | + auto *doneBB = IGF.createBasicBlock("done"); |
| 1093 | + |
| 1094 | + IGF.Builder.CreateCondBr(isInline, doneBB, outlineBB); |
| 1095 | + |
| 1096 | + IGF.Builder.emitBlock(outlineBB); |
| 1097 | + { |
| 1098 | + ConditionalDominanceScope scope(IGF); |
| 1099 | + auto *size = emitLoadOfSize(IGF, type); |
| 1100 | + auto *alignMask = emitLoadOfAlignmentMask(IGF, type); |
| 1101 | + auto *ptr = IGF.Builder.CreateLoad(Address( |
| 1102 | + IGF.Builder.CreateBitCast(buffer.getAddress(), IGM.Int8PtrPtrTy), |
| 1103 | + buffer.getAlignment())); |
| 1104 | + IGF.emitDeallocRawCall(ptr, size, alignMask); |
| 1105 | + IGF.Builder.CreateBr(doneBB); |
| 1106 | + } |
| 1107 | + |
| 1108 | + IGF.Builder.emitBlock(doneBB); |
988 | 1109 | }
|
0 commit comments