typeAlignment returns the type alignment for the given type.
(pkg *types.Package, obj types.Object)
| 31 | |
| 32 | // typeAlignment returns the type alignment for the given type. |
| 33 | func (pc *passContext) typeAlignment(pkg *types.Package, obj types.Object) atomicAlignment { |
| 34 | requiredOffset := atomicAlignment(1) |
| 35 | if pc.pass.ImportObjectFact(obj, &requiredOffset) { |
| 36 | return requiredOffset |
| 37 | } |
| 38 | |
| 39 | switch x := obj.Type().Underlying().(type) { |
| 40 | case *types.Struct: |
| 41 | fields := make([]*types.Var, x.NumFields()) |
| 42 | for i := 0; i < x.NumFields(); i++ { |
| 43 | fields[i] = x.Field(i) |
| 44 | } |
| 45 | offsets := pc.pass.TypesSizes.Offsetsof(fields) |
| 46 | for i := 0; i < x.NumFields(); i++ { |
| 47 | // Check the offset, and then assuming that this offset |
| 48 | // aligns with the offset for the broader type. |
| 49 | fieldRequired := pc.typeAlignment(pkg, fields[i]) |
| 50 | if offsets[i]%int64(fieldRequired) != 0 { |
| 51 | // The offset of this field is not compatible. |
| 52 | pc.maybeFail(fields[i].Pos(), "have alignment %d, need %d", offsets[i], fieldRequired) |
| 53 | } |
| 54 | // Ensure the requiredOffset is the LCM of the offset. |
| 55 | requiredOffset *= fieldRequired / gcd(requiredOffset, fieldRequired) |
| 56 | } |
| 57 | case *types.Array: |
| 58 | // Export direct alignment requirements. |
| 59 | if named, ok := types.Unalias(x.Elem()).(*types.Named); ok && !hasTypeParams(named) { |
| 60 | requiredOffset = pc.typeAlignment(pkg, named.Obj()) |
| 61 | } |
| 62 | default: |
| 63 | // Use the compiler's underlying alignment. |
| 64 | requiredOffset = atomicAlignment(pc.pass.TypesSizes.Alignof(obj.Type().Underlying())) |
| 65 | } |
| 66 | |
| 67 | if pkg == obj.Pkg() { |
| 68 | // Cache as an object fact, to subsequent calls. Note that we |
| 69 | // can only export object facts for the package that we are |
| 70 | // currently analyzing. There may be no exported facts for |
| 71 | // array types or alias types, for example. |
| 72 | pc.pass.ExportObjectFact(obj, &requiredOffset) |
| 73 | } |
| 74 | |
| 75 | return requiredOffset |
| 76 | } |
| 77 | |
| 78 | // hasTypeParams returns true iff the named type has type parameters. |
| 79 | func hasTypeParams(typ *types.Named) bool { |
no test coverage detected