]> Cypherpunks repositories - gostls13.git/commitdiff
liblink: make Prog, Addr more portable and document
authorRuss Cox <rsc@golang.org>
Mon, 26 Jan 2015 20:13:05 +0000 (15:13 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 30 Jan 2015 03:15:34 +0000 (03:15 +0000)
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>
include/link.h

index 7653ad27860bb4736fb7d95185f6a1c3ceb2a742..42071dbb35f3cde7ab6ee970f9f2e39b7080252d 100644 (file)
@@ -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;