diff --git a/CHANGELOG.md b/CHANGELOG.md index e6eff82..5912862 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file. xxx +## [2.3.1] - 2025-02-28 + +### Fixed + +- Fixed type definition ordering in `Module::fmt::Display` to ensure type definitions appear before function definitions, which is required by QBE for aggregate types ([#31](https://github.com/garritfra/qbe-rs/pull/31)). + ## [2.3.0] - 2025-01-13 ### Added diff --git a/Cargo.toml b/Cargo.toml index 10a64e6..71e2162 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "qbe" -version = "2.3.0" +version = "2.3.1" edition = "2021" authors = ["Garrit Franke "] license = "MIT OR Apache-2.0" diff --git a/src/lib.rs b/src/lib.rs index 0566d70..2dfbfe1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -683,12 +683,12 @@ impl<'a> Module<'a> { impl fmt::Display for Module<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for func in self.functions.iter() { - writeln!(f, "{}", func)?; - } for ty in self.types.iter() { writeln!(f, "{}", ty)?; } + for func in self.functions.iter() { + writeln!(f, "{}", func)?; + } for data in self.data.iter() { writeln!(f, "{}", data)?; } diff --git a/src/tests.rs b/src/tests.rs index b738b08..80f7f46 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -284,3 +284,58 @@ fn variadic_call() { assert_eq!(instr.to_string(), "call $printf(l $fmt, ..., w 0)"); } + +#[test] +fn module_fmt_order() { + // Create a module + let mut module = Module::new(); + + // Add a type definition to the module + let typedef = TypeDef { + name: "test_type".into(), + align: None, + items: vec![(Type::Long, 1)], + }; + module.add_type(typedef); + + // Add a function to the module + let mut func = Function::new(Linkage::public(), "test_func", Vec::new(), None); + + // Add a block to the function and an instruction to the block + let block = func.add_block("entry"); + block.add_instr(Instr::Ret(None)); + + module.add_function(func); + + // Add some data to the module for completeness + let data = DataDef::new( + Linkage::private(), + "test_data", + None, + vec![(Type::Word, DataItem::Const(42))], + ); + module.add_data(data); + + // Format the module to a string + let formatted = format!("{}", module); + + // Verify the order: types, then functions, then data + let type_pos = formatted + .find("type :test_type") + .expect("Type definition not found"); + let func_pos = formatted + .find("export function $test_func") + .expect("Function not found"); + let data_pos = formatted + .find("data $test_data") + .expect("Data definition not found"); + + assert!( + type_pos < func_pos, + "Type definition should appear before function" + ); + assert!( + func_pos < data_pos, + "Function should appear before data definition" + ); +}