GCC Code Coverage Report


Directory: ../
File: src/irgenerator/GenTargetDependent.cpp
Date: 2025-12-07 00:53:49
Coverage Exec Excl Total
Lines: 34.2% 26 6 82
Functions: 100.0% 2 0 2
Branches: 15.0% 31 0 206

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #include "IRGenerator.h"
4
5 #include <driver/Driver.h>
6
7 namespace spice::compiler {
8
9 1 std::string IRGenerator::getSysCallAsmString(uint8_t numRegs) const {
10 1 const llvm::Triple &targetTriple = cliOptions.targetTriple;
11
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 117 not taken.
1 std::stringstream asmString;
12
13 // For each OS/architecture we have a mapping of operand index -> register.
14
2/4
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 115 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 46 taken 1 time.
1 if (targetTriple.isOSDarwin()) {
15 if (targetTriple.getArch() == llvm::Triple::ArchType::x86_64) {
16 static constexpr const char *regs[] = {"%rax", "%rdi", "%rsi", "%rdx", "%r10", "%r8", "%r9"};
17 for (uint8_t i = 0; i < numRegs; i++) {
18 // macOS syscall numbers are offset by 0x2000000
19 if (i == 0)
20 asmString << "movq $(" << std::to_string(0x2000000) << " + " << std::to_string(i) << "), " << regs[i] << "\n";
21 else
22 asmString << "movq $" << std::to_string(i) << ", " << regs[i] << "\n";
23 }
24 asmString << "syscall\n";
25 } else if (targetTriple.isAArch64()) {
26 static constexpr const char *regs[] = {"x16", "x0", "x1", "x2", "x3", "x4", "x5"};
27 for (uint8_t i = 0; i < numRegs; ++i)
28 asmString << "mov " << regs[i] << ", $" << std::to_string(i) << "\n";
29 asmString << "svc #0x80\n";
30 } else { // LCOV_EXCL_LINE
31 assert_fail("Unsupported macOS target for inline assembly"); // LCOV_EXCL_LINE
32 } // LCOV_EXCL_LINE
33
1/2
✓ Branch 47 → 48 taken 1 time.
✗ Branch 47 → 88 not taken.
1 } else if (targetTriple.isOSLinux()) {
34
1/2
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 61 not taken.
1 if (targetTriple.getArch() == llvm::Triple::ArchType::x86_64) {
35 static constexpr const char *regs[] = {"%rax", "%rdi", "%rsi", "%rdx", "%r10", "%r8", "%r9"};
36
2/2
✓ Branch 59 → 51 taken 4 times.
✓ Branch 59 → 60 taken 1 time.
5 for (uint8_t i = 0; i < numRegs; ++i)
37
5/10
✓ Branch 51 → 52 taken 4 times.
✗ Branch 51 → 115 not taken.
✓ Branch 53 → 54 taken 4 times.
✗ Branch 53 → 106 not taken.
✓ Branch 54 → 55 taken 4 times.
✗ Branch 54 → 106 not taken.
✓ Branch 55 → 56 taken 4 times.
✗ Branch 55 → 106 not taken.
✓ Branch 56 → 57 taken 4 times.
✗ Branch 56 → 106 not taken.
4 asmString << "movq $" << std::to_string(i) << ", " << regs[i] << "\n";
38
1/2
✓ Branch 60 → 89 taken 1 time.
✗ Branch 60 → 115 not taken.
1 asmString << "syscall\n";
39 } else if (targetTriple.getArch() == llvm::Triple::ArchType::x86) {
40 // Note: Using movl for 32-bit registers.
41 static constexpr const char *regs[] = {"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp"};
42 for (uint8_t i = 0; i < numRegs; ++i)
43 asmString << "movl $" << std::to_string(i) << ", " << regs[i] << "\n";
44 asmString << "int $0x80\n";
45 } else if (targetTriple.isAArch64()) {
46 static constexpr const char *regs[] = {"x8", "x0", "x1", "x2", "x3", "x4", "x5"};
47 for (uint8_t i = 0; i < numRegs; ++i)
48 asmString << "mov " << regs[i] << ", $" << std::to_string(i) << "\n";
49 asmString << "svc 0\n";
50 } else { // LCOV_EXCL_LINE
51 assert_fail("Unsupported Linux target for inline assembly"); // LCOV_EXCL_LINE
52 } // LCOV_EXCL_LINE
53 } else { // LCOV_EXCL_LINE
54 assert_fail("Unsupported target for inline assembly"); // LCOV_EXCL_LINE
55 } // LCOV_EXCL_LINE
56
57
1/2
✓ Branch 89 → 90 taken 1 time.
✗ Branch 89 → 115 not taken.
2 return asmString.str();
58 1 }
59
60 1 std::string IRGenerator::getSysCallConstraintString(uint8_t numRegs) const {
61 1 const llvm::Triple &targetTriple = cliOptions.targetTriple;
62
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 87 not taken.
1 std::stringstream constraints;
63
64 // Generate a comma-separated constraint string: first the operand constraints,
65 // then the corresponding clobbers, then extra clobbers.
66
2/4
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 85 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 34 taken 1 time.
1 if (targetTriple.isOSDarwin()) {
67 if (targetTriple.getArch() == llvm::Triple::ArchType::x86_64) {
68 static constexpr const char *clobbers[] = {"~{rax}", "~{rdi}", "~{rsi}", "~{rdx}", "~{r10}", "~{r8}", "~{r9}"};
69 for (uint8_t i = 0; i < numRegs; i++) {
70 constraints << "r";
71 if (i != numRegs - 1)
72 constraints << ",";
73 }
74 for (uint8_t i = 0; i < numRegs; i++)
75 constraints << "," << clobbers[i];
76 constraints << ",~{dirflag},~{fpsr},~{flags}";
77 } else if (targetTriple.isAArch64()) {
78 static constexpr const char *clobbers[] = {"~{x16}", "~{x0}", "~{x1}", "~{x2}", "~{x3}", "~{x4}", "~{x5}"};
79 for (uint8_t i = 0; i < numRegs; i++) {
80 constraints << "r";
81 if (i != numRegs - 1)
82 constraints << ",";
83 }
84 for (uint8_t i = 0; i < numRegs; i++)
85 constraints << "," << clobbers[i];
86 constraints << ",~{dirflag},~{fpsr},~{flags}";
87 } else { // LCOV_EXCL_LINE
88 assert_fail("Unsupported macOS target for inline assembly"); // LCOV_EXCL_LINE
89 } // LCOV_EXCL_LINE
90
1/2
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 79 not taken.
1 } else if (targetTriple.isOSLinux()) {
91
1/2
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 50 not taken.
1 if (targetTriple.getArch() == llvm::Triple::ArchType::x86_64) {
92 static constexpr const char *clobbers[] = {"~{rax}", "~{rdi}", "~{rsi}", "~{rdx}", "~{r10}", "~{r8}", "~{r9}"};
93
2/2
✓ Branch 43 → 39 taken 4 times.
✓ Branch 43 → 44 taken 1 time.
5 for (uint8_t i = 0; i < numRegs; i++) {
94
1/2
✓ Branch 39 → 40 taken 4 times.
✗ Branch 39 → 85 not taken.
4 constraints << "r";
95
2/2
✓ Branch 40 → 41 taken 3 times.
✓ Branch 40 → 42 taken 1 time.
4 if (i != numRegs - 1)
96
1/2
✓ Branch 41 → 42 taken 3 times.
✗ Branch 41 → 85 not taken.
3 constraints << ",";
97 }
98
2/2
✓ Branch 48 → 45 taken 4 times.
✓ Branch 48 → 49 taken 1 time.
5 for (uint8_t i = 0; i < numRegs; i++)
99
2/4
✓ Branch 45 → 46 taken 4 times.
✗ Branch 45 → 85 not taken.
✓ Branch 46 → 47 taken 4 times.
✗ Branch 46 → 85 not taken.
4 constraints << "," << clobbers[i];
100
1/2
✓ Branch 49 → 80 taken 1 time.
✗ Branch 49 → 85 not taken.
1 constraints << ",~{dirflag},~{fpsr},~{flags}";
101 } else if (targetTriple.getArch() == llvm::Triple::ArchType::x86) {
102 static constexpr const char *clobbers[] = {"~{eax}", "~{ebx}", "~{ecx}", "~{edx}", "~{esi}", "~{edi}", "~{ebp}"};
103 for (uint8_t i = 0; i < numRegs; i++) {
104 constraints << "r";
105 if (i != numRegs - 1)
106 constraints << ",";
107 }
108 for (uint8_t i = 0; i < numRegs; i++)
109 constraints << "," << clobbers[i];
110 constraints << ",~{dirflag},~{fpsr},~{flags}";
111 } else if (targetTriple.isAArch64()) {
112 static constexpr const char *clobbers[] = {"~{x8}", "~{x0}", "~{x1}", "~{x2}", "~{x3}", "~{x4}", "~{x5}"};
113 for (uint8_t i = 0; i < numRegs; i++) {
114 constraints << "r";
115 if (i != numRegs - 1)
116 constraints << ",";
117 }
118 for (uint8_t i = 0; i < numRegs; i++)
119 constraints << "," << clobbers[i];
120 constraints << ",~{dirflag},~{fpsr},~{flags}";
121 } else { // LCOV_EXCL_LINE
122 assert_fail("Unsupported Linux target for inline assembly"); // LCOV_EXCL_LINE
123 } // LCOV_EXCL_LINE
124 } else { // LCOV_EXCL_LINE
125 assert_fail("Unsupported target for inline assembly"); // LCOV_EXCL_LINE
126 } // LCOV_EXCL_LINE
127
128
1/2
✓ Branch 80 → 81 taken 1 time.
✗ Branch 80 → 85 not taken.
2 return constraints.str();
129 1 }
130
131 } // namespace spice::compiler
132