⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bc-emit.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Emit data inline into bytecode.  */voidbc_emit_bytecode_const (data, size)     char *data;     unsigned int size;{  if (bytecode)    seg_data (bytecode, data, size);}/* Create a new "bytecode label", to have its value defined later.   Bytecode labels have nothing to do with the object file symbol table,   and are purely local to a given bytecoded function.  */struct bc_label *bc_get_bytecode_label (){  struct bc_label *result;  result = (struct bc_label *) xmalloc (sizeof (struct bc_label));  result->defined = 0;  result->next = labels;  result->uid = 0;  labels = result;  return result;}/* Define the given label with the current location counter.  */intbc_emit_bytecode_labeldef (label)     struct bc_label *label;{  extern int bc_new_uid ();  if (!label || label->defined)    return 0;  label->offset = bytecode->size;  label->defined = 1;  label->uid = bc_new_uid ();#ifdef DEBUG_PRINT_CODE  fprintf (stderr, "$%lx:\n", label);#endif  return 1;}/* Generate a location-relative reference to the given bytecode label.   It need not be defined yet; label references will be backpatched later.  */voidbc_emit_bytecode_labelref (label)     struct bc_label *label;{  struct bc_labelref *labelref;  static int zero;  labelref = (struct bc_labelref *) xmalloc (sizeof (struct bc_labelref));  labelref->label = label;  labelref->offset = bytecode->size;  labelref->next = labelrefs;  labelrefs = labelref;#ifdef DEBUG_PRINT_CODE  fprintf (stderr, " $%lx", label);#endif  seg_data (bytecode, (char *) &zero, sizeof zero);}/* Emit a reference to an external address; generate the reference in the   ptrconst area, and emit an offset in the bytecode.  */voidbc_emit_code_labelref (name, offset)     char *name;     int offset;{  int ptroff;  ptroff = ptrconsts->size / sizeof (char *);  seg_data (bytecode, (char *) &ptroff, sizeof ptroff);  seg_refsym (ptrconsts, name, offset);#ifdef DEBUG_PRINT_CODE  fprintf (stderr, " [external <%x> %s]", ptroff, name);#endif}/* Backpatch label references in the byte code, and concatenate the bytecode   and pointer constant segments to the cumulative text for the object file.   Return a label name for the pointer constants region.  */char *bc_end_function (){  int addr;  struct bc_label *label, *next;  struct bc_labelref *ref, *nextref;  char ptrconsts_label[20];  static int nlab;  /* Backpatch bytecode label references.  */  for (ref = labelrefs; ref; ref = ref->next)    if (ref->label->defined)      {	addr = ref->label->offset;	bcopy ((char *) &addr, bytecode->data + ref->offset, sizeof addr);      }  /* Free the chains of labelrefs and labeldefs.  */  for (ref = labelrefs; ref; ref = nextref)    {      nextref = ref->next;      free ((char *) ref);    }  for (label = labels; label; label = next)    {      next = label->next;      free ((char *) label);    }  seg_concat (trampoline, bytecode);  seg_align (trampoline, MACHINE_SEG_ALIGN);  sprintf (ptrconsts_label, "*LP%d", nlab++);  seg_defsym (trampoline, ptrconsts_label);  seg_concat (trampoline, ptrconsts);  seg_concat (bc_text_seg, trampoline);  labels = 0;  labelrefs = 0;  trampoline = 0;  bytecode = 0;  ptrconsts = 0;  return sym_lookup (ptrconsts_label)->name;}/* Force alignment in const data.  */voidbc_align_const (align)     int align;{  seg_align (bc_text_seg, align);}/* Emit const data.  */voidbc_emit_const (data, size)     char *data;     unsigned int size;{  seg_data (bc_text_seg, data, size);}/* Emit a zero-filled constant skip.  */voidbc_emit_const_skip (size)     unsigned int size;{  seg_skip (bc_text_seg, size);}/* Emit a label definition in const data.  */intbc_emit_const_labeldef (name)     char *name;{  return seg_defsym (bc_text_seg, name);}/* Emit a label reference in const data.  */voidbc_emit_const_labelref (name, offset)     char *name;     int offset;{  seg_refsym (bc_text_seg, name, offset);}/* Force alignment in data.  */voidbc_align_data (align)     int align;{  seg_align (bc_data_seg, align);}/* Emit data.  */voidbc_emit_data (data, size)     char *data;     unsigned int size;{  seg_data (bc_data_seg, data, size);}/* Emit a zero-filled data skip.  */voidbc_emit_data_skip (size)     unsigned int size;{  seg_skip (bc_data_seg, size);}/* Emit label definition in data.  */intbc_emit_data_labeldef (name)     char *name;{  return seg_defsym (bc_data_seg, name);}/* Emit label reference in data.  */voidbc_emit_data_labelref (name, offset)     char *name;     int offset;{  seg_refsym (bc_data_seg, name, offset);}/* Emit a common block of the given name and size.  Note that   when the .o file is actually written non-global "common"   blocks will have to be turned into space in the data section.  */intbc_emit_common (name, size)     char *name;     unsigned int size;{  struct bc_sym *sym;  sym = sym_lookup (name);  if (sym->defined)    return 0;  sym->defined = 1;  sym->common = 1;  sym->val = size;  return 1;}/* Globalize the given label.  */voidbc_globalize_label (name)     char *name;{  struct bc_sym *sym;  sym = sym_lookup (name);  sym->global = 1;}static enum { in_text, in_data } section = in_text;voidbc_text (){  section = in_text;}voidbc_data (){  section = in_data;}voidbc_align (align)     int align;{  if (section == in_text)    bc_align_const (align);  else    bc_align_data (align);}voidbc_emit (data, size)     char *data;     unsigned int size;{  if (section == in_text)    bc_emit_const (data, size);  else    bc_emit_data (data, size);}voidbc_emit_skip (size)     unsigned int size;{  if (section == in_text)    bc_emit_const_skip (size);  else    bc_emit_data_skip (size);}intbc_emit_labeldef (name)     char *name;{  if (section == in_text)    return bc_emit_const_labeldef (name);  else    return bc_emit_data_labeldef (name);}voidbc_emit_labelref (name, offset)     char *name;     int offset;{  if (section == in_text)    bc_emit_const_labelref (name, offset);  else    bc_emit_data_labelref (name, offset);}voidbc_write_file (file)     FILE *file;{  BC_WRITE_FILE (file);}/* Allocate a new bytecode rtx.   If you supply a null BC_LABEL, we generate one.  */rtxbc_gen_rtx (label, offset, bc_label)     char *label;     int offset;     struct bc_label *bc_label;{  rtx r;  if (bc_label == 0)    bc_label = (struct bc_label *) xmalloc (sizeof (struct bc_label));  r = gen_rtx (CODE_LABEL, VOIDmode, label, bc_label);  bc_label->offset = offset;  return r;}/* Print bytecode rtx */voidbc_print_rtl (fp, r)     FILE *fp;     rtx r;{#if 0 /* This needs to get fixed to really work again.  */  /* BC_WRITE_RTL has a definition     that doesn't even make sense for this use.  */  BC_WRITE_RTL (r, fp);#endif}/* Emit a bytecode, keeping a running tally of the stack depth.  */voidbc_emit_bytecode (bytecode)     enum bytecode_opcode bytecode;{  char byte;  static int prev_lineno = -1;  byte = (char) bytecode;#ifdef BCDEBUG_PRINT_CODE  if (lineno != prev_lineno)    {      fprintf (stderr, "<line %d>\n", lineno);      prev_lineno = lineno;    }  fputs (opcode_name[(unsigned int) bytecode], stderr);#endif  /* Due to errors we are often requested to output bytecodes that     will cause an interpreter stack undeflow when executed.  Instead of     dumping core on such occasions, we omit the bytecode.  Erroneous code     should not be executed, regardless.  This makes life much easier, since     we don't have to deceive ourselves about the known stack depth.  */  bc_emit_bytecode_const (&byte, 1);  if ((stack_depth -= arityvec[(int) bytecode].ninputs) >= 0)    {      if ((stack_depth += arityvec[(int) bytecode].noutputs) > max_stack_depth)	max_stack_depth = stack_depth;    }#ifdef VALIDATE_STACK_FOR_BC  VALIDATE_STACK_FOR_BC ();#endif}#ifdef BCDEBUG_PRINT_CODE#define PRLIT(TYPE, PTR)  fprintf (stderr, " [%x]", *(TYPE *) PTR)#else#define PRLIT(X,Y)#endif/* Emit a complete bytecode instruction, expecting the correct number   of literal values in the call.  First argument is the instruction, the   remaining arguments are literals of size HOST_WIDE_INT or smaller.  */voidbc_emit_instruction VPROTO((enum bytecode_opcode opcode, ...)){#ifndef __STDC__  enum bytecode_opcode opcode;#endif  va_list arguments;  int nliteral, instruction;  VA_START (arguments, opcode);#ifndef __STDC__  opcode = va_arg (arguments, enum bytecode_opcode);#endif  /* Emit instruction bytecode */  bc_emit_bytecode (opcode);  instruction = (int) opcode;  /* Loop literals and emit as bytecode constants */  for (nliteral = 0; nliteral < arityvec[instruction].nliterals; nliteral++)    {      switch (arityvec[instruction].literals[nliteral])	{/* This conditional is a kludge, but it's necessary   because TYPE might be long long.  */#ifdef __GNUC__	  /* Expand definitions into case statements */#define DEFTYPECODE(CODE, NAME, MODE, TYPE)				\	case CODE:							\	  {								\	    TYPE temp = va_arg (arguments, TYPE); 			\	    bc_emit_bytecode_const ((void *) &temp, sizeof temp); 	\	    PRLIT (TYPE, &temp); }					\	  break;#include "bc-typecd.def"#undef DEFTYPECODE#endif /* __GNUC__ */	default:	  abort ();	}    }  va_end (arguments);#ifdef BCDEBUG_PRINT_CODE  fputc ('\n', stderr);#endif}/* Emit the machine-code interface trampoline at the beginning of a byte   coded function.  The argument is a label name of the interpreter   bytecode callinfo structure; the return value is a label name for   the beginning of the actual bytecode.  */char *bc_emit_trampoline (callinfo)     char *callinfo;{  char mylab[20];  static int n;  sprintf (mylab, "*LB%d", n++);    BC_EMIT_TRAMPOLINE (trampoline, callinfo);  seg_defsym (bytecode, mylab);  return sym_lookup (mylab)->name;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -