void created this revision. void added reviewers: jyknight, nickdesaulniers, hfinkel. void added a project: LLVM. Herald added a project: clang. Herald added a subscriber: cfe-commits. void abandoned this revision.
THIS IS A WIP! Remove the restrictions that preventing "callbr" from returning non-void values. The value returned by "callbr" is only valid on the "normal" path. Values used on "abnormal" paths are poisoned. Allow output constraints on "asm goto" Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D69875 Files: clang/include/clang/AST/Stmt.h clang/lib/AST/Stmt.cpp clang/lib/Parse/ParseStmtAsm.cpp clang/lib/Sema/SemaStmtAsm.cpp clang/test/Parser/asm-goto.c clang/test/Parser/asm-goto.cpp llvm/lib/AsmParser/LLParser.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp llvm/lib/IR/Verifier.cpp llvm/test/CodeGen/X86/callbr-asm-outputs.ll
Index: llvm/test/CodeGen/X86/callbr-asm-outputs.ll =================================================================== --- llvm/test/CodeGen/X86/callbr-asm-outputs.ll +++ llvm/test/CodeGen/X86/callbr-asm-outputs.ll @@ -1,18 +1,26 @@ -; RUN: not llc -mtriple=i686-- < %s 2> %t -; RUN: FileCheck %s < %t +; RUN: llc -mtriple=i686-- < %s | FileCheck %s -; CHECK: error: asm-goto outputs not supported +; A test for asm-goto output -; A test for asm-goto output prohibition - -define i32 @test(i32 %a) { +; CHECK-LABEL: test1: +; CHECK: movl 4(%esp), %eax +; CHECK-NEXT: addl $4, %eax +; CHECK-NEXT: #APP +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: jmp .Ltmp0 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: .LBB0_1: +; CHECK-NEXT: retl +; CHECK-NEXT: .Ltmp0: +define i32 @test1(i32 %x) { entry: - %0 = add i32 %a, 4 - %1 = callbr i32 asm "xorl $1, $1; jmp ${1:l}", "=&r,r,X,~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* blockaddress(@test, %fail)) to label %normal [label %fail] + %add = add nsw i32 %x, 4 + %ret = callbr i32 asm "xorl $1, $0; jmp ${2:l}", "=r,r,X,~{dirflag},~{fpsr},~{flags}"(i32 %add, i8* blockaddress(@test1, %abnormal)) + to label %normal [label %abnormal] normal: - ret i32 %1 + ret i32 %ret -fail: +abnormal: ret i32 1 } Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -2492,8 +2492,6 @@ void Verifier::visitCallBrInst(CallBrInst &CBI) { Assert(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!", &CBI); - Assert(CBI.getType()->isVoidTy(), "Callbr return value is not supported!", - &CBI); for (unsigned i = 0, e = CBI.getNumSuccessors(); i != e; ++i) Assert(CBI.getSuccessor(i)->getType()->isLabelTy(), "Callbr successors must all have pointer type!", &CBI); Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2834,6 +2834,7 @@ assert(isa<InlineAsm>(I.getCalledValue()) && "Only know how to handle inlineasm callbr"); visitInlineAsm(&I); + CopyToExportRegsIfNeeded(&I); // Retrieve successors. MachineBasicBlock *Return = FuncInfo.MBBMap[I.getDefaultDest()]; Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -6416,9 +6416,6 @@ /*IsCall=*/true)) return true; - if (isa<InlineAsm>(Callee) && !Ty->getReturnType()->isVoidTy()) - return Error(RetTypeLoc, "asm-goto outputs not supported"); - // Set up the Attribute for the function. SmallVector<Value *, 8> Args; SmallVector<AttributeSet, 8> ArgAttrs; Index: clang/test/Parser/asm-goto.cpp =================================================================== --- clang/test/Parser/asm-goto.cpp +++ clang/test/Parser/asm-goto.cpp @@ -6,9 +6,7 @@ int x,cond,*e; // expected-error@+1 {{expected ')'}} asm ("mov %[e], %[e]" : : [e] "rm" (*e)::a) - // expected-error@+1 {{'asm goto' cannot have output constraints}} - asm goto ("decl %0; jnz %l[a]" :"=r"(x): "m"(x) : "memory" : a); - // expected-error@+1 {{expected identifie}} + // expected-error@+1 {{expected identifier}} asm goto ("decl %0;" :: "m"(x) : "memory" : ); // expected-error@+1 {{expected ':'}} asm goto ("decl %0;" :: "m"(x) : "memory" ); @@ -51,3 +49,12 @@ :: lab); lab: return; } + +int +fgoto3 (int x) +{ + __asm__ volatile goto ("decl %0; jnz %l[a]" + : "=r" (x) : "m" (x) : "memory" : a); +a: + return -x; +} Index: clang/test/Parser/asm-goto.c =================================================================== --- clang/test/Parser/asm-goto.c +++ clang/test/Parser/asm-goto.c @@ -31,14 +31,22 @@ lab: return; } -int zoo () +int +fgoto3 (int x) +{ + __asm__ volatile goto ("decl %0; jnz %l[a]" + : "=r" (x) : "m" (x) : "memory" : a); +a: + return -x; +} + +int +zoo (void) { int x,cond,*e; // expected-error@+1 {{expected ')'}} asm ("mov %[e], %[e]" : : [e] "rm" (*e)::a) - // expected-error@+1 {{'asm goto' cannot have output constraints}} - asm goto ("decl %0; jnz %l[a]" :"=r"(x): "m"(x) : "memory" : a); - // expected-error@+1 {{expected identifie}} + // expected-error@+1 {{expected identifier}} asm goto ("decl %0;" :: "m"(x) : "memory" : ); // expected-error@+1 {{expected ':'}} asm goto ("decl %0;" :: "m"(x) : "memory" ); Index: clang/lib/Sema/SemaStmtAsm.cpp =================================================================== --- clang/lib/Sema/SemaStmtAsm.cpp +++ clang/lib/Sema/SemaStmtAsm.cpp @@ -473,10 +473,10 @@ // Look for the correct constraint index. unsigned ConstraintIdx = Piece.getOperandNo(); - // Labels are the last in the Exprs list. - if (NS->isAsmGoto() && ConstraintIdx >= NS->getNumInputs()) - continue; unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs(); + // Labels are the last in the Exprs list. + if (NS->isAsmGoto() && ConstraintIdx >= NumOperands) + continue; // Look for the (ConstraintIdx - NumOperands + 1)th constraint with // modifier '+'. if (ConstraintIdx >= NumOperands) { Index: clang/lib/Parse/ParseStmtAsm.cpp =================================================================== --- clang/lib/Parse/ParseStmtAsm.cpp +++ clang/lib/Parse/ParseStmtAsm.cpp @@ -764,12 +764,6 @@ AteExtraColon = Tok.is(tok::coloncolon); ConsumeToken(); - if (!AteExtraColon && isGotoAsm && Tok.isNot(tok::colon)) { - Diag(Tok, diag::err_asm_goto_cannot_have_output); - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } - if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) return StmtError(); } Index: clang/lib/AST/Stmt.cpp =================================================================== --- clang/lib/AST/Stmt.cpp +++ clang/lib/AST/Stmt.cpp @@ -456,7 +456,7 @@ } AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const { - return cast<AddrLabelExpr>(Exprs[i + NumInputs]); + return cast<AddrLabelExpr>(Exprs[i + NumOutputs + NumInputs]); } StringRef GCCAsmStmt::getLabelName(unsigned i) const { @@ -522,7 +522,7 @@ for (unsigned i = 0, e = getNumLabels(); i != e; ++i) if (getLabelName(i) == SymbolicName) - return i + getNumInputs(); + return i + getNumOutputs() + getNumInputs(); // Not found. return -1; Index: clang/include/clang/AST/Stmt.h =================================================================== --- clang/include/clang/AST/Stmt.h +++ clang/include/clang/AST/Stmt.h @@ -3013,7 +3013,7 @@ } IdentifierInfo *getLabelIdentifier(unsigned i) const { - return Names[i + NumInputs]; + return Names[i + NumOutputs + NumInputs]; } AddrLabelExpr *getLabelExpr(unsigned i) const; @@ -3024,11 +3024,11 @@ using labels_const_range = llvm::iterator_range<const_labels_iterator>; labels_iterator begin_labels() { - return &Exprs[0] + NumInputs; + return &Exprs[0] + NumOutputs + NumInputs; } labels_iterator end_labels() { - return &Exprs[0] + NumInputs + NumLabels; + return &Exprs[0] + NumOutputs + NumInputs + NumLabels; } labels_range labels() { @@ -3036,11 +3036,11 @@ } const_labels_iterator begin_labels() const { - return &Exprs[0] + NumInputs; + return &Exprs[0] + NumOutputs + NumInputs; } const_labels_iterator end_labels() const { - return &Exprs[0] + NumInputs + NumLabels; + return &Exprs[0] + NumOutputs + NumInputs + NumLabels; } labels_const_range labels() const {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits