mirror of
https://github.com/golang/go
synced 2024-11-23 22:10:04 -07:00
liblink: make Prog, Addr more portable and document
Change-Id: Idda476b71ae23f7b73fe63f062cf3531c1268eb3 Reviewed-on: https://go-review.googlesource.com/3514 Reviewed-by: Rob Pike <r@golang.org> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Aram Hăvărneanu <aram@mgk.ro> Reviewed-by: Dave Cheney <dave@cheney.net>
This commit is contained in:
parent
a99369fdb5
commit
2ec293123f
199
include/link.h
199
include/link.h
@ -43,32 +43,157 @@ typedef struct Pcln Pcln;
|
||||
typedef struct Pcdata Pcdata;
|
||||
typedef struct Pciter Pciter;
|
||||
|
||||
// prevent incompatible type signatures between liblink and 8l on Plan 9
|
||||
#pragma incomplete struct Node
|
||||
|
||||
// An Addr is an argument to an instruction.
|
||||
// The general forms and their encodings are:
|
||||
//
|
||||
// sym±offset(symkind)(reg)(index*scale)
|
||||
// Memory reference at address &sym(symkind) + offset + reg + index*scale.
|
||||
// Any of sym(symkind), ±offset, (reg), (index*scale), and *scale can be omitted.
|
||||
// If (reg) and *scale are both omitted, the resulting expression (index) is parsed as (reg).
|
||||
// To force a parsing as index*scale, write (index*1).
|
||||
// Encoding:
|
||||
// type = TYPE_MEM
|
||||
// name = symkind (NAME_AUTO, ...) or 0 (NAME_NONE)
|
||||
// sym = sym
|
||||
// offset = ±offset
|
||||
// reg = reg (REG_*)
|
||||
// index = index (REG_*)
|
||||
// scale = scale (1, 2, 4, 8)
|
||||
//
|
||||
// $<mem>
|
||||
// Effective address of memory reference <mem>, defined above.
|
||||
// NOTE: Today, on arm and ppc64, type = TYPE_CONST instead.
|
||||
// Encoding: same as memory reference, but type = TYPE_ADDR.
|
||||
//
|
||||
// $<±integer value>
|
||||
// This is a special case of $<mem>, in which only ±offset is present.
|
||||
// It has a separate type for easy recognition.
|
||||
// NOTE: Today, on arm and ppc64, TYPE_CONST and TYPE_ADDR are merged into just TYPE_CONST.
|
||||
// Encoding:
|
||||
// type = TYPE_CONST
|
||||
// offset = ±integer value
|
||||
//
|
||||
// *<mem>
|
||||
// Indirect reference through memory reference <mem>, defined above.
|
||||
// Only used on x86 for CALL/JMP *sym(SB), which calls/jumps to a function
|
||||
// pointer stored in the data word sym(SB), not a function named sym(SB).
|
||||
// Encoding: same as above, but type = TYPE_INDIR.
|
||||
//
|
||||
// $*$<mem>
|
||||
// No longer used.
|
||||
// On machines with actual SB registers, $*$<mem> forced the
|
||||
// instruction encoding to use a full 32-bit constant, never a
|
||||
// reference relative to SB.
|
||||
//
|
||||
// $<floating point literal>
|
||||
// Floating point constant value.
|
||||
// Encoding:
|
||||
// type = TYPE_FCONST
|
||||
// u.dval = floating point value
|
||||
//
|
||||
// $<string literal, up to 8 chars>
|
||||
// String literal value (raw bytes used for DATA instruction).
|
||||
// Encoding:
|
||||
// type = TYPE_SCONST
|
||||
// u.sval = string
|
||||
//
|
||||
// <register name>
|
||||
// Any register: integer, floating point, control, segment, and so on.
|
||||
// If looking for specific register kind, must check type and reg value range.
|
||||
// Encoding:
|
||||
// type = TYPE_REG
|
||||
// reg = reg (REG_*)
|
||||
//
|
||||
// x(PC)
|
||||
// Encoding:
|
||||
// type = TYPE_BRANCH
|
||||
// u.branch = Prog* reference OR ELSE offset = target pc (branch takes priority)
|
||||
//
|
||||
// $±x-±y
|
||||
// Final argument to TEXT, specifying local frame size x and argument size y.
|
||||
// In this form, x and y are integer literals only, not arbitrary expressions.
|
||||
// This avoids parsing ambiguities due to the use of - as a separator.
|
||||
// The ± are optional.
|
||||
// If the final argument to TEXT omits the -±y, the encoding should still
|
||||
// use TYPE_TEXTSIZE (not TYPE_CONST), with u.argsize = ArgsSizeUnknown.
|
||||
// Encoding:
|
||||
// type = TYPE_TEXTSIZE
|
||||
// offset = x
|
||||
// u.argsize = y
|
||||
//
|
||||
// reg<<shift, reg>>shift, reg->shift, reg@>shift
|
||||
// Shifted register value, for ARM.
|
||||
// In this form, reg must be a register and shift can be a register or an integer constant.
|
||||
// Encoding:
|
||||
// type = TYPE_SHIFT
|
||||
// offset = (reg&15) | shifttype<<5 | count
|
||||
// shifttype = 0, 1, 2, 3 for <<, >>, ->, @>
|
||||
// count = (reg&15)<<8 | 1<<4 for a register shift count, (n&31)<<7 for an integer constant.
|
||||
//
|
||||
// (reg, reg)
|
||||
// A destination register pair. When used as the last argument of an instruction,
|
||||
// this form makes clear that both registers are destinations.
|
||||
// Encoding:
|
||||
// type = TYPE_REGREG
|
||||
// reg = first register
|
||||
// offset = second register
|
||||
//
|
||||
// reg, reg
|
||||
// TYPE_REGREG2, to be removed.
|
||||
//
|
||||
struct Addr
|
||||
{
|
||||
vlong offset;
|
||||
|
||||
int16 type; // could be int8
|
||||
int16 reg;
|
||||
int16 index;
|
||||
int8 scale;
|
||||
int8 name;
|
||||
int64 offset;
|
||||
LSym* sym;
|
||||
|
||||
union
|
||||
{
|
||||
char sval[8];
|
||||
float64 dval;
|
||||
Prog* branch; // for 5g, 6g, 8g, 9g
|
||||
Prog* branch;
|
||||
int32 argsize; // for 5l, 8l
|
||||
} u;
|
||||
|
||||
LSym* sym;
|
||||
// gotype is the name of the Go type descriptor for sym.
|
||||
// It cannot be set using assembly syntax.
|
||||
// It is generated by the Go compiler for global declarations,
|
||||
// to convey information about pointer locations to the back end
|
||||
// and for use in generating debug information.
|
||||
LSym* gotype;
|
||||
short type;
|
||||
uint8 index;
|
||||
int8 scale;
|
||||
int8 reg; // for 5l, 9l; GPRs and FPRs both start at 0
|
||||
int8 name; // for 5l, 9l
|
||||
int8 class; // for 5l, 9l
|
||||
uint8 etype; // for 5g, 6g, 8g
|
||||
int32 offset2; // for 5l, 8l
|
||||
void* node; // for 5g, 6g, 8g
|
||||
int64 width; // for 5g, 6g, 8g
|
||||
|
||||
int8 class; // for internal use by liblink
|
||||
uint8 etype; // for internal use by 5g, 6g, 8g
|
||||
void* node; // for internal use by 5g, 6g, 8g
|
||||
int64 width; // for internal use by 5g, 6g, 8g
|
||||
};
|
||||
|
||||
enum {
|
||||
NAME_NONE = 0,
|
||||
NAME_EXTERN,
|
||||
NAME_STATIC,
|
||||
NAME_AUTO,
|
||||
NAME_PARAM,
|
||||
};
|
||||
|
||||
enum {
|
||||
TYPE_NONE = 0,
|
||||
TYPE_BRANCH = 5, // avoid accidental conflicts with NAME_*
|
||||
TYPE_TEXTSIZE,
|
||||
TYPE_MEM,
|
||||
TYPE_CONST,
|
||||
TYPE_FCONST,
|
||||
TYPE_SCONST,
|
||||
TYPE_REG,
|
||||
TYPE_ADDR,
|
||||
TYPE_SHIFT,
|
||||
TYPE_REGREG,
|
||||
TYPE_REGREG2,
|
||||
TYPE_INDIR,
|
||||
};
|
||||
|
||||
struct Reloc
|
||||
@ -84,6 +209,8 @@ struct Reloc
|
||||
LSym* xsym;
|
||||
};
|
||||
|
||||
// TODO(rsc): Describe prog.
|
||||
// TOOD(rsc): Make ARM scond == 0 mean C_SCOND_NONE.
|
||||
struct Prog
|
||||
{
|
||||
vlong pc;
|
||||
@ -94,7 +221,7 @@ struct Prog
|
||||
|
||||
// operands
|
||||
Addr from;
|
||||
uchar reg; // arm, ppc64 only (e.g., ADD from, reg, to);
|
||||
int16 reg; // arm, ppc64 only (e.g., ADD from, reg, to);
|
||||
// starts at 0 for both GPRs and FPRs;
|
||||
// also used for ADATA width on arm, ppc64
|
||||
Addr from3; // ppc64 only (e.g., RLWM/FMADD from, reg, from3, to)
|
||||
@ -103,18 +230,18 @@ struct Prog
|
||||
// for 5g, 6g, 8g internal use
|
||||
void* opt;
|
||||
|
||||
// for 5l, 6l, 8l internal use
|
||||
// for liblink internal use
|
||||
Prog* forwd;
|
||||
Prog* pcond;
|
||||
Prog* comefrom; // 6l, 8l
|
||||
Prog* pcrel; // 5l
|
||||
Prog* comefrom; // amd64, 386
|
||||
Prog* pcrel; // arm
|
||||
int32 spadj;
|
||||
uint16 mark;
|
||||
uint16 optab; // 5l, 9l
|
||||
uchar back; // 6l, 8l
|
||||
uchar ft; /* 6l, 8l oclass cache */
|
||||
uchar tt; // 6l, 8l
|
||||
uchar isize; // 6l, 8l
|
||||
uint16 optab; // arm, ppc64
|
||||
uchar back; // amd64, 386
|
||||
uchar ft; // oclass cache
|
||||
uchar tt; // oclass cache
|
||||
uchar isize; // amd64, 386
|
||||
|
||||
char width; /* fake for DATA */
|
||||
char mode; /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */
|
||||
@ -273,7 +400,7 @@ enum
|
||||
RV_TYPE_MASK = (RV_CHECK_OVERFLOW - 1),
|
||||
};
|
||||
|
||||
// Auto.type
|
||||
// Auto.name
|
||||
enum
|
||||
{
|
||||
A_AUTO = 1,
|
||||
@ -285,7 +412,7 @@ struct Auto
|
||||
LSym* asym;
|
||||
Auto* link;
|
||||
int32 aoffset;
|
||||
int16 type;
|
||||
int16 name;
|
||||
LSym* gotype;
|
||||
};
|
||||
|
||||
@ -469,7 +596,7 @@ struct LinkArch
|
||||
int thechar; // '5', '6', and so on
|
||||
int32 endian; // LittleEndian or BigEndian
|
||||
|
||||
void (*addstacksplit)(Link*, LSym*);
|
||||
void (*preprocess)(Link*, LSym*);
|
||||
void (*assemble)(Link*, LSym*);
|
||||
int (*datasize)(Prog*);
|
||||
void (*follow)(Link*, LSym*);
|
||||
@ -478,26 +605,12 @@ struct LinkArch
|
||||
Prog* (*prg)(void);
|
||||
void (*progedit)(Link*, Prog*);
|
||||
void (*settextflag)(Prog*, int);
|
||||
int (*symtype)(Addr*);
|
||||
int (*textflag)(Prog*);
|
||||
|
||||
int minlc;
|
||||
int ptrsize;
|
||||
int regsize;
|
||||
|
||||
// TODO: Give these the same values on all systems.
|
||||
int D_ADDR;
|
||||
int D_AUTO;
|
||||
int D_BRANCH;
|
||||
int D_CONST;
|
||||
int D_EXTERN;
|
||||
int D_FCONST;
|
||||
int D_NONE;
|
||||
int D_PARAM;
|
||||
int D_SCONST;
|
||||
int D_STATIC;
|
||||
int D_OREG;
|
||||
|
||||
int ACALL;
|
||||
int ADATA;
|
||||
int AEND;
|
||||
|
Loading…
Reference in New Issue
Block a user