clang support gnu asm goto.
Syntax:
asm [volatile] goto ( AssemblerTemplate
:
: InputOperands
: Clobbers
: GotoLabels)
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
New llvm IR is "callbr" for inline asm goto instead "call" for inline asm
For:
asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop);
IR:
callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* blockaddress(@foo, %label_true), i8* blockaddress(@foo, %loop)) #1
to label %asm.fallthrough [label %label_true, label %loop], !srcloc !3
asm.fallthrough:
Compiler need to generate:
1> a dummy constarint 'X' for each label.
2> an unique fallthrough label for each asm goto stmt " asm.fallthrough%number".
Diagnostic
1> duplicate asm operand name are used in output, input and label.
2> goto out of scope.
llvm-svn: 362045
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index 4796ee8..e9a2c58 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -444,6 +444,14 @@
Exprs[i + NumOutputs] = E;
}
+AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const {
+ return cast<AddrLabelExpr>(Exprs[i + NumInputs]);
+}
+
+StringRef GCCAsmStmt::getLabelName(unsigned i) const {
+ return getLabelExpr(i)->getLabel()->getName();
+}
+
/// getInputConstraint - Return the specified input constraint. Unlike output
/// constraints, these can be empty.
StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
@@ -456,13 +464,16 @@
Stmt **Exprs,
unsigned NumOutputs,
unsigned NumInputs,
+ unsigned NumLabels,
StringLiteral **Clobbers,
unsigned NumClobbers) {
this->NumOutputs = NumOutputs;
this->NumInputs = NumInputs;
this->NumClobbers = NumClobbers;
+ this->NumLabels = NumLabels;
+ assert(!(NumOutputs && NumLabels) && "asm goto cannot have outputs");
- unsigned NumExprs = NumOutputs + NumInputs;
+ unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
C.Deallocate(this->Names);
this->Names = new (C) IdentifierInfo*[NumExprs];
@@ -497,6 +508,10 @@
if (getInputName(i) == SymbolicName)
return getNumOutputs() + NumPlusOperands + i;
+ for (unsigned i = 0, e = getNumLabels(); i != e; ++i)
+ if (getLabelName(i) == SymbolicName)
+ return i + getNumInputs();
+
// Not found.
return -1;
}
@@ -614,8 +629,8 @@
while (CurPtr != StrEnd && isDigit(*CurPtr))
N = N*10 + ((*CurPtr++)-'0');
- unsigned NumOperands =
- getNumOutputs() + getNumPlusOperands() + getNumInputs();
+ unsigned NumOperands = getNumOutputs() + getNumPlusOperands() +
+ getNumInputs() + getNumLabels();
if (N >= NumOperands) {
DiagOffs = CurPtr-StrStart-1;
return diag::err_asm_invalid_operand_number;
@@ -728,10 +743,12 @@
unsigned numinputs, IdentifierInfo **names,
StringLiteral **constraints, Expr **exprs,
StringLiteral *asmstr, unsigned numclobbers,
- StringLiteral **clobbers, SourceLocation rparenloc)
+ StringLiteral **clobbers, unsigned numlabels,
+ SourceLocation rparenloc)
: AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
- numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) {
- unsigned NumExprs = NumOutputs + NumInputs;
+ numinputs, numclobbers),
+ RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) {
+ unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
Names = new (C) IdentifierInfo*[NumExprs];
std::copy(names, names + NumExprs, Names);