1
- #include " codegen/ast-to-object.h" // for ASTToObjectVisitor, compile_o...
1
+ #include < cassert> // for assert
2
+ #include < cstdio> // for fprintf, stderr, fputc
3
+ #include < cstdlib> // for exit
4
+ #include < fstream> // for operator<<
5
+ #include < iostream>
6
+ #include < map> // for map, operator==, _Rb_tree_ite...
7
+ #include < memory> // for unique_ptr, allocator, make_u...
8
+ #include < numeric> // for accumulate
9
+ #include < sstream>
10
+ #include < string> // for string, operator<=>, operator+
11
+ #include < system_error> // for error_code
12
+ #include < utility> // for pair, move
13
+ #include < vector> // for vector
14
+
2
15
#include < glog/logging.h> // for COMPACT_GOOGLE_LOG_INFO, LOG
3
16
#include < llvm/ADT/APFloat.h> // for APFloat
4
17
#include < llvm/ADT/iterator_range.h> // for iterator_range
26
39
#include < llvm/Support/TargetSelect.h> // for InitializeAllAsmParsers, Init...
27
40
#include < llvm/Target/TargetMachine.h> // for TargetMachine
28
41
#include < llvm/Target/TargetOptions.h> // for TargetOptions
29
- #include < cassert> // for assert
30
- #include < cstdio> // for fprintf, stderr, fputc
31
- #include < cstdlib> // for exit
32
- #include < fstream> // for operator<<
33
- #include < map> // for map, operator==, _Rb_tree_ite...
34
- #include < memory> // for unique_ptr, allocator, make_u...
35
- #include < string> // for string, operator<=>, operator+
36
- #include < system_error> // for error_code
37
- #include < utility> // for pair, move
38
- #include < vector> // for vector
39
- #include " codegen/arx-llvm.h" // for ArxLLVM
40
- #include " error.h" // for LogErrorV
41
- #include " lexer.h" // for Lexer
42
- #include " parser.h" // for PrototypeAST, ExprAST, ForExp...
42
+
43
+ #include " codegen/arx-llvm.h" // for ArxLLVM
44
+ #include " codegen/ast-to-object.h" // for ASTToObjectVisitor, compile_o...
45
+ #include " error.h" // for LogErrorV
46
+ #include " io.h" // for ArxFile
47
+ #include " lexer.h" // for Lexer
48
+ #include " parser.h" // for PrototypeAST, ExprAST, ForExp...
43
49
44
50
namespace llvm {
45
51
class Value ;
46
52
}
47
53
54
+ std::string string_join (
55
+ const std::vector<std::string>& elements, const std::string& delimiter) {
56
+ if (elements.empty ()) {
57
+ return " " ;
58
+ }
59
+
60
+ std::string str;
61
+ for (auto v : elements) {
62
+ str += v + delimiter;
63
+ }
64
+ str = str.substr (0 , str.size () - delimiter.size ());
65
+ return str;
66
+ }
67
+
48
68
extern std::string INPUT_FILE;
49
69
extern std::string OUTPUT_FILE;
50
70
extern std::string ARX_VERSION;
@@ -635,7 +655,7 @@ extern "C" DLLEXPORT auto printd(double X) -> double {
635
655
*
636
656
* @param tree_ast The AST tree object.
637
657
*/
638
- auto compile_object (TreeAST& tree_ast) -> void {
658
+ auto compile_object (TreeAST& tree_ast) -> int {
639
659
auto codegen = std::make_unique<ASTToObjectVisitor>(ASTToObjectVisitor ());
640
660
641
661
Lexer::getNextToken ();
@@ -669,7 +689,7 @@ auto compile_object(TreeAST& tree_ast) -> void {
669
689
// TargetRegistry or we have a bogus target triple.
670
690
if (!Target) {
671
691
llvm::errs () << Error;
672
- exit ( 1 ) ;
692
+ return 1 ;
673
693
}
674
694
675
695
auto CPU = " generic" ;
@@ -692,40 +712,95 @@ auto compile_object(TreeAST& tree_ast) -> void {
692
712
std::error_code EC;
693
713
694
714
if (OUTPUT_FILE == " " ) {
695
- OUTPUT_FILE = " ./output .o" ;
715
+ OUTPUT_FILE = INPUT_FILE + " .o" ;
696
716
}
697
717
698
718
llvm::raw_fd_ostream dest (OUTPUT_FILE, EC, llvm::sys::fs::OF_None);
699
719
700
720
if (EC) {
701
721
llvm::errs () << " Could not open file: " << EC.message ();
702
- exit ( 1 ) ;
722
+ return 1 ;
703
723
}
704
724
705
725
llvm::legacy::PassManager pass;
726
+
706
727
auto FileType = llvm::CGFT_ObjectFile;
707
728
708
729
if (TheTargetMachine->addPassesToEmitFile (pass, dest, nullptr , FileType)) {
709
730
llvm::errs () << " TheTargetMachine can't emit a file of this type" ;
710
- exit ( 1 ) ;
731
+ return 1 ;
711
732
}
712
733
713
734
pass.run (*ArxLLVM::module );
714
735
dest.flush ();
736
+
737
+ if (IS_BUILD_LIB) {
738
+ return 0 ;
739
+ }
740
+
741
+ // generate an executable file
742
+
743
+ std::string linker_path = " clang++" ;
744
+ std::string executable_path = INPUT_FILE + " c" ;
745
+ // note: it just have a purpose to demonstrate an initial implementation
746
+ // it will be improved in a follow-up PR
747
+ std::string content =
748
+ " #include <iostream>\n "
749
+ " int main() {\n "
750
+ " std::cout << \" ARX[WARNING]: "
751
+ " This is an empty executable file\" << std::endl;\n "
752
+ " }\n " ;
753
+
754
+ std::string main_cpp_path = ArxFile::create_tmp_file (content);
755
+
756
+ if (main_cpp_path == " " ) {
757
+ llvm::errs () << " ARX[FAIL]: Executable file was not created." ;
758
+ return 1 ;
759
+ }
760
+
761
+ /* Example (running it from a shell prompt):
762
+ clang++ \
763
+ ${CLANG_EXTRAS} \
764
+ ${DEBUG_FLAGS} \
765
+ -fPIC \
766
+ -std=c++20 \
767
+ "${TEST_DIR_PATH}/main-objects/${test_name}.cpp" \
768
+ ${OBJECT_FILE} \
769
+ -o "${TMP_DIR}/main"
770
+ */
771
+
772
+ std::vector<std::string> compiler_args{
773
+ " -fPIC" , " -std=c++20" , main_cpp_path, OUTPUT_FILE, " -o" , executable_path};
774
+
775
+ // Add any additional compiler flags or include paths as needed
776
+ // compiler_args.push_back("-I/path/to/include");
777
+
778
+ std::string compiler_cmd =
779
+ linker_path + " " + string_join (compiler_args, " " );
780
+
781
+ std::cout << " ARX[INFO]: " << compiler_cmd << std::endl;
782
+ int compile_result = system (compiler_cmd.c_str ());
783
+
784
+ // ArxFile::delete_file(main_cpp_path);
785
+
786
+ if (compile_result != 0 ) {
787
+ llvm::errs () << " failed to compile and link object file" ;
788
+ exit (1 );
789
+ }
790
+
791
+ return 0 ;
715
792
}
716
793
717
794
/* *
718
795
* @brief Open the Arx shell.
719
796
*
720
797
*/
721
- auto open_shell_object () -> void {
798
+ auto open_shell_object () -> int {
722
799
// Prime the first token.
723
800
fprintf (stderr, " Arx %s \n " , ARX_VERSION.c_str ());
724
801
fprintf (stderr, " >>> " );
725
802
726
803
auto ast = std::make_unique<TreeAST>(TreeAST ());
727
804
728
- compile_object (*ast);
729
-
730
- exit (0 );
805
+ return compile_object (*ast);
731
806
}
0 commit comments