Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Perform basic codegen

author
Danielle Maywood
committer
nandi
date (Jul 26, 2026, 12:11 PM -0700) commit 14c245a6 parent ad476218 change-id nrmnwpon
+528 -228
+10 -4
compiler-core/src/codegen.rs
··· 350 350 } 351 351 352 352 pub fn render(&self, writer: &impl FileSystemWriter, modules: &[Module]) -> Result<()> { 353 - _ = self.output_directory; 354 - _ = writer; 355 - 356 353 let modules: Vec<_> = modules 357 354 .iter() 358 355 .map(|module| cranelift::mir::Translator::new(&module.ast).translate()) 359 356 .collect(); 360 357 361 358 let monomorphized = cranelift::mir::lower::lower(modules); 362 - dbg!(monomorphized); 359 + 360 + for module in monomorphized { 361 + let path = self 362 + .output_directory 363 + .join(&format!("{}.o", module.name.clone())); 364 + 365 + let object = cranelift::compile(module); 366 + 367 + writer.write_bytes(&path, &object)?; 368 + } 363 369 364 370 Ok(()) 365 371 }
+449 -206
compiler-core/src/cranelift.rs
··· 1 - // use std::collections::HashMap; 1 + use std::collections::HashMap; 2 + 3 + use cranelift::{ 4 + codegen::{Context, ir::BlockArg}, 5 + prelude::*, 6 + }; 7 + use cranelift_module::{Linkage, Module, default_libcall_names}; 8 + use cranelift_object::{ObjectBuilder, ObjectModule}; 9 + use ecow::{EcoString, eco_format}; 10 + use itertools::Itertools as _; 2 11 3 - // use cranelift::{codegen::ir::BlockArg, prelude::*}; 4 - // use cranelift_jit::{JITBuilder, JITModule}; 5 - // use cranelift_module::{FuncOrDataId, Linkage, Module, default_libcall_names}; 6 - // use ecow::EcoString; 7 - // use num_bigint::BigInt; 12 + use crate::cranelift::mir::ast; 8 13 9 14 pub mod mir; 10 15 11 - // pub fn compile(m: mir::ast::Module<mir::ast::IncompleteType>) { 12 - // let mut flag_builder = settings::builder(); 16 + struct CodeGen<M: Module> { 17 + module: M, 18 + context: Context, 19 + function_context: FunctionBuilderContext, 20 + } 13 21 14 - // flag_builder 15 - // .set("is_pic", "false") 16 - // .expect("unable to set `is_pic` to false"); 22 + pub fn compile(module: ast::Module<ast::CompleteType>) -> Vec<u8> { 23 + let mut flag_builder = settings::builder(); 17 24 18 - // let isa = cranelift_native::builder() 19 - // .unwrap_or_else(|reason| panic!("host machine not support: {reason}")) 20 - // .finish(settings::Flags::new(flag_builder)) 21 - // .expect("unable to build isa target"); 25 + flag_builder 26 + .set("is_pic", "true") 27 + .expect("unable to set `is_pic` to false"); 22 28 23 - // let mut module = JITModule::new(JITBuilder::with_isa(isa, default_libcall_names())); 24 - // let mut context = module.make_context(); 25 - // let mut function_context = FunctionBuilderContext::new(); 29 + let isa = cranelift_native::builder() 30 + .unwrap_or_else(|reason| panic!("host machine not support: {reason}")) 31 + .finish(settings::Flags::new(flag_builder)) 32 + .expect("unable to build isa target"); 26 33 27 - // for function in m.functions { 28 - // let sig = &mut context.func.signature; 34 + let mut cranelift = { 35 + let module = ObjectModule::new( 36 + ObjectBuilder::new(isa, module.name.to_string(), default_libcall_names()) 37 + .expect("unable to build object builder"), 38 + ); 29 39 30 - // for _ in &function.parameters { 31 - // sig.params.push(AbiParam::new(types::I64)); 32 - // } 40 + CodeGen { 41 + function_context: FunctionBuilderContext::new(), 42 + context: module.make_context(), 43 + module, 44 + } 45 + }; 33 46 34 - // sig.returns.push(AbiParam::new(types::I64)); 47 + for function in module.functions { 48 + FunctionTranslator::new(&mut cranelift).translate(module.name.clone(), function); 49 + } 35 50 36 - // let mut builder = FunctionBuilder::new(&mut context.func, &mut function_context); 51 + let product = cranelift.module.finish(); 37 52 38 - // let entry = builder.create_block(); 39 - // builder.append_block_params_for_function_params(entry); 40 - // builder.switch_to_block(entry); 41 - // builder.seal_block(entry); 53 + product.emit().expect("unable to emit finished product") 54 + } 42 55 43 - // let mut translator = FunctionTranslator { 44 - // builder, 45 - // module: &mut module, 46 - // variables: HashMap::new(), 47 - // }; 56 + struct FunctionTranslator<'m, M: Module> { 57 + cg: &'m mut CodeGen<M>, 58 + } 48 59 49 - // for (index, parameter) in function.parameters.into_iter().enumerate() { 50 - // if let Some(name) = parameter.name { 51 - // let var = translator.make_var(name); 52 - // let val = translator.builder.block_params(entry)[index]; 60 + fn mangle_type_name(type_: &ast::CompleteType) -> EcoString { 61 + match type_ { 62 + ast::CompleteType::Int => "I".into(), 63 + ast::CompleteType::Float => "F".into(), 64 + ast::CompleteType::Bool => "B".into(), 65 + ast::CompleteType::String => "S".into(), 66 + ast::CompleteType::Func { arguments, returns } => { 67 + let arguments = arguments 68 + .iter() 69 + .map(mangle_type_name) 70 + .map(|s| eco_format!("{}{}", s.len(), s)) 71 + .join(""); 53 72 54 - // translator.builder.def_var(var, val); 55 - // } 56 - // } 73 + let returns = mangle_type_name(returns); 57 74 58 - // let output = translator.translate_expression(function.body); 75 + eco_format!("F{}{}R{}", arguments.len(), arguments, returns) 76 + } 77 + ast::CompleteType::Struct { elements } => { 78 + let elements = elements 79 + .iter() 80 + .map(mangle_type_name) 81 + .map(|s| eco_format!("{}{}", s.len(), s)) 82 + .join(""); 59 83 60 - // _ = translator.builder.ins().return_(&[output]); 61 - // translator.builder.finalize(); 84 + eco_format!("C{}{}", elements.len(), elements) 85 + } 86 + ast::CompleteType::List(element_type) => { 87 + let element = mangle_type_name(element_type); 62 88 63 - // let id = module 64 - // .declare_function(&function.name, Linkage::Export, &context.func.signature) 65 - // .expect("unable to declare function"); 89 + eco_format!("L{}{}", element.len(), element) 90 + } 91 + } 92 + } 66 93 67 - // module 68 - // .define_function(id, &mut context) 69 - // .expect("unable to define function"); 94 + fn mangled_function_name( 95 + module: EcoString, 96 + name: EcoString, 97 + arguments: &[ast::CompleteType], 98 + returns: &ast::CompleteType, 99 + ) -> EcoString { 100 + let arguments = arguments.iter().map(mangle_type_name).join(","); 101 + let returns = mangle_type_name(returns); 102 + 103 + eco_format!( 104 + "M{}{}_{}{}_A{}{}_R{}", 105 + module.len(), 106 + module.replace("/", "_"), 107 + name.len(), 108 + name, 109 + arguments.len(), 110 + arguments, 111 + returns, 112 + ) 113 + } 70 114 71 - // module.clear_context(&mut context); 72 - // } 115 + impl<'m, M: Module> FunctionTranslator<'m, M> { 116 + fn new(cg: &'m mut CodeGen<M>) -> Self { 117 + Self { cg } 118 + } 73 119 74 - // module 75 - // .finalize_definitions() 76 - // .expect("unable to finalize definitions"); 120 + fn translate(self, module: EcoString, function: ast::Function<ast::CompleteType>) { 121 + let arguments: Vec<_> = function 122 + .parameters 123 + .iter() 124 + .map(|parameter| parameter.type_.clone()) 125 + .collect(); 77 126 78 - // let FuncOrDataId::Func(main) = module.get_name("main").expect("expected a main function") 79 - // else { 80 - // panic!("expected main to be a function") 81 - // }; 127 + let name = mangled_function_name( 128 + module, 129 + function.name.clone(), 130 + &arguments, 131 + &function.return_type, 132 + ); 133 + 134 + self.cg.context.func.signature = self.signature_from_function(&function); 135 + 136 + let mut builder = 137 + FunctionBuilder::new(&mut self.cg.context.func, &mut self.cg.function_context); 138 + 139 + let entry = builder.create_block(); 140 + builder.append_block_params_for_function_params(entry); 141 + builder.switch_to_block(entry); 142 + builder.seal_block(entry); 143 + 144 + let value = { 145 + let mut translator = ExpressionTranslator::new(&mut self.cg.module, &mut builder); 146 + 147 + for (index, parameter) in function.parameters.iter().enumerate() { 148 + if let Some(name) = &parameter.name { 149 + let var_type = translate_type(&parameter.type_); 150 + let var = translator.builder.declare_var(var_type); 151 + _ = translator.vars.insert(name.clone(), var); 152 + 153 + let val = translator.builder.block_params(entry)[index]; 154 + translator.builder.def_var(var, val); 155 + } 156 + } 157 + 158 + translator.translate(function.body) 159 + }; 160 + 161 + _ = builder.ins().return_(&[value]); 162 + 163 + builder.finalize(); 164 + 165 + let id = self 166 + .cg 167 + .module 168 + .declare_function(&name, Linkage::Export, &self.cg.context.func.signature) 169 + .expect("unable to declare function"); 170 + 171 + self.cg 172 + .module 173 + .define_function(id, &mut self.cg.context) 174 + .expect("unable to define function"); 175 + 176 + self.cg.module.clear_context(&mut self.cg.context); 177 + } 178 + 179 + fn signature_from_function(&self, function: &ast::Function<ast::CompleteType>) -> Signature { 180 + let mut sig = self.cg.module.make_signature(); 181 + 182 + for parameter in &function.parameters { 183 + sig.params 184 + .push(AbiParam::new(translate_type(&parameter.type_))); 185 + } 186 + 187 + sig.returns 188 + .push(AbiParam::new(translate_type(&function.return_type))); 189 + 190 + return sig; 191 + } 192 + } 193 + 194 + fn translate_type(type_: &ast::CompleteType) -> Type { 195 + match type_ { 196 + ast::CompleteType::Int => types::I64, 197 + ast::CompleteType::Float => types::F64, 198 + ast::CompleteType::Bool => types::I64, // wasteful but whatever 199 + ast::CompleteType::String => types::I64, 200 + ast::CompleteType::Func { 201 + arguments: _, 202 + returns: _, 203 + } => types::I64, 204 + ast::CompleteType::Struct { elements: _ } => types::I64, 205 + ast::CompleteType::List(_complete_type) => types::I64, 206 + } 207 + } 208 + 209 + struct ExpressionTranslator<'m, 'b, M: Module> { 210 + module: &'m mut M, 211 + builder: &'m mut FunctionBuilder<'b>, 212 + vars: HashMap<EcoString, Variable>, 213 + } 214 + 215 + impl<'m, 'b, M: Module> ExpressionTranslator<'m, 'b, M> { 216 + fn new(module: &'m mut M, builder: &'m mut FunctionBuilder<'b>) -> Self { 217 + Self { 218 + module, 219 + builder, 220 + vars: Default::default(), 221 + } 222 + } 223 + 224 + fn translate(&mut self, expression: ast::Expression<ast::CompleteType>) -> Value { 225 + _ = self.module; 226 + 227 + match expression { 228 + ast::Expression::Block(expressions) => expressions 229 + .into_iter() 230 + .map(|expression| self.translate(expression)) 231 + .last() 232 + .expect("block should be non-empty"), 233 + ast::Expression::FunctionRef { 234 + module, 235 + name, 236 + arity: _, 237 + type_, 238 + } => { 239 + let ast::CompleteType::Func { arguments, returns } = type_ else { 240 + unreachable!("function ref should have func type") 241 + }; 242 + 243 + let name = mangled_function_name(module, name, &arguments, &returns); 244 + let sig = { 245 + let mut sig = self.module.make_signature(); 246 + for argument in arguments { 247 + sig.params.push(AbiParam::new(translate_type(&argument))); 248 + } 249 + sig.returns.push(AbiParam::new(translate_type(&returns))); 250 + sig 251 + }; 252 + 253 + let id = self 254 + .module 255 + .declare_function(&name, Linkage::Import, &sig) 256 + .expect("unable to declare function for import"); 257 + 258 + let func = self.module.declare_func_in_func(id, self.builder.func); 259 + 260 + self.builder.ins().func_addr(types::I64, func) 261 + } 262 + ast::Expression::Var(var) => { 263 + let var = self 264 + .vars 265 + .get(&var.name) 266 + .cloned() 267 + .expect("variable to be defined"); 268 + 269 + self.builder.use_var(var) 270 + } 271 + ast::Expression::Int { value } => { 272 + let value = i64::try_from(value).expect("integer value too large"); 273 + 274 + self.builder.ins().iconst(types::I64, value) 275 + } 276 + ast::Expression::Float { value } => { 277 + let value: f64 = value.parse().expect("invalid float value"); 278 + 279 + self.builder.ins().f64const(value) 280 + } 281 + ast::Expression::Bool { value } => match value { 282 + true => self.builder.ins().iconst(types::I64, 1), 283 + false => self.builder.ins().iconst(types::I64, 0), 284 + }, 285 + ast::Expression::String { value: _ } => todo!(), 286 + ast::Expression::Equals { lhs, rhs } => match lhs.type_() { 287 + ast::CompleteType::Int => { 288 + let lhs = self.translate(*lhs); 289 + let rhs = self.translate(*rhs); 290 + 291 + self.builder.ins().icmp(IntCC::Equal, lhs, rhs) 292 + } 293 + ast::CompleteType::Float => todo!(), 294 + ast::CompleteType::Bool => todo!(), 295 + ast::CompleteType::String => todo!(), 296 + ast::CompleteType::Func { 297 + arguments: _, 298 + returns: _, 299 + } => todo!(), 300 + ast::CompleteType::Struct { elements: _ } => todo!(), 301 + ast::CompleteType::List(_complete_type) => todo!(), 302 + }, 303 + ast::Expression::NotEquals { lhs: _, rhs: _ } => todo!(), 304 + ast::Expression::IntGt { lhs, rhs } => { 305 + let lhs = self.translate(*lhs); 306 + let rhs = self.translate(*rhs); 82 307 83 - // let code = module.get_finalized_function(main); 84 - // #[allow(unsafe_code)] 85 - // let main = unsafe { std::mem::transmute::<_, extern "C" fn() -> i64>(code) }; 308 + self.builder.ins().icmp(IntCC::SignedGreaterThan, lhs, rhs) 309 + } 310 + ast::Expression::IntGtEq { lhs, rhs } => { 311 + let lhs = self.translate(*lhs); 312 + let rhs = self.translate(*rhs); 86 313 87 - // println!("{}", main()); 88 - // } 314 + self.builder 315 + .ins() 316 + .icmp(IntCC::SignedGreaterThanOrEqual, lhs, rhs) 317 + } 318 + ast::Expression::IntLt { lhs, rhs } => { 319 + let lhs = self.translate(*lhs); 320 + let rhs = self.translate(*rhs); 89 321 90 - // struct FunctionTranslator<'a, M: Module> { 91 - // builder: FunctionBuilder<'a>, 92 - // module: &'a mut M, 93 - // variables: HashMap<EcoString, Variable>, 94 - // } 322 + self.builder.ins().icmp(IntCC::SignedLessThan, lhs, rhs) 323 + } 324 + ast::Expression::IntLtEq { lhs, rhs } => { 325 + let lhs = self.translate(*lhs); 326 + let rhs = self.translate(*rhs); 95 327 96 - // impl<'a, M: Module> FunctionTranslator<'a, M> { 97 - // fn make_var(&mut self, name: EcoString) -> Variable { 98 - // let variable = self.builder.declare_var(types::I64); 99 - // _ = self.variables.insert(name, variable); 100 - // variable 101 - // } 328 + self.builder 329 + .ins() 330 + .icmp(IntCC::SignedLessThanOrEqual, lhs, rhs) 331 + } 332 + ast::Expression::IntAdd { lhs, rhs } => { 333 + let lhs = self.translate(*lhs); 334 + let rhs = self.translate(*rhs); 102 335 103 - // fn get_var(&mut self, name: &EcoString) -> Variable { 104 - // self.variables 105 - // .get(name) 106 - // .cloned() 107 - // .unwrap_or_else(|| panic!("variable '{}' not found", name)) 108 - // } 336 + self.builder.ins().iadd(lhs, rhs) 337 + } 338 + ast::Expression::IntSub { lhs, rhs } => { 339 + let lhs = self.translate(*lhs); 340 + let rhs = self.translate(*rhs); 109 341 110 - // fn make_int(&mut self, value: BigInt) -> Value { 111 - // let value: i64 = value.try_into().expect("bigint out of representable range"); 342 + self.builder.ins().isub(lhs, rhs) 343 + } 344 + ast::Expression::IntMul { lhs, rhs } => { 345 + let lhs = self.translate(*lhs); 346 + let rhs = self.translate(*rhs); 112 347 113 - // self.builder.ins().iconst(types::I64, value) 114 - // } 348 + self.builder.ins().imul(lhs, rhs) 349 + } 350 + ast::Expression::IntDiv { lhs, rhs } => { 351 + let lhs = self.translate(*lhs); 352 + let rhs = self.translate(*rhs); 115 353 116 - // fn translate_expression(&mut self, expression: mir::ast::Expression) -> Value { 117 - // _ = self.module; 354 + self.builder.ins().sdiv(lhs, rhs) 355 + } 356 + ast::Expression::IntRem { lhs, rhs } => { 357 + let lhs = self.translate(*lhs); 358 + let rhs = self.translate(*rhs); 118 359 119 - // match expression { 120 - // mir::ast::Expression::Block(expressions) => expressions 121 - // .into_iter() 122 - // .map(|expression| self.translate_expression(expression)) 123 - // .last() 124 - // .expect("block shouldn't be empty"), 125 - // mir::ast::Expression::FunctionRef { 126 - // module: _, 127 - // name, 128 - // arity, 129 - // } => { 130 - // let mut signature = self.module.make_signature(); 360 + self.builder.ins().srem(lhs, rhs) 361 + } 362 + ast::Expression::FloatGt { lhs, rhs } => { 363 + let lhs = self.translate(*lhs); 364 + let rhs = self.translate(*rhs); 131 365 132 - // for _ in 0..arity { 133 - // signature.params.push(AbiParam::new(types::I64)); 134 - // } 135 - // signature.returns.push(AbiParam::new(types::I64)); 366 + self.builder.ins().fcmp(FloatCC::GreaterThan, lhs, rhs) 367 + } 368 + ast::Expression::FloatGtEq { lhs, rhs } => { 369 + let lhs = self.translate(*lhs); 370 + let rhs = self.translate(*rhs); 136 371 137 - // let id = self 138 - // .module 139 - // .declare_function(&name, Linkage::Import, &signature) 140 - // .expect("unable to declare function for import"); 372 + self.builder 373 + .ins() 374 + .fcmp(FloatCC::GreaterThanOrEqual, lhs, rhs) 375 + } 376 + ast::Expression::FloatLt { lhs, rhs } => { 377 + let lhs = self.translate(*lhs); 378 + let rhs = self.translate(*rhs); 141 379 142 - // let func = self.module.declare_func_in_func(id, self.builder.func); 380 + self.builder.ins().fcmp(FloatCC::LessThan, lhs, rhs) 381 + } 382 + ast::Expression::FloatLtEq { lhs, rhs } => { 383 + let lhs = self.translate(*lhs); 384 + let rhs = self.translate(*rhs); 143 385 144 - // self.builder.ins().func_addr(types::I64, func) 145 - // } 146 - // mir::ast::Expression::Var(var) => { 147 - // let var = self.get_var(&var.name); 386 + self.builder.ins().fcmp(FloatCC::LessThanOrEqual, lhs, rhs) 387 + } 388 + ast::Expression::FloatAdd { lhs, rhs } => { 389 + let lhs = self.translate(*lhs); 390 + let rhs = self.translate(*rhs); 148 391 149 - // self.builder.use_var(var) 150 - // } 151 - // mir::ast::Expression::Int { value } => self.make_int(value), 152 - // mir::ast::Expression::Float { value: _ } => todo!(), 153 - // mir::ast::Expression::Bool { value: _ } => todo!(), 154 - // mir::ast::Expression::String { value: _ } => todo!(), 155 - // mir::ast::Expression::Equals { lhs, rhs } => { 156 - // let lhs = self.translate_expression(*lhs); 157 - // let rhs = self.translate_expression(*rhs); 392 + self.builder.ins().fadd(lhs, rhs) 393 + } 394 + ast::Expression::FloatSub { lhs, rhs } => { 395 + let lhs = self.translate(*lhs); 396 + let rhs = self.translate(*rhs); 158 397 159 - // self.builder.ins().icmp(IntCC::Equal, lhs, rhs) 160 - // } 161 - // mir::ast::Expression::NotEquals { lhs: _, rhs: _ } => todo!(), 162 - // mir::ast::Expression::IntGt { lhs: _, rhs: _ } => todo!(), 163 - // mir::ast::Expression::IntGtEq { lhs: _, rhs: _ } => todo!(), 164 - // mir::ast::Expression::IntLt { lhs: _, rhs: _ } => todo!(), 165 - // mir::ast::Expression::IntLtEq { lhs: _, rhs: _ } => todo!(), 166 - // mir::ast::Expression::IntAdd { lhs, rhs } => { 167 - // let lhs = self.translate_expression(*lhs); 168 - // let rhs = self.translate_expression(*rhs); 398 + self.builder.ins().fsub(lhs, rhs) 399 + } 400 + ast::Expression::FloatMul { lhs, rhs } => { 401 + let lhs = self.translate(*lhs); 402 + let rhs = self.translate(*rhs); 169 403 170 - // self.builder.ins().iadd(lhs, rhs) 171 - // } 172 - // mir::ast::Expression::IntSub { lhs, rhs } => { 173 - // let lhs = self.translate_expression(*lhs); 174 - // let rhs = self.translate_expression(*rhs); 404 + self.builder.ins().fmul(lhs, rhs) 405 + } 406 + ast::Expression::FloatDiv { lhs, rhs } => { 407 + let lhs = self.translate(*lhs); 408 + let rhs = self.translate(*rhs); 175 409 176 - // self.builder.ins().isub(lhs, rhs) 177 - // } 178 - // mir::ast::Expression::IntMul { lhs: _, rhs: _ } => todo!(), 179 - // mir::ast::Expression::IntDiv { lhs: _, rhs: _ } => todo!(), 180 - // mir::ast::Expression::IntRem { lhs: _, rhs: _ } => todo!(), 181 - // mir::ast::Expression::FloatGt { lhs: _, rhs: _ } => todo!(), 182 - // mir::ast::Expression::FloatGtEq { lhs: _, rhs: _ } => todo!(), 183 - // mir::ast::Expression::FloatLt { lhs: _, rhs: _ } => todo!(), 184 - // mir::ast::Expression::FloatLtEq { lhs: _, rhs: _ } => todo!(), 185 - // mir::ast::Expression::FloatAdd { lhs: _, rhs: _ } => todo!(), 186 - // mir::ast::Expression::FloatSub { lhs: _, rhs: _ } => todo!(), 187 - // mir::ast::Expression::FloatMul { lhs: _, rhs: _ } => todo!(), 188 - // mir::ast::Expression::FloatDiv { lhs: _, rhs: _ } => todo!(), 189 - // mir::ast::Expression::StringConcat { lhs: _, rhs: _ } => todo!(), 190 - // mir::ast::Expression::List { items: _, tail: _ } => todo!(), 191 - // mir::ast::Expression::Struct { tag: _, items: _ } => todo!(), 192 - // mir::ast::Expression::StructTag { value: _ } => todo!(), 193 - // mir::ast::Expression::StructAccess { value: _, index: _ } => todo!(), 194 - // mir::ast::Expression::Set { name, value } => { 195 - // let var = self.make_var(name.name); 196 - // let val = self.translate_expression(*value); 410 + self.builder.ins().fdiv(lhs, rhs) 411 + } 412 + ast::Expression::StringConcat { lhs: _, rhs: _ } => todo!(), 413 + ast::Expression::List { 414 + items: _, 415 + tail: _, 416 + type_: _, 417 + } => todo!(), 418 + ast::Expression::Struct { 419 + tag: _, 420 + items: _, 421 + type_: _, 422 + } => todo!(), 423 + ast::Expression::StructTag { value: _ } => todo!(), 424 + ast::Expression::StructAccess { 425 + value: _, 426 + index: _, 427 + type_: _, 428 + } => todo!(), 429 + ast::Expression::Set { name, value } => { 430 + let var = self.builder.declare_var(translate_type(&value.type_())); 431 + _ = self.vars.insert(name.name, var); 197 432 198 - // self.builder.def_var(var, val); 199 - // self.builder.use_var(var) 200 - // } 201 - // mir::ast::Expression::If { cond, then, else_ } => { 202 - // let cond = self.translate_expression(*cond); 433 + let val = self.translate(*value); 434 + self.builder.def_var(var, val); 435 + self.builder.use_var(var) 436 + } 437 + ast::Expression::If { cond, then, else_ } => { 438 + let cond = self.translate(*cond); 203 439 204 - // let then_block = self.builder.create_block(); 205 - // let else_block = self.builder.create_block(); 206 - // let merge_block = self.builder.create_block(); 440 + let then_block = self.builder.create_block(); 441 + let else_block = self.builder.create_block(); 442 + let merge_block = self.builder.create_block(); 207 443 208 - // _ = self.builder.append_block_param(merge_block, types::I64); 444 + _ = self 445 + .builder 446 + .append_block_param(merge_block, translate_type(&then.type_())); 209 447 210 - // _ = self 211 - // .builder 212 - // .ins() 213 - // .brif(cond, then_block, &[], else_block, &[]); 448 + _ = self 449 + .builder 450 + .ins() 451 + .brif(cond, then_block, &[], else_block, &[]); 214 452 215 - // self.builder.switch_to_block(then_block); 216 - // self.builder.seal_block(then_block); 453 + self.builder.switch_to_block(then_block); 454 + self.builder.seal_block(then_block); 217 455 218 - // let then_return = self.translate_expression(*then); 219 - // _ = self 220 - // .builder 221 - // .ins() 222 - // .jump(merge_block, &[BlockArg::Value(then_return)]); 456 + let then_return = self.translate(*then); 457 + _ = self 458 + .builder 459 + .ins() 460 + .jump(merge_block, &[BlockArg::Value(then_return)]); 223 461 224 - // self.builder.switch_to_block(else_block); 225 - // self.builder.seal_block(else_block); 462 + self.builder.switch_to_block(else_block); 463 + self.builder.seal_block(else_block); 226 464 227 - // let else_return = self.translate_expression(*else_); 228 - // _ = self 229 - // .builder 230 - // .ins() 231 - // .jump(merge_block, &[BlockArg::Value(else_return)]); 465 + let else_return = self.translate(*else_); 466 + _ = self 467 + .builder 468 + .ins() 469 + .jump(merge_block, &[BlockArg::Value(else_return)]); 232 470 233 - // self.builder.switch_to_block(merge_block); 234 - // self.builder.seal_block(merge_block); 471 + self.builder.switch_to_block(merge_block); 472 + self.builder.seal_block(merge_block); 235 473 236 - // self.builder.block_params(merge_block)[0] 237 - // } 238 - // mir::ast::Expression::Call { target, args } => { 239 - // let mut signature = self.module.make_signature(); 474 + self.builder.block_params(merge_block)[0] 475 + } 476 + ast::Expression::Call { 477 + target, 478 + args, 479 + type_, 480 + } => { 481 + let mut signature = self.module.make_signature(); 240 482 241 - // for _ in 0..args.len() { 242 - // signature.params.push(AbiParam::new(types::I64)); 243 - // } 244 - // signature.returns.push(AbiParam::new(types::I64)); 483 + for arg in &args { 484 + signature 485 + .params 486 + .push(AbiParam::new(translate_type(&arg.type_()))); 487 + } 488 + signature 489 + .returns 490 + .push(AbiParam::new(translate_type(&type_))); 245 491 246 - // let target = self.translate_expression(*target); 247 - // let args: Vec<_> = args 248 - // .into_iter() 249 - // .map(|arg| self.translate_expression(arg)) 250 - // .collect(); 492 + let target = self.translate(*target); 493 + let args: Vec<_> = args.into_iter().map(|arg| self.translate(arg)).collect(); 251 494 252 - // let sig = self.builder.import_signature(signature); 253 - // let call = self.builder.ins().call_indirect(sig, target, &args); 495 + let sig = self.builder.import_signature(signature); 496 + let call = self.builder.ins().call_indirect(sig, target, &args); 254 497 255 - // self.builder.inst_results(call)[0] 256 - // } 257 - // } 258 - // } 259 - // } 498 + self.builder.inst_results(call)[0] 499 + } 500 + } 501 + } 502 + }
+44
compiler-core/src/cranelift/mir/ast.rs
··· 274 274 } 275 275 } 276 276 } 277 + 278 + impl Expression<CompleteType> { 279 + pub fn type_(&self) -> CompleteType { 280 + match self { 281 + Expression::Block(expressions) => expressions 282 + .last() 283 + .expect("a block should not be empty") 284 + .type_(), 285 + Expression::FunctionRef { type_, .. } => type_.clone(), 286 + Expression::Var(var) => var.type_.clone(), 287 + Expression::Int { .. } => CompleteType::Int, 288 + Expression::Float { .. } => CompleteType::Float, 289 + Expression::Bool { .. } => CompleteType::Bool, 290 + Expression::String { .. } => CompleteType::String, 291 + Expression::Equals { .. } => CompleteType::Bool, 292 + Expression::NotEquals { .. } => CompleteType::Bool, 293 + Expression::IntGt { .. } => CompleteType::Bool, 294 + Expression::IntGtEq { .. } => CompleteType::Bool, 295 + Expression::IntLt { .. } => CompleteType::Bool, 296 + Expression::IntLtEq { .. } => CompleteType::Bool, 297 + Expression::IntAdd { .. } => CompleteType::Int, 298 + Expression::IntSub { .. } => CompleteType::Int, 299 + Expression::IntMul { .. } => CompleteType::Int, 300 + Expression::IntDiv { .. } => CompleteType::Int, 301 + Expression::IntRem { .. } => CompleteType::Int, 302 + Expression::FloatGt { .. } => CompleteType::Bool, 303 + Expression::FloatGtEq { .. } => CompleteType::Bool, 304 + Expression::FloatLt { .. } => CompleteType::Bool, 305 + Expression::FloatLtEq { .. } => CompleteType::Bool, 306 + Expression::FloatAdd { .. } => CompleteType::Bool, 307 + Expression::FloatSub { .. } => CompleteType::Bool, 308 + Expression::FloatMul { .. } => CompleteType::Bool, 309 + Expression::FloatDiv { .. } => CompleteType::Bool, 310 + Expression::StringConcat { .. } => CompleteType::Bool, 311 + Expression::List { type_, .. } => type_.clone(), 312 + Expression::Struct { type_, .. } => type_.clone(), 313 + Expression::StructTag { .. } => CompleteType::Int, 314 + Expression::StructAccess { type_, .. } => type_.clone(), 315 + Expression::Set { value, .. } => value.type_(), 316 + Expression::If { then, .. } => then.type_(), 317 + Expression::Call { type_, .. } => type_.clone(), 318 + } 319 + } 320 + }
test/project_cranelift/a.out

This is a binary file and will not be displayed.

test/project_cranelift/fib

This is a binary file and will not be displayed.

+11
test/project_cranelift/fib.c
··· 1 + #include <stdio.h> 2 + 3 + unsigned long long fib(unsigned long long n) { 4 + if (n==0)return 0; 5 + if (n==1)return 1; 6 + return fib(n-1)+fib(n-2); 7 + } 8 + 9 + int main(void) { 10 + printf("%lld\n", fib(40)); 11 + }
+8
test/project_cranelift/main.c
··· 1 + #include <stdio.h> 2 + 3 + int M17project_cranelift_4main_A0_RI(); 4 + 5 + int main() { 6 + unsigned long long outcome = M17project_cranelift_4main_A0_RI(); 7 + printf("%lld\n", outcome); 8 + }
+6 -18
test/project_cranelift/src/project_cranelift.gleam
··· 1 - pub type Option(some) { 2 - Some(some) 3 - None 4 - } 5 - 6 - fn replace(option: Option(a), with: b) -> Option(b) { 7 - case option { 8 - Some(_) -> Some(with) 9 - None -> None 1 + fn fib(n: Int) -> Int { 2 + case n { 3 + 0 -> 0 4 + 1 -> 1 5 + _ -> fib(n - 1) + fib(n - 2) 10 6 } 11 - } 12 - 13 - fn are_equal(lhs: a, rhs: a) -> Bool { 14 - lhs == rhs 15 7 } 16 8 17 9 pub fn main() { 18 - are_equal(1, 2) 19 - are_equal("hi", "hello") 20 - 21 - replace(Some(10), 20) 22 - replace(Some("hi"), "hello") 10 + fib(40) 23 11 }