[llvm] r214550 - MS inline asm: Use memory constraints for functions instead of registers
Reid Kleckner
reid at kleckner.net
Fri Aug 1 13:21:24 PDT 2014
Author: rnk
Date: Fri Aug 1 15:21:24 2014
New Revision: 214550
URL: http://llvm.org/viewvc/llvm-project?rev=214550&view=rev
Log:
MS inline asm: Use memory constraints for functions instead of registers
This is consistent with how we parse them in a standalone .s file, and
inline assembly shouldn't differ.
This fixes errors about requiring more registers than available in
cases like this:
void f();
void __declspec(naked) g() {
__asm pusha
__asm call f
__asm popa
__asm ret
}
There are no registers available to pass the address of 'f' into the asm
blob. The asm should now directly call 'f'.
Tests will land in Clang shortly.
Modified:
llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
llvm/trunk/test/CodeGen/X86/ms-inline-asm.ll
Modified: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=214550&r1=214549&r2=214550&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp Fri Aug 1 15:21:24 2014
@@ -731,6 +731,13 @@ private:
(X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit)));
}
+ unsigned getPointerWidth() {
+ if (is16BitMode()) return 16;
+ if (is32BitMode()) return 32;
+ if (is64BitMode()) return 64;
+ llvm_unreachable("invalid mode");
+ }
+
bool isParsingIntelSyntax() {
return getParser().getAssemblerDialect();
}
@@ -982,15 +989,20 @@ std::unique_ptr<X86Operand> X86AsmParser
unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg,
unsigned Scale, SMLoc Start, SMLoc End, unsigned Size, StringRef Identifier,
InlineAsmIdentifierInfo &Info) {
- // If this is not a VarDecl then assume it is a FuncDecl or some other label
- // reference. We need an 'r' constraint here, so we need to create register
- // operand to ensure proper matching. Just pick a GPR based on the size of
- // a pointer.
- if (isa<MCSymbolRefExpr>(Disp) && !Info.IsVarDecl) {
- unsigned RegNo =
- is64BitMode() ? X86::RBX : (is32BitMode() ? X86::EBX : X86::BX);
- return X86Operand::CreateReg(RegNo, Start, End, /*AddressOf=*/true,
- SMLoc(), Identifier, Info.OpDecl);
+ // If we found a decl other than a VarDecl, then assume it is a FuncDecl or
+ // some other label reference.
+ if (isa<MCSymbolRefExpr>(Disp) && Info.OpDecl && !Info.IsVarDecl) {
+ // Insert an explicit size if the user didn't have one.
+ if (!Size) {
+ Size = getPointerWidth();
+ InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_SizeDirective, Start,
+ /*Len=*/0, Size));
+ }
+
+ // Create an absolute memory reference in order to match against
+ // instructions taking a PC relative operand.
+ return X86Operand::CreateMem(Disp, Start, End, Size, Identifier,
+ Info.OpDecl);
}
// We either have a direct symbol reference, or an offset from a symbol. The
Modified: llvm/trunk/test/CodeGen/X86/ms-inline-asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/ms-inline-asm.ll?rev=214550&r1=214549&r2=214550&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/ms-inline-asm.ll (original)
+++ llvm/trunk/test/CodeGen/X86/ms-inline-asm.ll Fri Aug 1 15:21:24 2014
@@ -110,7 +110,7 @@ define i32 @t31() {
entry:
%val = alloca i32, align 64
store i32 -1, i32* %val, align 64
- call void asm sideeffect inteldialect "mov dword ptr $0, esp", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %val) #1
+ call void asm sideeffect inteldialect "mov dword ptr $0, esp", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %val)
%sp = load i32* %val, align 64
ret i32 %sp
; CHECK-LABEL: t31:
@@ -125,3 +125,12 @@ entry:
; CHECK: movl (%esp), %eax
; CHECK: ret
}
+
+declare void @other_func()
+
+define void @naked() #0 {
+ call void asm sideeffect inteldialect "call dword ptr $0", "*m,~{eax},~{ebx},~{ecx},~{edx},~{edi},~{esi},~{esp},~{ebp},~{dirflag},~{fpsr},~{flags}"(void()* @other_func)
+ unreachable
+}
+
+attributes #0 = { naked }
More information about the llvm-commits
mailing list