diff options
author | arphaman <arphaman@gmail.com> | 2013-09-13 18:14:38 +0100 |
---|---|---|
committer | arphaman <arphaman@gmail.com> | 2013-09-13 18:14:38 +0100 |
commit | 60c615aa6ef39869b461054f016f439290a1575e (patch) | |
tree | 4252323f84032146f7e4c349bafd088e0ad66364 | |
parent | f4debe09e4275ff0c2d046b1d6c029ff265578d4 (diff) | |
download | flang-60c615aa6ef39869b461054f016f439290a1575e.tar.gz |
added x86_64 target info for proper complex return abi
-rw-r--r-- | lib/CodeGen/ABIInfo.h | 33 | ||||
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 29 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 8 | ||||
-rw-r--r-- | lib/CodeGen/ModuleBuilder.cpp | 17 | ||||
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 86 | ||||
-rw-r--r-- | lib/CodeGen/TargetInfo.h | 54 | ||||
-rw-r--r-- | test/CodeGen/subprogram.f95 | 8 | ||||
-rw-r--r-- | test/CodeGen/x86_64LinuxAggregateABI.f95 | 9 | ||||
-rw-r--r-- | tools/driver/Main.cpp | 19 |
15 files changed, 256 insertions, 33 deletions
diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h index 652eef3f6a..259b6142bf 100644 --- a/lib/CodeGen/ABIInfo.h +++ b/lib/CodeGen/ABIInfo.h @@ -12,6 +12,12 @@ #include "flang/AST/Type.h" +namespace llvm { + +class Type; + +} + namespace flang { /// ABIArgInfo - Helper class to encapsulate information about how a @@ -74,16 +80,37 @@ public: Value, /// Returns a character value using an argument - CharacterValueAsArg + CharacterValueAsArg, + + /// Returns an aggregate value(complex or struct) using an argument + AggregateValueAsArg }; private: - Kind TheKind; + Kind TheKind; + llvm::Type *AggT; public: ABIRetInfo(Kind K = Nothing) : - TheKind(K) {} + TheKind(K), AggT(nullptr) {} + ABIRetInfo(Kind K, llvm::Type *T) : + TheKind(K), AggT(T) {} Kind getKind() const { return TheKind; } + + llvm::Type *getAggregateReturnType() const { + return AggT; + } + + bool hasAggregateReturnType() const { + return AggT != nullptr; + } +}; + +/// ABIInfo - Target specific hooks for defining how a type should be +/// passed or returned from functions. +class ABIInfo { +public: + virtual void computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const = 0; }; } // end namespace flang diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index e8a76fe659..49436246de 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -15,6 +15,8 @@ #include "CGCall.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "ABIInfo.h" +#include "TargetInfo.h" #include "flang/AST/Decl.h" #include "flang/Frontend/CodeGenOptions.h" #include "llvm/ADT/StringExtras.h" @@ -44,6 +46,13 @@ llvm::Type *CodeGenTypes::ConvertReturnType(QualType T, ReturnInfo.Kind = T->isComplexType()? CGFunctionInfo::RetInfo::ComplexValue : CGFunctionInfo::RetInfo::ScalarValue; + + if(T->isComplexType()) { + CGM.getTargetCodeGenInfo().getABIInfo().computeReturnTypeInfo(T, ReturnInfo.ABIInfo); + if(ReturnInfo.ABIInfo.hasAggregateReturnType()) + return ReturnInfo.ABIInfo.getAggregateReturnType(); + } + return ConvertType(T); } @@ -161,8 +170,8 @@ RValueTy CodeGenFunction::EmitCall(llvm::Value *Callee, for(size_t I = 0; I < Arguments.size(); ++I) EmitCallArg(FType->getParamType(ArgList.getOffset()), ArgList, Arguments[I], ArgumentInfo[I]); - auto ReturnInfo = FuncInfo->getReturnInfo().ABIInfo.getKind(); - if(ReturnInfo == ABIRetInfo::CharacterValueAsArg) + auto RetABIKind = FuncInfo->getReturnInfo().ABIInfo.getKind(); + if(RetABIKind == ABIRetInfo::CharacterValueAsArg) EmitCallArg(ArgList, ArgList.getReturnValueArg().asCharacter(), FuncInfo->getReturnInfo().ReturnArgInfo); @@ -171,12 +180,20 @@ RValueTy CodeGenFunction::EmitCall(llvm::Value *Callee, Result->setCallingConv(FuncInfo->getCallingConv()); if(ReturnsNothing || - ReturnInfo == ABIRetInfo::Nothing) + RetABIKind == ABIRetInfo::Nothing) return RValueTy(); - else if(ReturnInfo == ABIRetInfo::Value && - FuncInfo->getReturnInfo().Kind == CGFunctionInfo::RetInfo::ComplexValue) + else if(RetABIKind == ABIRetInfo::Value && + FuncInfo->getReturnInfo().Kind == CGFunctionInfo::RetInfo::ComplexValue) { + auto RetInfo = FuncInfo->getReturnInfo(); + if(RetInfo.ABIInfo.hasAggregateReturnType()) { + auto T = RetInfo.ABIInfo.getAggregateReturnType(); + if(T->isVectorTy()) + return ExtractComplexVectorValue(Result); + else llvm_unreachable("unsupported aggregate return ABI"); + } return ExtractComplexValue(Result); - else if(ReturnInfo == ABIRetInfo::CharacterValueAsArg) + } + else if(RetABIKind == ABIRetInfo::CharacterValueAsArg) return ArgList.getReturnValueArg(); return Result; } diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 0921ef1299..4786a66813 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -91,5 +91,17 @@ llvm::Value *CodeGenFunction::EmitAggregateMember(llvm::Value *Agg, const FieldD return Builder.CreateStructGEP(Agg, Field->getIndex()); } +void CodeGenFunction::EmitAggregateReturn(const CGFunctionInfo::RetInfo &Info, llvm::Value *Ptr) { + if(Info.Kind == CGFunctionInfo::RetInfo::ComplexValue) { + if(Info.ABIInfo.hasAggregateReturnType()) { + Builder.CreateRet(Builder.CreateLoad( + Builder.CreateBitCast(Ptr, llvm::PointerType::get(Info.ABIInfo.getAggregateReturnType(), 0)))); + return; + } + Builder.CreateRet(CreateComplexAggregate( + EmitComplexLoad(Ptr))); + } +} + } } diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index c4b963395c..f2268bdb65 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -238,6 +238,11 @@ ComplexValueTy CodeGenFunction::ExtractComplexValue(llvm::Value *Agg) { Builder.CreateExtractValue(Agg, 1, "im")); } +ComplexValueTy CodeGenFunction::ExtractComplexVectorValue(llvm::Value *Agg) { + return ComplexValueTy(Builder.CreateExtractElement(Agg, Builder.getInt32(0), "re"), + Builder.CreateExtractElement(Agg, Builder.getInt32(1), "im")); +} + llvm::Value *CodeGenFunction::CreateComplexAggregate(ComplexValueTy Value) { llvm::Value *Result = llvm::UndefValue::get( getTypes().GetComplexType(Value.Re->getType())); diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index ed8e5d045a..1be14f3433 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -5,6 +5,7 @@ add_flang_library(flangCodeGen CodeGenTypes.cpp CodeGenAction.cpp BackendUtil.cpp + TargetInfo.cpp CGABI.cpp CGDecl.cpp CGStmt.cpp diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 961dd1e540..d8b0661bcc 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -165,8 +165,7 @@ void CodeGenFunction::EmitFunctionEpilogue(const FunctionDecl *Func, Builder.CreateRet(Builder.CreateLoad(RetVar)); break; case CGFunctionInfo::RetInfo::ComplexValue: - Builder.CreateRet(CreateComplexAggregate( - EmitComplexLoad(RetVar))); + EmitAggregateReturn(ReturnInfo, RetVar); break; } } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 0c795dff3a..95783e38cd 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -200,6 +200,7 @@ public: void EmitFunctionBody(const DeclContext *DC, const Stmt *S); void EmitFunctionEpilogue(const FunctionDecl *Func, const CGFunctionInfo *Info); + void EmitAggregateReturn(const CGFunctionInfo::RetInfo &Info, llvm::Value *Ptr); void EmitCleanup(); void EmitVarDecl(const VarDecl *D); @@ -318,6 +319,7 @@ public: // complex expressions. ComplexValueTy ExtractComplexValue(llvm::Value *Agg); + ComplexValueTy ExtractComplexVectorValue(llvm::Value *Agg); llvm::Value *CreateComplexAggregate(ComplexValueTy Value); llvm::Value *CreateComplexVector(ComplexValueTy Value); llvm::Constant *CreateComplexConstant(ComplexValueTy Value); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 4563354979..a498282d01 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -40,7 +40,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, llvm::Module &M, const llvm::DataLayout &TD, DiagnosticsEngine &diags) : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M), - Diags(diags), TheDataLayout(TD), VMContext(M.getContext()), Types(*this) { + Diags(diags), TheDataLayout(TD), VMContext(M.getContext()), Types(*this), + TheTargetCodeGenInfo(nullptr) { llvm::LLVMContext &LLVMContext = M.getContext(); VoidTy = llvm::Type::getVoidTy(LLVMContext); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 1fd1f042c4..8aebab83c0 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -49,6 +49,7 @@ namespace flang { class VarDecl; class LangOptions; class DiagnosticsEngine; + class TargetCodeGenInfo; namespace CodeGen { @@ -120,6 +121,7 @@ class CodeGenModule : public CodeGenTypeCache { CodeGenTypes Types; LibflangABI RuntimeABI; + const TargetCodeGenInfo *TheTargetCodeGenInfo; CGIORuntime *IORuntime; CGSystemRuntime *SystemRuntime; @@ -129,6 +131,8 @@ class CodeGenModule : public CodeGenTypeCache { llvm::DenseMap<const FunctionDecl*, CGFunction> Functions; + + public: CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts, llvm::Module &M, const llvm::DataLayout &TD, @@ -168,6 +172,10 @@ public: return *SystemRuntime; } + /// getTargetCodeGenInfo - Retun a reference to the configured + /// target code gen information. + const TargetCodeGenInfo &getTargetCodeGenInfo(); + /// Release - Finalize LLVM code generation. void Release(); diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index 765f5d5f8f..8cd6ad3ef1 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -34,14 +34,18 @@ namespace { OwningPtr<const llvm::DataLayout> TD; ASTContext *Ctx; const CodeGenOptions CodeGenOpts; // Intentionally copied in. + const TargetOptions Target; protected: OwningPtr<llvm::Module> M; OwningPtr<CodeGen::CodeGenModule> Builder; public: CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName, - const CodeGenOptions &CGO, llvm::LLVMContext& C) + const CodeGenOptions &CGO, + const TargetOptions &TO, + llvm::LLVMContext& C) : Diags(diags), CodeGenOpts(CGO), - M(new llvm::Module(ModuleName, C)) {} + M(new llvm::Module(ModuleName, C)), + Target(TO) {} virtual ~CodeGeneratorImpl() {} @@ -58,9 +62,8 @@ namespace { //M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple()); //M->setDataLayout(Ctx->getTargetInfo().getTargetDescription()); - //M->setTargetTriple(""); - //M->setDataLayout(""); - TD.reset(new llvm::DataLayout(M.get()));//Ctx->getTargetInfo().getTargetDescription())); + M->setTargetTriple(Target.Triple); + TD.reset(new llvm::DataLayout(M.get())); Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD, Diags)); @@ -90,7 +93,7 @@ void CodeGenerator::anchor() { } CodeGenerator *flang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, const std::string& ModuleName, const CodeGenOptions &CGO, - const TargetOptions& /*TO*/, + const TargetOptions &TO, llvm::LLVMContext& C) { - return new CodeGeneratorImpl(Diags, ModuleName, CGO, C); + return new CodeGeneratorImpl(Diags, ModuleName, CGO, TO, C); } diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp new file mode 100644 index 0000000000..27336cb1a6 --- /dev/null +++ b/lib/CodeGen/TargetInfo.cpp @@ -0,0 +1,86 @@ +//===---- TargetInfo.cpp - Encapsulate target details -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes wrap the information about a call or function +// definition used to handle ABI compliancy. +// +//===----------------------------------------------------------------------===// + +#include "TargetInfo.h" +#include "ABIInfo.h" +#include "CGABI.h" +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/raw_ostream.h" + +namespace flang { + +TargetCodeGenInfo::~TargetCodeGenInfo() {} + +namespace CodeGen { + +class DefaultABIInfo : public ABIInfo { +public: + void computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const {} +}; + +/// ABI Info for x86_64 +/// NB: works only with x86_64-pc-{linux,darwin} +class X86_64ABIInfo : public ABIInfo { + CodeGenModule &CGM; +public: + X86_64ABIInfo(CodeGenModule &cgm) : CGM(cgm) {} + void computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const; +}; + +void X86_64ABIInfo::computeReturnTypeInfo(QualType T, ABIRetInfo &Info) const { + if(!T->isComplexType()) + return; + + if(Info.getKind() == ABIRetInfo::Value) { + auto Kind = CGM.getContext().getComplexTypeKind(T.getExtQualsPtrOrNull()); + switch(Kind) { + case BuiltinType::Real4: + Info = ABIRetInfo(ABIRetInfo::Value, llvm::VectorType::get(CGM.FloatTy, 2)); + break; + case BuiltinType::Real8: + break; + default: + llvm_unreachable("invalid type kind"); + } + } +} + +//===----------------------------------------------------------------------===// +// Driver code +//===----------------------------------------------------------------------===// + +const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { + if (TheTargetCodeGenInfo) + return *TheTargetCodeGenInfo; + + llvm::Triple Triple(TheModule.getTargetTriple()); + + switch (Triple.getArch()) { + default: + TheTargetCodeGenInfo = new TargetCodeGenInfo(new DefaultABIInfo()); + break; + + case llvm::Triple::x86_64: + TheTargetCodeGenInfo = new TargetCodeGenInfo(new X86_64ABIInfo(*this)); + break; + } + return *TheTargetCodeGenInfo; +} + +} +} diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h new file mode 100644 index 0000000000..5e50ae328a --- /dev/null +++ b/lib/CodeGen/TargetInfo.h @@ -0,0 +1,54 @@ +//===---- TargetInfo.h - Encapsulate target details -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes wrap the information about a call or function +// definition used to handle ABI compliancy. +// +//===----------------------------------------------------------------------===// + +#ifndef FLANG_CODEGEN_TARGETINFO_H +#define FLANG_CODEGEN_TARGETINFO_H + +#include "flang/AST/Type.h" +#include "flang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" + +namespace llvm { + class GlobalValue; + class Type; + class Value; +} + +namespace flang { + class ABIInfo; + class Decl; + + namespace CodeGen { + class CallArgList; + class CodeGenModule; + class CodeGenFunction; + class CGFunctionInfo; + } + + /// TargetCodeGenInfo - This class organizes various target-specific + /// codegeneration issues, like target-specific attributes, builtins and so + /// on. + class TargetCodeGenInfo { + ABIInfo *Info; + public: + TargetCodeGenInfo(ABIInfo *info = nullptr):Info(info) { } + virtual ~TargetCodeGenInfo(); + + /// getABIInfo() - Returns ABI info helper for the target. + const ABIInfo& getABIInfo() const { return *Info; } + }; +} + +#endif // FLANG_CODEGEN_TARGETINFO_H diff --git a/test/CodeGen/subprogram.f95 b/test/CodeGen/subprogram.f95 index 99dad4d0c6..d687d238d1 100644 --- a/test/CodeGen/subprogram.f95 +++ b/test/CodeGen/subprogram.f95 @@ -31,9 +31,6 @@ COMPLEX FUNCTION DOUBLE(C) CONTINUE ! CHECK: load float* CONTINUE ! CHECK: load float* - CONTINUE ! CHECK: insertvalue { float, float } undef - CONTINUE ! CHECK: insertvalue { float, float } - CONTINUE ! CHECK: ret { float, float } END PROGRAM test @@ -55,10 +52,7 @@ PROGRAM test C = DOUBLE((1.0, 2.0)) ! CHECK: store float 1 CONTINUE ! CHECK: store float 2 - CONTINUE ! CHECK: call { float, float } @double_ - CONTINUE ! CHECK: extractvalue { float, float } - CONTINUE ! CHECK: extractvalue { float, float } - + CONTINUE ! CHECK: call {{.*}} @double_ C = DOUBLE(DOUBLE(C)) C = DOUBLE(CMPLX(SQUARE(R))) diff --git a/test/CodeGen/x86_64LinuxAggregateABI.f95 b/test/CodeGen/x86_64LinuxAggregateABI.f95 new file mode 100644 index 0000000000..febd737e0a --- /dev/null +++ b/test/CodeGen/x86_64LinuxAggregateABI.f95 @@ -0,0 +1,9 @@ +! RUN: %flang -triple "x86_64-unknown-linux" -emit-llvm -o - %s | %file_check %s + +complex function foo() ! CHECK: define <2 x float> @foo_() + foo = (1.0, 2.0) +end + +complex(8) function bar() ! CHECK: define { double, double } @bar_() + bar = 0.0 +end diff --git a/tools/driver/Main.cpp b/tools/driver/Main.cpp index 32c2b66fc4..a8aad5d0ab 100644 --- a/tools/driver/Main.cpp +++ b/tools/driver/Main.cpp @@ -107,6 +107,9 @@ namespace { cl::opt<bool> Interpret("interpret", cl::desc("run the code from the given input"), cl::init(false)); + cl::opt<std::string> + TargetTriple("triple", cl::desc("target triple"), cl::init("")); + } // end anonymous namespace @@ -322,9 +325,14 @@ static bool ParseFile(const std::string &Filename, } // Emit - if(!SyntaxOnly && !Diag.hadErrors()) { + if(!SyntaxOnly && !Diag.hadErrors()) { + flang::TargetOptions TargetOptions; + TargetOptions.Triple = TargetTriple.empty()? llvm::sys::getDefaultTargetTriple() : + TargetTriple; + TargetOptions.CPU = llvm::sys::getHostCPUName(); + auto CG = CreateLLVMCodeGen(Diag, Filename == ""? std::string("module") : Filename, - CodeGenOptions(), flang::TargetOptions(), llvm::getGlobalContext()); + CodeGenOptions(), TargetOptions, llvm::getGlobalContext()); CG->Initialize(Context); CG->HandleTranslationUnit(Context); @@ -332,12 +340,9 @@ static bool ParseFile(const std::string &Filename, if(EmitASM) BA = Backend_EmitAssembly; if(EmitLLVM) BA = Backend_EmitLL; - llvm::Triple TheTriple(llvm::sys::getDefaultTargetTriple()); - auto CPU = llvm::sys::getHostCPUName(); const llvm::Target *TheTarget = 0; std::string Err; - TheTarget = llvm::TargetRegistry::lookupTarget(TheTriple.str(), Err); - + TheTarget = llvm::TargetRegistry::lookupTarget(TargetOptions.Triple, Err); CodeGenOpt::Level TMOptLevel = CodeGenOpt::Default; switch(OptLevel) { @@ -347,7 +352,7 @@ static bool ParseFile(const std::string &Filename, llvm::TargetOptions Options; - auto TM = TheTarget->createTargetMachine(TheTriple.getTriple(), CPU, "", Options, + auto TM = TheTarget->createTargetMachine(TargetOptions.Triple, TargetOptions.CPU, "", Options, Reloc::Default, CodeModel::Default, TMOptLevel); |