summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarphaman <arphaman@gmail.com>2013-09-14 09:46:56 +0100
committerarphaman <arphaman@gmail.com>2013-09-14 09:46:56 +0100
commitc5c76bd18831fd3fbd8706fd2d3de17cc56cae84 (patch)
treefb257a50a2c73ff03dee2f96b0dadd1b36e07835
parent60c615aa6ef39869b461054f016f439290a1575e (diff)
downloadflang-c5c76bd18831fd3fbd8706fd2d3de17cc56cae84.tar.gz
added target info for x86 complex return abi
-rw-r--r--lib/CodeGen/CGCall.cpp34
-rw-r--r--lib/CodeGen/CGCall.h4
-rw-r--r--lib/CodeGen/CGExprAgg.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp15
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp1
-rw-r--r--lib/CodeGen/TargetInfo.cpp26
-rw-r--r--test/CodeGen/x86LinuxAggregateABI.f9517
7 files changed, 79 insertions, 22 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 49436246de..5d364dd589 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -44,13 +44,15 @@ llvm::Type *CodeGenTypes::ConvertReturnType(QualType T,
break;
}
- ReturnInfo.Kind = T->isComplexType()? CGFunctionInfo::RetInfo::ComplexValue :
- CGFunctionInfo::RetInfo::ScalarValue;
-
+ ReturnInfo.Type = T;
if(T->isComplexType()) {
CGM.getTargetCodeGenInfo().getABIInfo().computeReturnTypeInfo(T, ReturnInfo.ABIInfo);
if(ReturnInfo.ABIInfo.hasAggregateReturnType())
return ReturnInfo.ABIInfo.getAggregateReturnType();
+ if(ReturnInfo.ABIInfo.getKind() == ABIRetInfo::AggregateValueAsArg) {
+ ReturnInfo.ReturnArgInfo.ABIInfo = ABIArgInfo(ABIArgInfo::Reference);
+ return CGM.VoidTy;
+ }
}
return ConvertType(T);
@@ -108,7 +110,8 @@ void CodeGenTypes::ConvertArgumentTypeForReturnValue(SmallVectorImpl<CGFunctionI
SmallVectorImpl<llvm::Type *> &AdditionalArgTypes,
QualType T,
const CGFunctionInfo::RetInfo &ReturnInfo) {
- if(ReturnInfo.ABIInfo.getKind() == ABIRetInfo::CharacterValueAsArg) {
+ if(ReturnInfo.ABIInfo.getKind() == ABIRetInfo::CharacterValueAsArg ||
+ ReturnInfo.ABIInfo.getKind() == ABIRetInfo::AggregateValueAsArg) {
ArgInfo.push_back(ReturnInfo.ReturnArgInfo);
ConvertArgumentType(ArgTypes, AdditionalArgTypes,
T, ReturnInfo.ReturnArgInfo);
@@ -163,17 +166,26 @@ RValueTy CodeGenFunction::EmitCall(llvm::Value *Callee,
CallArgList &ArgList,
ArrayRef<Expr*> Arguments,
bool ReturnsNothing) {
- llvm::Value *ResultTemp;
+ // arguments
auto ArgumentInfo = FuncInfo->getArguments();
auto FType = Callee->getType()->isFunctionTy()? cast<llvm::FunctionType>(Callee->getType())
: dyn_cast<llvm::FunctionType>(cast<llvm::PointerType>(Callee->getType())->getPointerElementType());
for(size_t I = 0; I < Arguments.size(); ++I)
EmitCallArg(FType->getParamType(ArgList.getOffset()),
ArgList, Arguments[I], ArgumentInfo[I]);
+
+ // return value
auto RetABIKind = FuncInfo->getReturnInfo().ABIInfo.getKind();
+ auto RetType = FuncInfo->getReturnInfo().Type;
if(RetABIKind == ABIRetInfo::CharacterValueAsArg)
EmitCallArg(ArgList, ArgList.getReturnValueArg().asCharacter(),
FuncInfo->getReturnInfo().ReturnArgInfo);
+ else if(RetABIKind == ABIRetInfo::AggregateValueAsArg) {
+ auto ResultTemp = CreateTempAlloca(ConvertTypeForMem(RetType),
+ "complex-return");
+ ArgList.addReturnValueArg(ResultTemp);
+ ArgList.add(ResultTemp);
+ }
auto Result = Builder.CreateCall(Callee,
ArgList.createValues(), "call");
@@ -183,7 +195,7 @@ RValueTy CodeGenFunction::EmitCall(llvm::Value *Callee,
RetABIKind == ABIRetInfo::Nothing)
return RValueTy();
else if(RetABIKind == ABIRetInfo::Value &&
- FuncInfo->getReturnInfo().Kind == CGFunctionInfo::RetInfo::ComplexValue) {
+ !RetType.isNull() && RetType->isComplexType()) {
auto RetInfo = FuncInfo->getReturnInfo();
if(RetInfo.ABIInfo.hasAggregateReturnType()) {
auto T = RetInfo.ABIInfo.getAggregateReturnType();
@@ -193,7 +205,12 @@ RValueTy CodeGenFunction::EmitCall(llvm::Value *Callee,
}
return ExtractComplexValue(Result);
}
- else if(RetABIKind == ABIRetInfo::CharacterValueAsArg)
+ else if(RetABIKind == ABIRetInfo::AggregateValueAsArg) {
+ if(RetType->isComplexType())
+ return EmitComplexLoad(ArgList.getReturnValueArg().asScalar());
+ else
+ llvm_unreachable("unsupported aggregate return ABI");
+ } else if(RetABIKind == ABIRetInfo::CharacterValueAsArg)
return ArgList.getReturnValueArg();
return Result;
}
@@ -216,7 +233,8 @@ RValueTy CodeGenFunction::EmitCall(CGFunction Func,
auto Result = Builder.CreateCall(Func.getFunction(),
ArgList.createValues(), "call");
Result->setCallingConv(FuncInfo->getCallingConv());
- if(FuncInfo->getReturnInfo().Kind == CGFunctionInfo::RetInfo::ComplexValue)
+ if(!FuncInfo->getReturnInfo().Type.isNull() &&
+ FuncInfo->getReturnInfo().Type->isComplexType())
return ExtractComplexValue(Result);
return Result;
}
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index ad14d88de8..b1ea770e3b 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -75,9 +75,9 @@ public:
ABIRetInfo ABIInfo;
ArgInfo ReturnArgInfo;
- ValueKind Kind;
+ QualType Type;
- RetInfo() : ABIInfo(ABIRetInfo::Nothing), Kind(ScalarValue) {}
+ RetInfo() : ABIInfo(ABIRetInfo::Nothing) {}
};
private:
llvm::FunctionType *Type;
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 4786a66813..e2d370a6a5 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -1,4 +1,4 @@
-//===--- CGExprAgg.cpp - Emit LLVM Code from Aggregate Expressions --------===//
+//===--- CGExprAgg.cpp - Emit LLVM Code from Aggregate Expressions --------===//
//
// The LLVM Compiler Infrastructure
//
@@ -92,7 +92,7 @@ llvm::Value *CodeGenFunction::EmitAggregateMember(llvm::Value *Agg, const FieldD
}
void CodeGenFunction::EmitAggregateReturn(const CGFunctionInfo::RetInfo &Info, llvm::Value *Ptr) {
- if(Info.Kind == CGFunctionInfo::RetInfo::ComplexValue) {
+ if(Info.Type->isComplexType()) {
if(Info.ABIInfo.hasAggregateReturnType()) {
Builder.CreateRet(Builder.CreateLoad(
Builder.CreateBitCast(Ptr, llvm::PointerType::get(Info.ABIInfo.getAggregateReturnType(), 0))));
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index d8b0661bcc..9ef0d28058 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -88,7 +88,9 @@ void CodeGenFunction::EmitFunctionArguments(const FunctionDecl *Func,
}
// Extra argument for the returned data.
- if(Info->getReturnInfo().ABIInfo.getKind() == ABIRetInfo::CharacterValueAsArg) {
+ auto RetABIKind = Info->getReturnInfo().ABIInfo.getKind();
+ if(RetABIKind == ABIRetInfo::CharacterValueAsArg ||
+ RetABIKind == ABIRetInfo::AggregateValueAsArg) {
Arg->setName(Func->getName());
ReturnValuePtr = Arg;
++Arg;
@@ -160,14 +162,11 @@ void CodeGenFunction::EmitFunctionEpilogue(const FunctionDecl *Func,
auto ReturnInfo = Info->getReturnInfo();
if(ReturnInfo.ABIInfo.getKind() == ABIRetInfo::Value) {
- switch(ReturnInfo.Kind) {
- case CGFunctionInfo::RetInfo::ScalarValue:
- Builder.CreateRet(Builder.CreateLoad(RetVar));
- break;
- case CGFunctionInfo::RetInfo::ComplexValue:
+ if(ReturnInfo.Type->isComplexType() ||
+ ReturnInfo.Type->isRecordType()) {
EmitAggregateReturn(ReturnInfo, RetVar);
- break;
- }
+ } else
+ Builder.CreateRet(Builder.CreateLoad(RetVar));
}
else Builder.CreateRetVoid();
} else
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index fe94917792..8b9a355767 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -198,7 +198,6 @@ CodeGenTypes::GetFunctionType(FortranABI &ABI,
}
else {
ReturnInfo.ABIInfo = ABIRetInfo(ABIRetInfo::Value);
- ReturnInfo.Kind = CGFunctionInfo::RetInfo::ScalarValue;
RetType = ReturnType.asLLVMType();
}
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 27336cb1a6..0a9bce32ea 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -30,9 +30,29 @@ namespace CodeGen {
class DefaultABIInfo : public ABIInfo {
public:
- void computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const {}
+ void computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const;
};
+void DefaultABIInfo::computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const {
+ if(!T->isComplexType())
+ return;
+
+ Info = ABIRetInfo(ABIRetInfo::AggregateValueAsArg);
+}
+
+/// ABI Info for x86_32
+class X86_32ABIInfo : public ABIInfo {
+public:
+ void computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const;
+};
+
+void X86_32ABIInfo::computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const {
+ if(!T->isComplexType())
+ return;
+
+ Info = ABIRetInfo(ABIRetInfo::AggregateValueAsArg);
+}
+
/// ABI Info for x86_64
/// NB: works only with x86_64-pc-{linux,darwin}
class X86_64ABIInfo : public ABIInfo {
@@ -75,6 +95,10 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
TheTargetCodeGenInfo = new TargetCodeGenInfo(new DefaultABIInfo());
break;
+ case llvm::Triple::x86:
+ TheTargetCodeGenInfo = new TargetCodeGenInfo(new X86_32ABIInfo());
+ break;
+
case llvm::Triple::x86_64:
TheTargetCodeGenInfo = new TargetCodeGenInfo(new X86_64ABIInfo(*this));
break;
diff --git a/test/CodeGen/x86LinuxAggregateABI.f95 b/test/CodeGen/x86LinuxAggregateABI.f95
new file mode 100644
index 0000000000..29bbe5efb2
--- /dev/null
+++ b/test/CodeGen/x86LinuxAggregateABI.f95
@@ -0,0 +1,17 @@
+! RUN: %flang -triple "i686-unknown-linux" -emit-llvm -o - %s | %file_check %s
+
+complex function foo() ! CHECK: define void @foo_({ float, float }*
+ foo = (1.0, 2.0)
+end
+
+complex(8) function bar() ! CHECK: define void @bar_({ double, double }*
+ bar = 0.0
+end
+
+program test
+ complex c
+ complex(8) dc
+
+ c = foo()
+ dc = bar()
+end