mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-11 14:33:41 +00:00
transform: add -print-allocs-cover and restore -print-allocs reason output
PR #5220 changed -print-allocs output to the go coverage tool format, which replaced the original human-readable explanation of why each object had to be heap allocated. That explanation is useful on its own, so this restores it as the default behavior of -print-allocs and moves the coverage format behind a -print-allocs-cover flag. Signed-off-by: Piotr Bocheński <piotr@bochen.ski>
This commit is contained in:
committed by
Ron Evans
parent
c33113ab5f
commit
4465360f3d
+20
-25
@@ -46,10 +46,6 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
|
||||
complex128Type := ctx.StructType([]llvm.Type{ctx.DoubleType(), ctx.DoubleType()}, false)
|
||||
maxAlign := int64(targetData.ABITypeAlignment(complex128Type))
|
||||
|
||||
if printAllocs != nil {
|
||||
fmt.Fprintln(os.Stderr, "mode: set")
|
||||
}
|
||||
|
||||
// Find all allocator calls.
|
||||
var heapallocs []llvm.Value
|
||||
for _, allocator := range allocators {
|
||||
@@ -61,7 +57,7 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
|
||||
if heapalloc.Operand(0).IsAConstantInt().IsNil() {
|
||||
// Do not allocate variable length arrays on the stack.
|
||||
if logAllocs {
|
||||
logAlloc(logger, heapalloc, "size is not constant")
|
||||
logger(getPosition(heapalloc), "size is not constant")
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -70,7 +66,8 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
|
||||
if size > maxStackAlloc {
|
||||
// The maximum size for a stack allocation.
|
||||
if logAllocs {
|
||||
logAlloc(logger, heapalloc, fmt.Sprintf("object size %d exceeds maximum stack allocation size %d", size, maxStackAlloc))
|
||||
logger(getPosition(heapalloc),
|
||||
fmt.Sprintf("object size %d exceeds maximum stack allocation size %d", size, maxStackAlloc))
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -107,7 +104,7 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
|
||||
if atPos.Line != 0 {
|
||||
msg = fmt.Sprintf("escapes at line %d", atPos.Line)
|
||||
}
|
||||
logAlloc(logger, heapalloc, msg)
|
||||
logger(getPosition(heapalloc), msg)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -146,6 +143,22 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
|
||||
}
|
||||
}
|
||||
|
||||
// FormatAllocReason renders the heap allocation in a human-readable format.
|
||||
func FormatAllocReason(pos token.Position, reason string) string {
|
||||
return fmt.Sprintf("%s: object allocated on the heap: %s", pos.String(), reason)
|
||||
}
|
||||
|
||||
// FormatAllocCover renders the heap allocation in the go coverage tool format.
|
||||
func FormatAllocCover(pos token.Position) string {
|
||||
if pos.Filename == "" || pos.Line <= 0 {
|
||||
return "" // no position info; a blank line would corrupt the profile
|
||||
}
|
||||
// Highlight the whole line: column 1 to one past the last byte (the end
|
||||
// column is exclusive, so add 1 to the line length).
|
||||
endCol := max(lineLengthAt(pos.Filename, pos.Line), 1) + 1
|
||||
return fmt.Sprintf("%s:%d.1,%d.%d 1 0", pos.Filename, pos.Line, pos.Line, endCol)
|
||||
}
|
||||
|
||||
// valueEscapesAt returns the instruction where the given value may escape and a
|
||||
// nil llvm.Value if it definitely doesn't. The value must be an instruction.
|
||||
func valueEscapesAt(value llvm.Value) llvm.Value {
|
||||
@@ -189,24 +202,6 @@ func valueEscapesAt(value llvm.Value) llvm.Value {
|
||||
return llvm.Value{}
|
||||
}
|
||||
|
||||
// logAlloc prints a message to stderr explaining why the given object had to be
|
||||
// allocated on the heap.
|
||||
func logAlloc(logger func(token.Position, string), allocCall llvm.Value, reason string) {
|
||||
pos := getPosition(allocCall)
|
||||
if pos.Filename == "" || pos.Line <= 0 {
|
||||
logger(pos, "")
|
||||
return
|
||||
}
|
||||
|
||||
endCol := lineLengthAt(pos.Filename, pos.Line)
|
||||
if endCol < 1 {
|
||||
endCol = 1
|
||||
}
|
||||
|
||||
// Only emit the coverprofile line, without position prefix.
|
||||
logger(token.Position{}, fmt.Sprintf("%s:%d.1,%d.%d 1 0", pos.Filename, pos.Line, pos.Line, endCol))
|
||||
}
|
||||
|
||||
func lineLengthAt(filename string, lineNumber int) int {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user