@@ -485,6 +485,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
485485 }
486486 InstOp :: IntToPtr ( val, _) => self . compile_no_op_move ( instr_val, val) ,
487487 InstOp :: Load ( src_val) => self . compile_load ( instr_val, src_val) ,
488+ InstOp :: Alloc { ty, count } => self . compile_alloc ( instr_val, ty, count) ,
488489 InstOp :: MemCopyBytes {
489490 dst_val_ptr,
490491 src_val_ptr,
@@ -1467,6 +1468,78 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
14671468 Ok ( ( ) )
14681469 }
14691470
1471+ fn compile_alloc (
1472+ & mut self ,
1473+ instr_val : & Value ,
1474+ ty : & Type ,
1475+ count : & Value ,
1476+ ) -> Result < ( ) , CompileError > {
1477+ let owning_span = self . md_mgr . val_to_span ( self . context , * instr_val) ;
1478+
1479+ let ty_size = ty. size ( self . context ) . in_bytes ( ) ;
1480+
1481+ let statically_known_count = count. get_constant ( self . context ) . and_then ( |count| {
1482+ if let ConstantValue :: Uint ( count_uint) = count. get_content ( self . context ) . value {
1483+ Some ( count_uint)
1484+ } else {
1485+ None
1486+ }
1487+ } ) ;
1488+
1489+ let size_reg = self . reg_seqr . next ( ) ;
1490+ // If we know the count statically, multiply it by the type size to get the total size.
1491+ // Otherwise, just load the type size and multiply later.
1492+ if let Some ( statically_known_count) = statically_known_count {
1493+ self . immediate_to_reg (
1494+ ty_size * statically_known_count,
1495+ size_reg. clone ( ) ,
1496+ None ,
1497+ "get total allocation size in bytes" ,
1498+ owning_span. clone ( ) ,
1499+ ) ;
1500+ } else {
1501+ self . immediate_to_reg (
1502+ ty_size,
1503+ size_reg. clone ( ) ,
1504+ None ,
1505+ "get size of allocation element type" ,
1506+ owning_span. clone ( ) ,
1507+ ) ;
1508+ let count_reg = self . value_to_register ( count) ?;
1509+ self . cur_bytecode . push ( Op {
1510+ opcode : Either :: Left ( VirtualOp :: MUL (
1511+ size_reg. clone ( ) ,
1512+ size_reg. clone ( ) ,
1513+ count_reg,
1514+ ) ) ,
1515+ comment : "get total allocation size in bytes" . into ( ) ,
1516+ owning_span : owning_span. clone ( ) ,
1517+ } ) ;
1518+ }
1519+
1520+ // Actually perform the allocation.
1521+ self . cur_bytecode . push ( Op {
1522+ opcode : Either :: Left ( VirtualOp :: ALOC (
1523+ VirtualRegister :: Constant ( ConstantRegister :: HeapPointer ) ,
1524+ size_reg,
1525+ ) ) ,
1526+ comment : "allocate memory" . into ( ) ,
1527+ owning_span,
1528+ } ) ;
1529+
1530+ let instr_reg = self . reg_seqr . next ( ) ;
1531+ // Move the resulting pointer from the heap pointer register to the instruction register.
1532+ self . cur_bytecode . push ( Op :: register_move (
1533+ instr_reg. clone ( ) ,
1534+ VirtualRegister :: Constant ( ConstantRegister :: HeapPointer ) ,
1535+ "save allocated memory pointer" ,
1536+ self . md_mgr . val_to_span ( self . context , * instr_val) ,
1537+ ) ) ;
1538+
1539+ self . reg_map . insert ( * instr_val, instr_reg) ;
1540+ Ok ( ( ) )
1541+ }
1542+
14701543 fn compile_load ( & mut self , instr_val : & Value , src_val : & Value ) -> Result < ( ) , CompileError > {
14711544 let owning_span = self . md_mgr . val_to_span ( self . context , * instr_val) ;
14721545 let src_ty = src_val
0 commit comments