1pub mod alloc;
2pub mod alloc_util;
3pub mod constants;
4pub mod ctx;
5mod vec;
6
7use crate::alloc::{FrameMemoryRegion, ScopeAllocator};
8use crate::alloc_util::{
9 layout_struct, layout_tuple, layout_union, reserve_space_for_type, type_size_and_alignment,
10};
11use crate::ctx::Context;
12use crate::vec::{VECTOR_DATA_PTR_OFFSET, VECTOR_LENGTH_OFFSET};
13use seq_map::SeqMap;
14use std::ops::Deref;
15use swamp_script_semantic::{
16 ArgumentExpressionOrLocation, BinaryOperator, BinaryOperatorKind, BooleanExpression,
17 CompoundOperatorKind, EnumLiteralData, Expression, ExpressionKind, ForPattern, Function,
18 FunctionScopeState, InternalFunctionDefinition, InternalFunctionDefinitionRef,
19 InternalFunctionId, InternalMainExpression, Iterable, Literal, LocationAccessKind,
20 MutOrImmutableExpression, Postfix, PostfixKind, SingleLocationExpression,
21 SingleMutLocationExpression, StructInstantiation, VariableRef,
22};
23use swamp_script_types::{AnonymousStructType, EnumVariantType, Signature, StructTypeField, Type};
24
25use crate::constants::ConstantsManager;
26use swamp_script_semantic::intr::IntrinsicFunction;
27use swamp_vm_instr_build::{InstructionBuilder, PTR_SIZE, PatchPosition, VEC_SIZE};
28use swamp_vm_types::opcode::OpCode;
29use swamp_vm_types::{
30 BinaryInstruction, FrameMemoryAddress, FrameMemorySize, InstructionPosition, MemoryAddress,
31 MemoryAlignment, MemoryOffset, MemorySize,
32};
33use tracing::{info, trace};
34
35pub struct FunctionInfo {
36 pub starts_at_ip: InstructionPosition,
37 pub internal_function_definition: InternalFunctionDefinitionRef,
38}
39
40pub struct FunctionFixup {
41 pub patch_position: PatchPosition,
42 pub fn_id: InternalFunctionId,
43 }
45
46pub struct CodeGenState {
47 builder: InstructionBuilder,
48 constants: ConstantsManager,
49 function_infos: SeqMap<InternalFunctionId, FunctionInfo>,
50 function_fixups: Vec<FunctionFixup>,
51}
52
53impl CodeGenState {
54 pub fn create_function_sections(&self) -> SeqMap<InstructionPosition, String> {
55 let mut lookups = SeqMap::new();
56 for (_func_id, function_info) in &self.function_infos {
57 let description = format!(
58 "{}",
59 function_info.internal_function_definition.assigned_name
60 );
61 lookups
62 .insert(function_info.starts_at_ip.clone(), description)
63 .unwrap()
64 }
65
66 lookups
67 }
68}
69
70impl CodeGenState {
71 pub(crate) fn add_call(&mut self, internal_fn: &InternalFunctionDefinitionRef, comment: &str) {
72 let call_comment = &format!("calling {} ({})", internal_fn.assigned_name, comment);
73
74 if let Some(found) = self.function_infos.get(&internal_fn.program_unique_id) {
75 self.builder.add_call(&found.starts_at_ip, call_comment);
76 } else {
77 let patch_position = self.builder.add_call_placeholder(call_comment);
78 self.function_fixups.push(FunctionFixup {
79 patch_position,
80 fn_id: internal_fn.program_unique_id,
81 });
82 }
83 }
84}
85
86impl CodeGenState {
87 #[must_use]
88 pub fn instructions(&self) -> &[BinaryInstruction] {
89 &self.builder.instructions
90 }
91
92 #[must_use]
93 pub fn comments(&self) -> &[String] {
94 &self.builder.comments
95 }
96
97 pub fn finalize(&mut self) {
98 for function_fixup in &self.function_fixups {
99 let func = self.function_infos.get(&function_fixup.fn_id).unwrap();
100 self.builder.patch_call(
101 PatchPosition(InstructionPosition(function_fixup.patch_position.0.0)),
102 &func.starts_at_ip,
103 );
104 }
105 }
106}
107
108pub struct GenOptions {
109 pub is_halt_function: bool,
110}
111impl Default for CodeGenState {
112 fn default() -> Self {
113 Self::new()
114 }
115}
116
117impl CodeGenState {
118 #[must_use]
119 pub fn new() -> Self {
120 Self {
121 builder: InstructionBuilder::default(),
122 constants: ConstantsManager::new(),
123 function_infos: SeqMap::default(),
124 function_fixups: vec![],
125 }
126 }
127
128 #[must_use]
129 pub fn take_instructions_and_constants(self) -> (Vec<BinaryInstruction>, Vec<u8>) {
130 (self.builder.instructions, self.constants.take_data())
131 }
132
133 pub fn gen_function_def(
134 &mut self,
135 internal_fn_def: &InternalFunctionDefinitionRef,
136 options: &GenOptions,
137 ) {
138 info!(?internal_fn_def.assigned_name, ?internal_fn_def.program_unique_id, "generating function");
139 assert_ne!(internal_fn_def.program_unique_id, 0);
140 self.function_infos
141 .insert(
142 internal_fn_def.program_unique_id,
143 FunctionInfo {
144 starts_at_ip: self.builder.position(),
145 internal_function_definition: internal_fn_def.clone(),
146 },
147 )
148 .unwrap();
149
150 let mut function_generator = FunctionCodeGen::new(self, internal_fn_def.program_unique_id);
151
152 let mut ctx = Context::new(FrameMemoryRegion::new(
153 FrameMemoryAddress(0),
154 MemorySize(512),
155 ));
156
157 function_generator.layout_variables(
158 &internal_fn_def.function_scope_state,
159 &internal_fn_def.signature.return_type,
160 );
161
162 function_generator.gen_expression(&internal_fn_def.body, &mut ctx);
163
164 self.finalize_function(options);
165 }
166
167 pub fn finalize_function(&mut self, options: &GenOptions) {
168 if options.is_halt_function {
169 self.builder.add_hlt("");
170 } else {
171 self.builder.add_ret("");
172 }
173 }
174
175 pub fn gen_main_function(&mut self, main: &InternalMainExpression, options: &GenOptions) {
176 let mut function_generator = FunctionCodeGen::new(self, main.program_unique_id);
177
178 function_generator.layout_variables(&main.function_scope_state, &main.expression.ty);
179 let mut empty_ctx = Context::new(FrameMemoryRegion::default()); function_generator.gen_expression(&main.expression, &mut empty_ctx);
181 self.finalize_function(options);
182 }
183}
184
185pub struct FunctionCodeGen<'a> {
186 state: &'a mut CodeGenState,
187 variable_offsets: SeqMap<usize, FrameMemoryRegion>,
188 frame_size: FrameMemorySize,
189 extra_frame_allocator: ScopeAllocator,
190 temp_allocator: ScopeAllocator,
191 fn_id: InternalFunctionId,
192}
193
194impl<'a> FunctionCodeGen<'a> {
195 #[must_use]
196 pub fn new(state: &'a mut CodeGenState, fn_id: InternalFunctionId) -> Self {
197 Self {
198 fn_id,
199 state,
200 variable_offsets: SeqMap::default(),
201 frame_size: FrameMemorySize(0),
202 extra_frame_allocator: ScopeAllocator::new(FrameMemoryRegion::default()),
203 temp_allocator: ScopeAllocator::new(FrameMemoryRegion::default()),
204 }
205 }
206
207 pub fn reserve(ty: &Type, allocator: &mut ScopeAllocator) -> FrameMemoryRegion {
208 let (size, alignment) = type_size_and_alignment(ty);
209 allocator.reserve(size, alignment)
210 }
211
212 pub fn layout_variables(&mut self, variables: &Vec<VariableRef>, return_type: &Type) {
213 let mut allocator = ScopeAllocator::new(FrameMemoryRegion::new(
214 FrameMemoryAddress(0),
215 MemorySize(1024),
216 ));
217 let _current_offset = Self::reserve(return_type, &mut allocator);
218
219 let mut enter_comment = "variables:\n".to_string();
220
221 for var_ref in variables {
222 let var_target = Self::reserve(&var_ref.resolved_type, &mut allocator);
223 trace!(?var_ref.assigned_name, ?var_target, "laying out");
224 enter_comment += &format!(
225 " ${:04X}:{} {}\n",
226 var_target.addr.0, var_target.size.0, var_ref.assigned_name
227 );
228 self.variable_offsets
229 .insert(var_ref.unique_id_within_function, var_target)
230 .unwrap();
231 }
232
233 let extra_frame_size = MemorySize(80);
234 let extra_target = FrameMemoryRegion::new(allocator.addr(), extra_frame_size);
235 self.extra_frame_allocator = ScopeAllocator::new(extra_target);
236 self.frame_size = allocator.addr().as_size().add(extra_frame_size);
237
238 self.state
239 .builder
240 .add_enter(self.frame_size, &enter_comment);
241
242 self.temp_allocator = ScopeAllocator::new(FrameMemoryRegion::new(
243 FrameMemoryAddress(self.frame_size.0),
244 MemorySize(1024),
245 ));
246 }
247
248 pub fn temp_memory_region_for_type(&mut self, ty: &Type, comment: &str) -> FrameMemoryRegion {
249 let new_target_info = reserve_space_for_type(ty, &mut self.temp_allocator);
250 trace!(?new_target_info, "creating temporary space");
251 new_target_info
252 }
253 pub fn temp_space_for_type(&mut self, ty: &Type, comment: &str) -> Context {
254 Context::new(self.temp_memory_region_for_type(ty, comment))
255 }
256
257 #[allow(clippy::single_match_else)]
260 pub fn gen_expression_for_access(
261 &mut self,
262 expr: &Expression,
263 ctx: &Context,
264 ) -> FrameMemoryRegion {
265 match &expr.kind {
266 ExpressionKind::VariableAccess(var_ref) => {
267 let frame_address = self
268 .variable_offsets
269 .get(&var_ref.unique_id_within_function)
270 .unwrap();
271
272 *frame_address
273 }
274
275 _ => {
276 let mut temp_ctx = self.temp_space_for_type(&expr.ty, "expression");
277
278 self.gen_expression(expr, &mut temp_ctx);
279
280 temp_ctx.target()
281 }
282 }
283 }
284
285 pub(crate) fn extra_frame_space_for_type(&mut self, ty: &Type) -> Context {
286 let target = Self::reserve(ty, &mut self.extra_frame_allocator);
287 Context::new(target)
288 }
289
290 pub fn gen_expression(&mut self, expr: &Expression, ctx: &Context) {
291 match &expr.kind {
292 ExpressionKind::ConstantAccess(_) => todo!(),
293 ExpressionKind::VariableAccess(variable_ref) => {
294 self.gen_variable_access(variable_ref, ctx);
295 }
296 ExpressionKind::IntrinsicFunctionAccess(_) => todo!(),
297 ExpressionKind::InternalFunctionAccess(function) => {
298 self.internal_function_access(function, ctx);
299 }
300 ExpressionKind::ExternalFunctionAccess(_) => todo!(),
301 ExpressionKind::BinaryOp(operator) => self.gen_binary_operator(operator, ctx),
302 ExpressionKind::UnaryOp(_) => todo!(),
303 ExpressionKind::PostfixChain(start, chain) => self.gen_postfix_chain(start, chain, ctx),
304 ExpressionKind::CoerceOptionToBool(_) => todo!(),
305 ExpressionKind::FunctionCall(_, _, _) => todo!(),
306 ExpressionKind::InterpolatedString(_) => todo!(),
307 ExpressionKind::VariableDefinition(variable, expression) => {
308 self.gen_variable_definition(variable, expression, ctx);
309 }
310 ExpressionKind::VariableReassignment(variable, expression) => {
311 self.gen_variable_reassignment(variable, expression, ctx);
312 }
313 ExpressionKind::StructInstantiation(struct_literal) => {
314 self.gen_struct_literal(struct_literal, ctx)
315 }
316 ExpressionKind::AnonymousStructLiteral(_) => todo!(),
317 ExpressionKind::Literal(basic_literal) => self.gen_literal(basic_literal, ctx),
318 ExpressionKind::Option(maybe_option) => {
319 self.gen_option_expression(maybe_option.as_deref(), ctx)
320 }
321 ExpressionKind::Range(_, _, _) => todo!(),
322 ExpressionKind::ForLoop(a, b, c) => self.gen_for_loop(a, b, c, ctx),
323 ExpressionKind::WhileLoop(condition, expression) => {
324 self.gen_while_loop(condition, expression, ctx);
325 }
326 ExpressionKind::Block(expressions) => self.gen_block(expressions, ctx),
327 ExpressionKind::Match(_) => todo!(),
328 ExpressionKind::Guard(_) => todo!(),
329 ExpressionKind::If(conditional, true_expr, false_expr) => {
330 self.gen_if(conditional, true_expr, false_expr.as_deref(), ctx);
331 }
332 ExpressionKind::When(_, _, _) => todo!(),
333 ExpressionKind::TupleDestructuring(_, _, _) => todo!(),
334 ExpressionKind::Assignment(_, _) => todo!(),
335 ExpressionKind::CompoundAssignment(target_location, operator_kind, source_expr) => {
336 self.compound_assignment(target_location, operator_kind, source_expr, ctx);
337 }
338 ExpressionKind::IntrinsicCallMut(_, _, _) => todo!(),
339 ExpressionKind::IntrinsicCallEx(intrinsic_fn, arguments) => {
340 self.gen_intrinsic_call_ex(intrinsic_fn, arguments, ctx);
341 }
342 }
343 }
344
345 fn gen_binary_operator(&mut self, binary_operator: &BinaryOperator, ctx: &Context) {
346 match (&binary_operator.left.ty, &binary_operator.right.ty) {
347 (Type::Int, Type::Int) => self.gen_binary_operator_i32(binary_operator, ctx),
348 _ => todo!(),
349 }
350 }
351
352 fn gen_binary_operator_i32(&mut self, binary_operator: &BinaryOperator, ctx: &Context) {
353 let left_source = self.gen_expression_for_access(&binary_operator.left, ctx);
354 let right_source = self.gen_expression_for_access(&binary_operator.right, ctx);
355
356 match binary_operator.kind {
357 BinaryOperatorKind::Add => {
358 self.state.builder.add_add_i32(
359 ctx.addr(),
360 left_source.addr(),
361 right_source.addr(),
362 "i32 add",
363 );
364 }
365
366 BinaryOperatorKind::Subtract => todo!(),
367 BinaryOperatorKind::Multiply => todo!(),
368 BinaryOperatorKind::Divide => todo!(),
369 BinaryOperatorKind::Modulo => todo!(),
370 BinaryOperatorKind::LogicalOr => todo!(),
371 BinaryOperatorKind::LogicalAnd => todo!(),
372 BinaryOperatorKind::Equal => todo!(),
373 BinaryOperatorKind::NotEqual => todo!(),
374 BinaryOperatorKind::LessThan => {
375 self.state.builder.add_lt_i32(
376 ctx.addr(),
377 left_source.addr(),
378 right_source.addr(),
379 "i32 lt",
380 );
381 }
382 BinaryOperatorKind::LessEqual => todo!(),
383 BinaryOperatorKind::GreaterThan => todo!(),
384 BinaryOperatorKind::GreaterEqual => todo!(),
385 BinaryOperatorKind::RangeExclusive => todo!(),
386 }
387 }
388
389 fn gen_condition_context(
390 &mut self,
391 condition: &BooleanExpression,
392 ctx: &Context,
393 ) -> (Context, PatchPosition) {
394 let mut condition_ctx = self.extra_frame_space_for_type(&Type::Bool);
395 self.gen_expression(&condition.expression, &mut condition_ctx);
396
397 let jump_on_false_condition = self
398 .state
399 .builder
400 .add_conditional_jump_placeholder(condition_ctx.addr(), "jump boolean condition false");
401
402 (condition_ctx, jump_on_false_condition)
403 }
404
405 fn gen_if(
406 &mut self,
407 condition: &BooleanExpression,
408 true_expr: &Expression,
409 maybe_false_expr: Option<&Expression>,
410 ctx: &Context,
411 ) {
412 let (_condition_ctx, jump_on_false_condition) = self.gen_condition_context(condition, ctx);
413
414 self.gen_expression(true_expr, ctx);
416
417 if let Some(false_expr) = maybe_false_expr {
418 let skip_false_if_true = self
420 .state
421 .builder
422 .add_jump_placeholder("condition is false skip");
423
424 self.state.builder.patch_jump_here(jump_on_false_condition);
426
427 self.gen_expression(false_expr, ctx);
429
430 self.state.builder.patch_jump_here(skip_false_if_true);
431 } else {
432 self.state.builder.patch_jump_here(jump_on_false_condition);
433 }
434 }
435
436 fn gen_while_loop(
437 &mut self,
438 condition: &BooleanExpression,
439 expression: &Expression,
440 ctx: &Context,
441 ) {
442 assert_eq!(ctx.target_size().0, 0);
444
445 let ip_for_condition = self.state.builder.position();
446
447 let (_condition_ctx, jump_on_false_condition) = self.gen_condition_context(condition, ctx);
448
449 let mut unit_ctx = self.temp_space_for_type(&Type::Unit, "while body expression");
451 self.gen_expression(expression, &mut unit_ctx);
452
453 self.state
455 .builder
456 .add_jmp(ip_for_condition, "jmp to while condition");
457
458 self.state.builder.patch_jump_here(jump_on_false_condition);
459 }
460
461 fn gen_location_argument(
462 &mut self,
463 argument: &SingleLocationExpression,
464 ctx: &Context,
465 comment: &str,
466 ) {
467 let region = self.gen_lvalue_address(argument);
468
469 self.state
470 .builder
471 .add_mov(ctx.addr(), region.addr, region.size, comment)
472 }
473
474 fn gen_argument(
475 &mut self,
476 argument: &ArgumentExpressionOrLocation,
477 ctx: &Context,
478 comment: &str,
479 ) {
480 match &argument {
481 ArgumentExpressionOrLocation::Expression(found_expression) => {
482 self.gen_expression(found_expression, ctx);
483 }
484 ArgumentExpressionOrLocation::Location(location_expression) => {
485 self.gen_location_argument(location_expression, ctx, comment);
486 }
487 }
488 }
489
490 fn gen_mut_or_immute(
491 &mut self,
492 mut_or_immutable_expression: &MutOrImmutableExpression,
493 ctx: &mut Context,
494 ) {
495 match &mut_or_immutable_expression.expression_or_location {
496 ArgumentExpressionOrLocation::Expression(found_expression) => {
497 self.gen_expression(found_expression, ctx);
498 }
499 ArgumentExpressionOrLocation::Location(location_expression) => {
500 self.gen_lvalue_address(location_expression);
501 }
502 }
503 }
504 fn gen_variable_assignment(
505 &mut self,
506 variable: &VariableRef,
507 mut_or_immutable_expression: &MutOrImmutableExpression,
508 ctx: &Context,
509 ) {
510 let target_relative_frame_pointer = self
511 .variable_offsets
512 .get(&variable.unique_id_within_function)
513 .unwrap_or_else(|| panic!("{}", variable.assigned_name));
514
515 let mut init_ctx =
516 ctx.with_target(*target_relative_frame_pointer, "variable assignment target");
517
518 self.gen_mut_or_immute(mut_or_immutable_expression, &mut init_ctx);
519 }
520
521 fn gen_variable_definition(
522 &mut self,
523 variable: &VariableRef,
524 mut_or_immutable_expression: &MutOrImmutableExpression,
525 ctx: &Context,
526 ) {
527 self.gen_variable_assignment(variable, mut_or_immutable_expression, ctx);
528 }
529
530 fn gen_variable_reassignment(
531 &mut self,
532 variable: &VariableRef,
533 mut_or_immutable_expression: &Box<MutOrImmutableExpression>,
534 ctx: &Context,
535 ) {
536 self.gen_variable_assignment(variable, mut_or_immutable_expression, ctx);
537 }
538
539 fn gen_lvalue_address(
540 &mut self,
541 location_expression: &SingleLocationExpression,
542 ) -> FrameMemoryRegion {
543 let frame_relative_base_address = self
544 .variable_offsets
545 .get(
546 &location_expression
547 .starting_variable
548 .unique_id_within_function,
549 )
550 .unwrap();
551
552 *frame_relative_base_address
553
554 }
574
575 fn copy_back_mutable_arguments(
576 &mut self,
577 signature: &Signature,
578 maybe_self: Option<FrameMemoryRegion>,
579 arguments: &Vec<ArgumentExpressionOrLocation>,
580 ) {
581 let arguments_memory_region = self.infinite_above_frame_size();
582 let mut arguments_allocator = ScopeAllocator::new(arguments_memory_region);
583
584 let _argument_addr = Self::reserve(&signature.return_type, &mut arguments_allocator);
585
586 let mut parameters = signature.parameters.clone();
587 if let Some(found_self) = maybe_self {
588 let source_region =
589 Self::reserve(¶meters[0].resolved_type, &mut arguments_allocator);
590 self.state.builder.add_mov(
591 found_self.addr,
592 source_region.addr,
593 source_region.size,
594 "copy back to <self>",
595 );
596 parameters.remove(0);
597 }
598 for (parameter, argument) in parameters.iter().zip(arguments) {
599 let source_region = Self::reserve(¶meter.resolved_type, &mut arguments_allocator);
600 if !parameter.is_mutable {
601 continue;
602 }
603
604 if let ArgumentExpressionOrLocation::Location(found_location) = argument {
605 let argument_target = self.gen_lvalue_address(found_location);
606 self.state.builder.add_mov(
607 argument_target.addr,
608 source_region.addr,
609 source_region.size,
610 &format!(
611 "copy back mutable argument {}",
612 found_location.starting_variable.assigned_name
613 ),
614 );
615 } else {
616 panic!("internal error. argument is mut but not a location")
617 }
618 }
619 }
620 fn gen_arguments(
621 &mut self,
622 signature: &Signature,
623 self_region: Option<FrameMemoryRegion>,
624 arguments: &Vec<ArgumentExpressionOrLocation>,
625 ) {
626 let arguments_memory_region = self.infinite_above_frame_size();
627 let mut arguments_allocator = ScopeAllocator::new(arguments_memory_region);
628
629 let _argument_addr = Self::reserve(&signature.return_type, &mut arguments_allocator);
630
631 let mut argument_targets = Vec::new();
632 let mut argument_comments = Vec::new();
633
634 for type_for_parameter in &signature.parameters {
635 let argument_target =
636 Self::reserve(&type_for_parameter.resolved_type, &mut arguments_allocator);
637 let arg_ctx = Context::new(argument_target);
638 argument_targets.push(arg_ctx);
639 argument_comments.push(format!("argument {}", type_for_parameter.name));
640 }
641
642 if let Some(push_self) = self_region {
643 self.state.builder.add_mov(
644 argument_targets[0].addr(),
645 push_self.addr,
646 push_self.size,
647 "<self>",
648 );
649 argument_targets.remove(0);
650 }
651
652 for ((argument_target_ctx, argument_expr_or_loc), argument_comment) in argument_targets
653 .iter()
654 .zip(arguments)
655 .zip(argument_comments)
656 {
657 self.gen_argument(
658 argument_expr_or_loc,
659 &argument_target_ctx,
660 &argument_comment,
661 );
662 }
663 }
664
665 fn gen_postfix_chain(
666 &mut self,
667 start_expression: &Expression,
668 chain: &[Postfix],
669 ctx: &Context,
670 ) {
671 if let ExpressionKind::InternalFunctionAccess(internal_fn) = &start_expression.kind {
672 if chain.len() == 1 {
673 if let PostfixKind::FunctionCall(args) = &chain[0].kind {
674 self.gen_arguments(&internal_fn.signature, None, args);
675 self.state
676 .add_call(internal_fn, &format!("frame size: {}", self.frame_size)); let (return_size, _alignment) =
678 type_size_and_alignment(&internal_fn.signature.return_type);
679 if return_size.0 != 0 {
680 self.state.builder.add_mov(
681 ctx.addr(),
682 self.infinite_above_frame_size().addr,
683 return_size,
684 "copy the return value to destination",
685 );
686 }
687 self.copy_back_mutable_arguments(&internal_fn.signature, None, args);
688
689 return;
690 }
691 }
692 }
693
694 let start_source = self.gen_expression_for_access(start_expression, ctx);
695
696 for element in chain {
697 match &element.kind {
698 PostfixKind::StructField(_, _) => todo!(),
699 PostfixKind::MemberCall(function_to_call, arguments) => {
700 match &**function_to_call {
701 Function::Internal(internal_fn) => {
702 self.gen_arguments(
703 &internal_fn.signature,
704 Some(start_source),
705 arguments,
706 );
707 self.state
708 .add_call(internal_fn, &format!("frame size: {}", self.frame_size)); let (return_size, _alignment) =
710 type_size_and_alignment(&internal_fn.signature.return_type);
711 if return_size.0 != 0 {
712 self.state.builder.add_mov(
713 ctx.addr(),
714 self.infinite_above_frame_size().addr,
715 return_size,
716 "copy the return value to destination",
717 );
718 }
719
720 self.copy_back_mutable_arguments(
721 &internal_fn.signature,
722 Some(start_source),
723 arguments,
724 );
725 }
726 Function::External(external_fn) => {
727 }
729 }
730 }
731 PostfixKind::FunctionCall(arguments) => {
732 }
735 PostfixKind::OptionUnwrap => todo!(),
736 PostfixKind::NoneCoalesce(_) => todo!(),
737 PostfixKind::IntrinsicCall(_, _) => todo!(),
738 }
739 }
740 }
741
742 fn gen_tuple(&mut self, expressions: &[Expression], ctx: &Context) {
743 let mut scope = ScopeAllocator::new(ctx.target());
744
745 for expr in expressions {
746 let (memory_size, alignment) = type_size_and_alignment(&expr.ty);
747 let start_addr = scope.allocate(memory_size, alignment);
748 let element_region = FrameMemoryRegion::new(start_addr, memory_size);
749 let element_ctx = Context::new(element_region);
750 self.gen_expression(expr, &element_ctx);
751 }
752 }
753
754 fn get_struct_field_offset(
755 fields: &SeqMap<String, StructTypeField>,
756 index_to_find: usize,
757 ) -> MemoryOffset {
758 let mut offset = 0;
759
760 for (index, (_name, field)) in fields.iter().enumerate() {
761 if index == index_to_find {
762 break;
763 }
764
765 let (struct_field, struct_field_align) = type_size_and_alignment(&field.field_type);
766 offset += struct_field.0;
767 }
768
769 MemoryOffset(offset)
770 }
771
772 fn gen_anonymous_struct(
773 &mut self,
774 anon_struct_type: &AnonymousStructType,
775 source_order_expressions: &Vec<(usize, Expression)>,
776 base_context: &Context,
777 ) {
778 for (field_index, expression) in source_order_expressions {
779 let field_memory_offset = Self::get_struct_field_offset(
780 &anon_struct_type.field_name_sorted_fields,
781 *field_index,
782 );
783 let mut field_ctx = base_context.with_offset(MemorySize(field_memory_offset.0));
784 self.gen_expression(expression, &mut field_ctx);
785 }
786 }
787
788 fn gen_literal(&mut self, literal: &Literal, ctx: &Context) {
789 match literal {
790 Literal::IntLiteral(int) => {
791 self.state.builder.add_ld32(ctx.addr(), *int, "int literal");
792 }
793 Literal::FloatLiteral(fixed_point) => {
794 self.state
795 .builder
796 .add_ld32(ctx.addr(), fixed_point.inner(), "float literal");
797 }
798 Literal::NoneLiteral => {
799 self.state.builder.add_ld8(ctx.addr(), 0, "none literal");
800 }
801 Literal::BoolLiteral(truthy) => {
802 self.state
803 .builder
804 .add_ld8(ctx.addr(), u8::from(*truthy), "bool literal");
805 }
806
807 Literal::EnumVariantLiteral(enum_type, a, b) => {
808 self.state.builder.add_ld8(
809 ctx.addr(),
810 a.common().container_index,
811 &format!("enum variant {} tag", a.common().assigned_name),
812 );
813
814 let starting_offset = MemoryOffset(1);
815
816 let (data_size, data_alignment) = match a {
817 EnumVariantType::Struct(enum_variant_struct) => {
818 layout_struct(&enum_variant_struct.anon_struct)
819 }
820 EnumVariantType::Tuple(tuple_type) => layout_tuple(&tuple_type.fields_in_order),
821 EnumVariantType::Nothing(_) => (MemorySize(0), MemoryAlignment::U8),
822 };
823
824 let skip_octets: usize = data_alignment.into();
825 let skip = MemorySize(skip_octets as u16);
826 let inner_addr = ctx.addr().add(skip);
827 let region = FrameMemoryRegion::new(inner_addr, data_size);
828 let inner_ctx = Context::new(region);
829
830 match b {
832 EnumLiteralData::Nothing => {}
833 EnumLiteralData::Tuple(expressions) => {
834 self.gen_tuple(expressions, &inner_ctx);
835 }
836 EnumLiteralData::Struct(sorted_expressions) => {
837 if let EnumVariantType::Struct(variant_struct_type) = a {
838 self.gen_anonymous_struct(
839 &variant_struct_type.anon_struct,
840 sorted_expressions,
841 &inner_ctx,
842 );
843 }
844 }
845 }
846 }
847 Literal::TupleLiteral(_, _) => todo!(),
848 Literal::StringLiteral(str) => {
849 self.gen_string_literal(str, ctx);
850 }
851 Literal::Slice(ty, expressions) => self.gen_slice_literal(ty, expressions, ctx),
852 Literal::SlicePair(_, _) => todo!(),
853 }
854 }
855
856 fn gen_string_literal(&mut self, string: &str, ctx: &Context) {
857 let data_ptr = self
858 .state
859 .constants
860 .allocate(string.as_bytes(), MemoryAlignment::U8);
861 let mem_size = MemorySize(string.len() as u16);
862
863 self.gen_vec_immediate(data_ptr, mem_size, mem_size, "string", ctx);
864 }
865
866 fn gen_vec_immediate(
867 &mut self,
868 data_ptr: MemoryAddress,
869 len: MemorySize,
870 capacity: MemorySize,
871 comment_prefix: &str,
872 ctx: &Context,
873 ) {
874 self.state
875 .builder
876 .add_ld_u16(ctx.addr(), len.0, &format!("{} len", comment_prefix));
877
878 self.state.builder.add_ld_u16(
879 ctx.addr().add(MemorySize(2)),
880 capacity.0,
881 &format!("{} capacity", comment_prefix),
882 );
883
884 self.state.builder.add_ld_u16(
885 ctx.addr().add(MemorySize(4)),
886 data_ptr.0,
887 &format!("{} ptr", comment_prefix),
888 );
889 }
890
891 fn gen_option_expression(&mut self, maybe_option: Option<&Expression>, ctx: &Context) {
892 if let Some(found_value) = maybe_option {
893 self.state.builder.add_ld8(ctx.addr(), 1, "option Some tag"); let mut one_offset_ctx = ctx.with_offset(MemorySize(1));
895 self.gen_expression(found_value, &mut one_offset_ctx); } else {
897 self.state.builder.add_ld8(ctx.addr(), 0, "option None tag"); }
900 }
901
902 fn gen_for_loop(
903 &mut self,
904 for_pattern: &ForPattern,
905 iterable: &Iterable,
906 body: &Box<Expression>,
907 ctx: &Context,
908 ) {
909 match for_pattern {
916 ForPattern::Single(value_variable) => {}
917 ForPattern::Pair(key_variable, value_variable) => {}
918 }
919
920 let mut unit_expr = self.temp_space_for_type(&Type::Unit, "for loop body");
921 self.gen_expression(body, &mut unit_expr);
922
923 }
926
927 fn gen_for_loop_for_vec(
928 &mut self,
929 element_type: &Type,
930 vector_expr: Expression,
931 ctx: &mut Context,
932 ) {
933 let mut vector_ctx = self.temp_space_for_type(&vector_expr.ty, "vector space");
935 self.gen_expression(&vector_expr, &mut vector_ctx);
936
937 }
1021
1022 fn gen_block(&mut self, expressions: &[Expression], ctx: &Context) {
1023 if let Some((last, others)) = expressions.split_last() {
1024 for expr in others {
1025 let mut temp_context = self.temp_space_for_type(&Type::Unit, "block target");
1026 self.gen_expression(expr, &mut temp_context);
1027 }
1028 self.gen_expression(last, ctx);
1029 }
1030 }
1031
1032 fn gen_variable_access(&mut self, variable: &VariableRef, ctx: &Context) {
1033 let frame_address = self
1034 .variable_offsets
1035 .get(&variable.unique_id_within_function)
1036 .unwrap();
1037 let (size, _align) = type_size_and_alignment(&variable.resolved_type);
1038 self.state.builder.add_mov(
1039 ctx.addr(),
1040 frame_address.addr,
1041 size,
1042 &format!(
1043 "variable access '{}' ({})",
1044 variable.assigned_name,
1045 ctx.comment()
1046 ),
1047 );
1048 }
1049
1050 fn referenced_or_not_type(ty: &Type) -> Type {
1051 if let Type::MutableReference(inner_type) = ty {
1052 *inner_type.clone()
1053 } else {
1054 ty.clone()
1055 }
1056 }
1057
1058 fn compound_assignment(
1059 &mut self,
1060 target_location: &SingleMutLocationExpression,
1061 op: &CompoundOperatorKind,
1062 source: &Expression,
1063 ctx: &Context,
1064 ) {
1065 let target_location = self.gen_lvalue_address(&target_location.0);
1066
1067 let source_info = self.gen_expression_for_access(source, ctx);
1068
1069 let type_to_consider = Self::referenced_or_not_type(&source.ty);
1070
1071 match &type_to_consider {
1072 Type::Int => {
1073 self.gen_compound_assignment_i32(&target_location, op, &source_info);
1074 }
1075 Type::Float => todo!(),
1076 Type::String => todo!(),
1077 Type::Bool => todo!(),
1078 Type::Unit => todo!(),
1079 Type::Never => todo!(),
1080 Type::Tuple(_) => todo!(),
1081 Type::NamedStruct(_) => todo!(),
1082 Type::AnonymousStruct(_) => todo!(),
1083 Type::Enum(_) => todo!(),
1084 Type::Function(_) => todo!(),
1085 Type::Iterable(_) => todo!(),
1086 Type::Optional(_) => todo!(),
1087 Type::Generic(_, _) => todo!(),
1088 Type::Blueprint(_) => todo!(),
1089 Type::Variable(_) => todo!(),
1090 Type::External(_) => todo!(),
1091 Type::MutableReference(x) => panic!("should have been checked"),
1092 Type::Slice(_) => todo!(),
1093 Type::SlicePair(_, _) => todo!(),
1094 }
1095 }
1096
1097 fn gen_compound_assignment_i32(
1098 &mut self,
1099 target: &FrameMemoryRegion,
1100 op: &CompoundOperatorKind,
1101 source_ctx: &FrameMemoryRegion,
1102 ) {
1103 match op {
1104 CompoundOperatorKind::Add => {
1105 self.state.builder.add_add_i32(
1106 target.addr(),
1107 target.addr(),
1108 source_ctx.addr(),
1109 "+= (i32)",
1110 );
1111 }
1112 CompoundOperatorKind::Sub => todo!(),
1113 CompoundOperatorKind::Mul => todo!(),
1114 CompoundOperatorKind::Div => todo!(),
1115 CompoundOperatorKind::Modulo => todo!(),
1116 }
1117 }
1118
1119 fn internal_function_access(
1120 &mut self,
1121 internal: &InternalFunctionDefinitionRef,
1122 ctx: &Context,
1123 ) {
1124 self.state.builder.add_ld_u16(
1125 ctx.addr(),
1126 internal.program_unique_id,
1127 &format!("function access '{}'", internal.assigned_name),
1128 );
1129 }
1130
1131 fn infinite_above_frame_size(&self) -> FrameMemoryRegion {
1132 FrameMemoryRegion::new(FrameMemoryAddress(self.frame_size.0), MemorySize(1024))
1133 }
1134
1135 fn gen_struct_literal(&mut self, struct_literal: &StructInstantiation, ctx: &Context) {
1136 let struct_type =
1137 Type::AnonymousStruct(struct_literal.struct_type_ref.anon_struct_type.clone());
1138 let (whole_struct_size, whole_struct_alignment) = type_size_and_alignment(&struct_type);
1139 if ctx.target_size().0 != whole_struct_size.0 {
1140 info!("problem");
1141 }
1142 assert_eq!(ctx.target_size().0, whole_struct_size.0);
1143
1144 for (field_index, expression) in &struct_literal.source_order_expressions {
1145 let (field_offset, field_size, field_alignment) = struct_field_offset(
1146 *field_index,
1147 &struct_literal.struct_type_ref.anon_struct_type,
1148 );
1149 let new_address = ctx.addr().advance(field_offset);
1151 let mut field_ctx = Context::new(FrameMemoryRegion::new(new_address, field_size));
1152 self.gen_expression(expression, &mut field_ctx);
1153 }
1154 }
1155
1156 fn gen_slice_literal(&mut self, ty: &Type, expressions: &Vec<Expression>, ctx: &Context) {
1157 let (element_size, element_alignment) = type_size_and_alignment(ty);
1158 let element_count = expressions.len() as u16;
1159 let total_slice_size = MemorySize(element_size.0 * element_count);
1160
1161 let start_frame_address_to_transfer = self
1162 .temp_allocator
1163 .allocate(total_slice_size, element_alignment);
1164 for (index, expr) in expressions.iter().enumerate() {
1165 let memory_offset = MemoryOffset((index as u16) * element_size.0);
1166 let region = FrameMemoryRegion::new(
1167 start_frame_address_to_transfer.advance(memory_offset),
1168 element_size,
1169 );
1170 let element_ctx = Context::new(region);
1171 self.gen_expression(expr, &element_ctx);
1172 }
1173
1174 let vec_len_addr = self
1175 .extra_frame_allocator
1176 .allocate(MemorySize(2), MemoryAlignment::U16);
1177 self.state
1178 .builder
1179 .add_ld_u16(vec_len_addr, element_count, "vec len");
1180
1181 let vec_capacity_addr = self
1182 .extra_frame_allocator
1183 .allocate(MemorySize(2), MemoryAlignment::U16);
1184 self.state
1185 .builder
1186 .add_ld_u16(vec_capacity_addr, element_count, "vec capacity");
1187
1188 let vec_element_size_addr = self
1189 .extra_frame_allocator
1190 .allocate(MemorySize(2), MemoryAlignment::U16);
1191 self.state
1192 .builder
1193 .add_ld_u16(vec_element_size_addr, element_size.0, "element size");
1194
1195 let allocated_vec_address = self
1196 .extra_frame_allocator
1197 .allocate(MemorySize(PTR_SIZE), MemoryAlignment::U16);
1198 self.state
1199 .builder
1200 .add_alloc(allocated_vec_address, total_slice_size, "slice literal");
1201
1202 self.state.builder.add_stx(
1203 allocated_vec_address,
1204 MemoryOffset(0),
1205 start_frame_address_to_transfer,
1206 total_slice_size,
1207 "copy from slice continuous temporary frame memory to allocated vec ptr heap area",
1208 );
1209 }
1210
1211 fn gen_intrinsic_call_ex(
1212 &mut self,
1213 intrinsic_fn: &IntrinsicFunction,
1214 arguments: &Vec<ArgumentExpressionOrLocation>,
1215 ctx: &Context,
1216 ) {
1217 match intrinsic_fn {
1220 IntrinsicFunction::FloatRound => todo!(),
1221 IntrinsicFunction::FloatFloor => todo!(),
1222 IntrinsicFunction::FloatSqrt => todo!(),
1223 IntrinsicFunction::FloatSign => todo!(),
1224 IntrinsicFunction::FloatAbs => todo!(),
1225 IntrinsicFunction::FloatRnd => todo!(),
1226 IntrinsicFunction::FloatCos => todo!(),
1227 IntrinsicFunction::FloatSin => todo!(),
1228 IntrinsicFunction::FloatAcos => todo!(),
1229 IntrinsicFunction::FloatAsin => todo!(),
1230 IntrinsicFunction::FloatAtan2 => todo!(),
1231 IntrinsicFunction::FloatMin => todo!(),
1232 IntrinsicFunction::FloatMax => todo!(),
1233 IntrinsicFunction::FloatClamp => todo!(),
1234 IntrinsicFunction::IntAbs => todo!(),
1235 IntrinsicFunction::IntRnd => todo!(),
1236 IntrinsicFunction::IntMax => todo!(),
1237 IntrinsicFunction::IntMin => todo!(),
1238 IntrinsicFunction::IntClamp => todo!(),
1239 IntrinsicFunction::IntToFloat => todo!(),
1240 IntrinsicFunction::StringLen => todo!(),
1241 IntrinsicFunction::VecFromSlice => self.gen_intrinsic_vec_from_slice(arguments, ctx),
1242 IntrinsicFunction::VecPush => {}
1243 IntrinsicFunction::VecPop => {}
1244 IntrinsicFunction::VecRemoveIndex => {}
1245 IntrinsicFunction::VecClear => {}
1246 IntrinsicFunction::VecCreate => self.gen_intrinsic_vec_create(arguments),
1247 IntrinsicFunction::VecSubscript => {}
1248 IntrinsicFunction::VecSubscriptMut => {}
1249 IntrinsicFunction::VecIter => {} IntrinsicFunction::VecIterMut => {} IntrinsicFunction::VecLen => {}
1252 IntrinsicFunction::VecIsEmpty => {}
1253
1254 IntrinsicFunction::VecSelfPush => todo!(),
1255 IntrinsicFunction::VecSelfExtend => todo!(),
1256 IntrinsicFunction::MapCreate => todo!(),
1257 IntrinsicFunction::MapFromSlicePair => todo!(),
1258 IntrinsicFunction::MapHas => todo!(),
1259 IntrinsicFunction::MapRemove => todo!(),
1260 IntrinsicFunction::MapIter => todo!(),
1261 IntrinsicFunction::MapIterMut => todo!(),
1262 IntrinsicFunction::MapLen => todo!(),
1263 IntrinsicFunction::MapIsEmpty => todo!(),
1264 IntrinsicFunction::MapSubscript => todo!(),
1265 IntrinsicFunction::MapSubscriptSet => todo!(),
1266 IntrinsicFunction::MapSubscriptMut => todo!(),
1267 IntrinsicFunction::MapSubscriptMutCreateIfNeeded => todo!(),
1268 IntrinsicFunction::SparseCreate => todo!(),
1269 IntrinsicFunction::SparseFromSlice => todo!(),
1270 IntrinsicFunction::SparseIter => todo!(),
1271 IntrinsicFunction::SparseIterMut => todo!(),
1272 IntrinsicFunction::SparseSubscript => todo!(),
1273 IntrinsicFunction::SparseSubscriptMut => todo!(),
1274 IntrinsicFunction::SparseHas => todo!(),
1275 IntrinsicFunction::SparseRemove => todo!(),
1276 IntrinsicFunction::GridCreate => todo!(),
1277 IntrinsicFunction::GridFromSlice => todo!(),
1278 IntrinsicFunction::GridSubscript => todo!(),
1279 IntrinsicFunction::GridSubscriptMut => todo!(),
1280 IntrinsicFunction::Float2Magnitude => todo!(),
1281 IntrinsicFunction::SparseAdd => todo!(),
1282 IntrinsicFunction::SparseNew => todo!(),
1283 };
1284 }
1285
1286 fn gen_intrinsic_vec_create(&self, arguments: &Vec<ArgumentExpressionOrLocation>) {
1287 for arg in arguments {
1288 info!(?arg, "argument");
1289 }
1290 }
1291
1292 fn gen_intrinsic_vec_from_slice(
1293 &mut self,
1294 arguments: &Vec<ArgumentExpressionOrLocation>,
1295 ctx: &Context,
1296 ) {
1297 if let ArgumentExpressionOrLocation::Expression(found_expr) = &arguments[0] {
1298 self.gen_expression_for_access(found_expr, ctx);
1299 } else {
1300 panic!("vec_from_slice");
1301 }
1302 }
1303}
1304
1305fn struct_field_offset(
1306 index_to_look_for: usize,
1307 anon_struct_type: &AnonymousStructType,
1308) -> (MemoryOffset, MemorySize, MemoryAlignment) {
1309 let mut offset = MemoryOffset(0);
1310 for (field_index, (_name, field)) in
1311 anon_struct_type.field_name_sorted_fields.iter().enumerate()
1312 {
1313 let (field_size, field_alignment) = type_size_and_alignment(&field.field_type);
1314 let field_start_offset = offset.space(field_size, field_alignment);
1315 if field_index == index_to_look_for {
1316 return (field_start_offset, field_size, field_alignment);
1317 }
1318 }
1319
1320 panic!("field index is wrong")
1321}