23 std::println(
"Phasor C++ Code Generator\nCopyright (c) 2026 Daniel McGuire\n");
33 std::println(std::cerr,
"Error: No input file provided\nUse --help for usage information");
39 m_args.mainFile =
"C:\\Program Files\\Phasor VM\\Development\\nativestub.cpp";
41 m_args.mainFile =
"/usr/local/share/phasor/dev/nativestub.cpp";
44 if (
m_args.moduleName.empty())
46 std::filesystem::path inputPath(
m_args.inputFile);
47 m_args.moduleName = inputPath.stem().string();
51 if (
m_args.outputFile.empty())
62 std::println(
"Input file: {}\nOutput file: {}",
m_args.inputFile.string(),
m_args.outputFile.string());
63 if (!
m_args.moduleName.empty())
64 std::println(
"Module name: {}",
m_args.moduleName);
88 std::println(
"Generating wrapper...");
91 std::println(
"{} -> {}.h",
m_args.inputFile.string(),
m_args.moduleName);
94 std::println(std::cerr,
"Error: Could not generate header file");
99 std::println(
"{} -> {}.cpp\n",
m_args.mainFile.filename().string(),
m_args.moduleName);
102 std::println(std::cerr,
"Could not generate source file");
106 std::println(
"Compiling...");
107 std::print(
"[COMPILER] ");
109 std::println(
"{}.cpp -> {}.obj\n",
m_args.moduleName,
m_args.moduleName);
112 std::println(std::cerr,
"Could not compile program");
116 std::println(
"Linking...");
117 std::print(
"[LINKER] ");
119 std::println(
"{}.obj -> {}",
m_args.moduleName,
m_args.outputFile.string());
122 std::println(std::cerr,
"Could not link program");
131 for (
int i = 1; i < argc; i++)
133 std::string arg = argv[i];
135 if (arg ==
"-h" || arg ==
"--help")
140 else if (arg ==
"-v" || arg ==
"--verbose")
144 else if (arg ==
"-o" || arg ==
"--output")
148 m_args.outputFile = argv[++i];
152 std::println(std::cerr,
"Error: {} requires an argument", arg);
157 else if (arg ==
"-n" || arg ==
"--nologo")
161 else if (arg ==
"-H" || arg ==
"--header-only")
165 else if (arg ==
"-g" || arg ==
"--generate-only")
167 m_args.generateOnly =
true;
169 else if (arg ==
"-O" || arg ==
"--object-only")
173 else if (arg ==
"-m" || arg ==
"--module")
177 m_args.moduleName = argv[++i];
181 std::println(std::cerr,
"Error: {} requires an argument", arg);
186 else if (arg ==
"-c" || arg ==
"--compiler")
190 m_args.compiler = argv[++i];
195 else if ((
m_args.compiler ==
"clang" ||
m_args.compiler ==
"clang++") &&
m_args.linker.empty())
199 else if ((
m_args.compiler ==
"gcc" ||
m_args.compiler ==
"g++") &&
m_args.linker.empty())
206 std::println(std::cerr,
"Error: {} requires an argument", arg);
211 else if (arg ==
"-l" || arg ==
"--linker")
215 m_args.linker = argv[++i];
219 std::println(std::cerr,
"Error: {} requires an argument", arg);
224 else if (arg ==
"-s" || arg ==
"--source")
226 m_args.mainFile = argv[++i];
228 else if (arg[0] ==
'-')
230 std::println(std::cerr,
"Error: Unknown option: {}", arg);
237 if (
m_args.inputFile.empty())
241 std::println(std::cerr,
"Error: Multiple input files specified");
252 std::println(
"Usage:\n"
253 " {} [options] <input.phs>\n\n"
255 " -c, --compiler <name> Compiler to use (default: g++)\n"
256 " -l, --linker <name> Linker to use (default: g++)\n"
257 " -s, --source <name> The source file to compile with\n"
258 " -o, --output <file> Output file\n"
259 " -m, --module <name> Module name for generated code (default: input filename)\n"
260 " -H, --header-only Generate header file only\n"
261 " -g, --generate-only Generate source file only\n"
262 " -O, --object-only Generate and compile to object only\n"
263 " -v, --verbose Enable verbose output\n"
264 " -h, --help Show this help message\n"
265 " -n, --nologo Do not show banner\n\n"
267 " {} program.phs -o program.exe -c clang++ -l lld\n"
268 " {} -O program.phs -o program.obj -c clang++\n"
269 " {} -H program.phs -o program.hpp\n"
270 " {} -g program.phs -o program.cpp", programName, programName, programName, programName, programName);
279 if (sourcePath.extension() ==
".phir")
288 std::println(
"Reading source file...");
290 std::ifstream file(sourcePath);
293 std::println(std::cerr,
"Error: Could not open input file: {}", sourcePath.string());
297 std::stringstream buffer;
298 buffer << file.rdbuf();
299 std::string source = buffer.str();
304 std::println(
"Lexing...");
311 std::println(
"Parsing...");
313 Parser parser(tokens, sourcePath);
314 auto program = parser.
parse();
318 std::println(
"Generating bytecode...");
321 bytecode = codegen.
generate(*program);
326 std::println(std::cerr,
"Error: No instructions generated");
332 std::println(
"Bytecode statistics:\n"
333 " Instructions: {}\n"
342 std::println(
"Generating C++ code...");
345 bool success = cppGen.
generate(bytecode, outputPath,
m_args.moduleName);
349 std::println(std::cerr,
"Error: Failed to generate C++ code");
354 std::println(
"Successfully generated: {}", outputPath.string());
356 catch (
const std::exception &e)
358 std::println(std::cerr,
"Compilation Error: {}", e.what());
366 std::ifstream file(sourcePath);
369 std::println(std::cerr,
"Error: Could not open input file: {}", sourcePath.string());
373 std::stringstream buffer;
374 buffer << file.rdbuf();
375 std::string source = buffer.str();
378 std::ofstream outputFile(outputPath);
379 if (!outputFile.is_open())
381 std::println(std::cerr,
"Error: Could not open output file: {}", outputPath.string());
386 std::filesystem::path headerPath = outputPath;
387 headerPath.replace_extension(
".h");
389 outputFile <<
"#include \"" << headerPath.filename().string() <<
"\"\n";
390 outputFile << source;
398 std::vector<std::string> flags;
399 if (
m_args.compiler ==
"cl")
400 flags = {
"/std:c++20",
"/Ox",
"/D",
"NDEBUG",
"/MD",
"/GL",
"/Gy-",
401 "/GS-",
"/Gw",
"/EHsc",
"/WX-",
"/nologo",
"/c", (
"/Fo" + outputPath.string())};
402 else if (
m_args.compiler ==
"g++" ||
m_args.compiler ==
"clang++")
403 flags = {
"-std=c++20",
408 "-fno-function-sections",
409 "-fno-stack-protector",
414 (
"-o" + outputPath.string())};
418 std::println(std::cerr,
"Error: Unknown compiler: {}",
m_args.compiler);
422 std::string command =
m_args.compiler;
423 for (
const auto &flag : flags)
425 command +=
" " + flag;
428 command +=
" " + sourcePath.string();
429 if (std::system(command.c_str()) != 0)
431 std::println(std::cerr,
"Error: Compilation failed");
440 std::string command =
m_args.linker;
441 command +=
" " + objectPath.string();
442 if (
m_args.linker ==
"link")
443 command +=
" /NOLOGO /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO /out:" + outputPath.string();
444 else if (
m_args.linker ==
"ld" ||
m_args.linker ==
"clang++" ||
m_args.linker ==
"clang")
445 command +=
"-flto -pthread -Wl,--gc-sections -o " + outputPath.string();
448 std::println(std::cerr,
"Error: Unknown linker: {}",
m_args.linker);
451 return (std::system(command.c_str()) == 0);
Code generator for Phasor VM.
Bytecode generate(const AST::Program &program, const std::map< std::string, int > &existingVars={}, int nextVarIdx=0, bool replMode=false)
Generate bytecode from program.
Generates C++ header files with embedded Phasor bytecode.
bool generate(const Bytecode &bytecode, const std::filesystem::path &outputPath, const std::string &moduleName="")
Generate C++ header file from bytecode.
bool generateSource(const std::filesystem::path &sourcePath, const std::filesystem::path &outputPath)
struct Phasor::CppCompiler::Args m_args
bool parseArguments(int argc, char *argv[])
bool showHelp(const std::string &programName)
bool generateHeader(const std::filesystem::path &sourcePath, const std::filesystem::path &outputPath)
bool linkObject(const std::filesystem::path &objectPath, const std::filesystem::path &outputPath)
bool compileSource(const std::filesystem::path &sourcePath, const std::filesystem::path &outputPath)
CppCompiler(int argc, char *argv[])
std::vector< Token > tokenize()
std::unique_ptr< AST::Program > parse()
Phasor IR Serializer/Deserializer.
static Bytecode loadFromFile(const std::filesystem::path &filename)
Load bytecode from .phir file.
The Phasor Programming Language and Runtime.
Complete bytecode structure.
std::vector< Value > constants
Constant pool.
std::map< std::string, int > functionEntries
Function name -> instruction index mapping.
std::map< std::string, int > variables
Variable name -> index mapping.
std::vector< Instruction > instructions
List of instructions.