diff --git a/CMakeLists.txt b/CMakeLists.txt index 72d82cf7d7..9cefe6da42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ include(CheckCXXCompilerFlag) # find_package(LLVM 3.5 REQUIRED - all-targets analysis asmparser asmprinter bitreader bitwriter codegen core debuginfocodeview debuginfodwarf debuginfopdb instcombine ipa ipo instrumentation irreader linker lto mc mcdisassembler mcparser objcarcopts object option profiledata scalaropts selectiondag support tablegen target transformutils vectorize ${EXTRA_LLVM_MODULES}) + all-targets analysis asmparser asmprinter bitreader bitwriter codegen core debuginfocodeview debuginfodwarf debuginfopdb globalisel instcombine ipa ipo instrumentation irreader linker lto mc mcdisassembler mcparser objcarcopts object option profiledata scalaropts selectiondag support tablegen target transformutils vectorize ${EXTRA_LLVM_MODULES}) math(EXPR LDC_LLVM_VER ${LLVM_VERSION_MAJOR}*100+${LLVM_VERSION_MINOR}) # Remove LLVMTableGen library from list of libraries string(REGEX MATCH "^-.*LLVMTableGen[^;]*;|;-.*LLVMTableGen[^;]*" LLVM_TABLEGEN_LIBRARY "${LLVM_LIBRARIES}") diff --git a/cmake/Modules/FindLLVM.cmake b/cmake/Modules/FindLLVM.cmake index cab447a349..1b9c372c1e 100644 --- a/cmake/Modules/FindLLVM.cmake +++ b/cmake/Modules/FindLLVM.cmake @@ -76,8 +76,9 @@ if ((WIN32 AND NOT(MINGW OR CYGWIN)) OR NOT LLVM_CONFIG) list(APPEND LLVM_FIND_COMPONENTS "debuginfo") endif() if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-8][\\.0-9A-Za-z]*") - # Versions below 3.9 do not support components debuginfocodeview + # Versions below 3.9 do not support components debuginfocodeview, globalisel list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfocodeview" index) + list(REMOVE_ITEM LLVM_FIND_COMPONENTS "globalisel" index) endif() if(${LLVM_VERSION_STRING} MATCHES "^3\\.[8-9][\\.0-9A-Za-z]*") # Versions beginning with 3.8 do not support component ipa @@ -155,8 +156,9 @@ else() list(APPEND LLVM_FIND_COMPONENTS "debuginfo") endif() if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-8][\\.0-9A-Za-z]*") - # Versions below 3.9 do not support components debuginfocodeview + # Versions below 3.9 do not support components debuginfocodeview, globalisel list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfocodeview" index) + list(REMOVE_ITEM LLVM_FIND_COMPONENTS "globalisel" index) endif() if(${LLVM_VERSION_STRING} MATCHES "^3\\.[8-9][\\.0-9A-Za-z]*") # Versions beginning with 3.8 do not support component ipa diff --git a/gen/abi-aarch64.cpp b/gen/abi-aarch64.cpp index 1fc8114803..b9b3b543bf 100644 --- a/gen/abi-aarch64.cpp +++ b/gen/abi-aarch64.cpp @@ -17,32 +17,97 @@ #include "gen/abi-generic.h" #include "gen/abi-aarch64.h" +namespace { + struct CompositeToArray64 : ABIRewrite { + LLValue *get(Type *dty, LLValue *v) override { + Logger::println("rewriting i64 array -> as %s", dty->toChars()); + LLValue *lval = DtoRawAlloca(v->getType(), 0); + DtoStore(v, lval); + + LLType *pTy = getPtrToType(DtoType(dty)); + return DtoLoad(DtoBitCast(lval, pTy), "get-result"); + } + + LLValue *put(DValue *dv) override { + Type *dty = dv->getType(); + Logger::println("rewriting %s -> as i64 array", dty->toChars()); + LLType *t = type(dty, nullptr); + return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t))); + } + + LLType *type(Type *t, LLType *) override { + // An i64 array that will hold Type 't' + size_t sz = (t->size() + 7) / 8; + return LLArrayType::get(LLIntegerType::get(gIR->context(), 64), sz); + } + }; +} + struct AArch64TargetABI : TargetABI { + HFAToArray hfaToArray; + CompositeToArray64 compositeToArray64; + IntegerRewrite integerRewrite; + bool returnInArg(TypeFunction *tf) override { if (tf->isref) { return false; } - // Return structs and static arrays on the stack. The latter is needed - // because otherwise LLVM tries to actually return the array in a number - // of physical registers, which leads, depending on the target, to - // either horrendous codegen or backend crashes. Type *rt = tf->next->toBasetype(); - return (rt->ty == Tstruct || rt->ty == Tsarray); + + // FIXME + if (tf->linkage == LINKd) + return rt->ty == Tsarray || rt->ty == Tstruct; + + return rt->ty == Tsarray || + (rt->ty == Tstruct && rt->size() > 16 && !isHFA((TypeStruct *)rt)); } - bool passByVal(Type *t) override { return t->toBasetype()->ty == Tstruct; } + bool passByVal(Type *t) override { + t = t->toBasetype(); + return t->ty == Tsarray || + (t->ty == Tstruct && t->size() > 16 && !isHFA((TypeStruct *)t)); + } - void rewriteFunctionType(TypeFunction *t, IrFuncTy &fty) override { - for (auto arg : fty.args) { - if (!arg->byref) { - rewriteArgument(fty, *arg); + void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override { + Type *retTy = fty.ret->type->toBasetype(); + if (!fty.ret->byref && retTy->ty == Tstruct) { + // Rewrite HFAs only because union HFAs are turned into IR types that are + // non-HFA and messes up register selection + if (isHFA((TypeStruct *)retTy, &fty.ret->ltype)) { + fty.ret->rewrite = &hfaToArray; + fty.ret->ltype = hfaToArray.type(fty.ret->type, fty.ret->ltype); } + else { + fty.ret->rewrite = &integerRewrite; + fty.ret->ltype = integerRewrite.type(fty.ret->type, fty.ret->ltype); + } + } + + for (auto arg : fty.args) { + if (!arg->byref) + rewriteArgument(fty, *arg); + else if (passByVal(arg->type)) + arg->attrs.remove(LLAttribute::ByVal); } } void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override { // FIXME + Type *ty = arg.type->toBasetype(); + + if (ty->ty == Tstruct || ty->ty == Tsarray) { + // Rewrite HFAs only because union HFAs are turned into IR types that are + // non-HFA and messes up register selection + if (ty->ty == Tstruct && isHFA((TypeStruct *)ty, &arg.ltype)) { + arg.rewrite = &hfaToArray; + arg.ltype = hfaToArray.type(arg.type, arg.ltype); + } + else { + arg.rewrite = &compositeToArray64; + arg.ltype = compositeToArray64.type(arg.type, arg.ltype); + } + } } /** diff --git a/gen/abi-generic.h b/gen/abi-generic.h index b3ff6983f7..17bacdbd37 100644 --- a/gen/abi-generic.h +++ b/gen/abi-generic.h @@ -119,7 +119,7 @@ struct RemoveStructPadding : ABIRewrite { */ struct IntegerRewrite : ABIRewrite { static LLType *getIntegerType(unsigned minSizeInBytes) { - if (minSizeInBytes > 8) { + if (minSizeInBytes > 16) { return nullptr; } @@ -136,6 +136,15 @@ struct IntegerRewrite : ABIRewrite { case 7: size = 8; break; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + size = 16; + break; default: break; } diff --git a/gen/abi.cpp b/gen/abi.cpp index 40cc182459..37579bc520 100644 --- a/gen/abi.cpp +++ b/gen/abi.cpp @@ -195,6 +195,9 @@ bool TargetABI::isHFA(TypeStruct *t, llvm::Type **rewriteType) { case 8: floatType = llvm::Type::getDoubleTy(gIR->context()); break; + case 16: + floatType = llvm::Type::getFP128Ty(gIR->context()); + break; default: llvm_unreachable("Unexpected size for float type"); } diff --git a/gen/optimizer.cpp b/gen/optimizer.cpp index 48bf468afa..531bf54b74 100644 --- a/gen/optimizer.cpp +++ b/gen/optimizer.cpp @@ -40,12 +40,6 @@ extern llvm::TargetMachine *gTargetMachine; using namespace llvm; -// Allow the user to specify specific optimizations to run. -static cl::list - passList(cl::desc("Running specific optimizations:"), - cl::Hidden // to clean up --help output - ); - static cl::opt optimizeLevel( cl::desc("Setting the optimization level:"), cl::ZeroOrMore, cl::values( @@ -384,37 +378,7 @@ bool ldc_optimize_module(llvm::Module *M) { mpm.add(createStripSymbolsPass(true)); } - bool defaultsAdded = false; - // Create a new optimization pass for each one specified on the command line - for (unsigned i = 0; i < passList.size(); ++i) { - if (optimizeLevel && - optimizeLevel.getPosition() < passList.getPosition(i)) { - addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); - defaultsAdded = true; - } - - const PassInfo *passInf = passList[i]; - Pass *pass = nullptr; - if (passInf->getNormalCtor()) { - pass = passInf->getNormalCtor()(); - } else { - const char *arg = passInf->getPassArgument(); // may return null - if (arg) { - error(Loc(), "Can't create pass '-%s' (%s)", arg, pass->getPassName()); - } else { - error(Loc(), "Can't create pass (%s)", pass->getPassName()); - } - llvm_unreachable("pass creation failed"); - } - if (pass) { - addPass(mpm, pass); - } - } - - // Add the default passes for the specified optimization level. - if (!defaultsAdded) { - addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); - } + addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); // Run per-function passes. fpm.doInitialization(); diff --git a/runtime/druntime b/runtime/druntime index 7e34fc3354..1afd767589 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 7e34fc3354306187165f4161cdf895974a7eb3d6 +Subproject commit 1afd76758971d21bbcf520dd54abed2bf972f4ed diff --git a/runtime/phobos b/runtime/phobos index cace03d663..c50e99d70e 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit cace03d663aedb39f83733931e29f031dfa4f36d +Subproject commit c50e99d70e8756f7991936d4419af458e025d54b diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 1ed287b135..6dfdabdba3 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 1ed287b135cbdefcb3a81ec94fc12c41cbbd5b31 +Subproject commit 6dfdabdba37caf5526a7f9d55d78e6f0c750f9f8