[llvm] [clang] [X86] Add "Ws" constraint and "p" modifier for symbolic address/label reference (PR #77886)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 11 23:43:13 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
Printing the raw symbol is useful in inline asm (e.g. getting the C++
mangled name, referencing a symbol in a custom way while ensuring it is
not optimized out even if internal). Similar constraints are available
in other targets (e.g. "S" for aarch64/riscv, "Cs" for m68k).
```
namespace ns { extern int var; }
asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "Ws"(&var));
asm (".reloc ., BFD_RELOC_NONE, %p0" :: "Ws"(&var));
```
DO NOT SUBMIT wait for Ws patch https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105576
---
Full diff: https://github.com/llvm/llvm-project/pull/77886.diff
8 Files Affected:
- (modified) clang/lib/Basic/Targets/X86.cpp (+11)
- (modified) clang/test/CodeGen/X86/inline-asm-constraints.c (+8)
- (modified) clang/test/Sema/inline-asm-validate-x86.c (+4)
- (modified) llvm/docs/LangRef.rst (+2)
- (modified) llvm/lib/Target/X86/X86AsmPrinter.cpp (+8)
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+15-5)
- (added) llvm/test/CodeGen/X86/inline-asm-Ws-constraint-error.ll (+9)
- (added) llvm/test/CodeGen/X86/inline-asm-Ws-constraint.ll (+34)
``````````diff
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index 64e281b888a95f..a68b662d9401aa 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -1418,6 +1418,14 @@ bool X86TargetInfo::validateAsmConstraint(
case 'O':
Info.setRequiresImmediate(0, 127);
return true;
+ case 'W':
+ switch (*++Name) {
+ default:
+ return false;
+ case 's':
+ Info.setAllowsRegister();
+ return true;
+ }
// Register constraints.
case 'Y': // 'Y' is the first character for several 2-character constraints.
// Shift the pointer to the second character of the constraint.
@@ -1715,6 +1723,9 @@ std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
return std::string("{st}");
case 'u': // second from top of floating point stack.
return std::string("{st(1)}"); // second from top of floating point stack.
+ case 'W':
+ assert(Constraint[1] == 's');
+ return '^' + std::string(Constraint++, 2);
case 'Y':
switch (Constraint[1]) {
default:
diff --git a/clang/test/CodeGen/X86/inline-asm-constraints.c b/clang/test/CodeGen/X86/inline-asm-constraints.c
index b75a84d7a7bcbf..bfcbbca7c4f6bf 100644
--- a/clang/test/CodeGen/X86/inline-asm-constraints.c
+++ b/clang/test/CodeGen/X86/inline-asm-constraints.c
@@ -53,3 +53,11 @@ __m512 testZMM0(void) {
#endif
return zmm0;
}
+
+extern int var;
+
+// CHECK-LABEL: test_Ws(
+// CHECK: call void asm sideeffect "// ${0:p} ${1:p}", "^Ws,^Ws,~{dirflag},~{fpsr},~{flags}"(ptr @var, ptr @test_Ws)
+void test_Ws(void) {
+ asm("// %p0 %p1" :: "Ws"(&var), "Ws"(test_Ws));
+}
diff --git a/clang/test/Sema/inline-asm-validate-x86.c b/clang/test/Sema/inline-asm-validate-x86.c
index 87b60a0955301a..032d76477c4ae6 100644
--- a/clang/test/Sema/inline-asm-validate-x86.c
+++ b/clang/test/Sema/inline-asm-validate-x86.c
@@ -130,3 +130,7 @@ void pr40890(void) {
__asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef));
#endif
}
+
+void test_W() {
+ asm("" : : "Wd"(test_W)); // expected-error{{invalid input constraint 'Wd' in asm}}
+}
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d881deb30049a2..076029976ffc5d 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -5336,6 +5336,7 @@ X86:
operand in a SSE register. If AVX is also enabled, can also be a 256-bit
vector operand in an AVX register. If AVX-512 is also enabled, can also be a
512-bit vector operand in an AVX512 register. Otherwise, an error.
+- ``Ws``: A symbolic reference or label reference.
- ``x``: The same as ``v``, except that when AVX-512 is enabled, the ``x`` code
only allocates into the first 16 AVX-512 registers, while the ``v`` code
allocates into any of the 32 AVX-512 registers.
@@ -5518,6 +5519,7 @@ X86:
the operand. (The behavior for relocatable symbol expressions is a
target-specific behavior for this typically target-independent modifier)
- ``H``: Print a memory reference with additional offset +8.
+- ``p``: Print a raw symbol name (without syntax-specific prefixes).
- ``P``: Print a memory reference used as the argument of a call instruction or
used with explicit base reg and index reg as its offset. So it can not use
additional regs to present the memory reference. (E.g. omit ``(rip)``, even
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index 15cfd247f125ca..9f0fd4d0938e97 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -774,6 +774,14 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
PrintOperand(MI, OpNo, O);
return false;
+ case 'p': {
+ const MachineOperand &MO = MI->getOperand(OpNo);
+ if (MO.getType() != MachineOperand::MO_GlobalAddress)
+ return true;
+ PrintSymbolOperand(MO, O);
+ return false;
+ }
+
case 'P': // This is the operand of a call, treat specially.
PrintPCRelImm(MI, OpNo, O);
return false;
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 700ab797b2f69f..aea8e8b40ff631 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -56676,6 +56676,10 @@ X86TargetLowering::getConstraintType(StringRef Constraint) const {
switch (Constraint[0]) {
default:
break;
+ case 'W':
+ if (Constraint[1] != 's')
+ break;
+ return C_Other;
case 'Y':
switch (Constraint[1]) {
default:
@@ -56880,11 +56884,6 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
std::vector<SDValue> &Ops,
SelectionDAG &DAG) const {
SDValue Result;
-
- // Only support length 1 constraints for now.
- if (Constraint.size() > 1)
- return;
-
char ConstraintLetter = Constraint[0];
switch (ConstraintLetter) {
default: break;
@@ -56966,6 +56965,17 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
}
return;
}
+ case 'W': {
+ assert(Constraint[1] == 's');
+ if (const auto *GA = dyn_cast<GlobalAddressSDNode>(Op)) {
+ Ops.push_back(DAG.getTargetGlobalAddress(GA->getGlobal(), SDLoc(Op),
+ GA->getValueType(0)));
+ } else if (const auto *BA = dyn_cast<BlockAddressSDNode>(Op)) {
+ Ops.push_back(DAG.getTargetBlockAddress(BA->getBlockAddress(),
+ BA->getValueType(0)));
+ }
+ return;
+ }
case 'Z': {
// 32-bit unsigned value
if (auto *C = dyn_cast<ConstantSDNode>(Op)) {
diff --git a/llvm/test/CodeGen/X86/inline-asm-Ws-constraint-error.ll b/llvm/test/CodeGen/X86/inline-asm-Ws-constraint-error.ll
new file mode 100644
index 00000000000000..38d0f08dfbd865
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inline-asm-Ws-constraint-error.ll
@@ -0,0 +1,9 @@
+; RUN: not llc -mtriple=x86_64 < %s 2>&1 | FileCheck %s
+
+; CHECK: error: invalid operand for inline asm constraint 'Ws'
+define void @test() {
+entry:
+ %x = alloca i32, align 4
+ call void asm sideeffect "// ${0:p}", "^Ws,~{dirflag},~{fpsr},~{flags}"(ptr %x)
+ ret void
+}
diff --git a/llvm/test/CodeGen/X86/inline-asm-Ws-constraint.ll b/llvm/test/CodeGen/X86/inline-asm-Ws-constraint.ll
new file mode 100644
index 00000000000000..72fc13795f08ce
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inline-asm-Ws-constraint.ll
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=i686 < %s | FileCheck %s
+; RUN: llc -mtriple=x86_64 < %s | FileCheck %s
+
+ at var = external dso_local global i32, align 4
+
+define dso_local void @test() {
+; CHECK-LABEL: test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: # var test
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ret{{[l|q]}}
+entry:
+ call void asm sideeffect "// ${0:p} ${1:p}", "^Ws,^Ws,~{dirflag},~{fpsr},~{flags}"(ptr @var, ptr @test)
+ ret void
+}
+
+define dso_local void @test_label() {
+; CHECK-LABEL: test_label:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: .Ltmp0: # Block address taken
+; CHECK-NEXT: # %bb.1: # %label
+; CHECK-NEXT: #APP
+; CHECK-NEXT: # .Ltmp0
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ret{{[l|q]}}
+entry:
+ br label %label
+
+label:
+ tail call void asm sideeffect "// ${0:p}", "Ws,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@test_label, %label))
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/77886
More information about the cfe-commits
mailing list