Implement basic overload support via a new builtin, __builtin_overload.
__builtin_overload takes 2 or more arguments:
0) a non-zero constant-expr for the number of arguments the overloaded
functions will take
1) the arguments to pass to the matching overloaded function
2) a list of functions to match.
The return type of __builtin_overload is inferred from the function whose args
match the types of the arguments passed to the builtin. For example:
float a;
float sinf(float);
int sini(int);
float b = __builtin_overload(1, a, sini, sinf);
Says that we are overloading functions that take one argument, and trying to
pass an argument of the same type as 'a'. sini() does not match since it takes
and argument of type int. sinf does match, so at codegen time this will turn
into float b = sinf(a);
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46132 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/CodeGen/CGBuiltin.cpp b/CodeGen/CGBuiltin.cpp
index cd3c2e6..b782b22 100644
--- a/CodeGen/CGBuiltin.cpp
+++ b/CodeGen/CGBuiltin.cpp
@@ -29,7 +29,8 @@
switch (BuiltinID) {
default: {
if (getContext().BuiltinInfo.isLibFunction(BuiltinID))
- return EmitCallExpr(CGM.getBuiltinLibFunction(BuiltinID), E);
+ return EmitCallExpr(CGM.getBuiltinLibFunction(BuiltinID), E->getType(),
+ E->arg_begin());
// See if we have a target specific intrinsic.
Intrinsic::ID IntrinsicID;
diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp
index 0fe25c8..ad9e15a 100644
--- a/CodeGen/CGExpr.cpp
+++ b/CodeGen/CGExpr.cpp
@@ -450,7 +450,12 @@
return EmitBuiltinExpr(builtinID, E);
llvm::Value *Callee = EmitScalarExpr(E->getCallee());
- return EmitCallExpr(Callee, E);
+ return EmitCallExpr(Callee, E->getType(), E->arg_begin());
+}
+
+RValue CodeGenFunction::EmitCallExpr(Expr *FnExpr, Expr *const *Args) {
+ llvm::Value *Callee = EmitScalarExpr(FnExpr);
+ return EmitCallExpr(Callee, FnExpr->getType(), Args);
}
LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
@@ -459,45 +464,42 @@
return LValue::MakeAddr(RV.getAggregateAddr());
}
-RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, const CallExpr *E) {
+RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType FnType,
+ Expr *const *ArgExprs) {
// The callee type will always be a pointer to function type, get the function
// type.
- QualType CalleeTy = E->getCallee()->getType();
- CalleeTy = cast<PointerType>(CalleeTy.getCanonicalType())->getPointeeType();
-
- // Get information about the argument types.
- FunctionTypeProto::arg_type_iterator ArgTyIt = 0, ArgTyEnd = 0;
+ FnType = cast<PointerType>(FnType.getCanonicalType())->getPointeeType();
+ QualType ResultType = cast<FunctionType>(FnType)->getResultType();
// Calling unprototyped functions provides no argument info.
- if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(CalleeTy)) {
- ArgTyIt = FTP->arg_type_begin();
- ArgTyEnd = FTP->arg_type_end();
- }
+ unsigned NumArgs = 0;
+ if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FnType))
+ NumArgs = FTP->getNumArgs();
llvm::SmallVector<llvm::Value*, 16> Args;
// Handle struct-return functions by passing a pointer to the location that
// we would like to return into.
- if (hasAggregateLLVMType(E->getType())) {
+ if (hasAggregateLLVMType(ResultType)) {
// Create a temporary alloca to hold the result of the call. :(
- Args.push_back(CreateTempAlloca(ConvertType(E->getType())));
+ Args.push_back(CreateTempAlloca(ConvertType(ResultType)));
// FIXME: set the stret attribute on the argument.
}
- for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
- QualType ArgTy = E->getArg(i)->getType();
+ for (unsigned i = 0, e = NumArgs; i != e; ++i) {
+ QualType ArgTy = ArgExprs[i]->getType();
if (!hasAggregateLLVMType(ArgTy)) {
// Scalar argument is passed by-value.
- Args.push_back(EmitScalarExpr(E->getArg(i)));
+ Args.push_back(EmitScalarExpr(ArgExprs[i]));
} else if (ArgTy->isComplexType()) {
// Make a temporary alloca to pass the argument.
llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
- EmitComplexExprIntoAddr(E->getArg(i), DestMem, false);
+ EmitComplexExprIntoAddr(ArgExprs[i], DestMem, false);
Args.push_back(DestMem);
} else {
llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
- EmitAggExpr(E->getArg(i), DestMem, false);
+ EmitAggExpr(ArgExprs[i], DestMem, false);
Args.push_back(DestMem);
}
}
@@ -505,14 +507,14 @@
llvm::Value *V = Builder.CreateCall(Callee, &Args[0], &Args[0]+Args.size());
if (V->getType() != llvm::Type::VoidTy)
V->setName("call");
- else if (E->getType()->isComplexType())
+ else if (ResultType->isComplexType())
return RValue::getComplex(LoadComplexFromAddr(Args[0], false));
- else if (hasAggregateLLVMType(E->getType()))
+ else if (hasAggregateLLVMType(ResultType))
// Struct return.
return RValue::getAggregate(Args[0]);
else {
// void return.
- assert(E->getType()->isVoidType() && "Should only have a void expr here");
+ assert(ResultType->isVoidType() && "Should only have a void expr here");
V = 0;
}
diff --git a/CodeGen/CGExprScalar.cpp b/CodeGen/CGExprScalar.cpp
index a76f1e1..410284a 100644
--- a/CodeGen/CGExprScalar.cpp
+++ b/CodeGen/CGExprScalar.cpp
@@ -282,6 +282,7 @@
// Other Operators.
Value *VisitConditionalOperator(const ConditionalOperator *CO);
Value *VisitChooseExpr(ChooseExpr *CE);
+ Value *VisitOverloadExpr(OverloadExpr *OE);
Value *VisitVAArgExpr(VAArgExpr *VE);
Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
return CGF.EmitObjCStringLiteral(E);
@@ -991,6 +992,10 @@
Visit(E->isConditionTrue(CGF.getContext()) ? E->getLHS() : E->getRHS());
}
+Value *ScalarExprEmitter::VisitOverloadExpr(OverloadExpr *E) {
+ return CGF.EmitCallExpr(E->getFn(), E->arg_begin()).getScalarVal();
+}
+
Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
llvm::Value *ArgValue = EmitLValue(VE->getSubExpr()).getAddress();
diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h
index 216b7cd..55a02a8 100644
--- a/CodeGen/CodeGenFunction.h
+++ b/CodeGen/CodeGenFunction.h
@@ -388,7 +388,8 @@
//===--------------------------------------------------------------------===//
RValue EmitCallExpr(const CallExpr *E);
- RValue EmitCallExpr(llvm::Value *Callee, const CallExpr *E);
+ RValue EmitCallExpr(Expr *FnExpr, Expr *const *Args);
+ RValue EmitCallExpr(llvm::Value *Callee, QualType FnType, Expr *const *Args);
RValue EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);