From 258aa4c9d61e86198a767392f082797969d85a82 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Fri, 27 May 2022 03:02:48 +0800 Subject: [PATCH] messy --- flake.nix | 2 + nac3artiq/src/lib.rs | 79 ++++++++---- nac3core/src/codegen/expr.rs | 6 +- nac3core/src/codegen/mod.rs | 149 ++++++++++++++++------ nac3standalone/demo/run_demo.sh | 4 +- nac3standalone/src/main.rs | 210 +++++++++++++++++++++++++++++++- 6 files changed, 381 insertions(+), 69 deletions(-) diff --git a/flake.nix b/flake.nix index 813d7ea5..7517aee7 100644 --- a/flake.nix +++ b/flake.nix @@ -158,7 +158,9 @@ cargo-insta clippy rustfmt + lldb_14 ]; + RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; }; devShells.x86_64-linux.msys2 = pkgs.mkShell { name = "nac3-dev-shell-msys2"; diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index 3c006350..c2b331b4 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -1,5 +1,6 @@ use std::collections::{HashMap, HashSet}; use std::fs; +use std::io::Write; use std::process::Command; use std::rc::Rc; use std::sync::Arc; @@ -763,34 +764,54 @@ impl Nac3 { let membuffer = membuffers.clone(); let f = Arc::new(WithCall::new(Box::new(move |module| { + // println!("\n\n--------------\n{}\n--------------\n", module.print_to_string().to_string()); let buffer = module.write_bitcode_to_memory(); let buffer = buffer.as_slice().into(); membuffer.lock().push(buffer); }))); let size_t = if self.isa == Isa::Host { 64 } else { 32 }; - let thread_names: Vec = (0..4).map(|_| "main".to_string()).collect(); + print!("input number of thread: "); + std::io::stdout().flush().unwrap(); + let mut buffer = String::with_capacity(2); + // std::io::stdin().read_line(&mut buffer)?; + // println!("{} as input", buffer); + let num_thread = buffer.trim().parse::().unwrap_or_else(|_| {/* println!("using default (4 thread)"); */4}); + let thread_names: Vec = (0..num_thread).map(|_| "main".to_string()).collect(); + // println!("number of threads: {}", thread_names.len()); + // let thread_names: Vec = (0..4).map(|_| "main".to_string()).collect(); let threads: Vec<_> = thread_names .iter() .map(|s| Box::new(ArtiqCodeGenerator::new(s.to_string(), size_t, self.time_fns))) .collect(); - - let membuffer = membuffers.clone(); + println!("------0:"); + // let membuffer = membuffers.clone(); py.allow_threads(|| { let (registry, handles) = WorkerRegistry::create_workers(threads, top_level.clone(), f); registry.add_task(task); registry.wait_tasks_complete(handles); + println!("------1:"); - let mut generator = ArtiqCodeGenerator::new("attributes_writeback".to_string(), size_t, self.time_fns); - let context = inkwell::context::Context::create(); - let module = context.create_module("attributes_writeback"); - let builder = context.create_builder(); - let (_, module, _) = gen_func_impl(&context, &mut generator, ®istry, builder, module, - attributes_writeback_task, |generator, ctx| { - attributes_writeback(ctx, generator, inner_resolver.as_ref(), host_attributes) - }).unwrap(); - let buffer = module.write_bitcode_to_memory(); - let buffer = buffer.as_slice().into(); - membuffer.lock().push(buffer); + // let mut generator = ArtiqCodeGenerator::new("attributes_writeback".to_string(), size_t, self.time_fns); + // let context = inkwell::context::Context::create(); + // let module = context.create_module("attributes_writeback"); + // module.add_basic_value_flag( + // "Debug Info Version", + // inkwell::module::FlagBehavior::Warning, + // context.i32_type().const_int(3, false), + // ); + // module.add_basic_value_flag( + // "Dwarf Version", + // inkwell::module::FlagBehavior::Warning, + // context.i32_type().const_int(4, false), + // ); + // let builder = context.create_builder(); + // let (_, module, _) = gen_func_impl(&context, &mut generator, ®istry, builder, module, + // attributes_writeback_task, |generator, ctx| { + // attributes_writeback(ctx, generator, inner_resolver.as_ref(), host_attributes) + // }).unwrap(); + // let buffer = module.write_bitcode_to_memory(); + // let buffer = buffer.as_slice().into(); + // membuffer.lock().push(buffer); }); let context = inkwell::context::Context::create(); @@ -798,21 +819,25 @@ impl Nac3 { let main = context .create_module_from_ir(MemoryBuffer::create_from_memory_range(&buffers[0], "main")) .unwrap(); + // println!(":1: {}", buffers.len()); for buffer in buffers.iter().skip(1) { let other = context .create_module_from_ir(MemoryBuffer::create_from_memory_range(buffer, "main")) .unwrap(); + // println!(":2:"); main.link_in_module(other) .map_err(|err| CompileError::new_err(err.to_string()))?; } - let builder = context.create_builder(); - let modinit_return = main.get_function("__modinit__").unwrap().get_last_basic_block().unwrap().get_terminator().unwrap(); - builder.position_before(&modinit_return); - builder.build_call(main.get_function("attributes_writeback").unwrap(), &[], "attributes_writeback"); + // let builder = context.create_builder(); + // let modinit_return = main.get_function("__modinit__").unwrap().get_last_basic_block().unwrap().get_terminator().unwrap(); + // builder.position_before(&modinit_return); + // builder.build_call(main.get_function("attributes_writeback").unwrap(), &[], "attributes_writeback"); - main.link_in_module(load_irrt(&context)) - .map_err(|err| CompileError::new_err(err.to_string()))?; + // main.link_in_module(load_irrt(&context)) + // .map_err(|err| CompileError::new_err(err.to_string()))?; + + // println!(":3:"); let mut function_iter = main.get_first_function(); while let Some(func) = function_iter { @@ -822,12 +847,14 @@ impl Nac3 { function_iter = func.get_next_function(); } - let builder = PassManagerBuilder::create(); - builder.set_optimization_level(OptimizationLevel::Aggressive); - let passes = PassManager::create(()); - builder.set_inliner_with_threshold(255); - builder.populate_module_pass_manager(&passes); - passes.run_on(&main); + // let builder = PassManagerBuilder::create(); + // builder.set_optimization_level(OptimizationLevel::Aggressive); + // let passes = PassManager::create(()); + // builder.set_inliner_with_threshold(255); + // builder.populate_module_pass_manager(&passes); + // passes.run_on(&main); + + // println!("\n\n==========={}\n=============", main.print_to_string().to_string()); let (triple, features) = match isa { Isa::Host => ( diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 964c88b3..ae2e6a1e 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -165,6 +165,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { ) -> BasicTypeEnum<'ctx> { get_llvm_type( self.ctx, + &self.module, generator, &mut self.unifier, self.top_level, @@ -460,7 +461,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { let i1_true = i1.const_all_ones(); let expect_fun = self.module.get_function("llvm.expect.i1").unwrap_or_else(|| { self.module.add_function( - "llvm.expect", + // FIXME: + "llvm.expect.i1", i1.fn_type(&[i1.into(), i1.into()], false), None, ) @@ -693,6 +695,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>( if let Some(obj) = &obj { args.insert(0, FuncArg { name: "self".into(), ty: obj.0, default_value: None }); } + // println!("\n2=======getting types for func `{}`=======", symbol); let ret_type = if ctx.unifier.unioned(fun.0.ret, ctx.primitives.none) { None } else { @@ -715,6 +718,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>( Some(ret_type) if !has_sret => ret_type.fn_type(¶ms, false), _ => ctx.ctx.void_type().fn_type(¶ms, false) }; + // println!("2=======got types for func `{}`: {}=======\n", symbol, fun_ty.print_to_string().to_string()); let fun_val = ctx.module.add_function(&symbol, fun_ty, None); let offset = if has_sret { fun_val.add_attribute(AttributeLoc::Param(0), diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index 4ee3f3a3..676e1e80 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -203,9 +203,13 @@ impl WorkerRegistry { } fn worker_thread(&self, generator: &mut G, f: Arc) { + // println!("thread start! 1"); let context = Context::create(); + // println!("thread start! 2"); let mut builder = context.create_builder(); - let module = context.create_module(generator.get_name()); + // println!("thread start! 3"); + let mut module = context.create_module(generator.get_name()); + // println!("thread start! 4"); module.add_basic_value_flag( "Debug Info Version", @@ -218,23 +222,46 @@ impl WorkerRegistry { context.i32_type().const_int(4, false), ); - let pass_builder = PassManagerBuilder::create(); - pass_builder.set_optimization_level(OptimizationLevel::Default); - let passes = PassManager::create(&module); - pass_builder.populate_function_pass_manager(&passes); - + let mut errors = HashSet::new(); + // while let Some(task) = self.receiver.recv().unwrap() { + // println!("creating tmp"); + // let tmp_module = context.create_module("tmp"); + // println!("creating tmp done {}", tmp_module.print_to_string().to_string()); + // let n = task.symbol_name.clone(); + // println!("{} start0:", n); + // let res = gen_func(&context, generator, self, builder, tmp_module, task); + // match res { + // Ok(result) => { + // builder = result.0; + // passes.run_on(&result.2); + // result.1.verify().unwrap(); + // module.link_in_module(result.1).unwrap(); + // } + // Err((old_builder, e)) => { + // builder = old_builder; + // errors.insert(e); + // } + // } + // println!("{} done0:", n); + // *self.task_count.lock() -= 1; + // self.wait_condvar.notify_all(); + // } + while let Some(task) = self.receiver.recv().unwrap() { - let tmp_module = context.create_module("tmp"); - match gen_func(&context, generator, self, builder, tmp_module, task) { + match gen_func(&context, generator, self, builder, module, task) { Ok(result) => { builder = result.0; - passes.run_on(&result.2); - module.link_in_module(result.1).unwrap(); + // passes.run_on(&result.2); + // module.link_in_module(result.1).unwrap(); + module = result.1; } Err((old_builder, e)) => { - builder = old_builder; + // builder = old_builder; + // create a new module to continue to just collect other errors + // module = context.create_module(generator.get_name()); errors.insert(e); + panic!("Codegen error: {}", errors.into_iter().sorted().join("\n----------\n")); } } *self.task_count.lock() -= 1; @@ -246,10 +273,20 @@ impl WorkerRegistry { let result = module.verify(); if let Err(err) = result { - println!("{}", module.print_to_string().to_str().unwrap()); - println!("{}", err); + println!("\n\n!!!!!!!!!!!!!!!!!!error!!!!!!!!!!!!!!!!!!!!!"); + println!("{}", module.print_to_string().to_string()); + println!("{}", err.to_string()); + println!("!!!!!!!!!!!!!!!!!!error!!!!!!!!!!!!!!!!!!!!!\n\n"); panic!() } + + println!("aaaa"); + let pass_builder = PassManagerBuilder::create(); + pass_builder.set_optimization_level(OptimizationLevel::Default); + let passes = PassManager::create(&module); + pass_builder.populate_function_pass_manager(&passes); + println!("ddddd"); + f.run(&module); let mut lock = self.task_count.lock(); *lock += 1; @@ -271,6 +308,7 @@ pub struct CodeGenTask { fn get_llvm_type<'ctx>( ctx: &'ctx Context, + module: &Module<'ctx>, generator: &mut dyn CodeGenerator, unifier: &mut Unifier, top_level: &TopLevelContext, @@ -282,6 +320,7 @@ fn get_llvm_type<'ctx>( // we assume the type cache should already contain primitive types, // and they should be passed by value instead of passing as pointer. type_cache.get(&unifier.get_representative(ty)).cloned().unwrap_or_else(|| { + // println!("getting new: {}", unifier.stringify(ty)); let ty_enum = unifier.get_ty(ty); let result = match &*ty_enum { TObj { obj_id, fields, .. } => { @@ -295,6 +334,7 @@ fn get_llvm_type<'ctx>( ) if *obj_id == *opt_id => { return get_llvm_type( ctx, + module, generator, unifier, top_level, @@ -314,24 +354,51 @@ fn get_llvm_type<'ctx>( let ty = if let TopLevelDef::Class { name, fields: fields_list, .. } = &*definition.read() { - let struct_type = ctx.opaque_struct_type(&name.to_string()); - type_cache.insert(unifier.get_representative(ty), struct_type.ptr_type(AddressSpace::Generic).into()); - let fields = fields_list - .iter() - .map(|f| { - get_llvm_type( - ctx, - generator, - unifier, - top_level, - type_cache, - primitives, - fields[&f.0].0, - ) - }) - .collect_vec(); - struct_type.set_body(&fields, false); - struct_type.ptr_type(AddressSpace::Generic).into() + // let struct_type = { + // let struct_type = ctx.opaque_struct_type(&name.to_string()); + // type_cache.insert(unifier.get_representative(ty), struct_type.ptr_type(AddressSpace::Generic).into()); + // let fields = fields_list + // .iter() + // .map(|f| { + // get_llvm_type( + // ctx, + // module, + // generator, + // unifier, + // top_level, + // type_cache, + // primitives, + // fields[&f.0].0, + // ) + // }) + // .collect_vec(); + // struct_type.set_body(&fields, false); + // struct_type + // }; + let struct_type = module.get_struct_type(&name.to_string()).unwrap_or_else(|| { + let struct_type = ctx.opaque_struct_type(&name.to_string()); + type_cache.insert(unifier.get_representative(ty), struct_type.ptr_type(AddressSpace::Generic).into()); + let fields = fields_list + .iter() + .map(|f| { + get_llvm_type( + ctx, + module, + generator, + unifier, + top_level, + type_cache, + primitives, + fields[&f.0].0, + ) + }) + .collect_vec(); + struct_type.set_body(&fields, false); + struct_type + }); + let res = struct_type.ptr_type(AddressSpace::Generic).into(); + // println!("got: {:?}", res); + res } else { unreachable!() }; @@ -341,14 +408,14 @@ fn get_llvm_type<'ctx>( // a struct with fields in the order present in the tuple let fields = ty .iter() - .map(|ty| get_llvm_type(ctx, generator, unifier, top_level, type_cache, primitives, *ty)) + .map(|ty| get_llvm_type(ctx, module, generator, unifier, top_level, type_cache, primitives, *ty)) .collect_vec(); ctx.struct_type(&fields, false).into() } TList { ty } => { // a struct with an integer and a pointer to an array let element_type = - get_llvm_type(ctx, generator, unifier, top_level, type_cache, primitives, *ty); + get_llvm_type(ctx, module, generator, unifier, top_level, type_cache, primitives, *ty); let fields = [ element_type.ptr_type(AddressSpace::Generic).into(), generator.get_size_type(ctx).into(), @@ -475,10 +542,11 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte } else { unreachable!() }; + // println!("\n=======getting types for func `{}`=======", task.symbol_name); let ret_type = if unifier.unioned(ret, primitives.none) { None } else { - Some(get_llvm_type(context, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, &primitives, ret)) + Some(get_llvm_type(context, &module, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, &primitives, ret)) }; let has_sret = ret_type.map_or(false, |ty| need_sret(context, ty)); @@ -487,6 +555,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte .map(|arg| { get_llvm_type( context, + &module, generator, &mut unifier, top_level_ctx.as_ref(), @@ -497,7 +566,6 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte .into() }) .collect_vec(); - if has_sret { params.insert(0, ret_type.unwrap().ptr_type(AddressSpace::Generic).into()); } @@ -506,7 +574,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte Some(ret_type) if !has_sret => ret_type.fn_type(¶ms, false), _ => context.void_type().fn_type(¶ms, false) }; - + // println!("=======got types for func `{}`: {:?}=======\n", task.symbol_name, fn_type); let symbol = &task.symbol_name; let fn_val = module.get_function(symbol).unwrap_or_else(|| module.add_function(symbol, fn_type, None)); @@ -535,6 +603,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte let alloca = builder.build_alloca( get_llvm_type( context, + &module, generator, &mut unifier, top_level_ctx.as_ref(), @@ -678,11 +747,15 @@ pub fn gen_func<'ctx, G: CodeGenerator>( module: Module<'ctx>, task: CodeGenTask, ) -> Result<(Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>), (Builder<'ctx>, String)> { + let n = task.symbol_name.clone(); + println!("{} start:", n); let body = task.body.clone(); - gen_func_impl(context, generator, registry, builder, module, task, |generator, ctx| { + let res = gen_func_impl(context, generator, registry, builder, module, task, |generator, ctx| { for stmt in body.iter() { generator.gen_stmt(ctx, stmt)?; } Ok(()) - }) + }); + println!("{} end:", n); + res } diff --git a/nac3standalone/demo/run_demo.sh b/nac3standalone/demo/run_demo.sh index 7734b249..6c87d393 100755 --- a/nac3standalone/demo/run_demo.sh +++ b/nac3standalone/demo/run_demo.sh @@ -7,8 +7,8 @@ if [ -z "$1" ]; then exit 1 fi -if [ -e ../../target/release/nac3standalone ]; then - nac3standalone=../../target/release/nac3standalone +if [ -e ../../target/debug/nac3standalone ]; then + nac3standalone=../../target/debug/nac3standalone else # used by Nix builds nac3standalone=../../target/x86_64-unknown-linux-gnu/release/nac3standalone diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs index 3d93d1da..e6f34a16 100644 --- a/nac3standalone/src/main.rs +++ b/nac3standalone/src/main.rs @@ -2,7 +2,7 @@ use inkwell::{ memory_buffer::MemoryBuffer, passes::{PassManager, PassManagerBuilder}, targets::*, - OptimizationLevel, + OptimizationLevel, module::Module, context::Context, AddressSpace, }; use parking_lot::{Mutex, RwLock}; use std::{borrow::Borrow, collections::HashMap, env, fs, path::Path, sync::Arc}; @@ -156,7 +156,7 @@ fn handle_assignment_pattern( fn main() { let file_name = env::args().nth(1).unwrap(); - let threads: u32 = env::args().nth(2).map(|s| str::parse(&s).unwrap()).unwrap_or(1); + let threads: u32 = env::args().nth(2).map(|s| str::parse(&s).unwrap()).unwrap_or(2); Target::initialize_all(&InitializationConfig::default()); @@ -313,4 +313,210 @@ fn main() { target_machine .write_to_file(&main, FileType::Object, Path::new("module.o")) .expect("couldn't write module to file"); + + + // =================================== + // let ctxx = inkwell::context::Context::create(); + // let ctxx2 = inkwell::context::Context::create(); + // let ctxx3 = inkwell::context::Context::create(); + + // // let builder = PassManagerBuilder::create(); + // // builder.set_optimization_level(OptimizationLevel::Aggressive); + // // let passes = PassManager::create(()); + // // builder.set_inliner_with_threshold(255); + // // builder.populate_module_pass_manager(&passes); + + // let mmm = test2(&ctxx, &ctxx, &ctxx3); + // // passes.run_on(&mmm); + // Target::initialize_all(&InitializationConfig::default()); + // let triple = TargetMachine::get_default_triple(); + // let target = Target::from_triple(&triple).expect("couldn't create target from target triple"); + // let target_machine = target + // .create_target_machine( + // &triple, + // "", + // "", + // OptimizationLevel::Default, + // RelocMode::Default, + // CodeModel::Default, + // ) + // .expect("couldn't create target machine"); + // target_machine + // .write_to_file(&mmm, FileType::Object, Path::new("module.o")) + // .expect("couldn't write module to file"); } + +fn test<'ctx>(ctx: &'ctx Context, ctx2: &'ctx Context, ctx3: &'ctx Context) -> Module<'ctx> { + let module = ctx.create_module("test"); + let module2 = ctx2.create_module("test2"); + let builder = ctx.create_builder(); + let builder2 = ctx2.create_builder(); + + let int32 = ctx.i32_type(); + let int8 = ctx.i8_type(); + let int322 = ctx2.i32_type(); + let int82 = ctx2.i8_type(); + + let opaque = ctx.opaque_struct_type("TestType"); + let opaque = ctx.opaque_struct_type("TestType"); + opaque.set_body(&[int32.into(), opaque.ptr_type(AddressSpace::Generic).into()], false); + let opaque = opaque.ptr_type(AddressSpace::Generic); + + // let opaque2 = module.get_struct_type("TestType").unwrap(); + let opaque2 = ctx2.opaque_struct_type("TestType"); + // let opaque2 = ctx2.opaque_struct_type("TestType"); + opaque2.set_body(&[int322.into(), opaque2.ptr_type(AddressSpace::Generic).into()], false); + let opaque2 = opaque2.ptr_type(AddressSpace::Generic); + + + let func2 = module2.add_function("f", ctx2.void_type().fn_type(&[opaque2.into()], false), None); + let func2_bb = ctx2.append_basic_block(func2, "init"); + builder2.position_at_end(func2_bb); + builder2.build_return(None); + + let func = module.add_function("run", ctx.void_type().fn_type(&[], false), None); + let fun2_mod1 = module.add_function("f", ctx.void_type().fn_type(&[opaque.into()], false), None); + let func1_bb = ctx.append_basic_block(func, "init"); + builder.position_at_end(func1_bb); + let opaque1_ptr = builder.build_alloca(opaque.get_element_type().into_struct_type(), "alloc1"); + let opaque2_ptr = builder.build_alloca(opaque.get_element_type().into_struct_type(), "alloc2"); + builder.build_store( + unsafe { builder.build_gep(opaque1_ptr, &[int32.const_zero(), int32.const_zero()], "gep") }, + int32.const_int(123, false) + ); + builder.build_store( + unsafe { builder.build_gep(opaque2_ptr, &[int32.const_zero(), int32.const_zero()], "gep") }, + int32.const_int(23, false) + ); + builder.build_store( + unsafe { builder.build_gep(opaque1_ptr, &[int32.const_zero(), int32.const_int(1, false)], "gep") }, + opaque2_ptr + ); + builder.build_store( + unsafe { builder.build_gep(opaque2_ptr, &[int32.const_zero(), int32.const_int(1, false)], "gep") }, + opaque1_ptr + ); + // let arr = builder.build_array_alloca(opaque, int32.const_int(2, false), "arr"); + // builder.build_store( + // unsafe { builder.build_gep(arr, &[int32.const_zero()], "zero")}, + // opaque1_ptr + // ); + let arr = module.add_global( + opaque.array_type(2), + None, + "arr_const", + ); + arr.set_initializer(&opaque.const_array(&[opaque1_ptr, opaque2_ptr])); + let arr = arr.as_pointer_value(); + let arg = builder.build_load( + unsafe { builder.build_gep(arr, &[int32.const_zero(), int32.const_zero()], "zero")}, + "load" + ); + builder.build_call(fun2_mod1, &[arg.into()], "call"); + builder.build_return(None); + + // builder.build_call(func2, args, name) + + println!("before: \n========= module1: \n{}\n=========module2: \n{}=======\n\n", module.print_to_string().to_string(), module2.print_to_string().to_string()); + module.verify().unwrap(); + module2.verify().unwrap(); + // module.link_in_module(module2).unwrap(); + let mut mem: Vec> = Default::default(); + let bitcode1 = module.write_bitcode_to_memory(); + let bitcode1 = bitcode1.as_slice(); + mem.push(bitcode1.into()); + let bitcode2 = module2.write_bitcode_to_memory(); + let bitcode2 = bitcode2.as_slice(); + mem.push(bitcode2.into()); + + let mod1 = ctx3.create_module_from_ir(MemoryBuffer::create_from_memory_range(&mem[0], "mod1")).unwrap(); + let mod2 = ctx3.create_module_from_ir(MemoryBuffer::create_from_memory_range(&mem[1], "mod2")).unwrap(); + mod1.verify().unwrap(); + mod2.verify().unwrap(); + mod1.link_in_module(mod2).unwrap(); + let module = mod1; + println!("after"); + + println!("\n\n====finish===\n{}\n=====finish=====\n\n\n", module.print_to_string().to_string()); + + + println!("before2"); + match module.verify() { + Ok(_) => (), + Err(s) => { + println!("after2"); + println!("\n\n=======\n{}\n==========\n{}\n\n", module.print_to_string().to_string(), s.to_string()); + println!("after3"); + panic!(); + } + }; + println!("\n=====done==========="); + module +} + +fn test2<'ctx>(ctx: &'ctx Context, ctx2: &'ctx Context, ctx3: &'ctx Context) -> Module<'ctx> { + let module = ctx.create_module("test"); + let module2 = ctx2.create_module("test2"); + let builder = ctx.create_builder(); + let builder2 = ctx2.create_builder(); + + let int32 = ctx.i32_type(); + let int8 = ctx.i8_type(); + let int322 = ctx2.i32_type(); + let int82 = ctx2.i8_type(); + + let opaque = ctx.opaque_struct_type("TestType"); + opaque.set_body(&[int32.into(), int8.into()], false); + let opaque = opaque.ptr_type(AddressSpace::Generic); + + let opaque2 = module2.get_struct_type("TestType").unwrap(); + // let opaque2 = ctx2.opaque_struct_type("TestType"); + // let opaque2 = ctx2.opaque_struct_type("TestType"); + opaque2.set_body(&[int322.into(), int82.into()], false); + let opaque2 = opaque2.ptr_type(AddressSpace::Generic); + + + let func2 = module2.add_function("f", ctx2.void_type().fn_type(&[opaque2.into()], false), None); + let func2_bb = ctx2.append_basic_block(func2, "init"); + builder2.position_at_end(func2_bb); + builder2.build_return(None); + + let func = module.add_function("run", ctx.void_type().fn_type(&[], false), None); + // let fun2_mod1 = module.add_function("f", ctx.void_type().fn_type(&[opaque2.into()], false), None); + let func1_bb = ctx.append_basic_block(func, "init"); + builder.position_at_end(func1_bb); + let opaque1_ptr = builder.build_alloca(opaque.get_element_type().into_struct_type(), "alloc1"); + builder.build_store( + unsafe { builder.build_gep(opaque1_ptr, &[int32.const_zero(), int32.const_zero()], "gep") }, + int32.const_int(123, false) + ); + builder.build_store( + unsafe { builder.build_gep(opaque1_ptr, &[int32.const_zero(), int32.const_int(1, false)], "gep") }, + int8.const_int(12, false), + ); + builder.build_call(func2, &[opaque1_ptr.into()], "call"); + builder.build_return(None); + + + println!("before: \n========= module1: \n{}\n=========module2: \n{}=======\n\n", module.print_to_string().to_string(), module2.print_to_string().to_string()); + module.verify().unwrap(); + module2.verify().unwrap(); + module.link_in_module(module2).unwrap(); + println!("after"); + + // println!("\n\n====finish===\n{}\n=====finish=====\n\n\n", module.print_to_string().to_string()); + + + println!("before2"); + match module.verify() { + Ok(_) => (), + Err(s) => { + println!("after2"); + println!("\n\n=======\n{}\n==========\n{}\n\n", module.print_to_string().to_string(), s.to_string()); + println!("after3"); + panic!(); + } + }; + println!("\n=====done==========="); + module +} \ No newline at end of file