From: Chad Rosier Date: Wed, 12 Sep 2012 18:14:25 +0000 (+0000) Subject: [ms-inline asm] If we have a single asm operand that maps to multiple X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7f9678b513f926dae27234858ed2586a6eb03b7b;p=clang [ms-inline asm] If we have a single asm operand that maps to multiple MCOperands then iterate over all of then when computing clobbers, inputs and outputs. On x86 the 1-to-many mapping is a memory operand that includes a BaseReg(reg), MemScale(imm), MemIndexReg(reg), an Expr(MCExpr or imm) and a MemSegReg(reg). Invalid register (Op.getReg() == 0) are not considered when computing clobber. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163728 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 3f57a6ec03..9109bcb854 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -581,62 +581,60 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, unsigned MCIdx = TargetParser->getMCInstOperandNum(Kind, Inst, Operands, i, NumMCOperands); assert (NumMCOperands && "Expected at least 1 MCOperand!"); - // If we have a one-to-many mapping, then search for the MCExpr. - if (NumMCOperands > 1) { - bool foundExpr = false; - for (unsigned j = MCIdx, e = MCIdx + NumMCOperands; j != e; ++j) { - if (Inst.getOperand(j).isExpr()) { - foundExpr = true; - MCIdx = j; - break; - } - } - assert (foundExpr && "Expected for find an expression!"); - } - - const llvm::MCOperand &Op = Inst.getOperand(MCIdx); - // Register/Clobber. - if (Op.isReg() && NumDefs && (MCIdx < NumDefs)) { - std::string Reg; - llvm::raw_string_ostream OS(Reg); - IP->printRegName(OS, Op.getReg()); - - StringRef Clobber(OS.str()); - if (!Context.getTargetInfo().isValidClobber(Clobber)) - return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) << - Clobber); - ClobberRegs.insert(Reg); - continue; - } - // Expr/Input or Output. - if (Op.isExpr()) { - const llvm::MCExpr *Expr = Op.getExpr(); - const llvm::MCSymbolRefExpr *SymRef; - if ((SymRef = dyn_cast(Expr))) { - StringRef Name = SymRef->getSymbol().getName(); - IdentifierInfo *II = getIdentifierInfo(Name, AsmToks, - AsmTokRanges[StrIdx].first, - AsmTokRanges[StrIdx].second); - if (II) { - CXXScopeSpec SS; - UnqualifiedId Id; - SourceLocation Loc; - Id.setIdentifier(II, AsmLoc); - ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id, - false, false); - if (!Result.isInvalid()) { - bool isMemDef = (i == 1) && Desc.mayStore(); - if (isMemDef) { - Outputs.push_back(II); - OutputExprs.push_back(Result.take()); - OutputExprNames.push_back(Name.str()); - OutputConstraints.push_back("=r"); - } else { - Inputs.push_back(II); - InputExprs.push_back(Result.take()); - InputExprNames.push_back(Name.str()); - InputConstraints.push_back("r"); + for (unsigned j = MCIdx, e = MCIdx + NumMCOperands; j != e; ++j) { + const llvm::MCOperand &Op = Inst.getOperand(j); + + // Skip immediates. + if (Op.isImm() || Op.isFPImm()) + continue; + + // Skip invalid register operands. + if (Op.isReg() && Op.getReg() == 0) + continue; + + // Register/Clobber. + if (Op.isReg() && NumDefs && (j < NumDefs)) { + std::string Reg; + llvm::raw_string_ostream OS(Reg); + IP->printRegName(OS, Op.getReg()); + + StringRef Clobber(OS.str()); + if (!Context.getTargetInfo().isValidClobber(Clobber)) + return StmtError( + Diag(AsmLoc, diag::err_asm_unknown_register_name) << Clobber); + ClobberRegs.insert(Reg); + continue; + } + // Expr/Input or Output. + if (Op.isExpr()) { + const llvm::MCExpr *Expr = Op.getExpr(); + const llvm::MCSymbolRefExpr *SymRef; + if ((SymRef = dyn_cast(Expr))) { + StringRef Name = SymRef->getSymbol().getName(); + IdentifierInfo *II = getIdentifierInfo(Name, AsmToks, + AsmTokRanges[StrIdx].first, + AsmTokRanges[StrIdx].second); + if (II) { + CXXScopeSpec SS; + UnqualifiedId Id; + SourceLocation Loc; + Id.setIdentifier(II, AsmLoc); + ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id, + false, false); + if (!Result.isInvalid()) { + bool isMemDef = (i == 1) && Desc.mayStore(); + if (isMemDef) { + Outputs.push_back(II); + OutputExprs.push_back(Result.take()); + OutputExprNames.push_back(Name.str()); + OutputConstraints.push_back("=r"); + } else { + Inputs.push_back(II); + InputExprs.push_back(Result.take()); + InputExprNames.push_back(Name.str()); + InputConstraints.push_back("r"); + } } } } diff --git a/test/CodeGen/ms-inline-asm.c b/test/CodeGen/ms-inline-asm.c index 8f8d687902..67e0eb46b6 100644 --- a/test/CodeGen/ms-inline-asm.c +++ b/test/CodeGen/ms-inline-asm.c @@ -127,3 +127,15 @@ void t14(void) { // CHECK: t14 // CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind } + +void t15(void) { + __asm mov eax, DWORD PTR [eax] +// CHECK: t15 +// CHECK: call void asm sideeffect inteldialect "mov eax, DWORD PTR [eax]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +} + +void t16(unsigned long long V) { + __asm mov eax, DWORD PTR [V] +// CHECK: t16 +// CHECK: call void asm sideeffect inteldialect "mov eax, DWORD PTR [$0]", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i64 %0) nounwind +}