Esempio n. 1
0
static void after_assert_return_nan(WasmType type,
                                    WasmParserCookie cookie,
                                    void* user_data) {
  Context* ctx = user_data;

  int num_local_f32 = 0;
  int num_local_f64 = 0;
  switch (type) {
    case WASM_TYPE_F32:
      num_local_f32++;
      out_opcode(&ctx->buf, WASM_OPCODE_F32_NE);
      break;
    case WASM_TYPE_F64:
      num_local_f64++;
      out_opcode(&ctx->buf, WASM_OPCODE_F64_NE);
      break;
    default:
      assert(0);
  }

  /* x != x is true iff x is NaN */
  out_opcode(&ctx->buf, WASM_OPCODE_GET_LOCAL);
  out_u8(&ctx->buf, 0, "remapped local index");
  out_opcode(&ctx->buf, WASM_OPCODE_GET_LOCAL);
  out_u8(&ctx->buf, 0, "remapped local index");

  char name[256];
  snprintf(name, 256, "$assert_return_nan_%d", ctx->assert_return_nan_count++);
  append_nullary_function(ctx, name, WASM_TYPE_I32, 0, 0, num_local_f32,
                          num_local_f64);

  ctx->in_assert = 0;
}
Esempio n. 2
0
static void
out_set_addr (symbolS *sym)
{
  expressionS exp;

  out_opcode (DW_LNS_extended_op);
  out_uleb128 (sizeof_address + 1);

  out_opcode (DW_LNE_set_address);
  exp.X_op = O_symbol;
  exp.X_add_symbol = sym;
  exp.X_add_number = 0;
  emit_expr (&exp, sizeof_address);
}
Esempio n. 3
0
static void before_call(int function_index, void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_CALL);
  /* defined functions are always after all imports */
  out_leb128(&ctx->buf, ctx->module->imports.size + function_index,
             "func index");
}
Esempio n. 4
0
static void before_store(enum WasmOpcode opcode,
                         uint8_t access,
                         void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, opcode);
  out_u8(&ctx->buf, access, "store access byte");
}
Esempio n. 5
0
static void
out_set_addr (segT seg, fragS *frag, addressT ofs)
{
  expressionS expr;
  symbolS *sym;

  sym = symbol_temp_new (seg, ofs, frag);

  out_opcode (DW_LNS_extended_op);
  out_uleb128 (sizeof_address + 1);

  out_opcode (DW_LNE_set_address);
  expr.X_op = O_symbol;
  expr.X_add_symbol = sym;
  expr.X_add_number = 0;
  emit_expr (&expr, sizeof_address);
}
Esempio n. 6
0
static WasmParserCookie before_loop(void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_LOOP);
  WasmParserCookie cookie = (WasmParserCookie)ctx->buf.size;
  out_u8(&ctx->buf, 0, "num expressions");
  ctx->block_depth++;
  return cookie;
}
Esempio n. 7
0
static WasmParserCookie before_assert_return_nan(WasmSourceLocation loc,
                                                 void* user_data) {
  Context* ctx = user_data;
  ctx->in_assert = 1;
  if (g_verbose)
    printf("; before assert_return_nan_%d\n", ctx->assert_return_nan_count);
  init_output_buffer(&ctx->buf, INITIAL_OUTPUT_BUFFER_CAPACITY);
  out_opcode(&ctx->buf, WASM_OPCODE_SET_LOCAL);
  out_u8(&ctx->buf, 0, "remapped local index");
  return 0;
}
Esempio n. 8
0
static WasmParserCookie before_assert_return(WasmSourceLocation loc,
                                             void* user_data) {
  Context* ctx = user_data;
  ctx->in_assert = 1;
  if (g_verbose)
    printf("; before assert_return_%d\n", ctx->assert_return_count);
  init_output_buffer(&ctx->buf, INITIAL_OUTPUT_BUFFER_CAPACITY);
  WasmParserCookie cookie = (WasmParserCookie)ctx->buf.size;
  out_opcode(&ctx->buf, WASM_OPCODE_I32_EQ);
  return cookie;
}
Esempio n. 9
0
static WasmParserCookie before_label(void* user_data) {
  Context* ctx = user_data;
  LabelInfo* label_info = malloc(sizeof(LabelInfo));
  label_info->offset = ctx->buf.size;
  label_info->block_depth = ctx->block_depth++;
  label_info->next_label = ctx->top_label;
  ctx->top_label = label_info;
  out_opcode(&ctx->buf, WASM_OPCODE_BLOCK);
  out_u8(&ctx->buf, 0, "num expressions");
  return (WasmParserCookie)label_info;
}
Esempio n. 10
0
static WasmParserCookie before_break(int with_expr,
                                     int label_depth,
                                     void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, with_expr ? WASM_OPCODE_EXPR_BREAK : WASM_OPCODE_BREAK);
  LabelInfo* label_info = ctx->top_label;
  for (; label_depth > 0; label_depth--)
    label_info = label_info->next_label;
  int block_depth = (ctx->block_depth - 1) - label_info->block_depth;
  out_u8(&ctx->buf, block_depth, "break depth");
  return 0;
}
Esempio n. 11
0
static void
out_fixed_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
{
  expressionS expr;

  /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence.  */
  if (line_delta == INT_MAX)
    {
      out_opcode (DW_LNS_fixed_advance_pc);
      expr.X_op = O_subtract;
      expr.X_add_symbol = to_sym;
      expr.X_op_symbol = from_sym;
      expr.X_add_number = 0;
      emit_expr (&expr, 2);

      out_opcode (DW_LNS_extended_op);
      out_byte (1);
      out_opcode (DW_LNE_end_sequence);
      return;
    }

  out_opcode (DW_LNS_advance_line);
  out_sleb128 (line_delta);

  out_opcode (DW_LNS_fixed_advance_pc);
  expr.X_op = O_subtract;
  expr.X_add_symbol = to_sym;
  expr.X_op_symbol = from_sym;
  expr.X_add_number = 0;
  emit_expr (&expr, 2);

  out_opcode (DW_LNS_copy);
}
Esempio n. 12
0
static void after_const(enum WasmOpcode opcode,
                        WasmType type,
                        WasmNumber value,
                        void* user_data) {
  Context* ctx = user_data;
  switch (type) {
    case WASM_TYPE_I32: {
      int32_t i32 = value.i32;
      if (i32 >= -128 && i32 < 127) {
        out_opcode(&ctx->buf, WASM_OPCODE_I8_CONST);
        out_u8(&ctx->buf, value.i32, "u8 literal");
      } else {
        out_opcode(&ctx->buf, opcode);
        out_u32(&ctx->buf, value.i32, "u32 literal");
      }
      break;
    }

    case WASM_TYPE_I64:
      out_opcode(&ctx->buf, opcode);
      out_u64(&ctx->buf, value.i64, "u64 literal");
      break;

    case WASM_TYPE_F32:
      out_opcode(&ctx->buf, opcode);
      out_f32(&ctx->buf, value.f32, "f32 literal");
      break;

    case WASM_TYPE_F64:
      out_opcode(&ctx->buf, opcode);
      out_f64(&ctx->buf, value.f64, "f64 literal");
      break;

    default:
      assert(0);
      break;
  }
}
Esempio n. 13
0
static WasmParserCookie before_invoke(WasmSourceLocation loc,
                                      const char* invoke_name,
                                      int invoke_function_index,
                                      void* user_data) {
  Context* ctx = user_data;
  if (!ctx->in_assert) {
    if (g_verbose)
      printf("; before invoke_%d\n", ctx->invoke_count);
    init_output_buffer(&ctx->buf, INITIAL_OUTPUT_BUFFER_CAPACITY);
  }

  out_opcode(&ctx->buf, WASM_OPCODE_CALL);
  /* defined functions are always after all imports */
  out_leb128(&ctx->buf, ctx->module->imports.size + invoke_function_index,
             "invoke func index");

  return (WasmParserCookie)invoke_function_index;
}
Esempio n. 14
0
static void after_load_global(int index, void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_GET_GLOBAL);
  out_leb128(&ctx->buf, index, "global index");
}
Esempio n. 15
0
static void
process_entries (segT seg, struct line_entry *e)
{
  unsigned filenum = 1;
  unsigned line = 1;
  unsigned column = 0;
  unsigned isa = 0;
  unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
  fragS *last_frag = NULL, *frag;
  addressT last_frag_ofs = 0, frag_ofs;
  symbolS *last_lab = NULL, *lab;
  struct line_entry *next;

  do
    {
      int line_delta;

      if (filenum != e->loc.filenum)
	{
	  filenum = e->loc.filenum;
	  out_opcode (DW_LNS_set_file);
	  out_uleb128 (filenum);
	}

      if (column != e->loc.column)
	{
	  column = e->loc.column;
	  out_opcode (DW_LNS_set_column);
	  out_uleb128 (column);
	}

      if (e->loc.discriminator != 0)
	{
	  out_opcode (DW_LNS_extended_op);
	  out_leb128 (1 + sizeof_leb128 (e->loc.discriminator, 0));
	  out_opcode (DW_LNE_set_discriminator);
	  out_uleb128 (e->loc.discriminator);
	}

      if (isa != e->loc.isa)
	{
	  isa = e->loc.isa;
	  out_opcode (DW_LNS_set_isa);
	  out_uleb128 (isa);
	}

      if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT)
	{
	  flags = e->loc.flags;
	  out_opcode (DW_LNS_negate_stmt);
	}

      if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK)
	out_opcode (DW_LNS_set_basic_block);

      if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END)
	out_opcode (DW_LNS_set_prologue_end);

      if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN)
	out_opcode (DW_LNS_set_epilogue_begin);

      /* Don't try to optimize away redundant entries; gdb wants two
	 entries for a function where the code starts on the same line as
	 the {, and there's no way to identify that case here.  Trust gcc
	 to optimize appropriately.  */
      line_delta = e->loc.line - line;
      lab = e->label;
      frag = symbol_get_frag (lab);
      frag_ofs = S_GET_VALUE (lab);

      if (last_frag == NULL)
	{
	  out_set_addr (lab);
	  out_inc_line_addr (line_delta, 0);
	}
      else if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
	out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
      else
	relax_inc_line_addr (line_delta, lab, last_lab);

      line = e->loc.line;
      last_lab = lab;
      last_frag = frag;
      last_frag_ofs = frag_ofs;

      next = e->next;
      free (e);
      e = next;
    }
  while (e);

  /* Emit a DW_LNE_end_sequence for the end of the section.  */
  frag = last_frag_for_seg (seg);
  frag_ofs = get_frag_fix (frag, seg);
  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
    out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
  else
    {
      lab = symbol_temp_new (seg, frag_ofs, frag);
      relax_inc_line_addr (INT_MAX, lab, last_lab);
    }
}
Esempio n. 16
0
static void before_unary(enum WasmOpcode opcode, void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, opcode);
}
Esempio n. 17
0
static void before_store_global(int index, void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_SET_GLOBAL);
  out_leb128(&ctx->buf, index, "global index");
}
Esempio n. 18
0
static void
process_entries (segT seg, struct line_entry *e)
{
  unsigned filenum = 1;
  unsigned line = 1;
  unsigned column = 0;
  unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_BEGIN_STMT : 0;
  fragS *frag = NULL;
  fragS *last_frag;
  addressT frag_ofs = 0;
  addressT last_frag_ofs;
  struct line_entry *next;

  while (e)
    {
      int changed = 0;

      if (filenum != e->loc.filenum)
	{
	  filenum = e->loc.filenum;
	  out_opcode (DW_LNS_set_file);
	  out_uleb128 (filenum);
	  changed = 1;
	}

      if (column != e->loc.column)
	{
	  column = e->loc.column;
	  out_opcode (DW_LNS_set_column);
	  out_uleb128 (column);
	  changed = 1;
	}

      if ((e->loc.flags ^ flags) & DWARF2_FLAG_BEGIN_STMT)
	{
	  flags = e->loc.flags;
	  out_opcode (DW_LNS_negate_stmt);
	  changed = 1;
	}

      if (e->loc.flags & DWARF2_FLAG_BEGIN_BLOCK)
	{
	  out_opcode (DW_LNS_set_basic_block);
	  changed = 1;
	}

      /* Don't try to optimize away redundant entries; gdb wants two
	 entries for a function where the code starts on the same line as
	 the {, and there's no way to identify that case here.  Trust gcc
	 to optimize appropriately.  */
      if (1 /* line != e->loc.line || changed */)
	{
	  int line_delta = e->loc.line - line;
	  if (frag == NULL)
	    {
	      out_set_addr (seg, e->frag, e->frag_ofs);
	      out_inc_line_addr (line_delta, 0);
	    }
	  else if (frag == e->frag)
	    out_inc_line_addr (line_delta, e->frag_ofs - frag_ofs);
	  else
	    relax_inc_line_addr (line_delta, seg, e->frag, e->frag_ofs,
				 frag, frag_ofs);

	  frag = e->frag;
	  frag_ofs = e->frag_ofs;
	  line = e->loc.line;
	}
      else if (frag == NULL)
	{
	  out_set_addr (seg, e->frag, e->frag_ofs);
	  frag = e->frag;
	  frag_ofs = e->frag_ofs;
	}

      next = e->next;
      free (e);
      e = next;
    }

  /* Emit a DW_LNE_end_sequence for the end of the section.  */
  last_frag = last_frag_for_seg (seg);
  last_frag_ofs = get_frag_fix (last_frag);
  if (frag == last_frag)
    out_inc_line_addr (INT_MAX, last_frag_ofs - frag_ofs);
  else
    relax_inc_line_addr (INT_MAX, seg, last_frag, last_frag_ofs,
			 frag, frag_ofs);
}
Esempio n. 19
0
static void before_set_local(int index, void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_SET_LOCAL);
  out_leb128(&ctx->buf, ctx->remapped_locals[index], "remapped local index");
}
Esempio n. 20
0
static void before_return(void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_RETURN);
}
Esempio n. 21
0
static void before_resize_memory(void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_RESIZE_MEMORY_I32);
}
Esempio n. 22
0
static void after_page_size(void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_PAGE_SIZE);
}
Esempio n. 23
0
static void after_nop(void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_NOP);
}
Esempio n. 24
0
static void after_memory_size(void* user_data) {
  Context* ctx = user_data;
  /* TODO(binji): not currently defined. Return 0 for now. */
  out_opcode(&ctx->buf, WASM_OPCODE_I8_CONST);
  out_u8(&ctx->buf, 0, "zero");
}
Esempio n. 25
0
static void before_call_import(int import_index, void* user_data) {
  Context* ctx = user_data;
  out_opcode(&ctx->buf, WASM_OPCODE_CALL);
  out_leb128(&ctx->buf, import_index, "import index");
}
Esempio n. 26
0
static WasmParserCookie before_if(void* user_data) {
  Context* ctx = user_data;
  uint32_t offset = ctx->buf.size;
  out_opcode(&ctx->buf, WASM_OPCODE_IF);
  return (WasmParserCookie)offset;
}