Meta Changes from #321 #325
|
@ -660,7 +660,8 @@ impl Nac3 {
|
|||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
pass_options.set_merge_functions(true);
|
||||
let result = main.run_passes("default<O3>", &target_machine, pass_options);
|
||||
let passes = format!("default<O{}>", self.llvm_options.opt_level as u32);
|
||||
let result = main.run_passes(passes.as_str(), &target_machine, pass_options);
|
||||
if let Err(err) = result {
|
||||
panic!("Failed to run optimization for module `main`: {}", err.to_string());
|
||||
}
|
||||
|
|
|
@ -365,6 +365,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
let mut return_slot = None;
|
||||
if fun.count_params() > 0 {
|
||||
let sret_id = Attribute::get_named_enum_kind_id("sret");
|
||||
let byref_id = Attribute::get_named_enum_kind_id("byref");
|
||||
let byval_id = Attribute::get_named_enum_kind_id("byval");
|
||||
|
||||
let offset = if fun.get_enum_attribute(AttributeLoc::Param(0), sret_id).is_some() {
|
||||
|
@ -376,7 +377,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
0
|
||||
};
|
||||
for (i, param) in params.iter().enumerate() {
|
||||
if fun.get_enum_attribute(AttributeLoc::Param((i + offset) as u32), byval_id).is_some() {
|
||||
let loc = AttributeLoc::Param((i + offset) as u32);
|
||||
if fun.get_enum_attribute(loc, byref_id).is_some() || fun.get_enum_attribute(loc, byval_id).is_some() {
|
||||
// lazy update
|
||||
if loc_params.is_empty() {
|
||||
loc_params.extend(params[0..i+offset].iter().copied());
|
||||
|
@ -745,11 +747,11 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||
Some(ctx.get_llvm_abi_type(generator, fun.0.ret))
|
||||
};
|
||||
let has_sret = ret_type.map_or(false, |ret_type| need_sret(ctx.ctx, ret_type));
|
||||
let mut byvals = Vec::new();
|
||||
let mut byrefs = Vec::new();
|
||||
let mut params = args.iter().enumerate()
|
||||
.map(|(i, arg)| match ctx.get_llvm_abi_type(generator, arg.ty) {
|
||||
BasicTypeEnum::StructType(ty) if is_extern => {
|
||||
byvals.push((i, ty));
|
||||
byrefs.push((i, ty));
|
||||
ty.ptr_type(AddressSpace::default()).into()
|
||||
},
|
||||
x => x
|
||||
|
@ -770,9 +772,19 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||
} else {
|
||||
0
|
||||
};
|
||||
for (i, ty) in byvals {
|
||||
fun_val.add_attribute(AttributeLoc::Param((i as u32) + offset),
|
||||
ctx.ctx.create_type_attribute(Attribute::get_named_enum_kind_id("byval"), ty.as_any_type_enum()));
|
||||
|
||||
// The attribute ID used to mark arguments of a structure type.
|
||||
// Structure-Typed parameters of extern functions must **not** be marked as `byval`, as
|
||||
// `byval` explicitly specifies that the argument is to be passed on the stack, which breaks
|
||||
// on most ABIs where the first several arguments are expected to be passed in registers.
|
||||
let passing_attr_id = Attribute::get_named_enum_kind_id(
|
||||
if is_extern { "byref" } else { "byval" }
|
||||
);
|
||||
for (i, ty) in byrefs {
|
||||
fun_val.add_attribute(
|
||||
AttributeLoc::Param((i as u32) + offset),
|
||||
ctx.ctx.create_type_attribute(passing_attr_id, ty.as_any_type_enum())
|
||||
);
|
||||
}
|
||||
fun_val
|
||||
});
|
||||
|
|
|
@ -328,7 +328,6 @@ impl WorkerRegistry {
|
|||
self.llvm_options.opt_level
|
||||
).expect(format!("could not create target machine from properties {:?}", self.llvm_options.target).as_str());
|
||||
let passes = format!("default<O{}>", self.llvm_options.opt_level as u32);
|
||||
|
||||
let result = module.run_passes(passes.as_str(), &target_machine, pass_options);
|
||||
if let Err(err) = result {
|
||||
panic!("Failed to run optimization for module `{}`: {}",
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::process::exit;
|
||||
|
||||
mod cslice {
|
||||
// copied from https://github.com/dherman/cslice
|
||||
use std::marker::PhantomData;
|
||||
|
@ -55,6 +59,14 @@ pub extern "C" fn output_asciiart(x: i32) {
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn output_str(x: &cslice::CSlice<u8>) {
|
||||
for e in x.as_ref().iter() {
|
||||
print!("{}", char::from(*e));
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn output_int32_list(x: &cslice::CSlice<i32>) {
|
||||
print!("[");
|
||||
|
@ -75,8 +87,14 @@ pub extern "C" fn __nac3_personality(_state: u32, _exception_object: u32, _conte
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __nac3_raise(_state: u32, _exception_object: u32, _context: u32) -> u32 {
|
||||
unimplemented!();
|
||||
pub extern "C" fn __nac3_raise(state: u32, exception_object: u32, context: u32) -> u32 {
|
||||
writeln!(io::stderr(),
|
||||
"__nac3_raise(state: {:#010x}, exception_object: {:#010x}, context: {:#010x})",
|
||||
state,
|
||||
exception_object,
|
||||
context
|
||||
).unwrap();
|
||||
exit(101);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
|
@ -58,7 +58,8 @@ def patch(module):
|
|||
"output_int32_list",
|
||||
"output_uint32",
|
||||
"output_uint64",
|
||||
"output_float64"
|
||||
"output_float64",
|
||||
"output_str",
|
||||
}:
|
||||
return print
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
@extern
|
||||
def output_int32(x: int32):
|
||||
...
|
||||
|
||||
@extern
|
||||
def output_int64(x: int64):
|
||||
...
|
||||
|
||||
@extern
|
||||
def output_uint32(x: uint32):
|
||||
...
|
||||
|
||||
@extern
|
||||
def output_uint64(x: uint64):
|
||||
...
|
||||
|
||||
@extern
|
||||
def output_int32_list(x: list[int32]):
|
||||
...
|
||||
|
||||
@extern
|
||||
def output_asciiart(x: int32):
|
||||
...
|
||||
|
||||
@extern
|
||||
def output_str(x: str):
|
||||
...
|
||||
|
||||
def test_output_int32():
|
||||
output_int32(-128)
|
||||
|
||||
def test_output_int64():
|
||||
output_int64(int64(-256))
|
||||
|
||||
def test_output_uint32():
|
||||
output_uint32(uint32(128))
|
||||
|
||||
def test_output_uint64():
|
||||
output_uint64(uint64(256))
|
||||
|
||||
def test_output_asciiart():
|
||||
for i in range(17):
|
||||
output_asciiart(i)
|
||||
output_asciiart(0)
|
||||
|
||||
def test_output_int32_list():
|
||||
output_int32_list([0, 1, 3, 5, 10])
|
||||
|
||||
def test_output_str_family():
|
||||
output_str("hello world")
|
||||
|
||||
def run() -> int32:
|
||||
test_output_int32()
|
||||
test_output_int64()
|
||||
test_output_uint32()
|
||||
test_output_uint64()
|
||||
test_output_asciiart()
|
||||
test_output_int32_list()
|
||||
test_output_str_family()
|
||||
return 0
|
|
@ -370,7 +370,8 @@ fn main() {
|
|||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
pass_options.set_merge_functions(true);
|
||||
let result = main.run_passes("default<O3>", &target_machine, pass_options);
|
||||
let passes = format!("default<O{}>", opt_level as u32);
|
||||
let result = main.run_passes(passes.as_str(), &target_machine, pass_options);
|
||||
if let Err(err) = result {
|
||||
panic!("Failed to run optimization for module `main`: {}", err.to_string());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue