| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* Copyright 2025 Jonathan S. Arney | ||
| 2 | * | ||
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | * you may not use this file except in compliance with the License. | ||
| 5 | * You may obtain a copy of the License at | ||
| 6 | * | ||
| 7 | * https://github.com/jarney/gyoji/blob/master/LICENSE | ||
| 8 | * | ||
| 9 | * Unless required by applicable law or agreed to in writing, software | ||
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | * See the License for the specific language governing permissions and | ||
| 13 | * limitations under the License. | ||
| 14 | */ | ||
| 15 | #include <gyoji-frontend.hpp> | ||
| 16 | #include <gyoji-misc/input-source-file.hpp> | ||
| 17 | #include <gyoji-analysis.hpp> | ||
| 18 | #include <gyoji-codegen.hpp> | ||
| 19 | |||
| 20 | using namespace Gyoji::codegen; | ||
| 21 | using namespace Gyoji::context; | ||
| 22 | using namespace Gyoji::frontend; | ||
| 23 | using namespace Gyoji::mir; | ||
| 24 | using namespace Gyoji::analysis; | ||
| 25 | |||
| 26 | 28 | int main(int argc, char **argv) | |
| 27 | { | ||
| 28 | |||
| 29 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | if (argc != 3) { |
| 30 | ✗ | fprintf(stderr, "Invalid number of arguments %d\n", argc); | |
| 31 | ✗ | fprintf(stderr, "Usage: jcc source-file object-file\n"); | |
| 32 | ✗ | exit(1); | |
| 33 | } | ||
| 34 | |||
| 35 | 28 | int input = open(argv[1], O_RDONLY); | |
| 36 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | if (input == -1) { |
| 37 | ✗ | fprintf(stderr, "Cannot open file %s\n", argv[1]); | |
| 38 | ✗ | exit(1); | |
| 39 | } | ||
| 40 | 56 | std::string input_filename(argv[1]); | |
| 41 | 28 | std::string output_filename(argv[2]); | |
| 42 | |||
| 43 | 28 | CompilerContext context(input_filename); | |
| 44 | 28 | Gyoji::misc::InputSourceFile input_source(input); | |
| 45 | |||
| 46 | Gyoji::owned<MIR> mir = | ||
| 47 | Parser::parse_to_mir( | ||
| 48 | context, | ||
| 49 | input_source | ||
| 50 | 28 | ); | |
| 51 | 28 | close(input); | |
| 52 | |||
| 53 | // Dump our MIR | ||
| 54 | // for debugging/review purposes | ||
| 55 | // before any analysis or code-generation | ||
| 56 | // passes. | ||
| 57 | { | ||
| 58 | 28 | std::string mir_filename = output_filename + std::string(".mir"); | |
| 59 | 28 | FILE *mir_output = fopen(mir_filename.c_str(), "w"); | |
| 60 | 28 | mir->dump(mir_output); | |
| 61 | 28 | fclose(mir_output); | |
| 62 | 28 | } | |
| 63 | |||
| 64 | // If we had errors at the MIR construction | ||
| 65 | // phase, it is likely we'll have an unsuitable | ||
| 66 | // MIR for analysis, so don't bother. | ||
| 67 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
|
28 | if (context.has_errors()) { |
| 68 | ✗ | context.get_errors().print(); | |
| 69 | ✗ | return -1; | |
| 70 | } | ||
| 71 | |||
| 72 | // Make sure that all types that are used in functions | ||
| 73 | // actually have 'complete' definitions. | ||
| 74 | 28 | std::vector<Gyoji::owned<AnalysisPass>> analysis_passes; | |
| 75 | |||
| 76 | 28 | analysis_passes.push_back(std::make_unique<AnalysisPassTypeResolution>(context)); | |
| 77 | 28 | analysis_passes.push_back(std::make_unique<AnalysisPassUnreachable>(context)); | |
| 78 | 28 | analysis_passes.push_back(std::make_unique<AnalysisPassReturnValues>(context)); | |
| 79 | 28 | analysis_passes.push_back(std::make_unique<AnalysisPassUseBeforeAssignment>(context)); | |
| 80 | 28 | analysis_passes.push_back(std::make_unique<AnalysisPassBorrowChecker>(context)); | |
| 81 | |||
| 82 | |||
| 83 |
2/2✓ Branch 5 taken 140 times.
✓ Branch 6 taken 28 times.
|
168 | for (const auto & analysis_pass : analysis_passes) { |
| 84 | 140 | fprintf(stderr, "============================\n"); | |
| 85 | 140 | fprintf(stderr, "Analysis pass %s\n", analysis_pass->get_name().c_str()); | |
| 86 | 140 | fprintf(stderr, "============================\n"); | |
| 87 | 140 | analysis_pass->check(*mir); | |
| 88 | } | ||
| 89 | |||
| 90 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
|
28 | if (context.has_errors()) { |
| 91 | ✗ | context.get_errors().print(); | |
| 92 | ✗ | return -1; | |
| 93 | } | ||
| 94 | |||
| 95 | 28 | fprintf(stderr, "============================\n"); | |
| 96 | 28 | fprintf(stderr, "Code Generation Pass\n"); | |
| 97 | 28 | fprintf(stderr, "============================\n"); | |
| 98 | // This leaks memory. The code-generation | ||
| 99 | // stage is a bit problematic | ||
| 100 | // because we're not really cleaning up the | ||
| 101 | // LLVM stuff at the moment. | ||
| 102 | 28 | generate_code(context, *mir, output_filename); | |
| 103 | |||
| 104 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
|
28 | if (context.has_errors()) { |
| 105 | ✗ | context.get_errors().print(); | |
| 106 | ✗ | return -1; | |
| 107 | } | ||
| 108 | 28 | return 0; | |
| 109 | 28 | } | |
| 110 |