Changeset View
Changeset View
Standalone View
Standalone View
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
1 | //===--- CGExprScalar.cpp - Emit LLVM Code for Scalar Exprs ---------------===// | 1 | //===--- CGExprScalar.cpp - Emit LLVM Code for Scalar Exprs ---------------===// | ||
---|---|---|---|---|---|
2 | // | 2 | // | ||
3 | // The LLVM Compiler Infrastructure | 3 | // The LLVM Compiler Infrastructure | ||
4 | // | 4 | // | ||
5 | // This file is distributed under the University of Illinois Open Source | 5 | // This file is distributed under the University of Illinois Open Source | ||
6 | // License. See LICENSE.TXT for details. | 6 | // License. See LICENSE.TXT for details. | ||
7 | // | 7 | // | ||
8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// | ||
9 | // | 9 | // | ||
10 | // This contains code to emit Expr nodes with scalar LLVM types as LLVM code. | 10 | // This contains code to emit Expr nodes with scalar LLVM types as LLVM code. | ||
11 | // | 11 | // | ||
12 | //===----------------------------------------------------------------------===// | 12 | //===----------------------------------------------------------------------===// | ||
13 | 13 | | |||
14 | #include "CodeGenFunction.h" | | |||
15 | #include "CGCleanup.h" | | |||
16 | #include "CGCXXABI.h" | 14 | #include "CGCXXABI.h" | ||
15 | #include "CGCleanup.h" | ||||
17 | #include "CGDebugInfo.h" | 16 | #include "CGDebugInfo.h" | ||
18 | #include "CGObjCRuntime.h" | 17 | #include "CGObjCRuntime.h" | ||
18 | #include "CodeGenFunction.h" | ||||
19 | #include "CodeGenModule.h" | 19 | #include "CodeGenModule.h" | ||
20 | #include "TargetInfo.h" | 20 | #include "TargetInfo.h" | ||
21 | #include "clang/AST/ASTContext.h" | 21 | #include "clang/AST/ASTContext.h" | ||
22 | #include "clang/AST/DeclObjC.h" | 22 | #include "clang/AST/DeclObjC.h" | ||
23 | #include "clang/AST/Expr.h" | 23 | #include "clang/AST/Expr.h" | ||
24 | #include "clang/AST/RecordLayout.h" | 24 | #include "clang/AST/RecordLayout.h" | ||
25 | #include "clang/AST/StmtVisitor.h" | 25 | #include "clang/AST/StmtVisitor.h" | ||
26 | #include "clang/Basic/FixedPoint.h" | ||||
26 | #include "clang/Basic/TargetInfo.h" | 27 | #include "clang/Basic/TargetInfo.h" | ||
27 | #include "clang/Frontend/CodeGenOptions.h" | 28 | #include "clang/Frontend/CodeGenOptions.h" | ||
28 | #include "llvm/ADT/Optional.h" | 29 | #include "llvm/ADT/Optional.h" | ||
29 | #include "llvm/IR/CFG.h" | 30 | #include "llvm/IR/CFG.h" | ||
30 | #include "llvm/IR/Constants.h" | 31 | #include "llvm/IR/Constants.h" | ||
31 | #include "llvm/IR/DataLayout.h" | 32 | #include "llvm/IR/DataLayout.h" | ||
32 | #include "llvm/IR/Function.h" | 33 | #include "llvm/IR/Function.h" | ||
33 | #include "llvm/IR/GetElementPtrTypeIterator.h" | 34 | #include "llvm/IR/GetElementPtrTypeIterator.h" | ||
▲ Show 20 Lines • Show All 288 Lines • ▼ Show 20 Line(s) | 322 | ScalarConversionOpts() | |||
322 | : TreatBooleanAsSigned(false), | 323 | : TreatBooleanAsSigned(false), | ||
323 | EmitImplicitIntegerTruncationChecks(false) {} | 324 | EmitImplicitIntegerTruncationChecks(false) {} | ||
324 | }; | 325 | }; | ||
325 | Value * | 326 | Value * | ||
326 | EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy, | 327 | EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy, | ||
327 | SourceLocation Loc, | 328 | SourceLocation Loc, | ||
328 | ScalarConversionOpts Opts = ScalarConversionOpts()); | 329 | ScalarConversionOpts Opts = ScalarConversionOpts()); | ||
329 | 330 | | |||
331 | Value *EmitFixedPointConversion(Value *Src, QualType SrcTy, QualType DstTy, | ||||
332 | SourceLocation Loc); | ||||
333 | | ||||
330 | /// Emit a conversion from the specified complex type to the specified | 334 | /// Emit a conversion from the specified complex type to the specified | ||
331 | /// destination type, where the destination type is an LLVM scalar type. | 335 | /// destination type, where the destination type is an LLVM scalar type. | ||
332 | Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, | 336 | Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, | ||
333 | QualType SrcTy, QualType DstTy, | 337 | QualType SrcTy, QualType DstTy, | ||
334 | SourceLocation Loc); | 338 | SourceLocation Loc); | ||
335 | 339 | | |||
336 | /// EmitNullValue - Emit a value that corresponds to null for the given type. | 340 | /// EmitNullValue - Emit a value that corresponds to null for the given type. | ||
337 | Value *EmitNullValue(QualType Ty); | 341 | Value *EmitNullValue(QualType Ty); | ||
▲ Show 20 Lines • Show All 668 Lines • ▼ Show 20 Line(s) | |||||
1006 | } | 1010 | } | ||
1007 | 1011 | | |||
1008 | /// Emit a conversion from the specified type to the specified destination type, | 1012 | /// Emit a conversion from the specified type to the specified destination type, | ||
1009 | /// both of which are LLVM scalar types. | 1013 | /// both of which are LLVM scalar types. | ||
1010 | Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, | 1014 | Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, | ||
1011 | QualType DstType, | 1015 | QualType DstType, | ||
1012 | SourceLocation Loc, | 1016 | SourceLocation Loc, | ||
1013 | ScalarConversionOpts Opts) { | 1017 | ScalarConversionOpts Opts) { | ||
1018 | assert(!SrcType->isFixedPointType() && !DstType->isFixedPointType() && | ||||
1019 | "Use the ScalarExprEmitter::EmitFixedPoint family functions for " | ||||
1020 | "handling conversions involving fixed point types."); | ||||
1021 | | ||||
1014 | QualType NoncanonicalSrcType = SrcType; | 1022 | QualType NoncanonicalSrcType = SrcType; | ||
1015 | QualType NoncanonicalDstType = DstType; | 1023 | QualType NoncanonicalDstType = DstType; | ||
1016 | 1024 | | |||
1017 | SrcType = CGF.getContext().getCanonicalType(SrcType); | 1025 | SrcType = CGF.getContext().getCanonicalType(SrcType); | ||
1018 | DstType = CGF.getContext().getCanonicalType(DstType); | 1026 | DstType = CGF.getContext().getCanonicalType(DstType); | ||
1019 | if (SrcType == DstType) return Src; | 1027 | if (SrcType == DstType) return Src; | ||
1020 | 1028 | | |||
1021 | if (DstType->isVoidType()) return nullptr; | 1029 | if (DstType->isVoidType()) return nullptr; | ||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Line(s) | |||||
1199 | 1207 | | |||
1200 | if (Opts.EmitImplicitIntegerTruncationChecks) | 1208 | if (Opts.EmitImplicitIntegerTruncationChecks) | ||
1201 | EmitIntegerTruncationCheck(Src, NoncanonicalSrcType, Res, | 1209 | EmitIntegerTruncationCheck(Src, NoncanonicalSrcType, Res, | ||
1202 | NoncanonicalDstType, Loc); | 1210 | NoncanonicalDstType, Loc); | ||
1203 | 1211 | | |||
1204 | return Res; | 1212 | return Res; | ||
1205 | } | 1213 | } | ||
1206 | 1214 | | |||
1215 | Value *ScalarExprEmitter::EmitFixedPointConversion(Value *Src, QualType SrcTy, | ||||
1216 | QualType DstTy, | ||||
1217 | SourceLocation Loc) { | ||||
1218 | using llvm::APInt; | ||||
1219 | using llvm::ConstantInt; | ||||
1220 | using llvm::Value; | ||||
1221 | | ||||
1222 | assert(SrcTy->isFixedPointType()); | ||||
1223 | assert(DstTy->isFixedPointType()); | ||||
1224 | | ||||
1225 | FixedPointSemantics SrcFPSema = | ||||
1226 | CGF.getContext().getFixedPointSemantics(SrcTy); | ||||
1227 | FixedPointSemantics DstFPSema = | ||||
1228 | CGF.getContext().getFixedPointSemantics(DstTy); | ||||
1229 | unsigned SrcWidth = SrcFPSema.getWidth(); | ||||
1230 | unsigned DstWidth = DstFPSema.getWidth(); | ||||
1231 | unsigned SrcScale = SrcFPSema.getScale(); | ||||
1232 | unsigned DstScale = DstFPSema.getScale(); | ||||
1233 | bool IsSigned = SrcFPSema.isSigned(); | ||||
1234 | | ||||
1235 | Value *Result = Src; | ||||
1236 | unsigned ResultWidth = SrcWidth; | ||||
1237 | | ||||
1238 | if (!DstFPSema.isSaturated()) { | ||||
1239 | // Downscale | ||||
1240 | if (DstScale < SrcScale) { | ||||
1241 | if (IsSigned) | ||||
1242 | Result = Builder.CreateAShr(Result, SrcScale - DstScale); | ||||
1243 | else | ||||
1244 | Result = Builder.CreateLShr(Result, SrcScale - DstScale); | ||||
1245 | } | ||||
1246 | | ||||
1247 | // Resize | ||||
1248 | llvm::Type *DstIntTy = Builder.getIntNTy(DstWidth); | ||||
1249 | if (IsSigned) | ||||
1250 | Result = Builder.CreateSExtOrTrunc(Result, DstIntTy); | ||||
1251 | else | ||||
1252 | Result = Builder.CreateZExtOrTrunc(Result, DstIntTy); | ||||
1253 | | ||||
1254 | // Upscale | ||||
1255 | if (DstScale > SrcScale) | ||||
1256 | Result = Builder.CreateShl(Result, DstScale - SrcScale); | ||||
1257 | } else { | ||||
1258 | if (DstScale > SrcScale) { | ||||
1259 | // Need to extend first before scaling up | ||||
1260 | ResultWidth = SrcWidth + DstScale - SrcScale; | ||||
1261 | llvm::Type *UpscaledTy = Builder.getIntNTy(ResultWidth); | ||||
1262 | | ||||
1263 | if (IsSigned) | ||||
1264 | Result = Builder.CreateSExt(Result, UpscaledTy); | ||||
1265 | else | ||||
1266 | Result = Builder.CreateZExt(Result, UpscaledTy); | ||||
1267 | | ||||
1268 | Result = Builder.CreateShl(Result, DstScale - SrcScale); | ||||
1269 | } else if (DstScale < SrcScale) { | ||||
1270 | if (IsSigned) | ||||
1271 | Result = Builder.CreateAShr(Result, SrcScale - DstScale); | ||||
1272 | else | ||||
1273 | Result = Builder.CreateLShr(Result, SrcScale - DstScale); | ||||
1274 | } | ||||
1275 | | ||||
1276 | if (DstFPSema.getIntegralBits() < SrcFPSema.getIntegralBits()) { | ||||
1277 | auto Max = ConstantInt::get( | ||||
1278 | CGF.getLLVMContext(), | ||||
1279 | APFixedPoint::getMax(DstFPSema).getValue().extOrTrunc(ResultWidth)); | ||||
1280 | Value *TooHigh = IsSigned ? Builder.CreateICmpSGT(Result, Max) | ||||
1281 | : Builder.CreateICmpUGT(Result, Max); | ||||
1282 | Result = Builder.CreateSelect(TooHigh, Max, Result); | ||||
1283 | | ||||
1284 | if (IsSigned) { | ||||
1285 | // Cannot overflow min to dest type is src is unsigned since all fixed | ||||
1286 | // point types can cover the unsigned min of 0. | ||||
1287 | auto Min = ConstantInt::get( | ||||
1288 | CGF.getLLVMContext(), | ||||
1289 | APFixedPoint::getMin(DstFPSema).getValue().extOrTrunc(ResultWidth)); | ||||
1290 | Value *TooLow = Builder.CreateICmpSLT(Result, Min); | ||||
1291 | Result = Builder.CreateSelect(TooLow, Min, Result); | ||||
1292 | } | ||||
1293 | } else if (IsSigned && !DstFPSema.isSigned()) { | ||||
1294 | llvm::Type *ResultTy = Builder.getIntNTy(ResultWidth); | ||||
1295 | Value *Zero = ConstantInt::getNullValue(ResultTy); | ||||
1296 | Value *LTZero = Builder.CreateICmpSLT(Result, Zero); | ||||
1297 | Result = Builder.CreateSelect(LTZero, Zero, Result); | ||||
1298 | } | ||||
1299 | | ||||
1300 | // Final resizing to dst width | ||||
1301 | llvm::Type *DstIntTy = Builder.getIntNTy(DstWidth); | ||||
1302 | if (IsSigned) | ||||
1303 | Result = Builder.CreateSExtOrTrunc(Result, DstIntTy); | ||||
1304 | else | ||||
1305 | Result = Builder.CreateZExtOrTrunc(Result, DstIntTy); | ||||
1306 | } | ||||
1307 | return Result; | ||||
1308 | } | ||||
1309 | | ||||
1207 | /// Emit a conversion from the specified complex type to the specified | 1310 | /// Emit a conversion from the specified complex type to the specified | ||
1208 | /// destination type, where the destination type is an LLVM scalar type. | 1311 | /// destination type, where the destination type is an LLVM scalar type. | ||
1209 | Value *ScalarExprEmitter::EmitComplexToScalarConversion( | 1312 | Value *ScalarExprEmitter::EmitComplexToScalarConversion( | ||
1210 | CodeGenFunction::ComplexPairTy Src, QualType SrcTy, QualType DstTy, | 1313 | CodeGenFunction::ComplexPairTy Src, QualType SrcTy, QualType DstTy, | ||
1211 | SourceLocation Loc) { | 1314 | SourceLocation Loc) { | ||
1212 | // Get the source element type. | 1315 | // Get the source element type. | ||
1213 | SrcTy = SrcTy->castAs<ComplexType>()->getElementType(); | 1316 | SrcTy = SrcTy->castAs<ComplexType>()->getElementType(); | ||
1214 | 1317 | | |||
▲ Show 20 Lines • Show All 674 Lines • ▼ Show 20 Line(s) | 1764 | Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { | |||
1889 | case CK_VectorSplat: { | 1992 | case CK_VectorSplat: { | ||
1890 | llvm::Type *DstTy = ConvertType(DestTy); | 1993 | llvm::Type *DstTy = ConvertType(DestTy); | ||
1891 | Value *Elt = Visit(const_cast<Expr*>(E)); | 1994 | Value *Elt = Visit(const_cast<Expr*>(E)); | ||
1892 | // Splat the element across to all elements | 1995 | // Splat the element across to all elements | ||
1893 | unsigned NumElements = DstTy->getVectorNumElements(); | 1996 | unsigned NumElements = DstTy->getVectorNumElements(); | ||
1894 | return Builder.CreateVectorSplat(NumElements, Elt, "splat"); | 1997 | return Builder.CreateVectorSplat(NumElements, Elt, "splat"); | ||
1895 | } | 1998 | } | ||
1896 | 1999 | | |||
2000 | case CK_FixedPointCast: | ||||
2001 | return EmitFixedPointConversion(Visit(E), E->getType(), DestTy, | ||||
2002 | CE->getExprLoc()); | ||||
2003 | | ||||
1897 | case CK_IntegralCast: { | 2004 | case CK_IntegralCast: { | ||
1898 | ScalarConversionOpts Opts; | 2005 | ScalarConversionOpts Opts; | ||
1899 | if (CGF.SanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)) { | 2006 | if (CGF.SanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)) { | ||
1900 | if (auto *ICE = dyn_cast<ImplicitCastExpr>(CE)) | 2007 | if (auto *ICE = dyn_cast<ImplicitCastExpr>(CE)) | ||
1901 | Opts.EmitImplicitIntegerTruncationChecks = !ICE->isPartOfExplicitCast(); | 2008 | Opts.EmitImplicitIntegerTruncationChecks = !ICE->isPartOfExplicitCast(); | ||
1902 | } | 2009 | } | ||
1903 | return EmitScalarConversion(Visit(E), E->getType(), DestTy, | 2010 | return EmitScalarConversion(Visit(E), E->getType(), DestTy, | ||
1904 | CE->getExprLoc(), Opts); | 2011 | CE->getExprLoc(), Opts); | ||
▲ Show 20 Lines • Show All 2316 Lines • Show Last 20 Lines |