summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2012-03-31 19:51:17 -0700
committerJoshua Haberman <jhaberman@gmail.com>2012-03-31 19:51:17 -0700
commit9a7037a2fa4f909eea561d6d89997b0b4203df9e (patch)
tree7171167f6602c658e31733993757b36f6ed16a9a
parentcca4818eb7769d6e776bdc30516a5f871f1d6393 (diff)
Got decoder & textprinter compiling in kernel mode.
-rw-r--r--bindings/linux/Makefile3
-rw-r--r--bindings/linux/ctype.h8
-rw-r--r--bindings/linux/inttypes.h22
-rw-r--r--bindings/linux/setjmp.h44
-rw-r--r--upb/pb/decoder.c37
-rw-r--r--upb/pb/decoder.h2
-rw-r--r--upb/pb/textprinter.c4
-rw-r--r--upb/pb/textprinter.h2
8 files changed, 108 insertions, 14 deletions
diff --git a/bindings/linux/Makefile b/bindings/linux/Makefile
index 1736b61..cf0cc7a 100644
--- a/bindings/linux/Makefile
+++ b/bindings/linux/Makefile
@@ -8,6 +8,9 @@ upb-objs = \
../../upb/table.o \
../../upb/refcount.o \
../../upb/msg.o \
+ ../../upb/pb/decoder.o \
+ ../../upb/pb/textprinter.o \
+ ../../upb/pb/varint.o \
KVERSION = $(shell uname -r)
diff --git a/bindings/linux/ctype.h b/bindings/linux/ctype.h
new file mode 100644
index 0000000..b6cbda5
--- /dev/null
+++ b/bindings/linux/ctype.h
@@ -0,0 +1,8 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2012 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ */
+
+#include <linux/ctype.h>
diff --git a/bindings/linux/inttypes.h b/bindings/linux/inttypes.h
new file mode 100644
index 0000000..e7a6e42
--- /dev/null
+++ b/bindings/linux/inttypes.h
@@ -0,0 +1,22 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2012 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ */
+
+#ifndef PRId64
+#define PRId64 "ld"
+#endif
+
+#ifndef PRIu64
+#define PRIu64 "lu"
+#endif
+
+#ifndef PRId32
+#define PRId32 "d"
+#endif
+
+#ifndef PRIu32
+#define PRIu32 "u"
+#endif
diff --git a/bindings/linux/setjmp.h b/bindings/linux/setjmp.h
new file mode 100644
index 0000000..6da4313
--- /dev/null
+++ b/bindings/linux/setjmp.h
@@ -0,0 +1,44 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2012 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ */
+
+// Linux doesn't provide setjmp/longjmp, boo.
+
+typedef void *jmp_buf[3]; // rsp, rbp, rip
+
+static inline int _setjmp(jmp_buf env) {
+ register int ret asm ("%eax");
+ __asm__ __volatile__ goto (
+ " movq %%rsp, 0(%0)\n" // Save rsp
+ " movq %%rbp, 8(%0)\n" // Save rbp
+ " movq $1f, 16(%0)\n" // Save rip
+ " jmp %l[setup]\n"
+ "1:"
+ : // No outputs allowed (GCC limitation).
+ : "b" (env) // Input
+ : // All registers clobbered except rsp, which save in env.
+ "%rcx", "%rdx", "%rdi", "%rsi", "memory", "cc",
+ "%r8" , "%r9" , "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+ : setup // Target labels.
+ );
+ return ret;
+
+setup:
+ return 0;
+}
+
+__attribute__((__noreturn__))
+static inline void _longjmp(jmp_buf env, int val) {
+ __asm__ __volatile__ (
+ " movq 0(%0), %%rsp\n" // Restore rsp
+ " movq 8(%0), %%rbp\n" // Restore rbp
+ " movq %0, %%rbx\n" // Restore rbx
+ " jmpq *16(%0)\n" // Jump to saved rip
+ : // No output.
+ : "r" (env), "a" (val) // Move val to %eax
+ );
+ __builtin_unreachable();
+}
diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c
index b0e2392..30f7c65 100644
--- a/upb/pb/decoder.c
+++ b/upb/pb/decoder.c
@@ -5,7 +5,6 @@
* Author: Josh Haberman <jhaberman@gmail.com>
*/
-#include <inttypes.h>
#include <stddef.h>
#include <stdlib.h>
#include "upb/bytestream.h"
@@ -13,6 +12,10 @@
#include "upb/pb/decoder.h"
#include "upb/pb/varint.h"
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xffffffff
+#endif
+
typedef struct {
uint8_t native_wire_type;
bool is_numeric;
@@ -97,13 +100,13 @@ bool upb_decoderplan_hasjitcode(upb_decoderplan *p) {
// configuration. But emperically on a Core i7, performance increases 30-50%
// with these annotations. Every instance where these appear, gcc 4.2.1 made
// the wrong decision and degraded performance in benchmarks.
-#define FORCEINLINE static __attribute__((always_inline))
-#define NOINLINE static __attribute__((noinline))
+#define FORCEINLINE static __attribute__((__always_inline__))
+#define NOINLINE static __attribute__((__noinline__))
UPB_NORETURN static void upb_decoder_exitjmp(upb_decoder *d) {
// Resumable decoder would back out to completed_ptr (and possibly get a
// previous buffer).
- siglongjmp(d->exitjmp, 1);
+ _longjmp(d->exitjmp, 1);
}
UPB_NORETURN static void upb_decoder_exitjmp2(void *d) {
upb_decoder_exitjmp(d);
@@ -348,9 +351,6 @@ INLINE void upb_push_msg(upb_decoder *d, upb_fhandlers *f, uint64_t end) {
upb_dispatch_value(&d->dispatcher, f, val); \
} \
-static double upb_asdouble(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
-static float upb_asfloat(uint32_t n) { float f; memcpy(&f, &n, 4); return f; }
-
T(INT32, varint, int32, int32_t)
T(INT64, varint, int64, int64_t)
T(UINT32, varint, uint32, uint32_t)
@@ -361,13 +361,30 @@ T(SFIXED32, fixed32, int32, int32_t)
T(SFIXED64, fixed64, int64, int64_t)
T(BOOL, varint, bool, bool)
T(ENUM, varint, int32, int32_t)
-T(DOUBLE, fixed64, double, upb_asdouble)
-T(FLOAT, fixed32, float, upb_asfloat)
T(SINT32, varint, int32, upb_zzdec_32)
T(SINT64, varint, int64, upb_zzdec_64)
T(STRING, string, byteregion, upb_byteregion*)
+
#undef T
+INLINE void upb_decode_DOUBLE(upb_decoder *d, upb_fhandlers *f) {
+ upb_value val;
+ double dbl;
+ uint64_t wireval = upb_decode_fixed64(d);
+ memcpy(&dbl, &wireval, 8);
+ upb_value_setdouble(&val, dbl);
+ upb_dispatch_value(&d->dispatcher, f, val);
+}
+
+INLINE void upb_decode_FLOAT(upb_decoder *d, upb_fhandlers *f) {
+ upb_value val;
+ float flt;
+ uint64_t wireval = upb_decode_fixed32(d);
+ memcpy(&flt, &wireval, 4);
+ upb_value_setfloat(&val, flt);
+ upb_dispatch_value(&d->dispatcher, f, val);
+}
+
static void upb_decode_GROUP(upb_decoder *d, upb_fhandlers *f) {
upb_push_msg(d, f, UPB_NONDELIMITED);
}
@@ -474,7 +491,7 @@ INLINE upb_fhandlers *upb_decode_tag(upb_decoder *d) {
upb_success_t upb_decoder_decode(upb_decoder *d) {
assert(d->input);
- if (sigsetjmp(d->exitjmp, 0)) {
+ if (_setjmp(d->exitjmp)) {
assert(!upb_ok(&d->status));
return UPB_ERROR;
}
diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h
index 13e5774..df65468 100644
--- a/upb/pb/decoder.h
+++ b/upb/pb/decoder.h
@@ -74,7 +74,7 @@ typedef struct _upb_decoder {
#endif
// For exiting the decoder on error.
- sigjmp_buf exitjmp;
+ jmp_buf exitjmp;
} upb_decoder;
void upb_decoder_init(upb_decoder *d);
diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c
index 0d9c967..2fe3452 100644
--- a/upb/pb/textprinter.c
+++ b/upb/pb/textprinter.c
@@ -41,7 +41,7 @@ static int upb_textprinter_putescaped(upb_textprinter *p,
// Based on CEscapeInternal() from Google's protobuf release.
// TODO; we could read directly from a bytesrc's buffer instead.
// TODO; we could write byteregions to the sink when possible.
- char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
+ char dstbuf[512], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
char *buf = malloc(upb_byteregion_len(bytes)), *src = buf;
char *end = src + upb_byteregion_len(bytes);
upb_byteregion_copyall(bytes, buf);
@@ -182,7 +182,7 @@ err:
return UPB_BREAK;
}
-upb_textprinter *upb_textprinter_new() {
+upb_textprinter *upb_textprinter_new(void) {
upb_textprinter *p = malloc(sizeof(*p));
return p;
}
diff --git a/upb/pb/textprinter.h b/upb/pb/textprinter.h
index 25f364e..174148e 100644
--- a/upb/pb/textprinter.h
+++ b/upb/pb/textprinter.h
@@ -18,7 +18,7 @@ extern "C" {
struct _upb_textprinter;
typedef struct _upb_textprinter upb_textprinter;
-upb_textprinter *upb_textprinter_new();
+upb_textprinter *upb_textprinter_new(void);
void upb_textprinter_free(upb_textprinter *p);
void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink,
bool single_line);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback