decomposeStruct packs struct fields into registers and adds them to `args`.
(args []ssa.Value, structure *ssa.Struct)
| 8 | |
| 9 | // decomposeStruct packs struct fields into registers and adds them to `args`. |
| 10 | func (f *Function) decomposeStruct(args []ssa.Value, structure *ssa.Struct) []ssa.Value { |
| 11 | if structure.Typ.Size() > 16 { |
| 12 | for _, field := range structure.Arguments { |
| 13 | nested, isNested := field.(*ssa.Struct) |
| 14 | |
| 15 | if isNested { |
| 16 | args = f.decomposeStruct(args, nested) |
| 17 | continue |
| 18 | } |
| 19 | |
| 20 | args = append(args, field) |
| 21 | } |
| 22 | |
| 23 | return args |
| 24 | } |
| 25 | |
| 26 | // Packed integer: Use the first argument, |
| 27 | // then bitwise OR with the shifted field values. |
| 28 | cursor := structure.Arguments[0] |
| 29 | typ := types.Unwrap(structure.Typ).(*types.Struct) |
| 30 | size := typ.Fields[0].Type.Size() |
| 31 | |
| 32 | for i, field := range structure.Arguments[1:] { |
| 33 | fieldSize := typ.Fields[i+1].Type.Size() |
| 34 | |
| 35 | if size+fieldSize > 8 { |
| 36 | // The field doesn't fit into the register anymore. |
| 37 | // We need to use this field as the starting value |
| 38 | // for the next argument. |
| 39 | args = append(args, cursor) |
| 40 | cursor = field |
| 41 | size = fieldSize |
| 42 | continue |
| 43 | } |
| 44 | |
| 45 | cursorMask := f.Append(&ssa.Int{Int: (1 << (size * 8)) - 1}) |
| 46 | cursor = f.Append(&ssa.BinaryOp{Op: token.And, Left: cursor, Right: cursorMask}) |
| 47 | sizeValue := f.Append(&ssa.Int{Int: size * 8}) |
| 48 | shifted := f.Append(&ssa.BinaryOp{Op: token.Shl, Left: field, Right: sizeValue}) |
| 49 | cursor = f.Append(&ssa.BinaryOp{Op: token.Or, Left: cursor, Right: shifted}) |