From: John McCall Date: Tue, 13 Sep 2011 23:05:03 +0000 (+0000) Subject: Correctly generate IR for casted "builtin" functions, where X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a45680b7e7c49ea9893c6cff585984f3e4120366;p=clang Correctly generate IR for casted "builtin" functions, where the builtin is really just a predefined declaration. These are totally valid to cast. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139657 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 271fe66ffe..ca2450a8b5 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -27,6 +27,30 @@ using namespace clang; using namespace CodeGen; using namespace llvm; +/// getBuiltinLibFunction - Given a builtin id for a function like +/// "__builtin_fabsf", return a Function* for "fabsf". +llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD, + unsigned BuiltinID) { + assert(Context.BuiltinInfo.isLibFunction(BuiltinID)); + + // Get the name, skip over the __builtin_ prefix (if necessary). + StringRef Name; + GlobalDecl D(FD); + + // If the builtin has been declared explicitly with an assembler label, + // use the mangled name. This differs from the plain label on platforms + // that prefix labels. + if (FD->hasAttr()) + Name = getMangledName(D); + else + Name = Context.BuiltinInfo.GetName(BuiltinID) + 10; + + llvm::FunctionType *Ty = + cast(getTypes().ConvertType(FD->getType())); + + return GetOrCreateLLVMFunction(Name, Ty, D, /*ForVTable=*/false); +} + /// Emit the conversions required to turn the given value into an /// integer of the given size. static Value *EmitToInt(CodeGenFunction &CGF, llvm::Value *V, @@ -142,6 +166,12 @@ static Value *EmitFAbs(CodeGenFunction &CGF, Value *V, QualType ValTy) { return CGF.Builder.CreateCall(Fn, V, "abs"); } +static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *Fn, + const CallExpr *E, llvm::Value *calleeValue) { + return CGF.EmitCall(E->getCallee()->getType(), calleeValue, + ReturnValueSlot(), E->arg_begin(), E->arg_end(), Fn); +} + RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E) { // See if we can constant fold this builtin. If so, don't emit it at all. @@ -1005,13 +1035,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, } } - // If this is an alias for a libm function (e.g. __builtin_sin) turn it into - // that function. - if (getContext().BuiltinInfo.isLibFunction(BuiltinID) || - getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return EmitCall(E->getCallee()->getType(), - CGM.getBuiltinLibFunction(FD, BuiltinID), - ReturnValueSlot(), E->arg_begin(), E->arg_end(), FD); + // If this is an alias for a lib function (e.g. __builtin_sin), emit + // the call using the normal call path, but using the unmangled + // version of the function name. + if (getContext().BuiltinInfo.isLibFunction(BuiltinID)) + return emitLibraryCall(*this, FD, E, + CGM.getBuiltinLibFunction(FD, BuiltinID)); + + // If this is a predefined lib function (e.g. malloc), emit the call + // using exactly the normal call path. + if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return emitLibraryCall(*this, FD, E, EmitScalarExpr(E->getCallee())); // See if we have a target specific intrinsic. const char *Name = getContext().BuiltinInfo.GetName(BuiltinID); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 7a946cb9d5..19c3b064d6 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -27,7 +27,6 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" -#include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -1611,35 +1610,6 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { SetCommonAttributes(D, GA); } -/// getBuiltinLibFunction - Given a builtin id for a function like -/// "__builtin_fabsf", return a Function* for "fabsf". -llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD, - unsigned BuiltinID) { - assert((Context.BuiltinInfo.isLibFunction(BuiltinID) || - Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) && - "isn't a lib fn"); - - // Get the name, skip over the __builtin_ prefix (if necessary). - StringRef Name; - GlobalDecl D(FD); - - // If the builtin has been declared explicitly with an assembler label, - // use the mangled name. This differs from the plain label on platforms - // that prefix labels. - if (FD->hasAttr()) - Name = getMangledName(D); - else if (Context.BuiltinInfo.isLibFunction(BuiltinID)) - Name = Context.BuiltinInfo.GetName(BuiltinID) + 10; - else - Name = Context.BuiltinInfo.GetName(BuiltinID); - - - llvm::FunctionType *Ty = - cast(getTypes().ConvertType(FD->getType())); - - return GetOrCreateLLVMFunction(Name, Ty, D, /*ForVTable=*/false); -} - llvm::Function *CodeGenModule::getIntrinsic(unsigned IID, ArrayRef Tys) { return llvm::Intrinsic::getDeclaration(&getModule(), (llvm::Intrinsic::ID)IID, diff --git a/test/CodeGenObjC/builtins.m b/test/CodeGenObjC/builtins.m new file mode 100644 index 0000000000..022ac1db33 --- /dev/null +++ b/test/CodeGenObjC/builtins.m @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +void test0(id receiver, SEL sel, const char *str) { + short s = ((short (*)(id, SEL, const char*)) objc_msgSend)(receiver, sel, str); +} +// CHECK: define void @test0( +// CHECK: call signext i16 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i16 (i8*, i8*, i8*)*)(