Change clang-command to ld, add util.rs

This commit is contained in:
Sofia 2025-06-25 21:38:30 +03:00
parent d0aa3e1410
commit 922afaa672
4 changed files with 117 additions and 51 deletions

View File

@ -7,5 +7,40 @@
export .env
cargo run --example libtest && \
clang++ main.cpp hello.o -o main && \
./main
# clang++ main.cpp hello.o -o main && \
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
-o main /usr/lib/crt1.o hello.o -lc && \
./main ; echo $?
## Command from: clang -v hello.o -o test
## Original command:
# ld --hash-style=gnu \
# --build-id \
# --eh-frame-hdr \
# -m elf_x86_64 \
# -pie \
# -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
# -o test \
# /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.1.1/../../../../lib64/Scrt1.o \
# /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.1.1/../../../../lib64/crti.o \
# /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.1.1/crtbeginS.o \
# -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.1.1 \
# -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.1.1/../../../../lib64 \
# -L/lib/../lib64 \
# -L/usr/lib/../lib64 \
# -L/lib \
# -L/usr/lib \
# hello.o \
# -lgcc \
# --as-needed \
# -lgcc_s \
# --no-as-needed \
# -lc \
# -lgcc \
# --as-needed \
# -lgcc_s \
# --no-as-needed \
# /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.1.1/crtendS.o \
# /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.1.1/../../../../lib64/crtn.o \
# && \

View File

@ -1,10 +1,16 @@
use reid_lib::*;
pub fn main() {
// Notes from inkwell:
// - Creating new values should probably just be functions in the context
// - Creating functions should probably be functions from module
// - Builder could well be it's own struct
// - Although, I do like the fact where blocks move the builder by itself..
let context = IRContext::new();
let module = IRModule::new(&context, &"hello".to_owned());
let mainfunc = IRFunction::new(&module, &"mainfunc".to_owned());
let mainfunc = IRFunction::new(&module, &"main".to_owned());
let secondary_func = IRFunction::new(&module, &"secondary".to_owned());

View File

@ -1,46 +1,22 @@
use std::ffi::{CStr, CString, c_char};
use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::mem;
use std::ptr::{null, null_mut};
use std::ptr::null_mut;
use llvm_sys::analysis::LLVMVerifyModule;
use llvm_sys::target::{
LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllTargetInfos,
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVM_InitializeNativeAsmParser,
LLVM_InitializeNativeTarget, LLVMInitializeAMDGPUAsmPrinter, LLVMInitializeX86Target,
LLVMInitializeX86TargetInfo, LLVMInitializeX86TargetMC, LLVMSetModuleDataLayout,
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout,
};
use llvm_sys::target_machine::{
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
LLVMGetDefaultTargetTriple, LLVMGetFirstTarget, LLVMGetHostCPUFeatures, LLVMGetHostCPUName,
LLVMGetTargetFromTriple, LLVMTargetMachineEmitToFile, LLVMTargetMachineEmitToMemoryBuffer,
};
use llvm_sys::transforms::pass_manager_builder::{
LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderPopulateModulePassManager,
LLVMPassManagerBuilderSetOptLevel,
LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToFile,
};
use llvm_sys::{
LLVMBasicBlock, LLVMBuilder, LLVMContext, LLVMModule, LLVMType, LLVMValue, core::*, prelude::*,
};
use util::{ErrorMessageHolder, from_cstring, into_cstring};
fn into_cstring<T: Into<String>>(value: T) -> CString {
let string = value.into();
unsafe { CString::from_vec_with_nul_unchecked((string + "\0").into_bytes()) }
}
fn from_cstring(value: *mut c_char) -> Option<String> {
if value.is_null() {
None
} else {
unsafe { CString::from_raw(value).into_string().ok() }
}
}
fn cstring_to_err(value: *mut c_char) -> Result<(), String> {
from_cstring(value)
.filter(|s| !s.is_empty())
.map_or(Ok(()), |s| Err(s))
}
mod util;
pub trait IRType {
const SIGNED: LLVMBool;
@ -131,12 +107,6 @@ impl<'a> IRModule<'a> {
pub fn print_to_string(&self) -> Result<&str, String> {
unsafe {
// let pmb = LLVMPassManagerBuilderCreate();
// LLVMPassManagerBuilderSetOptLevel(pmb, 0);
// let pm = LLVMCreatePassManager();
// LLVMPassManagerBuilderPopulateModulePassManager(pmb, pm);
// println!("{}", LLVMRunPassManager(pm, self.module));
LLVM_InitializeAllTargets();
LLVM_InitializeAllTargetInfos();
LLVM_InitializeAllTargetMCs();
@ -146,10 +116,14 @@ impl<'a> IRModule<'a> {
let triple = LLVMGetDefaultTargetTriple();
let mut target: _ = null_mut();
let mut err: _ = null_mut();
LLVMGetTargetFromTriple(c"x86_64-unknown-linux-gnu".as_ptr(), &mut target, &mut err);
let mut err = ErrorMessageHolder::null();
LLVMGetTargetFromTriple(
c"x86_64-unknown-linux-gnu".as_ptr(),
&mut target,
err.borrow_mut(),
);
println!("{:?}, {:?}", from_cstring(triple), target);
cstring_to_err(err).unwrap();
err.into_result().unwrap();
let target_machine = LLVMCreateTargetMachine(
target,
@ -164,33 +138,33 @@ impl<'a> IRModule<'a> {
let data_layout = LLVMCreateTargetDataLayout(target_machine);
LLVMSetModuleDataLayout(self.module, data_layout);
let mut err = null_mut();
let mut err = ErrorMessageHolder::null();
LLVMVerifyModule(
self.module,
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
&mut err,
err.borrow_mut(),
);
cstring_to_err(err).unwrap();
err.into_result().unwrap();
let mut err = null_mut();
let mut err = ErrorMessageHolder::null();
LLVMTargetMachineEmitToFile(
target_machine,
self.module,
CString::new("hello.asm").unwrap().into_raw(),
LLVMCodeGenFileType::LLVMAssemblyFile,
&mut err,
err.borrow_mut(),
);
cstring_to_err(err).unwrap();
err.into_result().unwrap();
let mut err = null_mut();
let mut err = ErrorMessageHolder::null();
LLVMTargetMachineEmitToFile(
target_machine,
self.module,
CString::new("hello.o").unwrap().into_raw(),
LLVMCodeGenFileType::LLVMObjectFile,
&mut err,
err.borrow_mut(),
);
cstring_to_err(err).unwrap();
err.into_result().unwrap();
Ok(CStr::from_ptr(LLVMPrintModuleToString(self.module))
.to_str()

51
reid-llvm-lib/src/util.rs Normal file
View File

@ -0,0 +1,51 @@
use std::{
ffi::{CString, c_char},
ptr::null_mut,
};
use llvm_sys::error::LLVMDisposeErrorMessage;
pub fn into_cstring<T: Into<String>>(value: T) -> CString {
let string = value.into();
unsafe { CString::from_vec_with_nul_unchecked((string + "\0").into_bytes()) }
}
pub fn from_cstring(value: *mut c_char) -> Option<String> {
if value.is_null() {
None
} else {
unsafe { CString::from_raw(value).into_string().ok() }
}
}
fn cstring_to_err(value: *mut c_char) -> Result<(), String> {
from_cstring(value)
.filter(|s| !s.is_empty())
.map_or(Ok(()), |s| Err(s))
}
pub struct ErrorMessageHolder(*mut c_char);
impl ErrorMessageHolder {
pub fn null() -> Self {
ErrorMessageHolder(null_mut())
}
pub fn borrow_mut(&mut self) -> *mut *mut c_char {
&mut self.0
}
pub fn into_result(&self) -> Result<(), String> {
cstring_to_err(self.0)
}
}
impl Drop for ErrorMessageHolder {
fn drop(&mut self) {
unsafe {
if !self.0.is_null() {
LLVMDisposeErrorMessage(self.0);
}
}
}
}