forked from OSchip/llvm-project
CodeGen: correct arguments for NSFastEnumeration
When performing a NSFastEnumeration, the compiler synthesizes a call to `countByEnumeratingWithState:objects:count:` where the `count` parameter is of type `NSUInteger` and the return type is a `NSUInteger`. We would previously always use a `UnsignedLongTy` for the `NSUInteger` type. On 32-bit targets, `long` is 32-bits which is the same as `unsigned int`. Most 64-bit targets are LP64, where `long` is 64-bits. However, on LLP64 targets, such as Windows, `long` is 32-bits. Introduce new `getNSUIntegerType` and `getNSIntegerType` helpers to allow us to determine the correct type for the `NSUInteger` type. Wire those through into the generation of the message dispatch to the selector. llvm-svn: 312835
This commit is contained in:
parent
cde9acbb5d
commit
94bb1a06fb
|
@ -39,6 +39,7 @@
|
|||
#include "clang/Basic/SanitizerBlacklist.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/XRayLists.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
@ -89,7 +90,6 @@ class DiagnosticsEngine;
|
|||
class Expr;
|
||||
class MangleNumberingContext;
|
||||
class MaterializeTemporaryExpr;
|
||||
class TargetInfo;
|
||||
// Decls
|
||||
class MangleContext;
|
||||
class ObjCIvarDecl;
|
||||
|
@ -1582,6 +1582,24 @@ public:
|
|||
return NSCopyingName;
|
||||
}
|
||||
|
||||
CanQualType getNSUIntegerType() const {
|
||||
assert(Target && "Expected target to be initialized");
|
||||
const llvm::Triple &T = Target->getTriple();
|
||||
// Windows is LLP64 rather than LP64
|
||||
if (T.isOSWindows() && T.isArch64Bit())
|
||||
return UnsignedLongLongTy;
|
||||
return UnsignedLongTy;
|
||||
}
|
||||
|
||||
CanQualType getNSIntegerType() const {
|
||||
assert(Target && "Expected target to be initialized");
|
||||
const llvm::Triple &T = Target->getTriple();
|
||||
// Windows is LLP64 rather than LP64
|
||||
if (T.isOSWindows() && T.isArch64Bit())
|
||||
return LongLongTy;
|
||||
return LongTy;
|
||||
}
|
||||
|
||||
/// Retrieve the identifier 'bool'.
|
||||
IdentifierInfo *getBoolName() const {
|
||||
if (!BoolName)
|
||||
|
|
|
@ -1546,16 +1546,15 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
|||
getContext().getPointerType(ItemsTy));
|
||||
|
||||
// The third argument is the capacity of that temporary array.
|
||||
llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy);
|
||||
llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems);
|
||||
Args.add(RValue::get(Count), getContext().UnsignedLongTy);
|
||||
llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType());
|
||||
llvm::Constant *Count = llvm::ConstantInt::get(NSUIntegerTy, NumItems);
|
||||
Args.add(RValue::get(Count), getContext().getNSUIntegerType());
|
||||
|
||||
// Start the enumeration.
|
||||
RValue CountRV =
|
||||
CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
|
||||
getContext().UnsignedLongTy,
|
||||
FastEnumSel,
|
||||
Collection, Args);
|
||||
CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
|
||||
getContext().getNSUIntegerType(),
|
||||
FastEnumSel, Collection, Args);
|
||||
|
||||
// The initial number of objects that were returned in the buffer.
|
||||
llvm::Value *initialBufferLimit = CountRV.getScalarVal();
|
||||
|
@ -1563,7 +1562,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
|||
llvm::BasicBlock *EmptyBB = createBasicBlock("forcoll.empty");
|
||||
llvm::BasicBlock *LoopInitBB = createBasicBlock("forcoll.loopinit");
|
||||
|
||||
llvm::Value *zero = llvm::Constant::getNullValue(UnsignedLongLTy);
|
||||
llvm::Value *zero = llvm::Constant::getNullValue(NSUIntegerTy);
|
||||
|
||||
// If the limit pointer was zero to begin with, the collection is
|
||||
// empty; skip all this. Set the branch weight assuming this has the same
|
||||
|
@ -1595,11 +1594,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
|||
EmitBlock(LoopBodyBB);
|
||||
|
||||
// The current index into the buffer.
|
||||
llvm::PHINode *index = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.index");
|
||||
llvm::PHINode *index = Builder.CreatePHI(NSUIntegerTy, 3, "forcoll.index");
|
||||
index->addIncoming(zero, LoopInitBB);
|
||||
|
||||
// The current buffer size.
|
||||
llvm::PHINode *count = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.count");
|
||||
llvm::PHINode *count = Builder.CreatePHI(NSUIntegerTy, 3, "forcoll.count");
|
||||
count->addIncoming(initialBufferLimit, LoopInitBB);
|
||||
|
||||
incrementProfileCounter(&S);
|
||||
|
@ -1709,8 +1708,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
|||
llvm::BasicBlock *FetchMoreBB = createBasicBlock("forcoll.refetch");
|
||||
|
||||
// First we check in the local buffer.
|
||||
llvm::Value *indexPlusOne
|
||||
= Builder.CreateAdd(index, llvm::ConstantInt::get(UnsignedLongLTy, 1));
|
||||
llvm::Value *indexPlusOne =
|
||||
Builder.CreateAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));
|
||||
|
||||
// If we haven't overrun the buffer yet, we can continue.
|
||||
// Set the branch weights based on the simplifying assumption that this is
|
||||
|
@ -1727,10 +1726,9 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
|||
EmitBlock(FetchMoreBB);
|
||||
|
||||
CountRV =
|
||||
CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
|
||||
getContext().UnsignedLongTy,
|
||||
FastEnumSel,
|
||||
Collection, Args);
|
||||
CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
|
||||
getContext().getNSUIntegerType(),
|
||||
FastEnumSel, Collection, Args);
|
||||
|
||||
// If we got a zero count, we're done.
|
||||
llvm::Value *refetchCount = CountRV.getScalarVal();
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: %clang_cc1 -triple i686-apple-ios10.3 -fobjc-runtime=ios-6.0 -Os -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK32
|
||||
// RUN: %clang_cc1 -triple i686--windows-msvc -fobjc-runtime=ios-6.0 -Os -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK32
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-ios10.3 -fobjc-runtime=ios-6.0 -Os -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK64
|
||||
// RUN: %clang_cc1 -triple x86_64--windows-msvc -fobjc-runtime=ios-6.0 -Os -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK64
|
||||
|
||||
void f(id a) {
|
||||
for (id i in a)
|
||||
(void)i;
|
||||
}
|
||||
|
||||
// CHECK32: call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i32)*)
|
||||
// CHECK32: call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i32)*)
|
||||
|
||||
// CHECK64: call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)
|
||||
// CHECK64: call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)
|
||||
|
Loading…
Reference in New Issue