Got decoder & textprinter compiling in kernel mode.

pull/13171/head
Joshua Haberman 13 years ago
parent cca4818eb7
commit 9a7037a2fa
  1. 3
      bindings/linux/Makefile
  2. 8
      bindings/linux/ctype.h
  3. 22
      bindings/linux/inttypes.h
  4. 44
      bindings/linux/setjmp.h
  5. 37
      upb/pb/decoder.c
  6. 2
      upb/pb/decoder.h
  7. 4
      upb/pb/textprinter.c
  8. 2
      upb/pb/textprinter.h

@ -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)

@ -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>

@ -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

@ -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();
}

@ -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;
}

@ -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);

@ -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;
}

@ -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);

Loading…
Cancel
Save