31 std::println(std::cerr,
"Error: No input file provided\nUse --help for usage information");
37 m_args.mainFile =
"C:\\Program Files\\Phasor VM\\Development\\nativestub.cpp";
39 m_args.mainFile =
"/usr/local/share/phasor/dev/nativestub.cpp";
42 if (
m_args.moduleName.empty())
44 std::filesystem::path inputPath(
m_args.inputFile);
45 m_args.moduleName = inputPath.stem().string();
49 if (
m_args.outputFile.empty())
60 std::println(
"Input file: {}\nOutput file: {}",
m_args.inputFile.string(),
m_args.outputFile.string());
61 if (!
m_args.moduleName.empty())
62 std::println(
"Module name: {}",
m_args.moduleName);
86 std::println(
"Generating wrapper...");
89 std::println(
"{} -> {}.h",
m_args.inputFile.string(),
m_args.moduleName);
92 std::println(std::cerr,
"Error: Could not generate header file");
97 std::println(
"{} -> {}.cpp\n",
m_args.mainFile.filename().string(),
m_args.moduleName);
100 std::println(std::cerr,
"Could not generate source file");
104 std::println(
"Compiling...");
105 std::print(
"[COMPILER] ");
107 std::println(
"{}.cpp -> {}.obj\n",
m_args.moduleName,
m_args.moduleName);
110 std::println(std::cerr,
"Could not compile program");
114 std::println(
"Linking...");
115 std::print(
"[LINKER] ");
117 std::println(
"{}.obj -> {}",
m_args.moduleName,
m_args.outputFile.string());
120 std::println(std::cerr,
"Could not link program");
129 for (
int i = 1; i < argc; i++)
131 std::string arg = argv[i];
133 if (arg ==
"-h" || arg ==
"--help")
138 else if (arg ==
"-v" || arg ==
"--verbose")
142 else if (arg ==
"-o" || arg ==
"--output")
146 m_args.outputFile = argv[++i];
150 std::println(std::cerr,
"Error: {} requires an argument", arg);
155 else if (arg ==
"-H" || arg ==
"--header-only")
159 else if (arg ==
"-g" || arg ==
"--generate-only")
161 m_args.generateOnly =
true;
163 else if (arg ==
"-O" || arg ==
"--object-only")
167 else if (arg ==
"-m" || arg ==
"--module")
171 m_args.moduleName = argv[++i];
175 std::println(std::cerr,
"Error: {} requires an argument", arg);
180 else if (arg ==
"-c" || arg ==
"--compiler")
184 m_args.compiler = argv[++i];
189 else if ((
m_args.compiler ==
"clang" ||
m_args.compiler ==
"clang++") &&
m_args.linker.empty())
193 else if ((
m_args.compiler ==
"gcc" ||
m_args.compiler ==
"g++") &&
m_args.linker.empty())
200 std::println(std::cerr,
"Error: {} requires an argument", arg);
205 else if (arg ==
"-l" || arg ==
"--linker")
209 m_args.linker = argv[++i];
213 std::println(std::cerr,
"Error: {} requires an argument", arg);
218 else if (arg ==
"-s" || arg ==
"--source")
220 m_args.mainFile = argv[++i];
222 else if (arg[0] ==
'-')
224 std::println(std::cerr,
"Error: Unknown option: {}", arg);
231 if (
m_args.inputFile.empty())
235 std::println(std::cerr,
"Error: Multiple input files specified");
246 std::println(
"Phasor C++ Bytecode Embedder v{}\n"
247 "(C) 2026 Daniel McGuire - Licensed under Apache 2.0\n\n"
249 " {} [options] <input.phs>\n\n"
251 " -c, --compiler <name> Compiler to use (default: g++)\n"
252 " -l, --linker <name> Linker to use (default: g++)\n"
253 " -s, --source <name> The source file to compile with\n"
254 " -o, --output <file> Output file\n"
255 " -m, --module <name> Module name for generated code (default: input filename)\n"
256 " -H, --header-only Generate header file only\n"
257 " -g, --generate-only Generate source file only\n"
258 " -O, --object-only Generate and compile to object only\n"
259 " -v, --verbose Enable verbose output\n"
260 " -h, --help Show this help message\n"
262 " {} program.phs -o program.exe -c clang++ -l lld\n"
263 " {} -O program.phs -o program.obj -c clang++\n"
264 " {} -H program.phs -o program.hpp\n"
265 " {} -g program.phs -o program.cpp",
266 PHASOR_VERSION_STRING, programName, programName, programName, programName, programName);
275 if (sourcePath.extension() ==
".phir")
284 std::println(
"Reading source file...");
286 std::ifstream file(sourcePath);
289 std::println(std::cerr,
"Error: Could not open input file: {}", sourcePath.string());
293 std::stringstream buffer;
294 buffer << file.rdbuf();
295 std::string source = buffer.str();
300 std::println(
"Lexing...");
307 std::println(
"Parsing...");
309 Parser parser(tokens, sourcePath);
310 auto program = parser.
parse();
314 std::println(
"Generating bytecode...");
317 bytecode = codegen.
generate(*program);
322 std::println(std::cerr,
"Error: No instructions generated");
328 std::println(
"Bytecode statistics:\n"
329 " Instructions: {}\n"
339 std::println(
"Generating C++ code...");
342 bool success = cppGen.
generate(bytecode, outputPath,
m_args.moduleName);
346 std::println(std::cerr,
"Error: Failed to generate C++ code");
351 std::println(
"Successfully generated: {}", outputPath.string());
353 catch (
const std::exception &e)
355 std::println(std::cerr,
"Compilation Error: {}", e.what());
363 std::ifstream file(sourcePath);
366 std::println(std::cerr,
"Error: Could not open input file: {}", sourcePath.string());
370 std::stringstream buffer;
371 buffer << file.rdbuf();
372 std::string source = buffer.str();
375 std::ofstream outputFile(outputPath);
376 if (!outputFile.is_open())
378 std::println(std::cerr,
"Error: Could not open output file: {}", outputPath.string());
383 std::filesystem::path headerPath = outputPath;
384 headerPath.replace_extension(
".h");
386 outputFile <<
"#include \"" << headerPath.filename().string() <<
"\"\n";
387 outputFile << source;
395 std::vector<std::string> flags;
396 if (
m_args.compiler ==
"cl")
397 flags = {
"/std:c++20",
"/Ox",
"/D",
"NDEBUG",
"/MD",
"/GL",
"/Gy-",
398 "/GS-",
"/Gw",
"/EHsc",
"/WX-",
"/nologo",
"/c", (
"/Fo" + outputPath.string())};
399 else if (
m_args.compiler ==
"g++" ||
m_args.compiler ==
"clang++")
400 flags = {
"-std=c++20",
405 "-fno-function-sections",
406 "-fno-stack-protector",
411 (
"-o" + outputPath.string())};
415 std::println(std::cerr,
"Error: Unknown compiler: {}",
m_args.compiler);
419 std::string command =
m_args.compiler;
420 for (
const auto &flag : flags)
422 command +=
" " + flag;
425 command +=
" " + sourcePath.string();
426 if (std::system(command.c_str()) != 0)
428 std::println(std::cerr,
"Error: Compilation failed");
437 std::string command =
m_args.linker;
438 command +=
" " + objectPath.string();
439 if (
m_args.linker ==
"link")
440 command +=
" /NOLOGO /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO /out:" + outputPath.string();
441 else if (
m_args.linker ==
"ld" ||
m_args.linker ==
"clang++" ||
m_args.linker ==
"clang")
442 command +=
"-flto -pthread -Wl,--gc-sections -o " + outputPath.string();
445 std::println(std::cerr,
"Error: Unknown linker: {}",
m_args.linker);
448 return (std::system(command.c_str()) == 0);
Code generator for Phasor VM.
Bytecode generate(const AST::Program &program, const std::unordered_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::unordered_map< std::string, int > variables
Variable name -> index mapping.
std::vector< Instruction > instructions
List of instructions.
std::unordered_map< std::string, int > functionEntries
Function name -> instruction index mapping.
std::vector< Value > constants
Constant pool.