// pactor64-llc — LLVM 21 codegen tool for Pactor64 // Freestanding: uses Linux x86-64 syscalls only, no libc dependency // Compatible with Pactor64's syscall ABI #include #include #include #include #include #include #include #include #include #include #include using namespace llvm; // Raw Linux x86-64 syscalls static long sys_write(int fd, const void *buf, unsigned long len) { long ret; __asm__ volatile ("syscall" : "=a"(ret) : "a"(1), "D"(fd), "S"(buf), "d"(len) : "rcx", "r11", "memory"); return ret; } static void sys_exit(int code) __attribute__((noreturn)); static void sys_exit(int code) { __asm__ volatile ("syscall" :: "a"(60), "D"(code)); __builtin_unreachable(); } static void *sys_brk(void *addr) { void *ret; __asm__ volatile ("syscall" : "=a"(ret) : "a"(12), "D"(addr) : "rcx", "r11", "memory"); return ret; } static void my_puts(const char *s) { const char *p = s; while (*p) p++; sys_write(1, s, p - s); } // Simple heap allocator using brk static void *heap_cur = nullptr; static void *heap_end = nullptr; static void *my_alloc(unsigned long sz) { sz = (sz + 15) & ~15UL; if (!heap_cur) { heap_cur = sys_brk(nullptr); heap_end = heap_cur; } if ((char*)heap_cur + sz > (char*)heap_end) { heap_end = sys_brk((char*)heap_end + sz + 1048576); if ((char*)heap_end < (char*)heap_cur + sz) { my_puts("OOM!\n"); sys_exit(1); } } void *r = heap_cur; heap_cur = (char*)heap_cur + sz; return r; } void *operator new(unsigned long s) { return my_alloc(s); } void *operator new[](unsigned long s) { return my_alloc(s); } void operator delete(void *p) noexcept { (void)p; } void operator delete[](void *p) noexcept { (void)p; } void operator delete(void *p, unsigned long) noexcept { (void)p; } void operator delete[](void *p, unsigned long) noexcept { (void)p; } extern "C" { int __cxa_atexit(void (*)(void*), void*, void*) { return 0; } void __cxa_pure_virtual() { sys_exit(99); } void *__dso_handle = nullptr; } extern "C" void _start() { my_puts("pactor64-llc: LLVM " LLVM_VERSION_STRING "\n"); my_puts("Default target: x86_64-pactor64-elf\n\n"); LLVMInitializeX86TargetInfo(); LLVMInitializeX86Target(); LLVMInitializeX86AsmPrinter(); LLVMContext Ctx; Module M("pactor64_demo", Ctx); FunctionType *FT = FunctionType::get( Type::getInt64Ty(Ctx), {Type::getInt64Ty(Ctx), Type::getInt64Ty(Ctx)}, false); Function *F = Function::Create(FT, Function::ExternalLinkage, "add", M); BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F); IRBuilder<> Builder(BB); auto Args = F->arg_begin(); Value *A = &*Args++; Value *B = &*Args; Builder.CreateRet(Builder.CreateAdd(A, B, "sum")); std::string Error; const Target *T = TargetRegistry::lookupTarget("x86_64", Error); if (!T) { my_puts("Error: no target\n"); sys_exit(1); } Triple TT("x86_64-unknown-elf"); TargetMachine *TM = T->createTargetMachine(TT, "generic", "", TargetOptions(), Reloc::PIC_); M.setDataLayout(TM->createDataLayout()); SmallVector Buf; raw_svector_ostream SOS(Buf); legacy::PassManager PM; TM->addPassesToEmitFile(PM, SOS, nullptr, CodeGenFileType::AssemblyFile); PM.run(M); my_puts("--- LLVM x86-64 Codegen Output ---\n"); sys_write(1, Buf.data(), Buf.size_in_bytes()); my_puts("\n--- End ---\n"); sys_exit(0); }