The current Asm does not support symbolic Scale at all. It's only possible to use immediate as Scale. This patch is the first one to close PR33848
Diff Detail
Event Timeline
I updated 2 tests in trunk to demonstarte the difference in code generation after this patch aplying. Now we can clearly see the issues and how they could be resolved with help of this patch.
I re-based the the code after the patch about replacing of assertions with corresponding diagnostic error messages. As result changes in tests show that X86 Asm supports symbolic Scale/Disp properly now (including its negative value).
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
1595–1600 | What is this accomplishing? Pulling on ImmVal makes sense, but the rest looks wrong - for instance, if Disp is a MCExpr::Constant doesn't that constant value is overriden by Imm instead of being added together? |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
1488 | I'm using clang-format for every new patch prepared for phab and this style was generated by clang-format (I've just checked it again). | |
1514 | See above. | |
1595–1600 | Oh, yes: if Disp is Constant and Imm != 0 then we should add 2 values and it was already done in one of the previous versions but disappeared. Tnank you. I'll add this clause asap. But the current override of Disp with Imm is correct as well because we have Disp == SM.getSym(). On the other hand the condition "if (!Disp || (Disp->getKind() == llvm::MCExpr::Constant && ImmVal))" looks wrong. |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
1595–1600 | Oh and Oh: I recalled the situation: if (Disp is Constant) it means Disp == SM.getSym() (see assertion): it's the same value that's why we don't replace one with other. I could simplify it like here: else if (!Disp) Disp = Imm; // It can be an immediate displacement only (maybe 0). OK? |
A few minors - does anyone have any more comments?
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
1585 | Another use of SM.getImm() - is it safe to move SM.getImm() earlier to replace this as well? | |
1595 | Flip to match the previous if(): else if (ImmVal && Disp->getKind() == llvm::MCExpr::Constant) { | |
test/MC/X86/intel-syntax-3.s | ||
32 | Now that these are passing - move them to another of the intel-syntax test files and add suitable checks |
test/MC/X86/intel-syntax-3.s | ||
---|---|---|
32 | In fact I kept it here specialy to show the difference but OK: I'll do it. |
A few minors - does anyone have any more comments?
Will have a look by tomorrow (at most)
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
591 | (#) | |
601 | if comment (#) evaluate to false (i.e. MSVC inline-assembler does not support Assembly Constants, and we do not plan to do it either) than you should error here appropriately (i.e. "symbolic scale aren't supported on inline-asm) | |
603 | BaseReg + SymScale * IndexReg | |
614 | What about other operations? | |
616–624 | Note that this patch breaks 'ms-inline-asm.c' on 'clang/test/Sema' | |
1015 | Rebase | |
1463–1467 | I suggest we'll adopt a more general approach and deal with assembly constants as a whole, and not just this private case. wouldn't it simplify the work? | |
1580 | if (Disp = SM.getSym() && isParsingInlineAsm()) |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
1461 | Suggested simplification (instead of the other changes as well): } else if (!isParsingInlineAsm()) { if (getParser().parsePrimaryExpr(Val, End)) return Error(Tok.getLoc(), "Unexpected identifier!"); if (Val->getKind() == MCExpr::Constant) { int64_t TmpInt; Val->evaluateAsAbsolute(TmpInt); StringRef ErrMsg; if (SM.onInteger(TmpInt, ErrMsg)) return Error(Tok.getLoc(), ErrMsg); } else SM.onIdentifierExpr(Val, Identifier); Will allow the use of an assembly constant as an immediate, as integral part of whatever compound expression (scale / other). |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
591 | Do you mean that this function can't be called if isParsingInlineAsm == true? | |
616–624 | I'm no sure I understand you here. As result of the patch we have the following: void t3() {
+ __asm { mov eax, [eax] UndeclaredId } // expected-error {{invalid address operation}} expected-error {{use of undeclared label 'UndeclaredId'}} // FIXME: Only emit one diagnostic here. // expected-error@+3 {{use of undeclared label 'A'}} // expected-error@+2 {{unexpected type name 'A': expected expression}}
+ // expected-error@+1 {{invalid address operation}} __asm { mov eax, [eax] A } } As you see "unknown token" message was replaced by "invalid address operation". Does it mean "break" for this test? |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
616–624 | Don't know the reason but "bullet" above means "minus". |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
591 | I mean that (isParsingInlineAsm() && SymRef->getKind() == llvm::MCExpr::Constant) will never yield 'true' on current code state. | |
616–624 | As long as the test remains unchanged :) |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
591 | In this case I could simply produce error message if (isParsingInlineAsm() && SymRef->getKind() == llvm::MCExpr::Constant) , right? |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
591 | Currently, yes. But I frankly believe we should completely ignore InlineAsm (i.e. confine the patch to assembly level only, as proposed on line 1461), or conduct a better research regarding the way assembly constants are represented (likely - aren't) by msvc inline-assembler, and act upon the findings |
I'm sorry, I guess I haven't been clear: I meant that the suggested code blob at line 1449 is a practical replacement of the entire patch (apart from the added diagnostics).
It seems to pass your added tests, and not to break anything else, Can you verify it answers your cause(s)?
I removed all changes (apart from the added diagnostics). Now it should fit to Coby requirements. Right?
few minors + add fixes in clang tests to adopt the added diagnostics.
nothing else has caught my eye
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
580 | You don't need this line | |
593 | CurrState is redundant, you can use 'PrevState = State' as in the original code. | |
1467 | line is redundant (ErrMsg is defined on the encapsulating function's scope) |
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
578–579 | Call this NewScale or something more informative than _Scale. | |
1466 | evaluateAsAbsolute may fail. I think you should rewrite this like so: if (const auto *CE = dyn_cast<MCConstantExpr>(Val)) { if (SM.onInteger(CE->getValue(), ErrMsg) return Error(Tok.getLoc(), ErrMsg); } That's all evaluateAsAbsolute is doing for you behind the scenes anyway. |
added one minor.
+ I'm currently having a patch on review (D36793) which contains most of the intended goals of this one (everything but the new error, afaik), can you verify it answers your needs?
lib/Target/X86/AsmParser/X86AsmParser.cpp | ||
---|---|---|
1463–1467 | this line is redundant, its semantics contained in the check performed on the next one. |
+ I'm currently having a patch on review (D36793) which contains most of the intended goals of this one (everything but the new error, afaik), can you verify it answers your needs?
Yes, I see that everything I need here is included in D36793. When are you going to commit it? BTW, I have some questions about D36793 but I'll include them in that review.
Finally, as I understand I should abandom this review because now it's a part of D36793 (including tests, etc.), right?
(typo) ErrMsg = "Invalid operand of multiplication";