1import lldb
2from lldbsuite.test.decorators import *
3from lldbsuite.test.lldbtest import *
4from lldbsuite.test import lldbutil
5from lldbsuite.test_event.build_exception import BuildError
6
7class TestCase(TestBase):
8
9    NO_DEBUG_INFO_TESTCASE = True
10
11    def build_and_run(self, test_file):
12        """
13        Tries building the given test source and runs to the first breakpoint.
14        Returns false if the file fails to build due to an unsupported calling
15        convention on the current test target. Returns true if building and
16        running to the breakpoint succeeded.
17        """
18        try:
19            self.build(dictionary={
20                "C_SOURCES" : test_file,
21                "CFLAGS_EXTRAS" : "-Werror=ignored-attributes"
22            })
23        except BuildError as e:
24             # Test source failed to build. Check if it failed because the
25             # calling convention argument is unsupported/unknown in which case
26             # the test should be skipped.
27             error_msg = str(e)
28             # Clang gives an explicit error when a calling convention is
29             # not supported.
30             if "calling convention is not supported for this target" in error_msg:
31               return False
32             # GCC's has two different generic warnings it can emit.
33             if "attribute ignored" in error_msg:
34               return False
35             if "attribute directive ignored " in error_msg:
36               return False
37             # We got a different build error, so raise it again to fail the
38             # test.
39             raise
40        lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec(test_file))
41        return True
42
43    @skipIf(compiler="clang", compiler_version=['<', '9.0'])
44    def test_regcall(self):
45        if not self.build_and_run("regcall.c"):
46            return
47        self.expect_expr("func(1, 2, 3, 4)", result_type="int", result_value="10")
48
49    @skipIf(compiler="clang", compiler_version=['<', '9.0'])
50    @expectedFailureDarwin(archs=["arm64", "arm64e"]) # rdar://84528755
51    def test_ms_abi(self):
52        if not self.build_and_run("ms_abi.c"):
53            return
54        self.expect_expr("func(1, 2, 3, 4)", result_type="int", result_value="10")
55
56    @skipIf(compiler="clang", compiler_version=['<', '9.0'])
57    def test_stdcall(self):
58        if not self.build_and_run("stdcall.c"):
59            return
60        self.expect_expr("func(1, 2, 3, 4)", result_type="int", result_value="10")
61
62    @expectedFailureAll(oslist=["freebsd"],
63                        bugnumber="github.com/llvm/llvm-project/issues/56084")
64    def test_vectorcall(self):
65        if not self.build_and_run("vectorcall.c"):
66            return
67        self.expect_expr("func(1.0)", result_type="int", result_value="1")
68
69    @skipIf(compiler="clang", compiler_version=['<', '9.0'])
70    def test_fastcall(self):
71        if not self.build_and_run("fastcall.c"):
72            return
73        self.expect_expr("func(1, 2, 3, 4)", result_type="int", result_value="10")
74
75    @skipIf(compiler="clang", compiler_version=['<', '9.0'])
76    def test_pascal(self):
77        if not self.build_and_run("pascal.c"):
78            return
79        self.expect_expr("func(1, 2, 3, 4)", result_type="int", result_value="10")
80
81    def test_sysv_abi(self):
82        if not self.build_and_run("sysv_abi.c"):
83            return
84        self.expect_expr("func(1, 2, 3, 4)", result_type="int", result_value="10")
85