diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 40 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 48 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 27 | ||||
-rw-r--r-- | lib/CodeGen/TargetABIInfo.cpp | 38 |
9 files changed, 140 insertions, 34 deletions
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index f9c44c8..a919dfa 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -17,7 +17,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "clang/AST/TargetBuiltins.h" +#include "clang/Basic/TargetBuiltins.h" #include "llvm/Intrinsics.h" using namespace clang; using namespace CodeGen; diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index b10b9c2..4037f32 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -682,10 +682,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // location that we would like to return into. QualType RetTy = CallInfo.getReturnType(); const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); - if (CGM.ReturnTypeUsesSret(CallInfo)) { - // Create a temporary alloca to hold the result of the call. :( + + + // If the call returns a temporary with struct return, create a temporary + // alloca to hold the result. + if (CGM.ReturnTypeUsesSret(CallInfo)) Args.push_back(CreateTempAlloca(ConvertTypeForMem(RetTy))); - } assert(CallInfo.arg_size() == CallArgs.size() && "Mismatch between function signature & arguments."); @@ -747,6 +749,35 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, break; } } + + // If the callee is a bitcast of a function to a varargs pointer to function + // type, check to see if we can remove the bitcast. This handles some cases + // with unprototyped functions. + if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee)) + if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) { + const llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType()); + const llvm::FunctionType *CurFT = + cast<llvm::FunctionType>(CurPT->getElementType()); + const llvm::FunctionType *ActualFT = CalleeF->getFunctionType(); + + if (CE->getOpcode() == llvm::Instruction::BitCast && + ActualFT->getReturnType() == CurFT->getReturnType() && + ActualFT->getNumParams() == CurFT->getNumParams()) { + bool ArgsMatch = true; + for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i) + if (ActualFT->getParamType(i) != CurFT->getParamType(i)) { + ArgsMatch = false; + break; + } + + // Strip the cast if we can get away with it. This is a nice cleanup, + // but also allows us to inline the function at -O0 if it is marked + // always_inline. + if (ArgsMatch) + Callee = CalleeF; + } + } + llvm::BasicBlock *InvokeDest = getInvokeDest(); CodeGen::AttributeListType AttributeList; @@ -765,7 +796,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } CS.setAttributes(Attrs); - if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee->stripPointerCasts())) + if (const llvm::Function *F = + dyn_cast<llvm::Function>(Callee->stripPointerCasts())) CS.setCallingConv(F->getCallingConv()); // If the call doesn't return, finish the basic block and clear the diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index c52e6bd..eb0db61 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1156,10 +1156,9 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { } } - if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E)) { + if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E)) if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl)) return EmitCXXOperatorMemberCallExpr(CE, MD); - } llvm::Value *Callee = EmitScalarExpr(E->getCallee()); return EmitCall(Callee, E->getCallee()->getType(), diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 41fb725..e1332ff 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -77,7 +77,14 @@ public: /// and returns the result. ComplexPairTy EmitLoadOfLValue(const Expr *E) { LValue LV = CGF.EmitLValue(E); - return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); + if (LV.isSimple()) + return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); + + if (LV.isPropertyRef()) + return CGF.EmitObjCPropertyGet(LV.getPropertyRefExpr()).getComplexVal(); + + assert(LV.isKVCRef() && "Unknown LValue type!"); + return CGF.EmitObjCPropertyGet(LV.getKVCRefExpr()).getComplexVal(); } /// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load @@ -107,6 +114,18 @@ public: // l-values. ComplexPairTy VisitDeclRefExpr(const Expr *E) { return EmitLoadOfLValue(E); } + ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + return EmitLoadOfLValue(E); + } + ComplexPairTy VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { + return EmitLoadOfLValue(E); + } + ComplexPairTy VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { + return EmitLoadOfLValue(E); + } + ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) { + return CGF.EmitObjCMessageExpr(E).getComplexVal(); + } ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); } ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); } @@ -522,15 +541,32 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { // Compute the address to store into. LValue LHS = CGF.EmitLValue(E->getLHS()); - - // Store into it. - EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified()); - // And now return the LHS + + // Store into it, if simple. + if (LHS.isSimple()) { + EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified()); + + // And now return the LHS + IgnoreReal = ignreal; + IgnoreImag = ignimag; + IgnoreRealAssign = ignreal; + IgnoreImagAssign = ignimag; + return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified()); + } + + // Otherwise we must have a property setter (no complex vector/bitfields). + if (LHS.isPropertyRef()) + CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), RValue::getComplex(Val)); + else + CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), RValue::getComplex(Val)); + + // There is no reload after a store through a method, but we need to restore + // the Ignore* flags. IgnoreReal = ignreal; IgnoreImag = ignimag; IgnoreRealAssign = ignreal; IgnoreImagAssign = ignimag; - return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified()); + return Val; } ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) { diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index b30bafb..0e21a00 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -17,6 +17,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Basic/Builtins.h" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/GlobalVariable.h" diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 75755ec..bd5b05a 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1508,6 +1508,8 @@ CodeGen::RValue CGObjCCommonMac::EmitLegacyMessageSend( BuiltinType::Kind k = BT->getKind(); Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper) : ObjCTypes.getSendFn2(IsSuper); + } else { + Fn = ObjCTypes.getSendFn2(IsSuper); } } else diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 5c12c81..82156e9 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -21,6 +21,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -1107,9 +1108,9 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) { Name += 10; // Get the type for the builtin. - Builtin::Context::GetBuiltinTypeError Error; - QualType Type = Context.BuiltinInfo.GetBuiltinType(BuiltinID, Context, Error); - assert(Error == Builtin::Context::GE_None && "Can't get builtin type"); + ASTContext::GetBuiltinTypeError Error; + QualType Type = Context.GetBuiltinType(BuiltinID, Error); + assert(Error == ASTContext::GE_None && "Can't get builtin type"); const llvm::FunctionType *Ty = cast<llvm::FunctionType>(getTypes().ConvertType(Type)); @@ -1481,7 +1482,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::CXXDestructor: EmitCXXDestructors(cast<CXXDestructorDecl>(D)); break; - + + case Decl::StaticAssert: + // Nothing to do. + break; + // Objective-C Decls // Forward declarations, no (immediate) code generation. diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 6ee1223..14392ab 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -87,19 +87,20 @@ static bool isInCLinkageSpecification(const Decl *D) { bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) { // Clang's "overloadable" attribute extension to C/C++ implies // name mangling (always). - if (FD->hasAttr<OverloadableAttr>()) { - ; // fall into mangling code unconditionally. - } else if (// C functions are not mangled - !Context.getLangOptions().CPlusPlus || - // "main" is not mangled in C++ - FD->isMain() || - // No mangling in an "implicit extern C" header. - (FD->getLocation().isValid() && - Context.getSourceManager().getFileCharacteristic(FD->getLocation())) - == SrcMgr::C_ExternCSystem || - // No name mangling in a C linkage specification. - isInCLinkageSpecification(FD)) - return false; + if (!FD->hasAttr<OverloadableAttr>()) { + // C functions are not mangled, and "main" is never mangled. + if (!Context.getLangOptions().CPlusPlus || FD->isMain()) + return false; + + // No mangling in an "implicit extern C" header. + if (FD->getLocation().isValid() && + Context.getSourceManager().isInExternCSystemHeader(FD->getLocation())) + return false; + + // No name mangling in a C linkage specification. + if (isInCLinkageSpecification(FD)) + return false; + } // If we get here, mangle the decl name! Out << "_Z"; diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp index 6f7bea2..361e5c0 100644 --- a/lib/CodeGen/TargetABIInfo.cpp +++ b/lib/CodeGen/TargetABIInfo.cpp @@ -159,6 +159,23 @@ static bool areAllFields32Or64BitBasicType(const RecordDecl *RD, return true; } +static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) { + for (RecordDecl::field_iterator i = RD->field_begin(Context), + e = RD->field_end(Context); i != e; ++i) { + const FieldDecl *FD = *i; + + if (FD->getType()->isVectorType() && + Context.getTypeSize(FD->getType()) >= 128) + return true; + + if (const RecordType* RT = FD->getType()->getAsRecordType()) + if (typeContainsSSEVector(RT->getDecl(), Context)) + return true; + } + + return false; +} + namespace { /// DefaultABIInfo - The default implementation for ABI specific /// details. This implementation provides information which results in @@ -193,6 +210,9 @@ class X86_32ABIInfo : public ABIInfo { static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context); + static unsigned getIndirectArgumentAlignment(QualType Ty, + ASTContext &Context); + public: ABIArgInfo classifyReturnType(QualType RetTy, ASTContext &Context) const; @@ -350,6 +370,16 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, } } +unsigned X86_32ABIInfo::getIndirectArgumentAlignment(QualType Ty, + ASTContext &Context) { + unsigned Align = Context.getTypeAlign(Ty); + if (Align < 128) return 0; + if (const RecordType* RT = Ty->getAsRecordType()) + if (typeContainsSSEVector(RT->getDecl(), Context)) + return 16; + return 0; +} + ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context) const { // FIXME: Set alignment on indirect arguments. @@ -357,11 +387,11 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, // Structures with flexible arrays are always indirect. if (const RecordType *RT = Ty->getAsStructureType()) if (RT->getDecl()->hasFlexibleArrayMember()) - return ABIArgInfo::getIndirect(0); + return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, + Context)); // Ignore empty structs. - uint64_t Size = Context.getTypeSize(Ty); - if (Ty->isStructureType() && Size == 0) + if (Ty->isStructureType() && Context.getTypeSize(Ty) == 0) return ABIArgInfo::getIgnore(); // Expand structs with size <= 128-bits which consist only of @@ -373,7 +403,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, return ABIArgInfo::getExpand(); } - return ABIArgInfo::getIndirect(0); + return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, Context)); } else { return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); |