13
13
14
14
#include " CodeGenFunction.h"
15
15
#include " CGCall.h"
16
+ #include " CGRecordLayout.h"
16
17
#include " CodeGenModule.h"
17
18
#include " clang/AST/ASTContext.h"
18
19
#include " clang/CodeGen/CGFunctionInfo.h"
@@ -36,34 +37,70 @@ namespace {
36
37
CharUnits LValueAlign;
37
38
TypeEvaluationKind EvaluationKind;
38
39
bool UseLibcall;
40
+ LValue LVal;
41
+ CGBitFieldInfo BFI;
39
42
public:
40
- AtomicInfo (CodeGenFunction &CGF, LValue &lvalue) : CGF(CGF) {
41
- assert (lvalue.isSimple ());
42
-
43
- AtomicTy = lvalue.getType ();
44
- ValueTy = AtomicTy->castAs <AtomicType>()->getValueType ();
45
- EvaluationKind = CGF.getEvaluationKind (ValueTy);
46
-
43
+ AtomicInfo (CodeGenFunction &CGF, LValue &lvalue)
44
+ : CGF(CGF), AtomicSizeInBits(0 ), ValueSizeInBits(0 ),
45
+ EvaluationKind (TEK_Scalar), UseLibcall(true ) {
46
+ assert (!lvalue.isGlobalReg ());
47
47
ASTContext &C = CGF.getContext ();
48
-
49
- uint64_t ValueAlignInBits;
50
- uint64_t AtomicAlignInBits;
51
- TypeInfo ValueTI = C.getTypeInfo (ValueTy);
52
- ValueSizeInBits = ValueTI.Width ;
53
- ValueAlignInBits = ValueTI.Align ;
54
-
55
- TypeInfo AtomicTI = C.getTypeInfo (AtomicTy);
56
- AtomicSizeInBits = AtomicTI.Width ;
57
- AtomicAlignInBits = AtomicTI.Align ;
58
-
59
- assert (ValueSizeInBits <= AtomicSizeInBits);
60
- assert (ValueAlignInBits <= AtomicAlignInBits);
61
-
62
- AtomicAlign = C.toCharUnitsFromBits (AtomicAlignInBits);
63
- ValueAlign = C.toCharUnitsFromBits (ValueAlignInBits);
64
- if (lvalue.getAlignment ().isZero ())
65
- lvalue.setAlignment (AtomicAlign);
66
-
48
+ if (lvalue.isSimple ()) {
49
+ AtomicTy = lvalue.getType ();
50
+ if (auto *ATy = AtomicTy->getAs <AtomicType>())
51
+ ValueTy = ATy->getValueType ();
52
+ else
53
+ ValueTy = AtomicTy;
54
+ EvaluationKind = CGF.getEvaluationKind (ValueTy);
55
+
56
+ uint64_t ValueAlignInBits;
57
+ uint64_t AtomicAlignInBits;
58
+ TypeInfo ValueTI = C.getTypeInfo (ValueTy);
59
+ ValueSizeInBits = ValueTI.Width ;
60
+ ValueAlignInBits = ValueTI.Align ;
61
+
62
+ TypeInfo AtomicTI = C.getTypeInfo (AtomicTy);
63
+ AtomicSizeInBits = AtomicTI.Width ;
64
+ AtomicAlignInBits = AtomicTI.Align ;
65
+
66
+ assert (ValueSizeInBits <= AtomicSizeInBits);
67
+ assert (ValueAlignInBits <= AtomicAlignInBits);
68
+
69
+ AtomicAlign = C.toCharUnitsFromBits (AtomicAlignInBits);
70
+ ValueAlign = C.toCharUnitsFromBits (ValueAlignInBits);
71
+ if (lvalue.getAlignment ().isZero ())
72
+ lvalue.setAlignment (AtomicAlign);
73
+
74
+ LVal = lvalue;
75
+ } else if (lvalue.isBitField ()) {
76
+ auto &OrigBFI = lvalue.getBitFieldInfo ();
77
+ auto Offset = OrigBFI.Offset % C.toBits (lvalue.getAlignment ());
78
+ AtomicSizeInBits = C.toBits (
79
+ C.toCharUnitsFromBits (Offset + OrigBFI.Size + C.getCharWidth () - 1 )
80
+ .RoundUpToAlignment (lvalue.getAlignment ()));
81
+ auto VoidPtrAddr = CGF.EmitCastToVoidPtr (lvalue.getBitFieldAddr ());
82
+ auto OffsetInChars =
83
+ (C.toCharUnitsFromBits (OrigBFI.Offset ) / lvalue.getAlignment ()) *
84
+ lvalue.getAlignment ();
85
+ VoidPtrAddr = CGF.Builder .CreateConstGEP1_64 (
86
+ VoidPtrAddr, OffsetInChars.getQuantity ());
87
+ auto Addr = CGF.Builder .CreatePointerBitCastOrAddrSpaceCast (
88
+ VoidPtrAddr,
89
+ CGF.Builder .getIntNTy (AtomicSizeInBits)->getPointerTo (),
90
+ " atomic_bitfield_base" );
91
+ BFI = OrigBFI;
92
+ BFI.Offset = Offset;
93
+ BFI.StorageSize = AtomicSizeInBits;
94
+ LVal = LValue::MakeBitfield (Addr, BFI, lvalue.getType (),
95
+ lvalue.getAlignment ());
96
+ } else if (lvalue.isVectorElt ()) {
97
+ AtomicSizeInBits = C.getTypeSize (lvalue.getType ());
98
+ LVal = lvalue;
99
+ } else {
100
+ assert (lvalue.isExtVectorElt ());
101
+ AtomicSizeInBits = C.getTypeSize (lvalue.getType ());
102
+ LVal = lvalue;
103
+ }
67
104
UseLibcall = !C.getTargetInfo ().hasBuiltinAtomic (
68
105
AtomicSizeInBits, C.toBits (lvalue.getAlignment ()));
69
106
}
@@ -76,6 +113,7 @@ namespace {
76
113
uint64_t getValueSizeInBits () const { return ValueSizeInBits; }
77
114
TypeEvaluationKind getEvaluationKind () const { return EvaluationKind; }
78
115
bool shouldUseLibcall () const { return UseLibcall; }
116
+ const LValue &getAtomicLValue () const { return LVal; }
79
117
80
118
// / Is the atomic size larger than the underlying value type?
81
119
// /
@@ -87,7 +125,7 @@ namespace {
87
125
return (ValueSizeInBits != AtomicSizeInBits);
88
126
}
89
127
90
- bool emitMemSetZeroIfNecessary (LValue dest ) const ;
128
+ bool emitMemSetZeroIfNecessary () const ;
91
129
92
130
llvm::Value *getAtomicSizeValue () const {
93
131
CharUnits size = CGF.getContext ().toCharUnitsFromBits (AtomicSizeInBits);
@@ -110,16 +148,17 @@ namespace {
110
148
SourceLocation Loc) const ;
111
149
112
150
// / Copy an atomic r-value into atomic-layout memory.
113
- void emitCopyIntoMemory (RValue rvalue, LValue lvalue ) const ;
151
+ void emitCopyIntoMemory (RValue rvalue) const ;
114
152
115
153
// / Project an l-value down to the value field.
116
- LValue projectValue (LValue lvalue) const {
117
- llvm::Value *addr = lvalue.getAddress ();
154
+ LValue projectValue () const {
155
+ assert (LVal.isSimple ());
156
+ llvm::Value *addr = LVal.getAddress ();
118
157
if (hasPadding ())
119
158
addr = CGF.Builder .CreateStructGEP (addr, 0 );
120
159
121
- return LValue::MakeAddr (addr, getValueType (), lvalue .getAlignment (),
122
- CGF.getContext (), lvalue .getTBAAInfo ());
160
+ return LValue::MakeAddr (addr, getValueType (), LVal .getAlignment (),
161
+ CGF.getContext (), LVal .getTBAAInfo ());
123
162
}
124
163
125
164
// / Materialize an atomic r-value in atomic-layout memory.
@@ -172,14 +211,15 @@ bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const {
172
211
llvm_unreachable (" bad evaluation kind" );
173
212
}
174
213
175
- bool AtomicInfo::emitMemSetZeroIfNecessary (LValue dest) const {
176
- llvm::Value *addr = dest.getAddress ();
214
+ bool AtomicInfo::emitMemSetZeroIfNecessary () const {
215
+ assert (LVal.isSimple ());
216
+ llvm::Value *addr = LVal.getAddress ();
177
217
if (!requiresMemSetZero (addr->getType ()->getPointerElementType ()))
178
218
return false ;
179
219
180
220
CGF.Builder .CreateMemSet (addr, llvm::ConstantInt::get (CGF.Int8Ty , 0 ),
181
221
AtomicSizeInBits / 8 ,
182
- dest .getAlignment ().getQuantity ());
222
+ LVal .getAlignment ().getQuantity ());
183
223
return true ;
184
224
}
185
225
@@ -902,21 +942,34 @@ llvm::Value *AtomicInfo::emitCastToAtomicIntPointer(llvm::Value *addr) const {
902
942
RValue AtomicInfo::convertTempToRValue (llvm::Value *addr,
903
943
AggValueSlot resultSlot,
904
944
SourceLocation loc) const {
905
- if (EvaluationKind == TEK_Aggregate)
906
- return resultSlot.asRValue ();
907
-
908
- // Drill into the padding structure if we have one.
909
- if (hasPadding ())
910
- addr = CGF.Builder .CreateStructGEP (addr, 0 );
911
-
912
- // Otherwise, just convert the temporary to an r-value using the
913
- // normal conversion routine.
914
- return CGF.convertTempToRValue (addr, getValueType (), loc);
945
+ if (LVal.isSimple ()) {
946
+ if (EvaluationKind == TEK_Aggregate)
947
+ return resultSlot.asRValue ();
948
+
949
+ // Drill into the padding structure if we have one.
950
+ if (hasPadding ())
951
+ addr = CGF.Builder .CreateStructGEP (addr, 0 );
952
+
953
+ // Otherwise, just convert the temporary to an r-value using the
954
+ // normal conversion routine.
955
+ return CGF.convertTempToRValue (addr, getValueType (), loc);
956
+ } else if (LVal.isBitField ())
957
+ return CGF.EmitLoadOfBitfieldLValue (LValue::MakeBitfield (
958
+ addr, LVal.getBitFieldInfo (), LVal.getType (), LVal.getAlignment ()));
959
+ else if (LVal.isVectorElt ())
960
+ return CGF.EmitLoadOfLValue (LValue::MakeVectorElt (addr, LVal.getVectorIdx (),
961
+ LVal.getType (),
962
+ LVal.getAlignment ()),
963
+ loc);
964
+ assert (LVal.isExtVectorElt ());
965
+ return CGF.EmitLoadOfExtVectorElementLValue (LValue::MakeExtVectorElt (
966
+ addr, LVal.getExtVectorElts (), LVal.getType (), LVal.getAlignment ()));
915
967
}
916
968
917
969
RValue AtomicInfo::convertIntToValue (llvm::Value *IntVal,
918
970
AggValueSlot ResultSlot,
919
971
SourceLocation Loc) const {
972
+ assert (LVal.isSimple ());
920
973
// Try not to in some easy cases.
921
974
assert (IntVal->getType ()->isIntegerTy () && " Expected integer value" );
922
975
if (getEvaluationKind () == TEK_Scalar && !hasPadding ()) {
@@ -958,25 +1011,43 @@ RValue AtomicInfo::convertIntToValue(llvm::Value *IntVal,
958
1011
RValue CodeGenFunction::EmitAtomicLoad (LValue src, SourceLocation loc,
959
1012
AggValueSlot resultSlot) {
960
1013
AtomicInfo atomics (*this , src);
1014
+ LValue LVal = atomics.getAtomicLValue ();
1015
+ llvm::Value *SrcAddr = nullptr ;
1016
+ llvm::AllocaInst *NonSimpleTempAlloca = nullptr ;
1017
+ if (LVal.isSimple ())
1018
+ SrcAddr = LVal.getAddress ();
1019
+ else {
1020
+ if (LVal.isBitField ())
1021
+ SrcAddr = LVal.getBitFieldAddr ();
1022
+ else if (LVal.isVectorElt ())
1023
+ SrcAddr = LVal.getVectorAddr ();
1024
+ else {
1025
+ assert (LVal.isExtVectorElt ());
1026
+ SrcAddr = LVal.getExtVectorAddr ();
1027
+ }
1028
+ NonSimpleTempAlloca = CreateTempAlloca (
1029
+ SrcAddr->getType ()->getPointerElementType (), " atomic-load-temp" );
1030
+ NonSimpleTempAlloca->setAlignment (getContext ().toBits (src.getAlignment ()));
1031
+ }
961
1032
962
1033
// Check whether we should use a library call.
963
1034
if (atomics.shouldUseLibcall ()) {
964
1035
llvm::Value *tempAddr;
965
- if (!resultSlot.isIgnored ()) {
966
- assert (atomics.getEvaluationKind () == TEK_Aggregate);
967
- tempAddr = resultSlot.getAddr ();
968
- } else {
969
- tempAddr = CreateMemTemp (atomics.getAtomicType (), " atomic-load-temp" );
970
- }
1036
+ if (LVal.isSimple ()) {
1037
+ if (!resultSlot.isIgnored ()) {
1038
+ assert (atomics.getEvaluationKind () == TEK_Aggregate);
1039
+ tempAddr = resultSlot.getAddr ();
1040
+ } else
1041
+ tempAddr = CreateMemTemp (atomics.getAtomicType (), " atomic-load-temp" );
1042
+ } else
1043
+ tempAddr = NonSimpleTempAlloca;
971
1044
972
1045
// void __atomic_load(size_t size, void *mem, void *return, int order);
973
1046
CallArgList args;
974
1047
args.add (RValue::get (atomics.getAtomicSizeValue ()),
975
1048
getContext ().getSizeType ());
976
- args.add (RValue::get (EmitCastToVoidPtr (src.getAddress ())),
977
- getContext ().VoidPtrTy );
978
- args.add (RValue::get (EmitCastToVoidPtr (tempAddr)),
979
- getContext ().VoidPtrTy );
1049
+ args.add (RValue::get (EmitCastToVoidPtr (SrcAddr)), getContext ().VoidPtrTy );
1050
+ args.add (RValue::get (EmitCastToVoidPtr (tempAddr)), getContext ().VoidPtrTy );
980
1051
args.add (RValue::get (llvm::ConstantInt::get (
981
1052
IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)),
982
1053
getContext ().IntTy );
@@ -987,7 +1058,7 @@ RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
987
1058
}
988
1059
989
1060
// Okay, we're doing this natively.
990
- llvm::Value *addr = atomics.emitCastToAtomicIntPointer (src. getAddress () );
1061
+ llvm::Value *addr = atomics.emitCastToAtomicIntPointer (SrcAddr );
991
1062
llvm::LoadInst *load = Builder.CreateLoad (addr, " atomic-load" );
992
1063
load->setAtomic (llvm::SequentiallyConsistent);
993
1064
@@ -1003,40 +1074,46 @@ RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
1003
1074
return RValue::getAggregate (nullptr , false );
1004
1075
1005
1076
// Okay, turn that back into the original value type.
1006
- return atomics.convertIntToValue (load, resultSlot, loc);
1077
+ if (src.isSimple ())
1078
+ return atomics.convertIntToValue (load, resultSlot, loc);
1079
+
1080
+ auto *IntAddr = atomics.emitCastToAtomicIntPointer (NonSimpleTempAlloca);
1081
+ Builder.CreateAlignedStore (load, IntAddr, src.getAlignment ().getQuantity ());
1082
+ return atomics.convertTempToRValue (NonSimpleTempAlloca, resultSlot, loc);
1007
1083
}
1008
1084
1009
1085
1010
1086
1011
1087
// / Copy an r-value into memory as part of storing to an atomic type.
1012
1088
// / This needs to create a bit-pattern suitable for atomic operations.
1013
- void AtomicInfo::emitCopyIntoMemory (RValue rvalue, LValue dest) const {
1089
+ void AtomicInfo::emitCopyIntoMemory (RValue rvalue) const {
1090
+ assert (LVal.isSimple ());
1014
1091
// If we have an r-value, the rvalue should be of the atomic type,
1015
1092
// which means that the caller is responsible for having zeroed
1016
1093
// any padding. Just do an aggregate copy of that type.
1017
1094
if (rvalue.isAggregate ()) {
1018
- CGF.EmitAggregateCopy (dest .getAddress (),
1095
+ CGF.EmitAggregateCopy (LVal .getAddress (),
1019
1096
rvalue.getAggregateAddr (),
1020
1097
getAtomicType (),
1021
1098
(rvalue.isVolatileQualified ()
1022
- || dest .isVolatileQualified ()),
1023
- dest .getAlignment ());
1099
+ || LVal .isVolatileQualified ()),
1100
+ LVal .getAlignment ());
1024
1101
return ;
1025
1102
}
1026
1103
1027
1104
// Okay, otherwise we're copying stuff.
1028
1105
1029
1106
// Zero out the buffer if necessary.
1030
- emitMemSetZeroIfNecessary (dest );
1107
+ emitMemSetZeroIfNecessary ();
1031
1108
1032
1109
// Drill past the padding if present.
1033
- dest = projectValue (dest );
1110
+ LValue TempLVal = projectValue ();
1034
1111
1035
1112
// Okay, store the rvalue in.
1036
1113
if (rvalue.isScalar ()) {
1037
- CGF.EmitStoreOfScalar (rvalue.getScalarVal (), dest , /* init*/ true );
1114
+ CGF.EmitStoreOfScalar (rvalue.getScalarVal (), TempLVal , /* init*/ true );
1038
1115
} else {
1039
- CGF.EmitStoreOfComplex (rvalue.getComplexVal (), dest , /* init*/ true );
1116
+ CGF.EmitStoreOfComplex (rvalue.getComplexVal (), TempLVal , /* init*/ true );
1040
1117
}
1041
1118
}
1042
1119
@@ -1051,8 +1128,10 @@ llvm::Value *AtomicInfo::materializeRValue(RValue rvalue) const {
1051
1128
1052
1129
// Otherwise, make a temporary and materialize into it.
1053
1130
llvm::Value *temp = CGF.CreateMemTemp (getAtomicType (), " atomic-store-temp" );
1054
- LValue tempLV = CGF.MakeAddrLValue (temp, getAtomicType (), getAtomicAlignment ());
1055
- emitCopyIntoMemory (rvalue, tempLV);
1131
+ LValue tempLV =
1132
+ CGF.MakeAddrLValue (temp, getAtomicType (), getAtomicAlignment ());
1133
+ AtomicInfo Atomics (CGF, tempLV);
1134
+ Atomics.emitCopyIntoMemory (rvalue);
1056
1135
return temp;
1057
1136
}
1058
1137
@@ -1098,7 +1177,7 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) {
1098
1177
1099
1178
// If this is an initialization, just put the value there normally.
1100
1179
if (isInit) {
1101
- atomics.emitCopyIntoMemory (rvalue, dest );
1180
+ atomics.emitCopyIntoMemory (rvalue);
1102
1181
return ;
1103
1182
}
1104
1183
@@ -1214,13 +1293,13 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
1214
1293
switch (atomics.getEvaluationKind ()) {
1215
1294
case TEK_Scalar: {
1216
1295
llvm::Value *value = EmitScalarExpr (init);
1217
- atomics.emitCopyIntoMemory (RValue::get (value), dest );
1296
+ atomics.emitCopyIntoMemory (RValue::get (value));
1218
1297
return ;
1219
1298
}
1220
1299
1221
1300
case TEK_Complex: {
1222
1301
ComplexPairTy value = EmitComplexExpr (init);
1223
- atomics.emitCopyIntoMemory (RValue::getComplex (value), dest );
1302
+ atomics.emitCopyIntoMemory (RValue::getComplex (value));
1224
1303
return ;
1225
1304
}
1226
1305
@@ -1229,8 +1308,8 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
1229
1308
// of atomic type.
1230
1309
bool Zeroed = false ;
1231
1310
if (!init->getType ()->isAtomicType ()) {
1232
- Zeroed = atomics.emitMemSetZeroIfNecessary (dest );
1233
- dest = atomics.projectValue (dest );
1311
+ Zeroed = atomics.emitMemSetZeroIfNecessary ();
1312
+ dest = atomics.projectValue ();
1234
1313
}
1235
1314
1236
1315
// Evaluate the expression directly into the destination.
0 commit comments