forked from OSchip/llvm-project
Correctly generate IR for casted "builtin" functions, where
the builtin is really just a predefined declaration. These are totally valid to cast. llvm-svn: 139657
This commit is contained in:
parent
75461af000
commit
30e4efd458
|
@ -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<AsmLabelAttr>())
|
||||
Name = getMangledName(D);
|
||||
else
|
||||
Name = Context.BuiltinInfo.GetName(BuiltinID) + 10;
|
||||
|
||||
llvm::FunctionType *Ty =
|
||||
cast<llvm::FunctionType>(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);
|
||||
|
|
|
@ -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<AsmLabelAttr>())
|
||||
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<llvm::FunctionType>(getTypes().ConvertType(FD->getType()));
|
||||
|
||||
return GetOrCreateLLVMFunction(Name, Ty, D, /*ForVTable=*/false);
|
||||
}
|
||||
|
||||
llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,
|
||||
ArrayRef<llvm::Type*> Tys) {
|
||||
return llvm::Intrinsic::getDeclaration(&getModule(), (llvm::Intrinsic::ID)IID,
|
||||
|
|
|
@ -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*)*)(
|
Loading…
Reference in New Issue