summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp42
-rw-r--r--lib/CodeGen/CodeGenModule.cpp59
-rw-r--r--lib/CodeGen/CodeGenModule.h2
3 files changed, 79 insertions, 24 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index d3da649..688e992 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -538,11 +538,12 @@ protected:
llvm::Value *cmd,
llvm::MDNode *node) {
CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *imp = Builder.CreateCall2(MsgLookupFn,
- EnforceType(Builder, Receiver, IdTy),
- EnforceType(Builder, cmd, SelectorTy));
- cast<llvm::CallInst>(imp)->setMetadata(msgSendMDKind, node);
- return imp;
+ llvm::Value *args[] = {
+ EnforceType(Builder, Receiver, IdTy),
+ EnforceType(Builder, cmd, SelectorTy) };
+ llvm::CallSite imp = CGF.EmitCallOrInvoke(MsgLookupFn, args);
+ imp->setMetadata(msgSendMDKind, node);
+ return imp.getInstruction();
}
virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
llvm::Value *ObjCSuper,
@@ -597,16 +598,17 @@ class CGObjCGNUstep : public CGObjCGNU {
// The lookup function is guaranteed not to capture the receiver pointer.
LookupFn->setDoesNotCapture(1);
- llvm::CallInst *slot =
- Builder.CreateCall3(LookupFn,
- EnforceType(Builder, ReceiverPtr, PtrToIdTy),
- EnforceType(Builder, cmd, SelectorTy),
- EnforceType(Builder, self, IdTy));
- slot->setOnlyReadsMemory();
+ llvm::Value *args[] = {
+ EnforceType(Builder, ReceiverPtr, PtrToIdTy),
+ EnforceType(Builder, cmd, SelectorTy),
+ EnforceType(Builder, self, IdTy) };
+ llvm::CallSite slot = CGF.EmitCallOrInvoke(LookupFn, args);
+ slot.setOnlyReadsMemory();
slot->setMetadata(msgSendMDKind, node);
// Load the imp from the slot
- llvm::Value *imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
+ llvm::Value *imp =
+ Builder.CreateLoad(Builder.CreateStructGEP(slot.getInstruction(), 4));
// The lookup function may have changed the receiver, so make sure we use
// the new one.
@@ -1361,8 +1363,8 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
LongTy, // abi_version
IvarOffsets->getType(), // ivar_offsets
Properties->getType(), // properties
- Int64Ty, // strong_pointers
- Int64Ty, // weak_pointers
+ IntPtrTy, // strong_pointers
+ IntPtrTy, // weak_pointers
NULL);
llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
// Fill in the structure
@@ -1723,12 +1725,14 @@ void CGObjCGNU::GenerateProtocolHolderCategory(void) {
/// bitfield / with the 63rd bit set will be 1<<64.
llvm::Constant *CGObjCGNU::MakeBitField(llvm::SmallVectorImpl<bool> &bits) {
int bitCount = bits.size();
- if (bitCount < 64) {
+ int ptrBits =
+ (TheModule.getPointerSize() == llvm::Module::Pointer32) ? 32 : 64;
+ if (bitCount < ptrBits) {
uint64_t val = 1;
for (int i=0 ; i<bitCount ; ++i) {
if (bits[i]) val |= 1ULL<<(i+1);
}
- return llvm::ConstantInt::get(Int64Ty, val);
+ return llvm::ConstantInt::get(IntPtrTy, val);
}
llvm::SmallVector<llvm::Constant*, 8> values;
int v=0;
@@ -1748,8 +1752,6 @@ llvm::Constant *CGObjCGNU::MakeBitField(llvm::SmallVectorImpl<bool> &bits) {
llvm::Constant *GS = MakeGlobal(llvm::StructType::get(Int32Ty, arrayTy,
NULL), fields);
llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
- if (IntPtrTy != Int64Ty)
- ptr = llvm::ConstantExpr::getZExt(ptr, Int64Ty);
return ptr;
}
@@ -2073,12 +2075,12 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
}
++ivarIndex;
}
- llvm::Constant *Zero64 = llvm::ConstantInt::get(Int64Ty, 0);
+ llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
//Generate metaclass for class methods
llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList(
empty, empty, empty), ClassMethodList, NULLPtr,
- NULLPtr, NULLPtr, Zero64, Zero64, true);
+ NULLPtr, NULLPtr, ZeroPtr, ZeroPtr, true);
// Generate the class structure
llvm::Constant *ClassStruct =
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 924ec84..275045c 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -29,6 +29,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -858,6 +859,59 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
}
}
+namespace {
+ struct FunctionIsDirectlyRecursive :
+ public RecursiveASTVisitor<FunctionIsDirectlyRecursive> {
+ const StringRef Name;
+ bool Result;
+ FunctionIsDirectlyRecursive(const FunctionDecl *F) :
+ Name(F->getName()), Result(false) {
+ }
+ typedef RecursiveASTVisitor<FunctionIsDirectlyRecursive> Base;
+
+ bool TraverseCallExpr(CallExpr *E) {
+ const Decl *D = E->getCalleeDecl();
+ if (!D)
+ return true;
+ AsmLabelAttr *Attr = D->getAttr<AsmLabelAttr>();
+ if (!Attr)
+ return true;
+ if (Name == Attr->getLabel()) {
+ Result = true;
+ return false;
+ }
+ return true;
+ }
+ };
+}
+
+// isTriviallyRecursiveViaAsm - Check if this function calls another
+// decl that, because of the asm attribute, ends up pointing to itself.
+bool
+CodeGenModule::isTriviallyRecursiveViaAsm(const FunctionDecl *F) {
+ if (getCXXABI().getMangleContext().shouldMangleDeclName(F))
+ return false;
+
+ FunctionIsDirectlyRecursive Walker(F);
+ Walker.TraverseFunctionDecl(const_cast<FunctionDecl*>(F));
+ return Walker.Result;
+}
+
+bool
+CodeGenModule::shouldEmitFunction(const FunctionDecl *F) {
+ if (getFunctionLinkage(F) != llvm::Function::AvailableExternallyLinkage)
+ return true;
+ if (CodeGenOpts.OptimizationLevel == 0 &&
+ !F->hasAttr<AlwaysInlineAttr>())
+ return false;
+ // PR9614. Avoid cases where the source code is lying to us. An available
+ // externally function should have an equivalent function somewhere else,
+ // but a function that calls itself is clearly not equivalent to the real
+ // implementation.
+ // This happens in glibc's btowc and in some configure checks.
+ return !isTriviallyRecursiveViaAsm(F);
+}
+
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
@@ -868,10 +922,7 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// At -O0, don't generate IR for functions with available_externally
// linkage.
- if (CodeGenOpts.OptimizationLevel == 0 &&
- !Function->hasAttr<AlwaysInlineAttr>() &&
- getFunctionLinkage(Function)
- == llvm::Function::AvailableExternallyLinkage)
+ if (!shouldEmitFunction(Function))
return;
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 8e38a89..dbc6a87 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -324,6 +324,8 @@ class CodeGenModule : public CodeGenTypeCache {
void createOpenCLRuntime();
void createCUDARuntime();
+ bool isTriviallyRecursiveViaAsm(const FunctionDecl *F);
+ bool shouldEmitFunction(const FunctionDecl *F);
llvm::LLVMContext &VMContext;
/// @name Cache for Blocks Runtime Globals
OpenPOWER on IntegriCloud