-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[SystemZ] Implement .machine (push|pop) directives #137302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-mc @llvm/pr-subscribers-backend-systemz Author: Dominik Steenken (dominik-steenken) ChangesThe Internally, this is modeled as a simple stack implemented on a This implementation makes the assumption that, without any Full diff: https://github.com/llvm/llvm-project/pull/137302.diff 3 Files Affected:
diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
index 6d9a7a73f72db..a7612ecfd954f 100644
--- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
+++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
@@ -410,6 +410,12 @@ class SystemZAsmParser : public MCTargetAsmParser {
private:
MCAsmParser &Parser;
+
+ // A vector to contain the stack of machine specs created by `.machine push`
+ SmallVector<StringRef> MachineStack;
+ // Specifies the current CPU
+ StringRef CurrentCPU = "";
+
enum RegisterGroup {
RegGR,
RegFP,
@@ -1382,17 +1388,37 @@ bool SystemZAsmParser::parseDirectiveMachine(SMLoc L) {
Parser.getTok().isNot(AsmToken::String))
return TokError("unexpected token in '.machine' directive");
- StringRef CPU = Parser.getTok().getIdentifier();
+ StringRef Id = Parser.getTok().getIdentifier();
+
+ // Parse push and pop directives first
+ StringRef CPU = "";
+ if (Id == "push") {
+ if (CurrentCPU.empty())
+ return TokError(
+ "push without preceding cpu spec in '.machine' directive");
+ MachineStack.push_back(CurrentCPU);
+ } else if (Id == "pop") {
+ if (MachineStack.empty())
+ return TokError("pop without corresponding push in '.machine' directive");
+ CPU = MachineStack.back();
+ MachineStack.pop_back();
+ } else {
+ CPU = Id;
+ }
+
Parser.Lex();
if (parseEOL())
return true;
- MCSubtargetInfo &STI = copySTI();
- STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
- setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
-
- getTargetStreamer().emitMachine(CPU);
+ // check if we need to change cpu
+ if (!CPU.empty()) {
+ MCSubtargetInfo &STI = copySTI();
+ STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
+ setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+ CurrentCPU = CPU;
+ getTargetStreamer().emitMachine(CPU);
+ }
return false;
}
diff --git a/llvm/test/MC/SystemZ/machine-directive-invalid.s b/llvm/test/MC/SystemZ/machine-directive-invalid.s
index 8b3147ecc62d4..f9e6aea4f2604 100644
--- a/llvm/test/MC/SystemZ/machine-directive-invalid.s
+++ b/llvm/test/MC/SystemZ/machine-directive-invalid.s
@@ -1,10 +1,17 @@
+// NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5
# RUN: not llvm-mc -triple=s390x %s 2>&1 | FileCheck %s
-# CHECK: [[#@LINE+1]]:9: error: unexpected token in '.machine' directive
.machine
+// CHECK: :[[@LINE-1]]:9: error: unexpected token in '.machine' directive
+
+.machine push
+// CHECK: :[[@LINE-1]]:10: error: push without preceding cpu spec in '.machine' directive
+
+.machine pop
+// CHECK: :[[@LINE-1]]:10: error: pop without corresponding push in '.machine' directive
-# CHECK: [[#@LINE+1]]:10: error: unexpected token in '.machine' directive
.machine 42
+// CHECK: :[[@LINE-1]]:10: error: unexpected token in '.machine' directive
-# CHECK: [[#@LINE+1]]:13: error: expected newline
.machine z13+
+// CHECK: :[[@LINE-1]]:13: error: expected newline
diff --git a/llvm/test/MC/SystemZ/machine-directive.s b/llvm/test/MC/SystemZ/machine-directive.s
index aa71c6aea5572..7861c56420cd3 100644
--- a/llvm/test/MC/SystemZ/machine-directive.s
+++ b/llvm/test/MC/SystemZ/machine-directive.s
@@ -12,9 +12,10 @@
# CHECK: vgbm %v0, 3
.machine z13
+.machine push
vgbm %v0, 0
.machine zEC12
vgbm %v0, 1
-.machine z13
+.machine pop
vgbm %v0, 3
|
@uweigand FYI |
investigating ci fail |
I don't think this matches GAS behavior. Why is this necessary? Can't we just push the feature bits instead of the name onto the stack? There's the default set of feature bits that's already detected (and used before any explicit machine directive); a first push would just push this; subsequent pops would restore whatever bits are set without having to re-compute them from a name. |
35949c3
to
0834e7a
Compare
// it always reflects the current FeatureBitset used to determine which | ||
// machine features are available, i.e. either the default or the result | ||
// of the most reecent `.machine` directive. | ||
FeatureBitset CurrentFeatures; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need this copy? You should be able to just use STI.getAvailableFeatures() ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, i have removed the copy and use getAvailableFeatures()
instead.
return TokError("pop without corresponding push in '.machine' directive"); | ||
CurrentFeatures = MachineStack.back(); | ||
MachineStack.pop_back(); | ||
setAvailableFeatures(CurrentFeatures); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be an inconsistency w.r.t. calling ComputeAvailableFeatures
. This needs to be called somewhere, either before setting up CurrentFeatures
or else when using it here. (If you do push STI.getAvailableFeatures()
instead as mentioned above, this issue would go away as well.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, i was a bit confused as to what ComputeAvailableFeatures
did since it takes and produces a FeatureBitset
. Since i took your advice above, i think this is now addressed as well.
STI.setDefaultFeatures(Id, /*TuneCPU*/ Id, ""); | ||
CurrentFeatures = STI.getFeatureBits(); | ||
setAvailableFeatures(ComputeAvailableFeatures(CurrentFeatures)); | ||
getTargetStreamer().emitMachine(Id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit: looks like you do the same emitMachine
call in all three branches, so it probably should be moved after the if.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, those were originally different but over the various edits they became the same. I've moved them as you suggested.
setAvailableFeatures(ComputeAvailableFeatures(CurrentFeatures)); | ||
getTargetStreamer().emitMachine(Id); | ||
} | ||
|
||
Parser.Lex(); | ||
if (parseEOL()) | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably better to leave this error check before performing any action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. This introduced a minor compilcation where i had to separate the reporting of the TokError
from the existing if
block, but i think it is now in the right place. Thanks for the feedback :)
0834e7a
to
8b0af95
Compare
Thanks, that was very helpful. I was somewhat unhappy with this solution as well. It originated from me having difficulties obtaining a string description of the CPU from the |
// Do error check before lexing the next token so that TokError | ||
// points at the correct token. | ||
if ((Id == "pop") && (MachineStack.empty())) | ||
return TokError("pop without corresponding push in '.machine' directive"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I do think it would be better to have the syntax check before the semantics check. E.g. if you do a .machine pop z15
or something, you should preferably see the error that there's an unexpected token at the end, over the error that there was no corresponding push.
To get the location correct, I think it would be better to use an Error
with an explicit location (e.g. by calling Parser.getTok().getLoc()
at the place where you do the getIdentifier
call, and then using that location with Error
further down).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense to me, i have reincorporated the check for the semantic error and added an additional line to the error test to check that the .machine pop <cpu>
situation you outlined does in fact point at the syntax issue and not the semantic one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually hang on i used a push instead of a pop...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and it does report the semantic issue first :/
GIve me a second please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved. It works now, at least in my local testing.
4c94500
to
17df235
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM now assuming CI passes.
17df235
to
1ace0c7
Compare
From what i can tell, this |
The `.machine push` and `.machine pop` directives were missing from the SystemZ Backend Asm Parser. This commit adds them, and expands the corresponding test to test proper operation.
1ace0c7
to
4774136
Compare
Thanks. The Windows failure looks unrelated, so I think this is good to go now. |
The `.machine push` and `.machine pop` directives were missing from the SystemZ Backend Asm Parser. This PR adds them, and expands the corresponding test to test proper operation. Internally, this is modeled as a simple stack implemented on a `SmallVector<StringRef>`.
The `.machine push` and `.machine pop` directives were missing from the SystemZ Backend Asm Parser. This PR adds them, and expands the corresponding test to test proper operation. Internally, this is modeled as a simple stack implemented on a `SmallVector<StringRef>`.
The `.machine push` and `.machine pop` directives were missing from the SystemZ Backend Asm Parser. This PR adds them, and expands the corresponding test to test proper operation. Internally, this is modeled as a simple stack implemented on a `SmallVector<StringRef>`.
The `.machine push` and `.machine pop` directives were missing from the SystemZ Backend Asm Parser. This PR adds them, and expands the corresponding test to test proper operation. Internally, this is modeled as a simple stack implemented on a `SmallVector<StringRef>`.
The
.machine push
and.machine pop
directives were missing from the SystemZ Backend Asm Parser. This PR adds them, and expands the corresponding test to test proper operation.Internally, this is modeled as a simple stack implemented on a
SmallVector<StringRef>
.