[PATCH] D109407: [InlineAsm] Support call function label in x86 inline asm with PIC
LuoYuanke via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 2 04:43:22 PDT 2021
LuoYuanke added a comment.
I have a general question. Can we handle it in X86DAGToDAGISel::PreprocessISelDAG()? We can create a new "X86ISD::Wrapper" and replace the corresponding memory operand of the INLINEASM node with the "X86ISD::Wrapper" node. Here is the pseudo example.
Transform the DAG
t0: ch = EntryToken
t12: i64 = X86ISD::WrapperRIP TargetGlobalAddress:i64<void (...)* @bar> 0 [TF=5]
t14: i64,ch = load<(load (s64) from got)> t0, t12, undef:i64
t10: ch,glue = inlineasm t0, TargetExternalSymbol:i64'call qword ptr ${0:P}
ret', MDNode:ch<0x6b0f848>, TargetConstant:i64<13>, TargetConstant:i32<196622>, t14, TargetConstant:i32<12>, Register:i32 $df, TargetConstant:i32<12>, Register:i16 $fpsw, TargetConstant:i32<12>, Register:i32 $eflags
to
t0: ch = EntryToken
t12: i64 = X86ISD::WrapperRIP TargetGlobalAddress:i64<void (...)* @bar> 0 [TF=5]
t14: i64,ch = load<(load (s64) from got)> t0, t12, undef:i64
t120: i64 = X86ISD::Wrapper TargetGlobalAddress:i64<void (...)* @bar> 0
t10: ch,glue = inlineasm t0, TargetExternalSymbol:i64'call qword ptr ${0:P}
ret', MDNode:ch<0x6b0f848>, TargetConstant:i64<13>, TargetConstant:i32<196622>, t120, TargetConstant:i32<12>, Register:i32 $df, TargetConstant:i32<12>, Register:i16 $fpsw, TargetConstant:i32<12>, Register:i32 $eflags
================
Comment at: llvm/docs/LangRef.rst:5047
- ``H``: Print a memory reference with additional offset +8.
-- ``P``: Print a memory reference or operand for use as the argument of a call
+- ``P``: Print branch target operand for use as the argument of a call
instruction. (E.g. omit ``(rip)``, even though it's PC-relative.)
----------------
Is it accurate? It seems only in PIC mode and in Intel dialect, we print the symbol operand.
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1189
+ if (StringRef(IDStart, IDEnd - IDStart).getAsInteger(10, Val))
+ report_fatal_error("Bad $ operand number in inline asm string: '" +
+ Twine(AsmStr) + "'");
----------------
The syntax should be ensured by front-end when emit IR. Right?
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1222
+ "'");
+ }
+ OpNo += InlineAsm::getNumOperandRegisters(Flags) + 1;
----------------
Drop brace.
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1246
+ return nullptr;
+ MachineSDNode::mmo_iterator I = MN->memoperands_begin();
+ if (!(*I)->isLoad())
----------------
Is it possible that there are multiple memory operands?
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1253
+ // "call in inline" and "got load" with global address.
+ SDNode *NodeIndex = Node->getOperand(OpNo + 2).getNode();
+ SDNode *OpIndex = Op.getOperand(2).getNode();
----------------
This code is X86 target specific. It assume the sibmem address mod of X86. I think we should refine this function in X86 target.
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1254
+ SDNode *NodeIndex = Node->getOperand(OpNo + 2).getNode();
+ SDNode *OpIndex = Op.getOperand(2).getNode();
+ if (cast<RegisterSDNode>(OpIndex)->getReg() ||
----------------
Why do we assume the 2nd operand is index operand? Is it always true?
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1255
+ SDNode *OpIndex = Op.getOperand(2).getNode();
+ if (cast<RegisterSDNode>(OpIndex)->getReg() ||
+ cast<RegisterSDNode>(NodeIndex)->getReg())
----------------
Why do we assume index register is noreg?
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1401
+ const TargetMachine &TM = MF->getTarget();
+ if (TM.getTargetTriple().isX86() && TM.isPositionIndependent() &&
+ TM.getTargetTriple().isOSLinux())
----------------
Maybe create a target function to determine if we want to transform operands for call instruction. The function return false by default.
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1486
+ TGA = getGAFromLoad(Node, i);
+ }
----------------
Drop brace.
================
Comment at: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp:1511
+ /*IsDebug=*/false, IsClone, IsCloned);
+ }
break;
----------------
Drop the brace.
================
Comment at: llvm/lib/Target/X86/X86AsmPrinter.cpp:611
+ if (Subtarget->isPositionIndependent() &&
+ MI->getOperand(OpNo).isGlobal())
+ PrintSymbolOperand(MI->getOperand(OpNo), O);
----------------
Do we have any test case when MI->getOperand(OpNo) is local symbol?
================
Comment at: llvm/test/CodeGen/X86/inline-asm-call.ll:5
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -relocation-model=pic -code-model=large | FileCheck %s --check-prefix=CHECK-X64-LARGE
+; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -relocation-model=pic -code-model=large | FileCheck %s --check-prefix=CHECK-X86-LARGE
+
----------------
Is it necessary to mix `-code-model=large` with `i386-unknown`?
gcc -mcmodel=large -m32 t2.c -m32
cc1: error: code model ‘large’ not supported in the 32 bit mode
================
Comment at: llvm/test/CodeGen/X86/inline-asm-call.ll:47
+; CHECK-X86-NEXT: pushl %edi
+; CHECK-X86-NEXT: .cfi_def_cfa_offset 8
+; CHECK-X86-NEXT: pushl %esi
----------------
Add "nounwind" to avoid CFI instructions.
================
Comment at: llvm/test/CodeGen/X86/inline-asm-call.ll:82
+; CHECK-X64-LARGE-NEXT: addq %rax, %rsi
+; CHECK-X64-LARGE-NEXT: movabsq $sincos at GOT, %r9
+; CHECK-X64-LARGE-NEXT: movq (%rsi,%r9), %r8
----------------
rsi hold the GOTbase. What does `$sincos at GOT` means? Is it the sincos entry offset to GOT base?
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D109407/new/
https://reviews.llvm.org/D109407
More information about the llvm-commits
mailing list