diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -252,6 +252,7 @@ EXTENSION(pragma_clang_attribute_namespaces, true) EXTENSION(pragma_clang_attribute_external_declaration, true) EXTENSION(gnu_asm, LangOpts.GNUAsm) +EXTENSION(gnu_asm_goto_with_outputs, true) #undef EXTENSION #undef FEATURE diff --git a/clang/test/Parser/asm-goto-with-outputs.c b/clang/test/Parser/asm-goto-with-outputs.c new file mode 100644 --- /dev/null +++ b/clang/test/Parser/asm-goto-with-outputs.c @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -triple i386-pc-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s +// expected-no-diagnostics + +#if !__has_extension(gnu_asm) +#error Extension 'gnu_asm' should be available by default +#endif +#if !__has_extension(gnu_asm_goto_with_outputs) +#error Extension 'gnu_asm_goto_with_outputs' should be available by default +#endif + +int test1(int cond) { + asm volatile goto("testl %0, %0; jne %l2;" : "=r"(cond) : "r"(cond) :: label_true, loop); + asm volatile goto("testl %0, %0; jne %l3;" : "=r"(cond) : "r"(cond) :: label_true, loop); + return 0; +loop: + return 0; +label_true: + return 1; +} + +int test2(int out1, int out2) { + asm volatile goto("testl %0, %0; jne %l3;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop); + asm volatile goto("testl %0, %0; jne %l4;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop); + return 0; +loop: + return 0; +label_true: + return 1; +} + +int test3(int out1, int out2) { + if (out1 < out2) + asm volatile goto("jne %l3" : "+S"(out1), "+D"(out2) : "r"(out1) :: label_true, loop); + else + asm volatile goto("jne %l5" : "+S"(out1), "+D"(out2) : "r"(out1), "r"(out2) :: label_true, loop); + return out1 + out2; +loop: + return -1; +label_true: + return -2; +} + +int test4(int addr, int size, int limit) { + asm goto( + "add %1,%0 ; " + "jc %l[t_err] ; " + "cmp %2,%0 ; " + "ja %l[t_err] ; " + : "+r" (addr) + : "g" (size), "g" (limit) + : : t_err); + return 0; +t_err: + return 1; +} + +int test5(int out1) { + int out2 = 42; + asm volatile goto("testl %0, %0; testl %1, %1; jne %l2" : "+S"(out2) : "r"(out1) :: label_true, landing); +landing: + return out1 + out2; +label_true: + return -2; +}