Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve inline assembler support for VC & GCC #1761

Merged
merged 1 commit into from
Sep 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions cxx-squid/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ public enum CxxGrammarImpl implements GrammarRuleKey {
usingDeclarator,
usingDirective,
asmDefinition,
asmLabel,
linkageSpecification,
attributeSpecifierSeq,
attributeSpecifier,
Expand Down Expand Up @@ -1227,16 +1228,26 @@ private static void declarations(LexerfulGrammarBuilder b) {
b.rule(usingDirective).is(
b.optional(attributeSpecifierSeq), CxxKeyword.USING, CxxKeyword.NAMESPACE, b.optional(nestedNameSpecifier), namespaceName, ";" // C++
);

b.rule(asmDefinition).is(
CxxKeyword.ASM,
b.firstOf(
b.sequence("(", STRING, ")", ";"), // C++
b.sequence("{", b.oneOrMore(b.nextNot(b.firstOf("}", EOF)), b.anyToken()), "}", b.optional(";")), // VS
b.sequence(b.oneOrMore(b.nextNot(b.firstOf(";", EOF)), b.anyToken()), ";") // VS
b.sequence(
b.firstOf(CxxKeyword.ASM, "__asm__"), // C++ asm; GCC: __asm__
b.optional(b.firstOf(CxxKeyword.VIRTUAL, CxxKeyword.INLINE, "__virtual__")), // GCC asm qualifiers
"(", STRING, ")", ";"
),
b.sequence(b.firstOf("__asm", CxxKeyword.ASM), b.firstOf( // VS
b.sequence("{", b.oneOrMore(b.nextNot(b.firstOf("}", EOF)), b.anyToken()), "}", b.optional(";")), // VS __asm block
b.sequence(b.oneOrMore(b.nextNot(b.firstOf(";", EOF)), b.anyToken()), ";") // VS __asm ... ;
)
)
)
);

b.rule(asmLabel).is(
b.firstOf(CxxKeyword.ASM, "__asm__"), "(", STRING, ")" // GCC ASM label
);

b.rule(linkageSpecification).is(
CxxKeyword.EXTERN, STRING,
b.firstOf(
Expand Down Expand Up @@ -1319,7 +1330,7 @@ private static void declarators(LexerfulGrammarBuilder b) {
);

b.rule(initDeclarator).is(
declarator, b.optional(initializer) // C++
declarator, b.optional(asmLabel), b.optional(initializer) // C++ (asmLabel: GCC ASM label)
);

b.rule(declarator).is(
Expand Down
50 changes: 45 additions & 5 deletions cxx-squid/src/test/java/org/sonar/cxx/parser/AssemblerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,74 @@ public void asmIsoStandard() {
assertThat(p).matches("asm(\"mov eax, num\");");
}

@Test
public void asmGcc() {
p.setRootRule(g.rule(CxxGrammarImpl.asmDefinition));
assertThat(p).matches("asm(\"mov eax, num\");");
assertThat(p).matches("__asm__(\"mov eax, num\");");
assertThat(p).matches("asm virtual(\"mov eax, num\");");
assertThat(p).matches("asm inline(\"mov eax, num\");");
assertThat(p).matches("__asm__ __virtual__(\"mov eax, num\");");
}

@Test
public void asmVcAssemblyInstruction1() {
p.setRootRule(g.rule(CxxGrammarImpl.asmDefinition));
assertThat(p).matches("__asm mov eax, num ;");
assertThat(p).matches("asm mov eax, num ;");
}

@Test
public void asmVcAssemblyInstructionList1() {
p.setRootRule(g.rule(CxxGrammarImpl.asmDefinition));
assertThat(p).matches("__asm { mov eax, num }");
assertThat(p).matches("asm { mov eax, num }");
}

@Test
public void asmVcAssemblyInstructionList2() {
p.setRootRule(g.rule(CxxGrammarImpl.asmDefinition));
assertThat(p).matches("__asm { mov eax, num };");
assertThat(p).matches("asm { mov eax, num };");
}

@Test
public void asmVcAssemblyInstructionList3() {
p.setRootRule(g.rule(CxxGrammarImpl.asmDefinition));
assertThat(p).matches(
"asm {\n"
+ "mov eax, num ; Get first argument\n"
+ "mov ecx, power ; Get second argument\n"
+ "shl eax, cl ; EAX = EAX * ( 2 to the power of CL )\n"
+ "}"
"__asm {\n"
+ "mov eax, num ; Get first argument\n"
+ "mov ecx, power ; Get second argument\n"
+ "shl eax, cl ; EAX = EAX * ( 2 to the power of CL )\n"
+ "}"
);
assertThat(p).matches(
"asm {\n"
+ "mov eax, num ; Get first argument\n"
+ "mov ecx, power ; Get second argument\n"
+ "shl eax, cl ; EAX = EAX * ( 2 to the power of CL )\n"
+ "}"
);
}

@Test
public void asmGccLabel() {
p.setRootRule(g.rule(CxxGrammarImpl.asmLabel));
assertThat(p).matches("asm (\"myfoo\")");
assertThat(p).matches("__asm__ (\"myfoo\")");
}

@Test
public void asmGccLabel_reallife() {
p.setRootRule(g.rule(CxxGrammarImpl.simpleDeclaration));

assertThat(p).matches("extern const char cert_start[] asm(\"_binary_firmware_pho_by_crt_start\");");
assertThat(p).matches("int func (int x, int y) asm (\"MYFUNC\");");
assertThat(p).matches("int foo asm (\"myfoo\") = 2;");

assertThat(p).matches("extern const char cert_start[] __asm__(\"_binary_firmware_pho_by_crt_start\");");
assertThat(p).matches("int func (int x, int y) __asm__ (\"MYFUNC\");");
assertThat(p).matches("int foo __asm__ (\"myfoo\") = 2;");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
public class CxxParserTest {

String errSources = "/parser/bad/error_recovery_declaration.cc";
String[] goodFiles = {"own", "VC", "cli", "cuda", "examples"};
String[] goodFiles = {"own", "VC", "GCC", "cli", "cuda", "examples"};
String[] preprocessorFiles = {"preprocessor"};
String[] cCompatibilityFiles = {"C", "C99"};
String rootDir = "src/test/resources/parser";
Expand Down
14 changes: 14 additions & 0 deletions cxx-squid/src/test/java/org/sonar/cxx/parser/DeclaratorsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@

public class DeclaratorsTest extends ParserBaseTestHelper {

@Test
public void initDeclarator() {
p.setRootRule(g.rule(CxxGrammarImpl.initDeclarator));

mockRule(CxxGrammarImpl.declarator);
mockRule(CxxGrammarImpl.asmLabel);
mockRule(CxxGrammarImpl.initializer);

assertThat(p).matches("declarator");
assertThat(p).matches("declarator initializer");
assertThat(p).matches("declarator asmLabel");
assertThat(p).matches("declarator asmLabel initializer");
}

@Test
public void initDeclaratorList() {
p.setRootRule(g.rule(CxxGrammarImpl.initDeclaratorList));
Expand Down
46 changes: 46 additions & 0 deletions cxx-squid/src/test/resources/parser/GCC/inline-assembler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
void main()
{
asm("movl %ecx %eax"); /* moves the contents of ecx to eax */
__asm__("movb %bh (%eax)"); /*moves the byte from bh to the memory pointed by eax */

__asm__ ("movl %eax, %ebx\n\t"
"movl $56, %esi\n\t"
"movl %ecx, $label(%edx,%ebx,$4)\n\t"
"movb %ah, (%ebx)");

// Qualifiers
asm volatile ( "movl %ecx %eax" )
asm __volatile__ ( "movl %ecx %eax" )
asm inline ( "movl %ecx %eax" )
__asm__ volatile ( "movl %ecx %eax" )
__asm__ __inline__ ( "movl %ecx %eax" )
__asm__ inline ( "movl %ecx %eax" )

// Extended Asm
int a=10, b;
asm ("movl %1, %%eax;
movl %%eax, %0;"
:"=r"(b) /* output */
:"r"(a) /* input */
:"%eax" /* clobbered register */
);
}

// Asm Labels:

// Assembler names for data:
int foo1 asm ("myfoo1") = 2;
int foo2 __asm__ ("myfoo2") = 2;
extern const char cert_start1[] asm("_binary_firmware_pho_by_crt_start1");
extern const char cert_start2[] __asm__("_binary_firmware_pho_by_crt_start2");

// Assembler names for functions:
int func2 (int x, int y) asm ("MYFUNC1");
int func3 (int x, int y) __asm__ ("MYFUNC2");

// support workaround
#define __asm__ asm
void func()
{
__asm__("movl %ecx %eax");
}
28 changes: 28 additions & 0 deletions cxx-squid/src/test/resources/parser/VC/inline-assembler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// asm_overview.cpp
// processor: x86
void main()
{
// Naked functions must provide their own prolog...
__asm {
push ebp
mov ebp, esp
sub esp, __LOCAL_SIZE
}

// ... and epilog
__asm {
pop ebp
ret
}

__asm push ebp;
__asm mov ebp, esp;
__asm sub esp, __LOCAL_SIZE;
}

// support workaround
#define __asm asm
void func()
{
__asm push ebp;
}