aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2021-04-21 08:01:30 +0200
committerDmitry Vyukov <dvyukov@google.com>2021-04-21 14:05:20 +0200
commitad3ce6afab30fb68cfcda40a1910b87279795c5a (patch)
tree6a6febdaae83e071a85576bb6fa1fd5b8abb2936 /pkg
parent7ffd6ad61b0d0c6290f73b3652f79c63b305351e (diff)
pkg/compiler: optimize array[const] representation
Represent array[const[X, int8], N] as string["XX...X"]. This replaces potentially huge number of: NONFAILING(*(uint8_t*)0x2000126c = 0); NONFAILING(*(uint8_t*)0x2000126d = 0); NONFAILING(*(uint8_t*)0x2000126e = 0); with a single memcpy. In one reproducer we had 3991 such lines. Also replace memcpy's with memset's when possible. Update #1070
Diffstat (limited to 'pkg')
-rw-r--r--pkg/compiler/types.go24
-rw-r--r--pkg/csource/csource.go9
-rw-r--r--pkg/csource/csource_test.go30
3 files changed, 37 insertions, 26 deletions
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go
index b2c8c3204..038a05f24 100644
--- a/pkg/compiler/types.go
+++ b/pkg/compiler/types.go
@@ -4,6 +4,8 @@
package compiler
import (
+ "bytes"
+ "encoding/binary"
"fmt"
"sort"
"strconv"
@@ -249,6 +251,28 @@ var typeArray = &typeDesc{
RangeEnd: end,
}
}
+ if ct, ok := elemType.(*prog.ConstType); ok &&
+ (ct.ArgFormat == prog.FormatNative || ct.ArgFormat == prog.FormatBigEndian) &&
+ kind == prog.ArrayRangeLen && begin == end {
+ // Special case: const string takes less space in C programs.
+ base.TypeSize = begin * ct.Size()
+ base.TypeAlign = ct.TypeAlign
+ val := make([]byte, 8)
+ if ct.ArgFormat == prog.FormatBigEndian {
+ binary.BigEndian.PutUint64(val, ct.Val)
+ val = val[8-ct.Size():]
+ } else {
+ binary.LittleEndian.PutUint64(val, ct.Val)
+ val = val[:ct.Size()]
+ }
+ val = bytes.Repeat(val, int(begin))
+ return &prog.BufferType{
+ TypeCommon: base.TypeCommon,
+ Kind: prog.BufferString,
+ Values: []string{string(val)},
+ NoZ: true,
+ }
+ }
// TypeSize is assigned later in layoutArray.
base.TypeAlign = elemType.Alignment()
return &prog.ArrayType{
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go
index 24717a31a..c30db6b9d 100644
--- a/pkg/csource/csource.go
+++ b/pkg/csource/csource.go
@@ -366,8 +366,13 @@ func (ctx *context) copyin(w *bytes.Buffer, csumSeq *int, copyin prog.ExecCopyin
case prog.ExecArgResult:
ctx.copyinVal(w, copyin.Addr, arg.Size, ctx.resultArgToStr(arg), arg.Format)
case prog.ExecArgData:
- fmt.Fprintf(w, "\tNONFAILING(memcpy((void*)0x%x, \"%s\", %v));\n",
- copyin.Addr, toCString(arg.Data, arg.Readable), len(arg.Data))
+ if bytes.Equal(arg.Data, bytes.Repeat(arg.Data[:1], len(arg.Data))) {
+ fmt.Fprintf(w, "\tNONFAILING(memset((void*)0x%x, %v, %v));\n",
+ copyin.Addr, arg.Data[0], len(arg.Data))
+ } else {
+ fmt.Fprintf(w, "\tNONFAILING(memcpy((void*)0x%x, \"%s\", %v));\n",
+ copyin.Addr, toCString(arg.Data, arg.Readable), len(arg.Data))
+ }
case prog.ExecArgCsum:
switch arg.Kind {
case prog.ExecArgCsumInet:
diff --git a/pkg/csource/csource_test.go b/pkg/csource/csource_test.go
index 752ff919b..e2035b286 100644
--- a/pkg/csource/csource_test.go
+++ b/pkg/csource/csource_test.go
@@ -160,37 +160,19 @@ csource2(&AUTO="12345678")
csource3(&AUTO)
csource4(&AUTO)
csource5(&AUTO)
+csource6(&AUTO)
`,
output: `
NONFAILING(memcpy((void*)0x20000040, "\x12\x34\x56\x78", 4));
syscall(SYS_csource2, 0x20000040ul);
-NONFAILING(*(uint8*)0x20000080 = 0);
-NONFAILING(*(uint8*)0x20000081 = 0);
-NONFAILING(*(uint8*)0x20000082 = 0);
-NONFAILING(*(uint8*)0x20000083 = 0);
-NONFAILING(*(uint8*)0x20000084 = 0);
-NONFAILING(*(uint8*)0x20000085 = 0);
-NONFAILING(*(uint8*)0x20000086 = 0);
-NONFAILING(*(uint8*)0x20000087 = 0);
-NONFAILING(*(uint8*)0x20000088 = 0);
-NONFAILING(*(uint8*)0x20000089 = 0);
+NONFAILING(memset((void*)0x20000080, 0, 10));
syscall(SYS_csource3, 0x20000080ul);
-NONFAILING(*(uint8*)0x200000c0 = 0xab);
-NONFAILING(*(uint8*)0x200000c1 = 0xab);
-NONFAILING(*(uint8*)0x200000c2 = 0xab);
-NONFAILING(*(uint8*)0x200000c3 = 0xab);
-NONFAILING(*(uint8*)0x200000c4 = 0xab);
-NONFAILING(*(uint8*)0x200000c5 = 0xab);
-NONFAILING(*(uint8*)0x200000c6 = 0xab);
-NONFAILING(*(uint8*)0x200000c7 = 0xab);
-NONFAILING(*(uint8*)0x200000c8 = 0xab);
-NONFAILING(*(uint8*)0x200000c9 = 0xab);
+NONFAILING(memset((void*)0x200000c0, 48, 10));
syscall(SYS_csource4, 0x200000c0ul);
-NONFAILING(*(uint32*)0x20000100 = 0x12345678);
-NONFAILING(*(uint32*)0x20000104 = 0x12345678);
-NONFAILING(*(uint32*)0x20000108 = 0x12345678);
-NONFAILING(*(uint32*)0x2000010c = 0x12345678);
+NONFAILING(memcpy((void*)0x20000100, "0101010101", 10));
syscall(SYS_csource5, 0x20000100ul);
+NONFAILING(memcpy((void*)0x20000140, "101010101010", 12));
+syscall(SYS_csource6, 0x20000140ul);
`,
},
}