Skip to content

Commit 974bac5

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:92b821f2dcdd into amd-gfx:6d9e4de0f6ce
Local branch amd-gfx 6d9e4de Merged main:75a9ed42461a into amd-gfx:be511ccac9f5 Remote branch main 92b821f Reland "[llvm-exegesis] Switch from MCJIT to LLJIT (llvm#72838)"
2 parents 6d9e4de + 92b821f commit 974bac5

File tree

8 files changed

+167
-61
lines changed

8 files changed

+167
-61
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,11 @@ Bug Fixes to C++ Support
741741
declaration definition. Fixes:
742742
(`#61763 <https://github.com/llvm/llvm-project/issues/61763>`_)
743743

744+
- Fix a bug where implicit deduction guides are not correctly generated for nested template
745+
classes. Fixes:
746+
(`#46200 <https://github.com/llvm/llvm-project/issues/46200>`_)
747+
(`#57812 <https://github.com/llvm/llvm-project/issues/57812>`_)
748+
744749
- Diagnose use of a variable-length array in a coroutine. The design of
745750
coroutines is such that it is not possible to support VLA use. Fixes:
746751
(`#65858 <https://github.com/llvm/llvm-project/issues/65858>`_)

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,10 +2250,24 @@ class ExtractTypeForDeductionGuide
22502250
struct ConvertConstructorToDeductionGuideTransform {
22512251
ConvertConstructorToDeductionGuideTransform(Sema &S,
22522252
ClassTemplateDecl *Template)
2253-
: SemaRef(S), Template(Template) {}
2253+
: SemaRef(S), Template(Template) {
2254+
// If the template is nested, then we need to use the original
2255+
// pattern to iterate over the constructors.
2256+
ClassTemplateDecl *Pattern = Template;
2257+
while (Pattern->getInstantiatedFromMemberTemplate()) {
2258+
if (Pattern->isMemberSpecialization())
2259+
break;
2260+
Pattern = Pattern->getInstantiatedFromMemberTemplate();
2261+
NestedPattern = Pattern;
2262+
}
2263+
2264+
if (NestedPattern)
2265+
OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template);
2266+
}
22542267

22552268
Sema &SemaRef;
22562269
ClassTemplateDecl *Template;
2270+
ClassTemplateDecl *NestedPattern = nullptr;
22572271

22582272
DeclContext *DC = Template->getDeclContext();
22592273
CXXRecordDecl *Primary = Template->getTemplatedDecl();
@@ -2266,6 +2280,10 @@ struct ConvertConstructorToDeductionGuideTransform {
22662280
// depth-0 template parameters.
22672281
unsigned Depth1IndexAdjustment = Template->getTemplateParameters()->size();
22682282

2283+
// Instantiation arguments for the outermost depth-1 templates
2284+
// when the template is nested
2285+
MultiLevelTemplateArgumentList OuterInstantiationArgs;
2286+
22692287
/// Transform a constructor declaration into a deduction guide.
22702288
NamedDecl *transformConstructor(FunctionTemplateDecl *FTD,
22712289
CXXConstructorDecl *CD) {
@@ -2284,21 +2302,43 @@ struct ConvertConstructorToDeductionGuideTransform {
22842302
if (FTD) {
22852303
TemplateParameterList *InnerParams = FTD->getTemplateParameters();
22862304
SmallVector<NamedDecl *, 16> AllParams;
2305+
SmallVector<TemplateArgument, 16> Depth1Args;
22872306
AllParams.reserve(TemplateParams->size() + InnerParams->size());
22882307
AllParams.insert(AllParams.begin(),
22892308
TemplateParams->begin(), TemplateParams->end());
22902309
SubstArgs.reserve(InnerParams->size());
2310+
Depth1Args.reserve(InnerParams->size());
22912311

22922312
// Later template parameters could refer to earlier ones, so build up
22932313
// a list of substituted template arguments as we go.
22942314
for (NamedDecl *Param : *InnerParams) {
22952315
MultiLevelTemplateArgumentList Args;
22962316
Args.setKind(TemplateSubstitutionKind::Rewrite);
2297-
Args.addOuterTemplateArguments(SubstArgs);
2317+
Args.addOuterTemplateArguments(Depth1Args);
22982318
Args.addOuterRetainedLevel();
2319+
if (NestedPattern)
2320+
Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
22992321
NamedDecl *NewParam = transformTemplateParameter(Param, Args);
23002322
if (!NewParam)
23012323
return nullptr;
2324+
2325+
// Constraints require that we substitute depth-1 arguments
2326+
// to match depths when substituted for evaluation later
2327+
Depth1Args.push_back(SemaRef.Context.getCanonicalTemplateArgument(
2328+
SemaRef.Context.getInjectedTemplateArg(NewParam)));
2329+
2330+
if (NestedPattern) {
2331+
TemplateDeclInstantiator Instantiator(SemaRef, DC,
2332+
OuterInstantiationArgs);
2333+
Instantiator.setEvaluateConstraints(false);
2334+
SemaRef.runWithSufficientStackSpace(NewParam->getLocation(), [&] {
2335+
NewParam = cast<NamedDecl>(Instantiator.Visit(NewParam));
2336+
});
2337+
}
2338+
2339+
assert(NewParam->getTemplateDepth() == 0 &&
2340+
"Unexpected template parameter depth");
2341+
23022342
AllParams.push_back(NewParam);
23032343
SubstArgs.push_back(SemaRef.Context.getCanonicalTemplateArgument(
23042344
SemaRef.Context.getInjectedTemplateArg(NewParam)));
@@ -2309,8 +2349,10 @@ struct ConvertConstructorToDeductionGuideTransform {
23092349
if (Expr *InnerRC = InnerParams->getRequiresClause()) {
23102350
MultiLevelTemplateArgumentList Args;
23112351
Args.setKind(TemplateSubstitutionKind::Rewrite);
2312-
Args.addOuterTemplateArguments(SubstArgs);
2352+
Args.addOuterTemplateArguments(Depth1Args);
23132353
Args.addOuterRetainedLevel();
2354+
if (NestedPattern)
2355+
Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
23142356
ExprResult E = SemaRef.SubstExpr(InnerRC, Args);
23152357
if (E.isInvalid())
23162358
return nullptr;
@@ -2333,6 +2375,9 @@ struct ConvertConstructorToDeductionGuideTransform {
23332375
Args.addOuterRetainedLevel();
23342376
}
23352377

2378+
if (NestedPattern)
2379+
Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
2380+
23362381
FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()->getTypeLoc()
23372382
.getAsAdjusted<FunctionProtoTypeLoc>();
23382383
assert(FPTL && "no prototype for constructor declaration");
@@ -2394,7 +2439,7 @@ struct ConvertConstructorToDeductionGuideTransform {
23942439
// substitute it directly.
23952440
auto *NewTTP = TemplateTypeParmDecl::Create(
23962441
SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(),
2397-
/*Depth*/ 0, Depth1IndexAdjustment + TTP->getIndex(),
2442+
TTP->getDepth() - 1, Depth1IndexAdjustment + TTP->getIndex(),
23982443
TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
23992444
TTP->isParameterPack(), TTP->hasTypeConstraint(),
24002445
TTP->isExpandedParameterPack()
@@ -2429,7 +2474,8 @@ struct ConvertConstructorToDeductionGuideTransform {
24292474
// the index of the parameter once it's done.
24302475
auto *NewParam =
24312476
cast<TemplateParmDecl>(SemaRef.SubstDecl(OldParam, DC, Args));
2432-
assert(NewParam->getDepth() == 0 && "unexpected template param depth");
2477+
assert(NewParam->getDepth() == OldParam->getDepth() - 1 &&
2478+
"unexpected template param depth");
24332479
NewParam->setPosition(NewParam->getPosition() + Depth1IndexAdjustment);
24342480
return NewParam;
24352481
}
@@ -2446,6 +2492,9 @@ struct ConvertConstructorToDeductionGuideTransform {
24462492
for (auto *OldParam : TL.getParams()) {
24472493
ParmVarDecl *NewParam =
24482494
transformFunctionTypeParam(OldParam, Args, MaterializedTypedefs);
2495+
if (NestedPattern && NewParam)
2496+
NewParam = transformFunctionTypeParam(NewParam, OuterInstantiationArgs,
2497+
MaterializedTypedefs);
24492498
if (!NewParam)
24502499
return QualType();
24512500
ParamTypes.push_back(NewParam->getType());
@@ -2655,9 +2704,12 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
26552704
// FIXME: Skip constructors for which deduction must necessarily fail (those
26562705
// for which some class template parameter without a default argument never
26572706
// appears in a deduced context).
2707+
ClassTemplateDecl *Pattern =
2708+
Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;
2709+
ContextRAII SavedContext(*this, Pattern->getTemplatedDecl());
26582710
llvm::SmallPtrSet<NamedDecl *, 8> ProcessedCtors;
26592711
bool AddedAny = false;
2660-
for (NamedDecl *D : LookupConstructors(Transform.Primary)) {
2712+
for (NamedDecl *D : LookupConstructors(Pattern->getTemplatedDecl())) {
26612713
D = D->getUnderlyingDecl();
26622714
if (D->isInvalidDecl() || D->isImplicit())
26632715
continue;
@@ -2703,6 +2755,8 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
27032755
Transform.buildSimpleDeductionGuide(Transform.DeducedType))
27042756
->getTemplatedDecl())
27052757
->setDeductionCandidateKind(DeductionCandidate::Copy);
2758+
2759+
SavedContext.pop();
27062760
}
27072761

27082762
/// Diagnose the presence of a default template argument on a

clang/test/SemaTemplate/nested-deduction-guides.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44
template<typename T> struct A {
55
template<typename U> struct B {
66
B(...);
7+
B(const B &) = default;
78
};
89
template<typename U> B(U) -> B<U>;
910
};
1011
A<void>::B b = 123;
12+
A<void>::B copy = b;
1113

1214
using T = decltype(b);
1315
using T = A<void>::B<int>;
16+
17+
using Copy = decltype(copy);
18+
using Copy = A<void>::B<int>;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %clang_cc1 -std=c++20 -verify %s
2+
// expected-no-diagnostics
3+
4+
template<class T> struct S {
5+
template<class U> struct N {
6+
N(T) {}
7+
N(T, U) {}
8+
template<class V> N(V, U) {}
9+
};
10+
};
11+
12+
S<int>::N x{"a", 1};
13+
using T = decltype(x);
14+
using T = S<int>::N<int>;
15+
16+
template<class X> struct default_ftd_argument {
17+
template<class Y> struct B {
18+
template<class W = X, class Z = Y, class V = Z, int I = 0> B(Y);
19+
};
20+
};
21+
22+
default_ftd_argument<int>::B default_arg("a");
23+
using DefaultArg = decltype(default_arg);
24+
using DefaultArg = default_ftd_argument<int>::B<const char *>;
25+
26+
template<bool> struct test;
27+
template<class X> struct non_type_param {
28+
template<class Y> struct B {
29+
B(Y);
30+
template<class Z, test<Z::value> = 0> B(Z);
31+
};
32+
};
33+
34+
non_type_param<int>::B ntp = 5;
35+
using NonTypeParam = decltype(ntp);
36+
using NonTypeParam = non_type_param<int>::B<int>;
37+
38+
template<typename A, typename T>
39+
concept C = (sizeof(T) == sizeof(A));
40+
41+
template<class X> struct concepts {
42+
template<class Y> struct B {
43+
template<class K = X, C<K> Z> B(Y, Z);
44+
};
45+
};
46+
47+
concepts<int>::B cc(1, 3);
48+
using Concepts = decltype(cc);
49+
using Concepts = concepts<int>::B<int>;
50+
51+
template<class X> struct requires_clause {
52+
template<class Y> struct B {
53+
template<class Z> requires (sizeof(Z) == sizeof(X))
54+
B(Y, Z);
55+
};
56+
};
57+
58+
requires_clause<int>::B req(1, 2);
59+
using RC = decltype(req);
60+
using RC = requires_clause<int>::B<int>;

llvm/include/llvm/Config/llvm-config.h.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
/* Indicate that this is LLVM compiled from the amd-gfx branch. */
1818
#define LLVM_HAVE_BRANCH_AMD_GFX
19-
#define LLVM_MAIN_REVISION 481718
19+
#define LLVM_MAIN_REVISION 481720
2020

2121
/* Define if LLVM_ENABLE_DUMP is enabled */
2222
#cmakedefine LLVM_ENABLE_DUMP

llvm/tools/llvm-exegesis/lib/Assembler.cpp

Lines changed: 32 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@
2121
#include "llvm/CodeGen/TargetInstrInfo.h"
2222
#include "llvm/CodeGen/TargetPassConfig.h"
2323
#include "llvm/CodeGen/TargetSubtargetInfo.h"
24-
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
24+
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
2525
#include "llvm/IR/BasicBlock.h"
2626
#include "llvm/IR/Instructions.h"
2727
#include "llvm/IR/LegacyPassManager.h"
2828
#include "llvm/MC/MCInstrInfo.h"
29+
#include "llvm/Object/SymbolSize.h"
2930
#include "llvm/Support/Alignment.h"
3031
#include "llvm/Support/MemoryBuffer.h"
3132
#include "llvm/Support/raw_ostream.h"
@@ -105,7 +106,7 @@ MachineFunction &createVoidVoidPtrMachineFunction(StringRef FunctionName,
105106
FunctionType *FunctionType =
106107
FunctionType::get(ReturnType, {MemParamType}, false);
107108
Function *const F = Function::Create(
108-
FunctionType, GlobalValue::InternalLinkage, FunctionName, Module);
109+
FunctionType, GlobalValue::ExternalLinkage, FunctionName, Module);
109110
BasicBlock *BB = BasicBlock::Create(Module->getContext(), "", F);
110111
new UnreachableInst(Module->getContext(), BB);
111112
return MMI->getOrCreateMachineFunction(*F);
@@ -324,66 +325,48 @@ object::OwningBinary<object::ObjectFile> getObjectFromFile(StringRef Filename) {
324325
return cantFail(object::ObjectFile::createObjectFile(Filename));
325326
}
326327

327-
namespace {
328-
329-
// Implementation of this class relies on the fact that a single object with a
330-
// single function will be loaded into memory.
331-
class TrackingSectionMemoryManager : public SectionMemoryManager {
332-
public:
333-
explicit TrackingSectionMemoryManager(uintptr_t *CodeSize)
334-
: CodeSize(CodeSize) {}
335-
336-
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
337-
unsigned SectionID,
338-
StringRef SectionName) override {
339-
*CodeSize = Size;
340-
return SectionMemoryManager::allocateCodeSection(Size, Alignment, SectionID,
341-
SectionName);
342-
}
343-
344-
private:
345-
uintptr_t *const CodeSize = nullptr;
346-
};
347-
348-
} // namespace
349-
350328
Expected<ExecutableFunction> ExecutableFunction::create(
351329
std::unique_ptr<LLVMTargetMachine> TM,
352330
object::OwningBinary<object::ObjectFile> &&ObjectFileHolder) {
353331
assert(ObjectFileHolder.getBinary() && "cannot create object file");
354332
std::unique_ptr<LLVMContext> Ctx = std::make_unique<LLVMContext>();
355-
// Initializing the execution engine.
356-
// We need to use the JIT EngineKind to be able to add an object file.
357-
LLVMLinkInMCJIT();
358-
uintptr_t CodeSize = 0;
359-
std::string Error;
360-
std::unique_ptr<ExecutionEngine> EE(
361-
EngineBuilder(createModule(Ctx, TM->createDataLayout()))
362-
.setErrorStr(&Error)
363-
.setMCPU(TM->getTargetCPU())
364-
.setEngineKind(EngineKind::JIT)
365-
.setMCJITMemoryManager(
366-
std::make_unique<TrackingSectionMemoryManager>(&CodeSize))
367-
.create(TM.release()));
368-
if (!EE)
369-
return make_error<StringError>(Twine(Error), inconvertibleErrorCode());
370-
// Adding the generated object file containing the assembled function.
371-
// The ExecutionEngine makes sure the object file is copied into an
372-
// executable page.
373-
EE->addObjectFile(std::move(ObjectFileHolder));
374-
// Fetching function bytes.
375-
const uint64_t FunctionAddress = EE->getFunctionAddress(FunctionID);
333+
334+
auto SymbolSizes = object::computeSymbolSizes(*ObjectFileHolder.getBinary());
335+
// Get the size of the function that we want to call into (with the name of
336+
// FunctionID). This should always be the third symbol returned by
337+
// calculateSymbolSizes.
338+
assert(SymbolSizes.size() == 3);
339+
assert(cantFail(std::get<0>(SymbolSizes[2]).getName()) == FunctionID);
340+
uintptr_t CodeSize = std::get<1>(SymbolSizes[2]);
341+
342+
auto EJITOrErr = orc::LLJITBuilder().create();
343+
if (!EJITOrErr)
344+
return EJITOrErr.takeError();
345+
346+
auto EJIT = std::move(*EJITOrErr);
347+
348+
if (auto ObjErr =
349+
EJIT->addObjectFile(std::get<1>(ObjectFileHolder.takeBinary())))
350+
return std::move(ObjErr);
351+
352+
auto FunctionAddressOrErr = EJIT->lookup(FunctionID);
353+
if (!FunctionAddressOrErr)
354+
return FunctionAddressOrErr.takeError();
355+
356+
const uint64_t FunctionAddress = FunctionAddressOrErr->getValue();
357+
376358
assert(isAligned(kFunctionAlignment, FunctionAddress) &&
377359
"function is not properly aligned");
360+
378361
StringRef FBytes =
379362
StringRef(reinterpret_cast<const char *>(FunctionAddress), CodeSize);
380-
return ExecutableFunction(std::move(Ctx), std::move(EE), FBytes);
363+
return ExecutableFunction(std::move(Ctx), std::move(EJIT), FBytes);
381364
}
382365

383366
ExecutableFunction::ExecutableFunction(std::unique_ptr<LLVMContext> Ctx,
384-
std::unique_ptr<ExecutionEngine> EE,
367+
std::unique_ptr<orc::LLJIT> EJIT,
385368
StringRef FB)
386-
: FunctionBytes(FB), Context(std::move(Ctx)), ExecEngine(std::move(EE)) {}
369+
: FunctionBytes(FB), Context(std::move(Ctx)), ExecJIT(std::move(EJIT)) {}
387370

388371
Error getBenchmarkFunctionBytes(const StringRef InputData,
389372
std::vector<uint8_t> &Bytes) {

llvm/tools/llvm-exegesis/lib/Assembler.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include "llvm/ADT/BitVector.h"
2424
#include "llvm/CodeGen/MachineFunction.h"
2525
#include "llvm/CodeGen/MachineModuleInfo.h"
26-
#include "llvm/ExecutionEngine/ExecutionEngine.h"
26+
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
2727
#include "llvm/IR/LLVMContext.h"
2828
#include "llvm/IR/Module.h"
2929
#include "llvm/MC/MCInst.h"
@@ -124,11 +124,10 @@ class ExecutableFunction {
124124

125125
private:
126126
ExecutableFunction(std::unique_ptr<LLVMContext> Ctx,
127-
std::unique_ptr<ExecutionEngine> EE,
128-
StringRef FunctionBytes);
127+
std::unique_ptr<orc::LLJIT> EJIT, StringRef FunctionBytes);
129128

130129
std::unique_ptr<LLVMContext> Context;
131-
std::unique_ptr<ExecutionEngine> ExecEngine;
130+
std::unique_ptr<orc::LLJIT> ExecJIT;
132131
};
133132

134133
// Copies benchmark function's bytes from benchmark object.

0 commit comments

Comments
 (0)