This patch adds the support for atomic compare capture in parser and part of
sema. We don't create an AST node for this because the spec doesn't say compare
and capture clauses should be used tightly, so we cannot look one more token
ahead in the parser.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Time | Test | |
---|---|---|
130 ms | x64 debian > Clang.OpenMP::atomic_messages.cpp |
Event Timeline
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11368 | This is the place where the dummy kind OMPC_compare_capture is used. We will have another use in CodeGen. |
clang/include/clang/AST/OpenMPClause.h | ||
---|---|---|
2277 ↗ | (On Diff #406867) | final |
clang/lib/AST/OpenMPClause.cpp | ||
1804 ↗ | (On Diff #406867) | Output? |
clang/lib/Sema/SemaOpenMP.cpp | ||
11327 | Use LLVM_FALLTHROUGH | |
11362–11363 | Why? | |
11812–11817 | Emit in codegen |
clang/lib/AST/OpenMPClause.cpp | ||
---|---|---|
1804 ↗ | (On Diff #406867) | I did it on purpose because OMPCompareCaptureClause is a dummy node. When it is visited (I really doubt if it can be visited because we don't create it explicitly), it should not output any thing. compare and capture are printed when visiting the two clauses. |
clang/lib/Sema/SemaOpenMP.cpp | ||
11362–11363 | For the same reason for the output in AST. |
clang/lib/AST/OpenMPClause.cpp | ||
---|---|---|
1804 ↗ | (On Diff #406867) | Why? I see ActOnOpenMPCompareCaptureClause, which creates such nodes. |
clang/lib/AST/OpenMPClause.cpp | ||
---|---|---|
1804 ↗ | (On Diff #406867) | I updated those functions. They should be unreachable. |
clang/lib/Sema/SemaOpenMP.cpp | ||
11812–11817 | Since we are lack of Sema, putting it in Sema for now sounds more reasonable. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11806–11812 | Better to build a node and emit error in codegen. Without it you're unable to create ast-print/dump tests, test for serialization/deserialization etc. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11806–11812 | IIUC, OMPC_compare_capture will only be used in Sema and CodeGen to tell we actually want compare_capture instead of compare or capture. The corresponding class(es) have no actual use. If I could directly have OMPC_compare_capture w/o adding a class, I would like to do it. On the other hand, we already have a node for compare, and a node for capture, we don't want a node for compare and capture, especially the spec doesn't say they should be tightly close. That being said, it should not affect other functionality. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11806–11812 | Then why do you need OMPC_compare_capture? Just emit compare and capture and check for both of them at the same time. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11806–11812 | OMPC_compare_capture is the natural way, especially when we call emitOMPAtomicExpr. Of course we can set Kind to OMPC_compare and add a boolean argument bool IsCompareCapture = false. It's just not as clear as this way, but TBH not a bad way. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11806–11812 | I think it is better to have a flag (or an internal enum) rather than adding an extra external enum and a class just for internal processing. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11806–11812 | Done. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11786–11805 | Better not to emit error here, if possible. What's prevent this? |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11786–11805 | I put it here because I think we don't have Sema support yet, so it is not good to move it to later phase like codegen because that will implicitly mean Sema has already passed but apparently it doesn't. Of course like atomic compare, I'll move it to codegen in the Sema patch. |
Add ast print with serialization/deserialization tests.
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11320 | SmallVector with 2 elements should be enough, no need to use SmallSet here. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11320 | SmallVector doesn't provide contains, which we use to check if OMPC_compare and OMPC_capture exist at the same time. Using SmallVector requires us to have a complicated comparison, for example: (EncounteredAtomicKinds[0] == OMPC_compare && EncounteredAtomicKinds[1] == OMPC_capture) || (EncounteredAtomicKinds[1] == OMPC_compare && EncounteredAtomicKinds[0] == OMPC_capture) which is not as neat as SmallSet. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11320 | Use llvm::find |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11320 | That is linear time. Why it is better than SmallSet? |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11320 | Because there are only 2 elements, no? |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11320 | It could have more. If user writes it like atomic compare compare capture capture capture, then it will have 5 elements. SmallSet<T>::insert returns a pair and we know if it is already in the set, which I have not added it yet but I'll. SmallVector then is not that easy to use. Of course you could say do llvm::find beforehand but it's not neat. |
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11320 | It's not correct. We can easily check via the following code: if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) { // emit an error } Using SmallVector we need to: if (llvm::find(EncounteredAtomicKinds.begin(), EncounteredAtomicKinds.end(), C->getClauseKind() != EncounteredAtomicKinds.end()) { // emit an error } else { EncounteredAtomicKinds.push_back(C->getClauseKind()); } It's obvious which one looks better and have better readability. I can't see any point of using SmallVector here, unless there is huge performance difference, which I really doubt that matters. |
Erroneous tests?
clang/lib/Sema/SemaOpenMP.cpp | ||
---|---|---|
11320 | if (llvm::find(EncounteredAtomicKinds, C->getClauseKind() != EncounteredAtomicKinds.end()) { // emit an error } else { EncounteredAtomicKinds.push_back(C->getClauseKind()); } but ok, let's keep SmallSet |
SmallVector with 2 elements should be enough, no need to use SmallSet here.