Change clang-command to ld, add util.rs
This commit is contained in:
parent
d0aa3e1410
commit
922afaa672
39
libtest.sh
39
libtest.sh
@ -7,5 +7,40 @@
|
|||||||
|
|
||||||
export .env
|
export .env
|
||||||
cargo run --example libtest && \
|
cargo run --example libtest && \
|
||||||
clang++ main.cpp hello.o -o main && \
|
# clang++ main.cpp hello.o -o main && \
|
||||||
./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 \
|
||||||
|
# && \
|
@ -1,10 +1,16 @@
|
|||||||
use reid_lib::*;
|
use reid_lib::*;
|
||||||
|
|
||||||
pub fn main() {
|
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 context = IRContext::new();
|
||||||
let module = IRModule::new(&context, &"hello".to_owned());
|
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());
|
let secondary_func = IRFunction::new(&module, &"secondary".to_owned());
|
||||||
|
|
||||||
|
@ -1,46 +1,22 @@
|
|||||||
use std::ffi::{CStr, CString, c_char};
|
use std::ffi::{CStr, CString};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::ptr::null_mut;
|
||||||
use std::ptr::{null, null_mut};
|
|
||||||
|
|
||||||
use llvm_sys::analysis::LLVMVerifyModule;
|
use llvm_sys::analysis::LLVMVerifyModule;
|
||||||
use llvm_sys::target::{
|
use llvm_sys::target::{
|
||||||
LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllTargetInfos,
|
LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllTargetInfos,
|
||||||
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVM_InitializeNativeAsmParser,
|
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout,
|
||||||
LLVM_InitializeNativeTarget, LLVMInitializeAMDGPUAsmPrinter, LLVMInitializeX86Target,
|
|
||||||
LLVMInitializeX86TargetInfo, LLVMInitializeX86TargetMC, LLVMSetModuleDataLayout,
|
|
||||||
};
|
};
|
||||||
use llvm_sys::target_machine::{
|
use llvm_sys::target_machine::{
|
||||||
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
|
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
|
||||||
LLVMGetDefaultTargetTriple, LLVMGetFirstTarget, LLVMGetHostCPUFeatures, LLVMGetHostCPUName,
|
LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToFile,
|
||||||
LLVMGetTargetFromTriple, LLVMTargetMachineEmitToFile, LLVMTargetMachineEmitToMemoryBuffer,
|
|
||||||
};
|
|
||||||
use llvm_sys::transforms::pass_manager_builder::{
|
|
||||||
LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderPopulateModulePassManager,
|
|
||||||
LLVMPassManagerBuilderSetOptLevel,
|
|
||||||
};
|
};
|
||||||
use llvm_sys::{
|
use llvm_sys::{
|
||||||
LLVMBasicBlock, LLVMBuilder, LLVMContext, LLVMModule, LLVMType, LLVMValue, core::*, prelude::*,
|
LLVMBasicBlock, LLVMBuilder, LLVMContext, LLVMModule, LLVMType, LLVMValue, core::*, prelude::*,
|
||||||
};
|
};
|
||||||
|
use util::{ErrorMessageHolder, from_cstring, into_cstring};
|
||||||
|
|
||||||
fn into_cstring<T: Into<String>>(value: T) -> CString {
|
mod util;
|
||||||
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))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IRType {
|
pub trait IRType {
|
||||||
const SIGNED: LLVMBool;
|
const SIGNED: LLVMBool;
|
||||||
@ -131,12 +107,6 @@ impl<'a> IRModule<'a> {
|
|||||||
|
|
||||||
pub fn print_to_string(&self) -> Result<&str, String> {
|
pub fn print_to_string(&self) -> Result<&str, String> {
|
||||||
unsafe {
|
unsafe {
|
||||||
// let pmb = LLVMPassManagerBuilderCreate();
|
|
||||||
// LLVMPassManagerBuilderSetOptLevel(pmb, 0);
|
|
||||||
// let pm = LLVMCreatePassManager();
|
|
||||||
// LLVMPassManagerBuilderPopulateModulePassManager(pmb, pm);
|
|
||||||
// println!("{}", LLVMRunPassManager(pm, self.module));
|
|
||||||
|
|
||||||
LLVM_InitializeAllTargets();
|
LLVM_InitializeAllTargets();
|
||||||
LLVM_InitializeAllTargetInfos();
|
LLVM_InitializeAllTargetInfos();
|
||||||
LLVM_InitializeAllTargetMCs();
|
LLVM_InitializeAllTargetMCs();
|
||||||
@ -146,10 +116,14 @@ impl<'a> IRModule<'a> {
|
|||||||
let triple = LLVMGetDefaultTargetTriple();
|
let triple = LLVMGetDefaultTargetTriple();
|
||||||
|
|
||||||
let mut target: _ = null_mut();
|
let mut target: _ = null_mut();
|
||||||
let mut err: _ = null_mut();
|
let mut err = ErrorMessageHolder::null();
|
||||||
LLVMGetTargetFromTriple(c"x86_64-unknown-linux-gnu".as_ptr(), &mut target, &mut err);
|
LLVMGetTargetFromTriple(
|
||||||
|
c"x86_64-unknown-linux-gnu".as_ptr(),
|
||||||
|
&mut target,
|
||||||
|
err.borrow_mut(),
|
||||||
|
);
|
||||||
println!("{:?}, {:?}", from_cstring(triple), target);
|
println!("{:?}, {:?}", from_cstring(triple), target);
|
||||||
cstring_to_err(err).unwrap();
|
err.into_result().unwrap();
|
||||||
|
|
||||||
let target_machine = LLVMCreateTargetMachine(
|
let target_machine = LLVMCreateTargetMachine(
|
||||||
target,
|
target,
|
||||||
@ -164,33 +138,33 @@ impl<'a> IRModule<'a> {
|
|||||||
let data_layout = LLVMCreateTargetDataLayout(target_machine);
|
let data_layout = LLVMCreateTargetDataLayout(target_machine);
|
||||||
LLVMSetModuleDataLayout(self.module, data_layout);
|
LLVMSetModuleDataLayout(self.module, data_layout);
|
||||||
|
|
||||||
let mut err = null_mut();
|
let mut err = ErrorMessageHolder::null();
|
||||||
LLVMVerifyModule(
|
LLVMVerifyModule(
|
||||||
self.module,
|
self.module,
|
||||||
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
|
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(
|
LLVMTargetMachineEmitToFile(
|
||||||
target_machine,
|
target_machine,
|
||||||
self.module,
|
self.module,
|
||||||
CString::new("hello.asm").unwrap().into_raw(),
|
CString::new("hello.asm").unwrap().into_raw(),
|
||||||
LLVMCodeGenFileType::LLVMAssemblyFile,
|
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(
|
LLVMTargetMachineEmitToFile(
|
||||||
target_machine,
|
target_machine,
|
||||||
self.module,
|
self.module,
|
||||||
CString::new("hello.o").unwrap().into_raw(),
|
CString::new("hello.o").unwrap().into_raw(),
|
||||||
LLVMCodeGenFileType::LLVMObjectFile,
|
LLVMCodeGenFileType::LLVMObjectFile,
|
||||||
&mut err,
|
err.borrow_mut(),
|
||||||
);
|
);
|
||||||
cstring_to_err(err).unwrap();
|
err.into_result().unwrap();
|
||||||
|
|
||||||
Ok(CStr::from_ptr(LLVMPrintModuleToString(self.module))
|
Ok(CStr::from_ptr(LLVMPrintModuleToString(self.module))
|
||||||
.to_str()
|
.to_str()
|
||||||
|
51
reid-llvm-lib/src/util.rs
Normal file
51
reid-llvm-lib/src/util.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user