mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Add compiler source to new directory structure
SVN=121164
This commit is contained in:
parent
896c8f4ecc
commit
0cafb9ea3d
65 changed files with 46104 additions and 0 deletions
206
src/cmd/6a/a.h
Normal file
206
src/cmd/6a/a.h
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
// Inferno utils/6a/a.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "../6l/6.out.h"
|
||||
#include "compat.h"
|
||||
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Ref Ref;
|
||||
typedef struct Gen Gen;
|
||||
typedef struct Io Io;
|
||||
typedef struct Hist Hist;
|
||||
typedef struct Gen2 Gen2;
|
||||
|
||||
#define MAXALIGN 7
|
||||
#define FPCHIP 1
|
||||
#define NSYMB 500
|
||||
#define BUFSIZ 8192
|
||||
#define HISTSZ 20
|
||||
#define NINCLUDE 10
|
||||
#define NHUNK 10000
|
||||
#define EOF (-1)
|
||||
#define IGN (-2)
|
||||
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
|
||||
#define NHASH 503
|
||||
#define STRINGSZ 200
|
||||
#define NMACRO 10
|
||||
|
||||
struct Sym
|
||||
{
|
||||
Sym* link;
|
||||
Ref* ref;
|
||||
char* macro;
|
||||
vlong value;
|
||||
ushort type;
|
||||
char *name;
|
||||
char sym;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
|
||||
struct Ref
|
||||
{
|
||||
int class;
|
||||
};
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
char* p;
|
||||
int c;
|
||||
} fi;
|
||||
|
||||
struct Io
|
||||
{
|
||||
Io* link;
|
||||
char b[BUFSIZ];
|
||||
char* p;
|
||||
short c;
|
||||
short f;
|
||||
};
|
||||
#define I ((Io*)0)
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
Sym* sym;
|
||||
short type;
|
||||
} h[NSYM];
|
||||
|
||||
struct Gen
|
||||
{
|
||||
double dval;
|
||||
char sval[8];
|
||||
vlong offset;
|
||||
Sym* sym;
|
||||
short type;
|
||||
short index;
|
||||
short scale;
|
||||
};
|
||||
struct Gen2
|
||||
{
|
||||
Gen from;
|
||||
Gen to;
|
||||
};
|
||||
|
||||
struct Hist
|
||||
{
|
||||
Hist* link;
|
||||
char* name;
|
||||
long line;
|
||||
vlong offset;
|
||||
};
|
||||
#define H ((Hist*)0)
|
||||
|
||||
enum
|
||||
{
|
||||
CLAST,
|
||||
CMACARG,
|
||||
CMACRO,
|
||||
CPREPROC,
|
||||
};
|
||||
|
||||
|
||||
EXTERN char debug[256];
|
||||
EXTERN Sym* hash[NHASH];
|
||||
EXTERN char* Dlist[30];
|
||||
EXTERN int nDlist;
|
||||
EXTERN Hist* ehist;
|
||||
EXTERN int newflag;
|
||||
EXTERN Hist* hist;
|
||||
EXTERN char* hunk;
|
||||
EXTERN char* include[NINCLUDE];
|
||||
EXTERN Io* iofree;
|
||||
EXTERN Io* ionext;
|
||||
EXTERN Io* iostack;
|
||||
EXTERN long lineno;
|
||||
EXTERN int nerrors;
|
||||
EXTERN long nhunk;
|
||||
EXTERN int ninclude;
|
||||
EXTERN Gen nullgen;
|
||||
EXTERN char* outfile;
|
||||
EXTERN int pass;
|
||||
EXTERN char* pathname;
|
||||
EXTERN long pc;
|
||||
EXTERN int peekc;
|
||||
EXTERN int sym;
|
||||
EXTERN char symb[NSYMB];
|
||||
EXTERN int thechar;
|
||||
EXTERN char* thestring;
|
||||
EXTERN long thunk;
|
||||
EXTERN Biobuf obuf;
|
||||
|
||||
void* allocn(void*, long, long);
|
||||
void errorexit(void);
|
||||
void pushio(void);
|
||||
void newio(void);
|
||||
void newfile(char*, int);
|
||||
Sym* slookup(char*);
|
||||
Sym* lookup(void);
|
||||
void syminit(Sym*);
|
||||
long yylex(void);
|
||||
int getc(void);
|
||||
int getnsc(void);
|
||||
void unget(int);
|
||||
int escchar(int);
|
||||
void cinit(void);
|
||||
void checkscale(int);
|
||||
void pinit(char*);
|
||||
void cclean(void);
|
||||
int isreg(Gen*);
|
||||
void outcode(int, Gen2*);
|
||||
void outhist(void);
|
||||
void zaddr(Gen*, int);
|
||||
void zname(char*, int, int);
|
||||
void ieeedtod(Ieee*, double);
|
||||
int filbuf(void);
|
||||
Sym* getsym(void);
|
||||
void domacro(void);
|
||||
void macund(void);
|
||||
void macdef(void);
|
||||
void macexpand(Sym*, char*);
|
||||
void macinc(void);
|
||||
void macprag(void);
|
||||
void maclin(void);
|
||||
void macif(int);
|
||||
void macend(void);
|
||||
void dodefine(char*);
|
||||
void prfile(long);
|
||||
void linehist(char*, int);
|
||||
void gethunk(void);
|
||||
void yyerror(char*, ...);
|
||||
int yyparse(void);
|
||||
void setinclude(char*);
|
||||
int assemble(char*);
|
||||
592
src/cmd/6a/a.y
Normal file
592
src/cmd/6a/a.y
Normal file
|
|
@ -0,0 +1,592 @@
|
|||
// Inferno utils/6a/a.y
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.y
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
%{
|
||||
#include "a.h"
|
||||
%}
|
||||
%union {
|
||||
Sym *sym;
|
||||
vlong lval;
|
||||
double dval;
|
||||
char sval[8];
|
||||
Gen gen;
|
||||
Gen2 gen2;
|
||||
}
|
||||
%left '|'
|
||||
%left '^'
|
||||
%left '&'
|
||||
%left '<' '>'
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
|
||||
%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT
|
||||
%token <lval> LCONST LFP LPC LSB
|
||||
%token <lval> LBREG LLREG LSREG LFREG LMREG LXREG
|
||||
%token <dval> LFCONST
|
||||
%token <sval> LSCONST LSP
|
||||
%token <sym> LNAME LLAB LVAR
|
||||
%type <lval> con expr pointer offset
|
||||
%type <gen> mem imm reg nam rel rem rim rom omem nmem
|
||||
%type <gen2> nonnon nonrel nonrem rimnon rimrem remrim spec10
|
||||
%type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
|
||||
%%
|
||||
prog:
|
||||
| prog line
|
||||
|
||||
line:
|
||||
LLAB ':'
|
||||
{
|
||||
if($1->value != pc)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| LNAME ':'
|
||||
{
|
||||
$1->type = LLAB;
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| ';'
|
||||
| inst ';'
|
||||
| error ';'
|
||||
|
||||
inst:
|
||||
LNAME '=' expr
|
||||
{
|
||||
$1->type = LVAR;
|
||||
$1->value = $3;
|
||||
}
|
||||
| LVAR '=' expr
|
||||
{
|
||||
if($1->value != $3)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = $3;
|
||||
}
|
||||
| LTYPE0 nonnon { outcode($1, &$2); }
|
||||
| LTYPE1 nonrem { outcode($1, &$2); }
|
||||
| LTYPE2 rimnon { outcode($1, &$2); }
|
||||
| LTYPE3 rimrem { outcode($1, &$2); }
|
||||
| LTYPE4 remrim { outcode($1, &$2); }
|
||||
| LTYPER nonrel { outcode($1, &$2); }
|
||||
| LTYPED spec1 { outcode($1, &$2); }
|
||||
| LTYPET spec2 { outcode($1, &$2); }
|
||||
| LTYPEC spec3 { outcode($1, &$2); }
|
||||
| LTYPEN spec4 { outcode($1, &$2); }
|
||||
| LTYPES spec5 { outcode($1, &$2); }
|
||||
| LTYPEM spec6 { outcode($1, &$2); }
|
||||
| LTYPEI spec7 { outcode($1, &$2); }
|
||||
| LTYPEXC spec8 { outcode($1, &$2); }
|
||||
| LTYPEX spec9 { outcode($1, &$2); }
|
||||
| LTYPERT spec10 { outcode($1, &$2); }
|
||||
|
||||
nonnon:
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| ','
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
|
||||
rimrem:
|
||||
rim ',' rem
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
|
||||
remrim:
|
||||
rem ',' rim
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
|
||||
rimnon:
|
||||
rim ','
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| rim
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
|
||||
nonrem:
|
||||
',' rem
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $2;
|
||||
}
|
||||
| rem
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $1;
|
||||
}
|
||||
|
||||
nonrel:
|
||||
',' rel
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $2;
|
||||
}
|
||||
| rel
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $1;
|
||||
}
|
||||
|
||||
spec1: /* DATA */
|
||||
nam '/' con ',' imm
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.from.scale = $3;
|
||||
$$.to = $5;
|
||||
}
|
||||
|
||||
spec2: /* TEXT */
|
||||
mem ',' imm
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
| mem ',' con ',' imm
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.from.scale = $3;
|
||||
$$.to = $5;
|
||||
}
|
||||
|
||||
spec3: /* JMP/CALL */
|
||||
',' rom
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $2;
|
||||
}
|
||||
| rom
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $1;
|
||||
}
|
||||
|
||||
spec4: /* NOP */
|
||||
nonnon
|
||||
| nonrem
|
||||
|
||||
spec5: /* SHL/SHR */
|
||||
rim ',' rem
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
| rim ',' rem ':' LLREG
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
if($$.from.index != D_NONE)
|
||||
yyerror("dp shift with lhs index");
|
||||
$$.from.index = $5;
|
||||
}
|
||||
|
||||
spec6: /* MOVW/MOVL */
|
||||
rim ',' rem
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
| rim ',' rem ':' LSREG
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
if($$.to.index != D_NONE)
|
||||
yyerror("dp move with lhs index");
|
||||
$$.to.index = $5;
|
||||
}
|
||||
|
||||
spec7:
|
||||
rim ','
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| rim
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| rim ',' rem
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
|
||||
spec8: /* CMPPS/CMPPD */
|
||||
reg ',' rem ',' con
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
$$.from.offset = $5;
|
||||
}
|
||||
|
||||
spec9: /* shufl */
|
||||
imm ',' rem ',' reg
|
||||
{
|
||||
$$.from = $3;
|
||||
$$.to = $5;
|
||||
if($1.type != D_CONST)
|
||||
yyerror("illegal constant");
|
||||
$$.to.offset = $1.offset;
|
||||
}
|
||||
|
||||
spec10: /* RET/RETF */
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| imm
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
|
||||
rem:
|
||||
reg
|
||||
| mem
|
||||
|
||||
rom:
|
||||
rel
|
||||
| nmem
|
||||
| '*' reg
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '*' omem
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| reg
|
||||
| omem
|
||||
|
||||
rim:
|
||||
rem
|
||||
| imm
|
||||
|
||||
rel:
|
||||
con '(' LPC ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $1 + pc;
|
||||
}
|
||||
| LNAME offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
if(pass == 2)
|
||||
yyerror("undefined label: %s", $1->name);
|
||||
$$.type = D_BRANCH;
|
||||
$$.sym = $1;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LLAB offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_BRANCH;
|
||||
$$.sym = $1;
|
||||
$$.offset = $1->value + $2;
|
||||
}
|
||||
|
||||
reg:
|
||||
LBREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LFREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LLREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LMREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LSP
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_SP;
|
||||
}
|
||||
| LSREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LXREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
|
||||
imm:
|
||||
'$' con
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_CONST;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| '$' nam
|
||||
{
|
||||
$$ = $2;
|
||||
$$.index = $2.type;
|
||||
$$.type = D_ADDR;
|
||||
/*
|
||||
if($2.type == D_AUTO || $2.type == D_PARAM)
|
||||
yyerror("constant cannot be automatic: %s",
|
||||
$2.sym->name);
|
||||
*/
|
||||
}
|
||||
| '$' LSCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_SCONST;
|
||||
memcpy($$.sval, $2, sizeof($$.sval));
|
||||
}
|
||||
| '$' LFCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCONST;
|
||||
$$.dval = $2;
|
||||
}
|
||||
| '$' '(' LFCONST ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCONST;
|
||||
$$.dval = $3;
|
||||
}
|
||||
| '$' '-' LFCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCONST;
|
||||
$$.dval = -$3;
|
||||
}
|
||||
|
||||
mem:
|
||||
omem
|
||||
| nmem
|
||||
|
||||
omem:
|
||||
con
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_NONE;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| con '(' LLREG ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$3;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| con '(' LSP ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_SP;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| con '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_NONE;
|
||||
$$.offset = $1;
|
||||
$$.index = $3;
|
||||
$$.scale = $5;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
| con '(' LLREG ')' '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$3;
|
||||
$$.offset = $1;
|
||||
$$.index = $6;
|
||||
$$.scale = $8;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
| '(' LLREG ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$2;
|
||||
}
|
||||
| '(' LSP ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_SP;
|
||||
}
|
||||
| '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_NONE;
|
||||
$$.index = $2;
|
||||
$$.scale = $4;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
| '(' LLREG ')' '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$2;
|
||||
$$.index = $5;
|
||||
$$.scale = $7;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
|
||||
nmem:
|
||||
nam
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| nam '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = $1;
|
||||
$$.index = $3;
|
||||
$$.scale = $5;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
|
||||
nam:
|
||||
LNAME offset '(' pointer ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $4;
|
||||
$$.sym = $1;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LNAME '<' '>' offset '(' LSB ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_STATIC;
|
||||
$$.sym = $1;
|
||||
$$.offset = $4;
|
||||
}
|
||||
|
||||
offset:
|
||||
{
|
||||
$$ = 0;
|
||||
}
|
||||
| '+' con
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '-' con
|
||||
{
|
||||
$$ = -$2;
|
||||
}
|
||||
|
||||
pointer:
|
||||
LSB
|
||||
| LSP
|
||||
{
|
||||
$$ = D_AUTO;
|
||||
}
|
||||
| LFP
|
||||
|
||||
con:
|
||||
LCONST
|
||||
| LVAR
|
||||
{
|
||||
$$ = $1->value;
|
||||
}
|
||||
| '-' con
|
||||
{
|
||||
$$ = -$2;
|
||||
}
|
||||
| '+' con
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '~' con
|
||||
{
|
||||
$$ = ~$2;
|
||||
}
|
||||
| '(' expr ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
expr:
|
||||
con
|
||||
| expr '+' expr
|
||||
{
|
||||
$$ = $1 + $3;
|
||||
}
|
||||
| expr '-' expr
|
||||
{
|
||||
$$ = $1 - $3;
|
||||
}
|
||||
| expr '*' expr
|
||||
{
|
||||
$$ = $1 * $3;
|
||||
}
|
||||
| expr '/' expr
|
||||
{
|
||||
$$ = $1 / $3;
|
||||
}
|
||||
| expr '%' expr
|
||||
{
|
||||
$$ = $1 % $3;
|
||||
}
|
||||
| expr '<' '<' expr
|
||||
{
|
||||
$$ = $1 << $4;
|
||||
}
|
||||
| expr '>' '>' expr
|
||||
{
|
||||
$$ = $1 >> $4;
|
||||
}
|
||||
| expr '&' expr
|
||||
{
|
||||
$$ = $1 & $3;
|
||||
}
|
||||
| expr '^' expr
|
||||
{
|
||||
$$ = $1 ^ $3;
|
||||
}
|
||||
| expr '|' expr
|
||||
{
|
||||
$$ = $1 | $3;
|
||||
}
|
||||
1337
src/cmd/6a/lex.c
Normal file
1337
src/cmd/6a/lex.c
Normal file
File diff suppressed because it is too large
Load diff
1971
src/cmd/6c/cgen.c
Normal file
1971
src/cmd/6c/cgen.c
Normal file
File diff suppressed because it is too large
Load diff
236
src/cmd/6c/div.c
Normal file
236
src/cmd/6c/div.c
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
// Inferno utils/6c/div.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/div.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
/*
|
||||
* Based on: Granlund, T.; Montgomery, P.L.
|
||||
* "Division by Invariant Integers using Multiplication".
|
||||
* SIGPLAN Notices, Vol. 29, June 1994, page 61.
|
||||
*/
|
||||
|
||||
#define TN(n) ((uvlong)1 << (n))
|
||||
#define T31 TN(31)
|
||||
#define T32 TN(32)
|
||||
|
||||
int
|
||||
multiplier(ulong d, int p, uvlong *mp)
|
||||
{
|
||||
int l;
|
||||
uvlong mlo, mhi, tlo, thi;
|
||||
|
||||
l = topbit(d - 1) + 1;
|
||||
mlo = (((TN(l) - d) << 32) / d) + T32;
|
||||
if(l + p == 64)
|
||||
mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
|
||||
else
|
||||
mhi = (TN(32 + l) + TN(32 + l - p)) / d;
|
||||
/*assert(mlo < mhi);*/
|
||||
while(l > 0) {
|
||||
tlo = mlo >> 1;
|
||||
thi = mhi >> 1;
|
||||
if(tlo == thi)
|
||||
break;
|
||||
mlo = tlo;
|
||||
mhi = thi;
|
||||
l--;
|
||||
}
|
||||
*mp = mhi;
|
||||
return l;
|
||||
}
|
||||
|
||||
int
|
||||
sdiv(ulong d, ulong *mp, int *sp)
|
||||
{
|
||||
int s;
|
||||
uvlong m;
|
||||
|
||||
s = multiplier(d, 32 - 1, &m);
|
||||
*mp = m;
|
||||
*sp = s;
|
||||
if(m >= T31)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
udiv(ulong d, ulong *mp, int *sp, int *pp)
|
||||
{
|
||||
int p, s;
|
||||
uvlong m;
|
||||
|
||||
s = multiplier(d, 32, &m);
|
||||
p = 0;
|
||||
if(m >= T32) {
|
||||
while((d & 1) == 0) {
|
||||
d >>= 1;
|
||||
p++;
|
||||
}
|
||||
s = multiplier(d, 32 - p, &m);
|
||||
}
|
||||
*mp = m;
|
||||
*pp = p;
|
||||
if(m >= T32) {
|
||||
/*assert(p == 0);*/
|
||||
*sp = s - 1;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
*sp = s;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdivgen(Node *l, Node *r, Node *ax, Node *dx)
|
||||
{
|
||||
int a, s;
|
||||
ulong m;
|
||||
vlong c;
|
||||
|
||||
c = r->vconst;
|
||||
if(c < 0)
|
||||
c = -c;
|
||||
a = sdiv(c, &m, &s);
|
||||
//print("a=%d i=%ld s=%d m=%lux\n", a, (long)r->vconst, s, m);
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AIMULL, l, Z);
|
||||
gins(AMOVL, l, ax);
|
||||
if(a)
|
||||
gins(AADDL, ax, dx);
|
||||
gins(ASHRL, nodconst(31), ax);
|
||||
gins(ASARL, nodconst(s), dx);
|
||||
gins(AADDL, ax, dx);
|
||||
if(r->vconst < 0)
|
||||
gins(ANEGL, Z, dx);
|
||||
}
|
||||
|
||||
void
|
||||
udivgen(Node *l, Node *r, Node *ax, Node *dx)
|
||||
{
|
||||
int a, s, t;
|
||||
ulong m;
|
||||
Node nod;
|
||||
|
||||
a = udiv(r->vconst, &m, &s, &t);
|
||||
//print("a=%ud i=%ld p=%d s=%d m=%lux\n", a, (long)r->vconst, t, s, m);
|
||||
if(t != 0) {
|
||||
gins(AMOVL, l, ax);
|
||||
gins(ASHRL, nodconst(t), ax);
|
||||
gins(AMOVL, nodconst(m), dx);
|
||||
gins(AMULL, dx, Z);
|
||||
}
|
||||
else if(a) {
|
||||
if(l->op != OREGISTER) {
|
||||
regalloc(&nod, l, Z);
|
||||
gins(AMOVL, l, &nod);
|
||||
l = &nod;
|
||||
}
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AMULL, l, Z);
|
||||
gins(AADDL, l, dx);
|
||||
gins(ARCRL, nodconst(1), dx);
|
||||
if(l == &nod)
|
||||
regfree(l);
|
||||
}
|
||||
else {
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AMULL, l, Z);
|
||||
}
|
||||
if(s != 0)
|
||||
gins(ASHRL, nodconst(s), dx);
|
||||
}
|
||||
|
||||
void
|
||||
sext(Node *d, Node *s, Node *l)
|
||||
{
|
||||
if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
|
||||
reg[D_DX]++;
|
||||
gins(ACDQ, Z, Z);
|
||||
}
|
||||
else {
|
||||
regalloc(d, l, Z);
|
||||
gins(AMOVL, s, d);
|
||||
gins(ASARL, nodconst(31), d);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdiv2(long c, int v, Node *l, Node *n)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(v > 0) {
|
||||
if(v > 1) {
|
||||
sext(&nod, n, l);
|
||||
gins(AANDL, nodconst((1 << v) - 1), &nod);
|
||||
gins(AADDL, &nod, n);
|
||||
regfree(&nod);
|
||||
}
|
||||
else {
|
||||
gins(ACMPL, n, nodconst(0x80000000));
|
||||
gins(ASBBL, nodconst(-1), n);
|
||||
}
|
||||
gins(ASARL, nodconst(v), n);
|
||||
}
|
||||
if(c < 0)
|
||||
gins(ANEGL, Z, n);
|
||||
}
|
||||
|
||||
void
|
||||
smod2(long c, int v, Node *l, Node *n)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(c == 1) {
|
||||
zeroregm(n);
|
||||
return;
|
||||
}
|
||||
|
||||
sext(&nod, n, l);
|
||||
if(v == 0) {
|
||||
zeroregm(n);
|
||||
gins(AXORL, &nod, n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
else if(v > 1) {
|
||||
gins(AANDL, nodconst((1 << v) - 1), &nod);
|
||||
gins(AADDL, &nod, n);
|
||||
gins(AANDL, nodconst((1 << v) - 1), n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
else {
|
||||
gins(AANDL, nodconst(1), n);
|
||||
gins(AXORL, &nod, n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
regfree(&nod);
|
||||
}
|
||||
411
src/cmd/6c/gc.h
Normal file
411
src/cmd/6c/gc.h
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
// Inferno utils/6c/gc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "../cc/cc.h"
|
||||
#include "../6l/6.out.h"
|
||||
|
||||
/*
|
||||
* 6c/amd64
|
||||
* Intel 386 with AMD64 extensions
|
||||
*/
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_IND 8
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_VLONG 8
|
||||
#define SZ_DOUBLE 8
|
||||
#define FNX 100
|
||||
|
||||
typedef struct Adr Adr;
|
||||
typedef struct Prog Prog;
|
||||
typedef struct Case Case;
|
||||
typedef struct C1 C1;
|
||||
typedef struct Var Var;
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
typedef struct Renv Renv;
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
Node* regtree;
|
||||
Node* basetree;
|
||||
short scale;
|
||||
short reg;
|
||||
short ptr;
|
||||
} idx;
|
||||
|
||||
struct Adr
|
||||
{
|
||||
vlong offset;
|
||||
double dval;
|
||||
char sval[NSNAME];
|
||||
|
||||
Sym* sym;
|
||||
uchar type;
|
||||
uchar index;
|
||||
uchar etype;
|
||||
uchar scale; /* doubles as width in DATA op */
|
||||
};
|
||||
#define A ((Adr*)0)
|
||||
|
||||
#define INDEXED 9
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
Adr to;
|
||||
Prog* link;
|
||||
long lineno;
|
||||
short as;
|
||||
};
|
||||
#define P ((Prog*)0)
|
||||
|
||||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
vlong val;
|
||||
long label;
|
||||
char def;
|
||||
char isv;
|
||||
};
|
||||
#define C ((Case*)0)
|
||||
|
||||
struct C1
|
||||
{
|
||||
vlong val;
|
||||
long label;
|
||||
};
|
||||
|
||||
struct Var
|
||||
{
|
||||
vlong offset;
|
||||
Sym* sym;
|
||||
char name;
|
||||
char etype;
|
||||
};
|
||||
|
||||
struct Reg
|
||||
{
|
||||
long pc;
|
||||
long rpo; /* reverse post ordering */
|
||||
|
||||
Bits set;
|
||||
Bits use1;
|
||||
Bits use2;
|
||||
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
long regu;
|
||||
long loop; /* could be shorter */
|
||||
|
||||
Reg* log5;
|
||||
long active;
|
||||
|
||||
Reg* p1;
|
||||
Reg* p2;
|
||||
Reg* p2link;
|
||||
Reg* s1;
|
||||
Reg* s2;
|
||||
Reg* link;
|
||||
Prog* prog;
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
|
||||
struct Renv
|
||||
{
|
||||
int safe;
|
||||
Node base;
|
||||
Node* saved;
|
||||
Node* scope;
|
||||
};
|
||||
|
||||
#define NRGN 600
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN long breakpc;
|
||||
EXTERN long nbreak;
|
||||
EXTERN Case* cases;
|
||||
EXTERN Node constnode;
|
||||
EXTERN Node fconstnode;
|
||||
EXTERN Node vconstnode;
|
||||
EXTERN long continpc;
|
||||
EXTERN long curarg;
|
||||
EXTERN long cursafe;
|
||||
EXTERN Prog* firstp;
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN long maxargsafe;
|
||||
EXTERN int mnstring;
|
||||
EXTERN Node* nodrat;
|
||||
EXTERN Node* nodret;
|
||||
EXTERN Node* nodsafe;
|
||||
EXTERN long nrathole;
|
||||
EXTERN long nstring;
|
||||
EXTERN Prog* p;
|
||||
EXTERN long pc;
|
||||
EXTERN Node lregnode;
|
||||
EXTERN Node qregnode;
|
||||
EXTERN char string[NSNAME];
|
||||
EXTERN Sym* symrathole;
|
||||
EXTERN Node znode;
|
||||
EXTERN Prog zprog;
|
||||
EXTERN int reg[D_NONE];
|
||||
EXTERN long exregoffset;
|
||||
EXTERN long exfregoffset;
|
||||
EXTERN uchar typechlpv[NTYPE];
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
|
||||
|
||||
#define CLOAD 5
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
|
||||
EXTERN long regbits;
|
||||
EXTERN long exregbits;
|
||||
|
||||
EXTERN int change;
|
||||
EXTERN int suppress;
|
||||
|
||||
EXTERN Reg* firstr;
|
||||
EXTERN Reg* lastr;
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN Var var[NVAR];
|
||||
EXTERN long* idom;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN long maxnr;
|
||||
|
||||
extern char* anames[];
|
||||
|
||||
/*
|
||||
* sgen.c
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gen(Node*);
|
||||
void noretval(int);
|
||||
void usedset(Node*, int);
|
||||
void xcom(Node*);
|
||||
void indx(Node*);
|
||||
int bcomplex(Node*, Node*);
|
||||
|
||||
/*
|
||||
* cgen.c
|
||||
*/
|
||||
void zeroregm(Node*);
|
||||
void cgen(Node*, Node*);
|
||||
void reglcgen(Node*, Node*, Node*);
|
||||
void lcgen(Node*, Node*);
|
||||
void bcgen(Node*, int);
|
||||
void boolgen(Node*, int, Node*);
|
||||
void sugen(Node*, Node*, long);
|
||||
int needreg(Node*, int);
|
||||
int hardconst(Node*);
|
||||
int immconst(Node*);
|
||||
|
||||
/*
|
||||
* cgen64.c
|
||||
*/
|
||||
int vaddr(Node*, int);
|
||||
void loadpair(Node*, Node*);
|
||||
int cgen64(Node*, Node*);
|
||||
void testv(Node*, int);
|
||||
|
||||
/*
|
||||
* txt.c
|
||||
*/
|
||||
void ginit(void);
|
||||
void gclean(void);
|
||||
void nextpc(void);
|
||||
void gargs(Node*, Node*, Node*);
|
||||
void garg1(Node*, Node*, Node*, int, Node**);
|
||||
Node* nodconst(long);
|
||||
Node* nodfconst(double);
|
||||
Node* nodgconst(vlong, Type*);
|
||||
int nodreg(Node*, Node*, int);
|
||||
int isreg(Node*, int);
|
||||
void regret(Node*, Node*);
|
||||
void regalloc(Node*, Node*, Node*);
|
||||
void regfree(Node*);
|
||||
void regialloc(Node*, Node*, Node*);
|
||||
void regsalloc(Node*, Node*);
|
||||
void regaalloc1(Node*, Node*);
|
||||
void regaalloc(Node*, Node*);
|
||||
void regind(Node*, Node*);
|
||||
void gprep(Node*, Node*);
|
||||
void naddr(Node*, Adr*);
|
||||
void gcmp(int, Node*, vlong);
|
||||
void gmove(Node*, Node*);
|
||||
void gins(int a, Node*, Node*);
|
||||
void gopcode(int, Type*, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void gbranch(int);
|
||||
void patch(Prog*, long);
|
||||
int sconst(Node*);
|
||||
void gpseudo(int, Sym*, Node*);
|
||||
|
||||
/*
|
||||
* swt.c
|
||||
*/
|
||||
int swcmp(const void*, const void*);
|
||||
void doswit(Node*);
|
||||
void swit1(C1*, int, long, Node*);
|
||||
void cas(void);
|
||||
void bitload(Node*, Node*, Node*, Node*, Node*);
|
||||
void bitstore(Node*, Node*, Node*, Node*, Node*);
|
||||
long outstring(char*, long);
|
||||
void nullwarn(Node*, Node*);
|
||||
void sextern(Sym*, Node*, long, long);
|
||||
void gextern(Sym*, Node*, long, long);
|
||||
void outcode(void);
|
||||
void ieeedtod(Ieee*, double);
|
||||
|
||||
/*
|
||||
* list
|
||||
*/
|
||||
void listinit(void);
|
||||
int Pconv(Fmt*);
|
||||
int Aconv(Fmt*);
|
||||
int Dconv(Fmt*);
|
||||
int Sconv(Fmt*);
|
||||
int Rconv(Fmt*);
|
||||
int Xconv(Fmt*);
|
||||
int Bconv(Fmt*);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg*, Adr*);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, long);
|
||||
void synch(Reg*, Bits);
|
||||
ulong allreg(ulong, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
ulong paint2(Reg*, int);
|
||||
void paint3(Reg*, int, long, int);
|
||||
void addreg(Adr*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(void);
|
||||
void excise(Reg*);
|
||||
Reg* uniqp(Reg*);
|
||||
Reg* uniqs(Reg*);
|
||||
int regtyp(Adr*);
|
||||
int anyvar(Adr*);
|
||||
int subprop(Reg*);
|
||||
int copyprop(Reg*);
|
||||
int copy1(Adr*, Adr*, Reg*, int);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int copyas(Adr*, Adr*);
|
||||
int copyau(Adr*, Adr*);
|
||||
int copysub(Adr*, Adr*, Adr*, int);
|
||||
int copysub1(Prog*, Adr*, Adr*, int);
|
||||
|
||||
long RtoB(int);
|
||||
long FtoB(int);
|
||||
int BtoR(long);
|
||||
int BtoF(long);
|
||||
|
||||
#define D_HI D_NONE
|
||||
#define D_LO D_NONE
|
||||
|
||||
#define isregtype(t) ((t)>= D_AX && (t)<=D_R15)
|
||||
|
||||
/*
|
||||
* bound
|
||||
*/
|
||||
void comtarg(void);
|
||||
|
||||
/*
|
||||
* com64
|
||||
*/
|
||||
int cond(int);
|
||||
int com64(Node*);
|
||||
void com64init(void);
|
||||
void bool64(Node*);
|
||||
long lo64v(Node*);
|
||||
long hi64v(Node*);
|
||||
Node* lo64(Node*);
|
||||
Node* hi64(Node*);
|
||||
|
||||
/*
|
||||
* div/mul
|
||||
*/
|
||||
void sdivgen(Node*, Node*, Node*, Node*);
|
||||
void udivgen(Node*, Node*, Node*, Node*);
|
||||
void sdiv2(long, int, Node*, Node*);
|
||||
void smod2(long, int, Node*, Node*);
|
||||
void mulgen(Type*, Node*, Node*);
|
||||
void genmuladd(Node*, Node*, int, Node*);
|
||||
void shiftit(Type*, Node*, Node*);
|
||||
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck type "B" Bits
|
||||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
#pragma varargck type "S" char*
|
||||
|
||||
#define D_X7 (D_X0+7)
|
||||
|
||||
void fgopcode(int, Node*, Node*, int, int);
|
||||
372
src/cmd/6c/list.c
Normal file
372
src/cmd/6c/list.c
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Inferno utils/6c/list.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#define EXTERN
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
|
||||
fmtinstall('A', Aconv);
|
||||
fmtinstall('B', Bconv);
|
||||
fmtinstall('P', Pconv);
|
||||
fmtinstall('S', Sconv);
|
||||
fmtinstall('D', Dconv);
|
||||
fmtinstall('R', Rconv);
|
||||
}
|
||||
|
||||
int
|
||||
Bconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ], ss[STRINGSZ], *s;
|
||||
Bits bits;
|
||||
int i;
|
||||
|
||||
str[0] = 0;
|
||||
bits = va_arg(fp->args, Bits);
|
||||
while(bany(&bits)) {
|
||||
i = bnum(bits);
|
||||
if(str[0])
|
||||
strcat(str, " ");
|
||||
if(var[i].sym == S) {
|
||||
sprint(ss, "$%lld", var[i].offset);
|
||||
s = ss;
|
||||
} else
|
||||
s = var[i].sym->name;
|
||||
if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
|
||||
break;
|
||||
strcat(str, s);
|
||||
bits.b[i/32] &= ~(1L << (i%32));
|
||||
}
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Pconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Prog *p;
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
if(p->as == ADATA)
|
||||
sprint(str, " %A %D/%d,%D",
|
||||
p->as, &p->from, p->from.scale, &p->to);
|
||||
else if(p->as == ATEXT)
|
||||
sprint(str, " %A %D,%d,%D",
|
||||
p->as, &p->from, p->from.scale, &p->to);
|
||||
else
|
||||
sprint(str, " %A %D,%D",
|
||||
p->as, &p->from, &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Aconv(Fmt *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = va_arg(fp->args, int);
|
||||
return fmtstrcpy(fp, anames[i]);
|
||||
}
|
||||
|
||||
int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[40], s[20];
|
||||
Adr *a;
|
||||
int i;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
i = a->type;
|
||||
if(i >= D_INDIR) {
|
||||
if(a->offset)
|
||||
sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
|
||||
else
|
||||
sprint(str, "(%R)", i-D_INDIR);
|
||||
goto brk;
|
||||
}
|
||||
switch(i) {
|
||||
|
||||
default:
|
||||
if(a->offset)
|
||||
sprint(str, "$%lld,%R", a->offset, i);
|
||||
else
|
||||
sprint(str, "%R", i);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
str[0] = 0;
|
||||
break;
|
||||
|
||||
case D_BRANCH:
|
||||
sprint(str, "%lld(PC)", a->offset-pc);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
sprint(str, "%s<>+%lld(SB)", a->sym->name,
|
||||
a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
if(a->sym) {
|
||||
sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
|
||||
break;
|
||||
}
|
||||
sprint(str, "%lld(SP)", a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
if(a->sym) {
|
||||
sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
|
||||
break;
|
||||
}
|
||||
sprint(str, "%lld(FP)", a->offset);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
sprint(str, "$%lld", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
sprint(str, "$(%.17e)", a->dval);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
sprint(str, "$\"%S\"", a->sval);
|
||||
break;
|
||||
|
||||
case D_ADDR:
|
||||
a->type = a->index;
|
||||
a->index = D_NONE;
|
||||
sprint(str, "$%D", a);
|
||||
a->index = a->type;
|
||||
a->type = D_ADDR;
|
||||
goto conv;
|
||||
}
|
||||
brk:
|
||||
if(a->index != D_NONE) {
|
||||
sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
|
||||
strcat(str, s);
|
||||
}
|
||||
conv:
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
char* regstr[] =
|
||||
{
|
||||
"AL", /* [D_AL] */
|
||||
"CL",
|
||||
"DL",
|
||||
"BL",
|
||||
"SPB",
|
||||
"BPB",
|
||||
"SIB",
|
||||
"DIB",
|
||||
"R8B",
|
||||
"R9B",
|
||||
"R10B",
|
||||
"R11B",
|
||||
"R12B",
|
||||
"R13B",
|
||||
"R14B",
|
||||
"R15B",
|
||||
|
||||
"AX", /* [D_AX] */
|
||||
"CX",
|
||||
"DX",
|
||||
"BX",
|
||||
"SP",
|
||||
"BP",
|
||||
"SI",
|
||||
"DI",
|
||||
"R8",
|
||||
"R9",
|
||||
"R10",
|
||||
"R11",
|
||||
"R12",
|
||||
"R13",
|
||||
"R14",
|
||||
"R15",
|
||||
|
||||
"AH",
|
||||
"CH",
|
||||
"DH",
|
||||
"BH",
|
||||
|
||||
"F0", /* [D_F0] */
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
|
||||
"M0",
|
||||
"M1",
|
||||
"M2",
|
||||
"M3",
|
||||
"M4",
|
||||
"M5",
|
||||
"M6",
|
||||
"M7",
|
||||
|
||||
"X0",
|
||||
"X1",
|
||||
"X2",
|
||||
"X3",
|
||||
"X4",
|
||||
"X5",
|
||||
"X6",
|
||||
"X7",
|
||||
"X8",
|
||||
"X9",
|
||||
"X10",
|
||||
"X11",
|
||||
"X12",
|
||||
"X13",
|
||||
"X14",
|
||||
"X15",
|
||||
|
||||
"CS", /* [D_CS] */
|
||||
"SS",
|
||||
"DS",
|
||||
"ES",
|
||||
"FS",
|
||||
"GS",
|
||||
|
||||
"GDTR", /* [D_GDTR] */
|
||||
"IDTR", /* [D_IDTR] */
|
||||
"LDTR", /* [D_LDTR] */
|
||||
"MSW", /* [D_MSW] */
|
||||
"TASK", /* [D_TASK] */
|
||||
|
||||
"CR0", /* [D_CR] */
|
||||
"CR1",
|
||||
"CR2",
|
||||
"CR3",
|
||||
"CR4",
|
||||
"CR5",
|
||||
"CR6",
|
||||
"CR7",
|
||||
"CR8",
|
||||
"CR9",
|
||||
"CR10",
|
||||
"CR11",
|
||||
"CR12",
|
||||
"CR13",
|
||||
"CR14",
|
||||
"CR15",
|
||||
|
||||
"DR0", /* [D_DR] */
|
||||
"DR1",
|
||||
"DR2",
|
||||
"DR3",
|
||||
"DR4",
|
||||
"DR5",
|
||||
"DR6",
|
||||
"DR7",
|
||||
|
||||
"TR0", /* [D_TR] */
|
||||
"TR1",
|
||||
"TR2",
|
||||
"TR3",
|
||||
"TR4",
|
||||
"TR5",
|
||||
"TR6",
|
||||
"TR7",
|
||||
|
||||
"NONE", /* [D_NONE] */
|
||||
};
|
||||
|
||||
int
|
||||
Rconv(Fmt *fp)
|
||||
{
|
||||
char str[20];
|
||||
int r;
|
||||
|
||||
r = va_arg(fp->args, int);
|
||||
if(r >= D_AL && r <= D_NONE)
|
||||
sprint(str, "%s", regstr[r-D_AL]);
|
||||
else
|
||||
sprint(str, "gok(%d)", r);
|
||||
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Sconv(Fmt *fp)
|
||||
{
|
||||
int i, c;
|
||||
char str[30], *p, *a;
|
||||
|
||||
a = va_arg(fp->args, char*);
|
||||
p = str;
|
||||
for(i=0; i<sizeof(double); i++) {
|
||||
c = a[i] & 0xff;
|
||||
if(c >= 'a' && c <= 'z' ||
|
||||
c >= 'A' && c <= 'Z' ||
|
||||
c >= '0' && c <= '9') {
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
*p++ = '\\';
|
||||
switch(c) {
|
||||
default:
|
||||
if(c < 040 || c >= 0177)
|
||||
break; /* not portable */
|
||||
p[-1] = c;
|
||||
continue;
|
||||
case 0:
|
||||
*p++ = 'z';
|
||||
continue;
|
||||
case '\\':
|
||||
case '"':
|
||||
*p++ = c;
|
||||
continue;
|
||||
case '\n':
|
||||
*p++ = 'n';
|
||||
continue;
|
||||
case '\t':
|
||||
*p++ = 't';
|
||||
continue;
|
||||
}
|
||||
*p++ = (c>>6) + '0';
|
||||
*p++ = ((c>>3) & 7) + '0';
|
||||
*p++ = (c & 7) + '0';
|
||||
}
|
||||
*p = 0;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
108
src/cmd/6c/machcap.c
Normal file
108
src/cmd/6c/machcap.c
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Inferno utils/6c/machcap.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/machcap.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
|
||||
if(n == Z)
|
||||
return 1; /* test */
|
||||
|
||||
switch(n->op) {
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
if(typechl[n->type->etype])
|
||||
return 1;
|
||||
if(typev[n->type->etype]) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OCOM:
|
||||
case ONEG:
|
||||
case OADD:
|
||||
case OAND:
|
||||
case OOR:
|
||||
case OSUB:
|
||||
case OXOR:
|
||||
case OASHL:
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
if(typechlv[n->left->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
return 1;
|
||||
|
||||
case OCOND:
|
||||
case OCOMMA:
|
||||
case OLIST:
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
case ONOT:
|
||||
return 1;
|
||||
|
||||
case OASADD:
|
||||
case OASSUB:
|
||||
case OASAND:
|
||||
case OASOR:
|
||||
case OASXOR:
|
||||
return 1;
|
||||
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASLSHR:
|
||||
return 1;
|
||||
|
||||
case OPOSTINC:
|
||||
case OPOSTDEC:
|
||||
case OPREINC:
|
||||
case OPREDEC:
|
||||
return 1;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OGT:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
458
src/cmd/6c/mul.c
Normal file
458
src/cmd/6c/mul.c
Normal file
|
|
@ -0,0 +1,458 @@
|
|||
// Inferno utils/6c/mul.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/mul.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
typedef struct Malg Malg;
|
||||
typedef struct Mparam Mparam;
|
||||
|
||||
struct Malg
|
||||
{
|
||||
char vals[10];
|
||||
};
|
||||
|
||||
struct Mparam
|
||||
{
|
||||
ulong value;
|
||||
char alg;
|
||||
char neg;
|
||||
char shift;
|
||||
char arg;
|
||||
char off;
|
||||
};
|
||||
|
||||
static Mparam multab[32];
|
||||
static int mulptr;
|
||||
|
||||
static Malg malgs[] =
|
||||
{
|
||||
{0, 100},
|
||||
{-1, 1, 100},
|
||||
{-9, -5, -3, 3, 5, 9, 100},
|
||||
{6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
|
||||
{-8, -4, -2, 2, 4, 8, 100},
|
||||
};
|
||||
|
||||
/*
|
||||
* return position of lowest 1
|
||||
*/
|
||||
int
|
||||
lowbit(ulong v)
|
||||
{
|
||||
int s, i;
|
||||
ulong m;
|
||||
|
||||
s = 0;
|
||||
m = 0xFFFFFFFFUL;
|
||||
for(i = 16; i > 0; i >>= 1) {
|
||||
m >>= i;
|
||||
if((v & m) == 0) {
|
||||
v >>= i;
|
||||
s += i;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
genmuladd(Node *d, Node *s, int m, Node *a)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
nod.op = OINDEX;
|
||||
nod.left = a;
|
||||
nod.right = s;
|
||||
nod.scale = m;
|
||||
nod.type = types[TIND];
|
||||
nod.xoffset = 0;
|
||||
xcom(&nod);
|
||||
gopcode(OADDR, d->type, &nod, d);
|
||||
}
|
||||
|
||||
void
|
||||
mulparam(ulong m, Mparam *mp)
|
||||
{
|
||||
int c, i, j, n, o, q, s;
|
||||
int bc, bi, bn, bo, bq, bs, bt;
|
||||
char *p;
|
||||
long u;
|
||||
ulong t;
|
||||
|
||||
bc = bq = 10;
|
||||
bi = bn = bo = bs = bt = 0;
|
||||
for(i = 0; i < nelem(malgs); i++) {
|
||||
for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
|
||||
for(s = 0; s < 2; s++) {
|
||||
c = 10;
|
||||
q = 10;
|
||||
u = m - o;
|
||||
if(u == 0)
|
||||
continue;
|
||||
if(s) {
|
||||
o = -o;
|
||||
if(o > 0)
|
||||
continue;
|
||||
u = -u;
|
||||
}
|
||||
n = lowbit(u);
|
||||
t = (ulong)u >> n;
|
||||
switch(i) {
|
||||
case 0:
|
||||
if(t == 1) {
|
||||
c = s + 1;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
switch(t) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
c = s + 1;
|
||||
if(n)
|
||||
c++;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
if(s)
|
||||
break;
|
||||
switch(t) {
|
||||
case 15:
|
||||
case 25:
|
||||
case 27:
|
||||
case 45:
|
||||
case 81:
|
||||
c = 2;
|
||||
if(n)
|
||||
c++;
|
||||
q = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 3;
|
||||
break;
|
||||
}
|
||||
switch(t) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
c = 3;
|
||||
q = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(s)
|
||||
break;
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(c < bc || (c == bc && q > bq)) {
|
||||
bc = c;
|
||||
bi = i;
|
||||
bn = n;
|
||||
bo = o;
|
||||
bq = q;
|
||||
bs = s;
|
||||
bt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
mp->value = m;
|
||||
if(bc <= 3) {
|
||||
mp->alg = bi;
|
||||
mp->shift = bn;
|
||||
mp->off = bo;
|
||||
mp->neg = bs;
|
||||
mp->arg = bt;
|
||||
}
|
||||
else
|
||||
mp->alg = -1;
|
||||
}
|
||||
|
||||
int
|
||||
m0(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case -2:
|
||||
case 2:
|
||||
return 2;
|
||||
case -3:
|
||||
case 3:
|
||||
return 2;
|
||||
case -4:
|
||||
case 4:
|
||||
return 4;
|
||||
case -5:
|
||||
case 5:
|
||||
return 4;
|
||||
case 6:
|
||||
return 2;
|
||||
case -8:
|
||||
case 8:
|
||||
return 8;
|
||||
case -9:
|
||||
case 9:
|
||||
return 8;
|
||||
case 10:
|
||||
return 4;
|
||||
case 12:
|
||||
return 2;
|
||||
case 15:
|
||||
return 2;
|
||||
case 18:
|
||||
return 8;
|
||||
case 20:
|
||||
return 4;
|
||||
case 24:
|
||||
return 2;
|
||||
case 25:
|
||||
return 4;
|
||||
case 27:
|
||||
return 2;
|
||||
case 36:
|
||||
return 8;
|
||||
case 40:
|
||||
return 4;
|
||||
case 45:
|
||||
return 4;
|
||||
case 72:
|
||||
return 8;
|
||||
case 81:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
m1(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case 15:
|
||||
return 4;
|
||||
case 25:
|
||||
return 4;
|
||||
case 27:
|
||||
return 8;
|
||||
case 45:
|
||||
return 8;
|
||||
case 81:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
m2(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case 6:
|
||||
return 2;
|
||||
case 10:
|
||||
return 2;
|
||||
case 12:
|
||||
return 4;
|
||||
case 18:
|
||||
return 2;
|
||||
case 20:
|
||||
return 4;
|
||||
case 24:
|
||||
return 8;
|
||||
case 36:
|
||||
return 4;
|
||||
case 40:
|
||||
return 8;
|
||||
case 72:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
shiftit(Type *t, Node *s, Node *d)
|
||||
{
|
||||
long c;
|
||||
|
||||
c = (long)s->vconst & 31;
|
||||
switch(c) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
gopcode(OADD, t, d, d);
|
||||
break;
|
||||
default:
|
||||
gopcode(OASHL, t, s, d);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mulgen1(ulong v, Node *n)
|
||||
{
|
||||
int i, o;
|
||||
Mparam *p;
|
||||
Node nod, nods;
|
||||
|
||||
for(i = 0; i < nelem(multab); i++) {
|
||||
p = &multab[i];
|
||||
if(p->value == v)
|
||||
goto found;
|
||||
}
|
||||
|
||||
p = &multab[mulptr];
|
||||
if(++mulptr == nelem(multab))
|
||||
mulptr = 0;
|
||||
|
||||
mulparam(v, p);
|
||||
|
||||
found:
|
||||
// print("v=%.lx a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
|
||||
if(p->alg < 0)
|
||||
return 0;
|
||||
|
||||
nods = *nodconst(p->shift);
|
||||
|
||||
o = OADD;
|
||||
if(p->alg > 0) {
|
||||
regalloc(&nod, n, Z);
|
||||
if(p->off < 0)
|
||||
o = OSUB;
|
||||
}
|
||||
|
||||
switch(p->alg) {
|
||||
case 0:
|
||||
switch(p->arg) {
|
||||
case 1:
|
||||
shiftit(n->type, &nods, n);
|
||||
break;
|
||||
case 15:
|
||||
case 25:
|
||||
case 27:
|
||||
case 45:
|
||||
case 81:
|
||||
genmuladd(n, n, m1(p->arg), n);
|
||||
/* fall thru */
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
genmuladd(n, n, m0(p->arg), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if(p->neg == 1)
|
||||
gins(ANEGL, Z, n);
|
||||
break;
|
||||
case 1:
|
||||
switch(p->arg) {
|
||||
case 1:
|
||||
gmove(n, &nod);
|
||||
shiftit(n->type, &nods, &nod);
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
genmuladd(&nod, n, m0(p->arg), n);
|
||||
shiftit(n->type, &nods, &nod);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if(p->neg)
|
||||
gopcode(o, n->type, &nod, n);
|
||||
else {
|
||||
gopcode(o, n->type, n, &nod);
|
||||
gmove(&nod, n);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
genmuladd(&nod, n, m0(p->off), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
goto comop;
|
||||
case 3:
|
||||
genmuladd(&nod, n, m0(p->off), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
genmuladd(n, &nod, m2(p->off), n);
|
||||
break;
|
||||
case 4:
|
||||
genmuladd(&nod, n, m0(p->off), nodconst(0));
|
||||
shiftit(n->type, &nods, n);
|
||||
goto comop;
|
||||
default:
|
||||
diag(Z, "bad mul alg");
|
||||
break;
|
||||
comop:
|
||||
if(p->neg) {
|
||||
gopcode(o, n->type, n, &nod);
|
||||
gmove(&nod, n);
|
||||
}
|
||||
else
|
||||
gopcode(o, n->type, &nod, n);
|
||||
}
|
||||
|
||||
if(p->alg > 0)
|
||||
regfree(&nod);
|
||||
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
diag(Z, "mulgen botch");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
mulgen(Type *t, Node *r, Node *n)
|
||||
{
|
||||
if(!mulgen1(r->vconst, n))
|
||||
gopcode(OMUL, t, r, n);
|
||||
}
|
||||
876
src/cmd/6c/peep.c
Normal file
876
src/cmd/6c/peep.c
Normal file
|
|
@ -0,0 +1,876 @@
|
|||
// Inferno utils/6c/peep.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
static int
|
||||
needc(Prog *p)
|
||||
{
|
||||
while(p != P) {
|
||||
switch(p->as) {
|
||||
case AADCL:
|
||||
case AADCQ:
|
||||
case ASBBL:
|
||||
case ASBBQ:
|
||||
case ARCRL:
|
||||
case ARCRQ:
|
||||
return 1;
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case AJMP:
|
||||
case ARET:
|
||||
case ACALL:
|
||||
return 0;
|
||||
default:
|
||||
if(p->to.type == D_BRANCH)
|
||||
return 0;
|
||||
}
|
||||
p = p->link;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Reg*
|
||||
rnops(Reg *r)
|
||||
{
|
||||
Prog *p;
|
||||
Reg *r1;
|
||||
|
||||
if(r != R)
|
||||
for(;;){
|
||||
p = r->prog;
|
||||
if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
|
||||
break;
|
||||
r1 = uniqs(r);
|
||||
if(r1 == R)
|
||||
break;
|
||||
r = r1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
peep(void)
|
||||
{
|
||||
Reg *r, *r1, *r2;
|
||||
Prog *p, *p1;
|
||||
int t;
|
||||
|
||||
/*
|
||||
* complete R structure
|
||||
*/
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r1) {
|
||||
r1 = r->link;
|
||||
if(r1 == R)
|
||||
break;
|
||||
p = r->prog->link;
|
||||
while(p != r1->prog)
|
||||
switch(p->as) {
|
||||
default:
|
||||
r2 = rega();
|
||||
r->link = r2;
|
||||
r2->link = r1;
|
||||
|
||||
r2->prog = p;
|
||||
r2->p1 = r;
|
||||
r->s1 = r2;
|
||||
r2->s1 = r1;
|
||||
r1->p1 = r2;
|
||||
|
||||
r = r2;
|
||||
t++;
|
||||
|
||||
case ADATA:
|
||||
case AGLOBL:
|
||||
case ANAME:
|
||||
case ASIGNAME:
|
||||
p = p->link;
|
||||
}
|
||||
}
|
||||
|
||||
pc = 0; /* speculating it won't kill */
|
||||
|
||||
loop1:
|
||||
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r->link) {
|
||||
p = r->prog;
|
||||
switch(p->as) {
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
case AMOVSS:
|
||||
case AMOVSD:
|
||||
if(regtyp(&p->to))
|
||||
if(regtyp(&p->from)) {
|
||||
if(copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
} else
|
||||
if(subprop(r) && copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AMOVBLZX:
|
||||
case AMOVWLZX:
|
||||
case AMOVBLSX:
|
||||
case AMOVWLSX:
|
||||
if(regtyp(&p->to)) {
|
||||
r1 = rnops(uniqs(r));
|
||||
if(r1 != R) {
|
||||
p1 = r1->prog;
|
||||
if(p->as == p1->as && p->to.type == p1->from.type){
|
||||
p1->as = AMOVL;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AMOVBQSX:
|
||||
case AMOVBQZX:
|
||||
case AMOVWQSX:
|
||||
case AMOVWQZX:
|
||||
case AMOVLQSX:
|
||||
case AMOVLQZX:
|
||||
if(regtyp(&p->to)) {
|
||||
r1 = rnops(uniqs(r));
|
||||
if(r1 != R) {
|
||||
p1 = r1->prog;
|
||||
if(p->as == p1->as && p->to.type == p1->from.type){
|
||||
p1->as = AMOVQ;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case AADDW:
|
||||
if(p->from.type != D_CONST || needc(p->link))
|
||||
break;
|
||||
if(p->from.offset == -1){
|
||||
if(p->as == AADDQ)
|
||||
p->as = ADECQ;
|
||||
else if(p->as == AADDL)
|
||||
p->as = ADECL;
|
||||
else
|
||||
p->as = ADECW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
else if(p->from.offset == 1){
|
||||
if(p->as == AADDQ)
|
||||
p->as = AINCQ;
|
||||
else if(p->as == AADDL)
|
||||
p->as = AINCL;
|
||||
else
|
||||
p->as = AINCW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case ASUBW:
|
||||
if(p->from.type != D_CONST || needc(p->link))
|
||||
break;
|
||||
if(p->from.offset == -1) {
|
||||
if(p->as == ASUBQ)
|
||||
p->as = AINCQ;
|
||||
else if(p->as == ASUBL)
|
||||
p->as = AINCL;
|
||||
else
|
||||
p->as = AINCW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
else if(p->from.offset == 1){
|
||||
if(p->as == ASUBQ)
|
||||
p->as = ADECQ;
|
||||
else if(p->as == ASUBL)
|
||||
p->as = ADECL;
|
||||
else
|
||||
p->as = ADECW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(t)
|
||||
goto loop1;
|
||||
}
|
||||
|
||||
void
|
||||
excise(Reg *r)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = r->prog;
|
||||
p->as = ANOP;
|
||||
p->from = zprog.from;
|
||||
p->to = zprog.to;
|
||||
}
|
||||
|
||||
Reg*
|
||||
uniqp(Reg *r)
|
||||
{
|
||||
Reg *r1;
|
||||
|
||||
r1 = r->p1;
|
||||
if(r1 == R) {
|
||||
r1 = r->p2;
|
||||
if(r1 == R || r1->p2link != R)
|
||||
return R;
|
||||
} else
|
||||
if(r->p2 != R)
|
||||
return R;
|
||||
return r1;
|
||||
}
|
||||
|
||||
Reg*
|
||||
uniqs(Reg *r)
|
||||
{
|
||||
Reg *r1;
|
||||
|
||||
r1 = r->s1;
|
||||
if(r1 == R) {
|
||||
r1 = r->s2;
|
||||
if(r1 == R)
|
||||
return R;
|
||||
} else
|
||||
if(r->s2 != R)
|
||||
return R;
|
||||
return r1;
|
||||
}
|
||||
|
||||
int
|
||||
regtyp(Adr *a)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = a->type;
|
||||
if(t >= D_AX && t <= D_R15)
|
||||
return 1;
|
||||
if(t >= D_X0 && t <= D_X0+15)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the idea is to substitute
|
||||
* one register for another
|
||||
* from one MOV to another
|
||||
* MOV a, R0
|
||||
* ADD b, R0 / no use of R1
|
||||
* MOV R0, R1
|
||||
* would be converted to
|
||||
* MOV a, R1
|
||||
* ADD b, R1
|
||||
* MOV R1, R0
|
||||
* hopefully, then the former or latter MOV
|
||||
* will be eliminated by copy propagation.
|
||||
*/
|
||||
int
|
||||
subprop(Reg *r0)
|
||||
{
|
||||
Prog *p;
|
||||
Adr *v1, *v2;
|
||||
Reg *r;
|
||||
int t;
|
||||
|
||||
p = r0->prog;
|
||||
v1 = &p->from;
|
||||
if(!regtyp(v1))
|
||||
return 0;
|
||||
v2 = &p->to;
|
||||
if(!regtyp(v2))
|
||||
return 0;
|
||||
for(r=uniqp(r0); r!=R; r=uniqp(r)) {
|
||||
if(uniqs(r) == R)
|
||||
break;
|
||||
p = r->prog;
|
||||
switch(p->as) {
|
||||
case ACALL:
|
||||
return 0;
|
||||
|
||||
case AIMULL:
|
||||
case AIMULQ:
|
||||
case AIMULW:
|
||||
if(p->to.type != D_NONE)
|
||||
break;
|
||||
|
||||
case ADIVB:
|
||||
case ADIVL:
|
||||
case ADIVQ:
|
||||
case ADIVW:
|
||||
case AIDIVB:
|
||||
case AIDIVL:
|
||||
case AIDIVQ:
|
||||
case AIDIVW:
|
||||
case AIMULB:
|
||||
case AMULB:
|
||||
case AMULL:
|
||||
case AMULQ:
|
||||
case AMULW:
|
||||
|
||||
case AROLB:
|
||||
case AROLL:
|
||||
case AROLQ:
|
||||
case AROLW:
|
||||
case ARORB:
|
||||
case ARORL:
|
||||
case ARORQ:
|
||||
case ARORW:
|
||||
case ASALB:
|
||||
case ASALL:
|
||||
case ASALQ:
|
||||
case ASALW:
|
||||
case ASARB:
|
||||
case ASARL:
|
||||
case ASARQ:
|
||||
case ASARW:
|
||||
case ASHLB:
|
||||
case ASHLL:
|
||||
case ASHLQ:
|
||||
case ASHLW:
|
||||
case ASHRB:
|
||||
case ASHRL:
|
||||
case ASHRQ:
|
||||
case ASHRW:
|
||||
|
||||
case AREP:
|
||||
case AREPN:
|
||||
|
||||
case ACWD:
|
||||
case ACDQ:
|
||||
case ACQO:
|
||||
|
||||
case AMOVSL:
|
||||
case AMOVSQ:
|
||||
return 0;
|
||||
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
if(p->to.type == v1->type)
|
||||
goto gotit;
|
||||
break;
|
||||
}
|
||||
if(copyau(&p->from, v2) ||
|
||||
copyau(&p->to, v2))
|
||||
break;
|
||||
if(copysub(&p->from, v1, v2, 0) ||
|
||||
copysub(&p->to, v1, v2, 0))
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
gotit:
|
||||
copysub(&p->to, v1, v2, 1);
|
||||
if(debug['P']) {
|
||||
print("gotit: %D->%D\n%P", v1, v2, r->prog);
|
||||
if(p->from.type == v2->type)
|
||||
print(" excise");
|
||||
print("\n");
|
||||
}
|
||||
for(r=uniqs(r); r!=r0; r=uniqs(r)) {
|
||||
p = r->prog;
|
||||
copysub(&p->from, v1, v2, 1);
|
||||
copysub(&p->to, v1, v2, 1);
|
||||
if(debug['P'])
|
||||
print("%P\n", r->prog);
|
||||
}
|
||||
t = v1->type;
|
||||
v1->type = v2->type;
|
||||
v2->type = t;
|
||||
if(debug['P'])
|
||||
print("%P last\n", r->prog);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The idea is to remove redundant copies.
|
||||
* v1->v2 F=0
|
||||
* (use v2 s/v2/v1/)*
|
||||
* set v1 F=1
|
||||
* use v2 return fail
|
||||
* -----------------
|
||||
* v1->v2 F=0
|
||||
* (use v2 s/v2/v1/)*
|
||||
* set v1 F=1
|
||||
* set v2 return success
|
||||
*/
|
||||
int
|
||||
copyprop(Reg *r0)
|
||||
{
|
||||
Prog *p;
|
||||
Adr *v1, *v2;
|
||||
Reg *r;
|
||||
|
||||
p = r0->prog;
|
||||
v1 = &p->from;
|
||||
v2 = &p->to;
|
||||
if(copyas(v1, v2))
|
||||
return 1;
|
||||
for(r=firstr; r!=R; r=r->link)
|
||||
r->active = 0;
|
||||
return copy1(v1, v2, r0->s1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
copy1(Adr *v1, Adr *v2, Reg *r, int f)
|
||||
{
|
||||
int t;
|
||||
Prog *p;
|
||||
|
||||
if(r->active) {
|
||||
if(debug['P'])
|
||||
print("act set; return 1\n");
|
||||
return 1;
|
||||
}
|
||||
r->active = 1;
|
||||
if(debug['P'])
|
||||
print("copy %D->%D f=%d\n", v1, v2, f);
|
||||
for(; r != R; r = r->s1) {
|
||||
p = r->prog;
|
||||
if(debug['P'])
|
||||
print("%P", p);
|
||||
if(!f && uniqp(r) == R) {
|
||||
f = 1;
|
||||
if(debug['P'])
|
||||
print("; merge; f=%d", f);
|
||||
}
|
||||
t = copyu(p, v2, A);
|
||||
switch(t) {
|
||||
case 2: /* rar, cant split */
|
||||
if(debug['P'])
|
||||
print("; %D rar; return 0\n", v2);
|
||||
return 0;
|
||||
|
||||
case 3: /* set */
|
||||
if(debug['P'])
|
||||
print("; %D set; return 1\n", v2);
|
||||
return 1;
|
||||
|
||||
case 1: /* used, substitute */
|
||||
case 4: /* use and set */
|
||||
if(f) {
|
||||
if(!debug['P'])
|
||||
return 0;
|
||||
if(t == 4)
|
||||
print("; %D used+set and f=%d; return 0\n", v2, f);
|
||||
else
|
||||
print("; %D used and f=%d; return 0\n", v2, f);
|
||||
return 0;
|
||||
}
|
||||
if(copyu(p, v2, v1)) {
|
||||
if(debug['P'])
|
||||
print("; sub fail; return 0\n");
|
||||
return 0;
|
||||
}
|
||||
if(debug['P'])
|
||||
print("; sub %D/%D", v2, v1);
|
||||
if(t == 4) {
|
||||
if(debug['P'])
|
||||
print("; %D used+set; return 1\n", v2);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!f) {
|
||||
t = copyu(p, v1, A);
|
||||
if(!f && (t == 2 || t == 3 || t == 4)) {
|
||||
f = 1;
|
||||
if(debug['P'])
|
||||
print("; %D set and !f; f=%d", v1, f);
|
||||
}
|
||||
}
|
||||
if(debug['P'])
|
||||
print("\n");
|
||||
if(r->s2)
|
||||
if(!copy1(v1, v2, r->s2, f))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* return
|
||||
* 1 if v only used (and substitute),
|
||||
* 2 if read-alter-rewrite
|
||||
* 3 if set
|
||||
* 4 if set and used
|
||||
* 0 otherwise (not touched)
|
||||
*/
|
||||
int
|
||||
copyu(Prog *p, Adr *v, Adr *s)
|
||||
{
|
||||
|
||||
switch(p->as) {
|
||||
|
||||
default:
|
||||
if(debug['P'])
|
||||
print("unknown op %A\n", p->as);
|
||||
/* SBBL; ADCL; FLD1; SAHF */
|
||||
return 2;
|
||||
|
||||
|
||||
case ANEGB:
|
||||
case ANEGW:
|
||||
case ANEGL:
|
||||
case ANEGQ:
|
||||
case ANOTB:
|
||||
case ANOTW:
|
||||
case ANOTL:
|
||||
case ANOTQ:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
break;
|
||||
|
||||
case ALEAL: /* lhs addr, rhs store */
|
||||
case ALEAQ:
|
||||
if(copyas(&p->from, v))
|
||||
return 2;
|
||||
|
||||
|
||||
case ANOP: /* rhs store */
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
case AMOVBLSX:
|
||||
case AMOVBLZX:
|
||||
case AMOVBQSX:
|
||||
case AMOVBQZX:
|
||||
case AMOVLQSX:
|
||||
case AMOVLQZX:
|
||||
case AMOVWLSX:
|
||||
case AMOVWLZX:
|
||||
case AMOVWQSX:
|
||||
case AMOVWQZX:
|
||||
|
||||
case AMOVSS:
|
||||
case AMOVSD:
|
||||
case ACVTSD2SL:
|
||||
case ACVTSD2SQ:
|
||||
case ACVTSD2SS:
|
||||
case ACVTSL2SD:
|
||||
case ACVTSL2SS:
|
||||
case ACVTSQ2SD:
|
||||
case ACVTSQ2SS:
|
||||
case ACVTSS2SD:
|
||||
case ACVTSS2SL:
|
||||
case ACVTSS2SQ:
|
||||
case ACVTTSD2SL:
|
||||
case ACVTTSD2SQ:
|
||||
case ACVTTSS2SL:
|
||||
case ACVTTSS2SQ:
|
||||
if(copyas(&p->to, v)) {
|
||||
if(s != A)
|
||||
return copysub(&p->from, v, s, 1);
|
||||
if(copyau(&p->from, v))
|
||||
return 4;
|
||||
return 3;
|
||||
}
|
||||
goto caseread;
|
||||
|
||||
case AROLB:
|
||||
case AROLL:
|
||||
case AROLQ:
|
||||
case AROLW:
|
||||
case ARORB:
|
||||
case ARORL:
|
||||
case ARORQ:
|
||||
case ARORW:
|
||||
case ASALB:
|
||||
case ASALL:
|
||||
case ASALQ:
|
||||
case ASALW:
|
||||
case ASARB:
|
||||
case ASARL:
|
||||
case ASARQ:
|
||||
case ASARW:
|
||||
case ASHLB:
|
||||
case ASHLL:
|
||||
case ASHLQ:
|
||||
case ASHLW:
|
||||
case ASHRB:
|
||||
case ASHRL:
|
||||
case ASHRQ:
|
||||
case ASHRW:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
if(copyas(&p->from, v))
|
||||
if(p->from.type == D_CX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AADDB: /* rhs rar */
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case AADDW:
|
||||
case AANDB:
|
||||
case AANDL:
|
||||
case AANDQ:
|
||||
case AANDW:
|
||||
case ADECL:
|
||||
case ADECQ:
|
||||
case ADECW:
|
||||
case AINCL:
|
||||
case AINCQ:
|
||||
case AINCW:
|
||||
case ASUBB:
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case ASUBW:
|
||||
case AORB:
|
||||
case AORL:
|
||||
case AORQ:
|
||||
case AORW:
|
||||
case AXORB:
|
||||
case AXORL:
|
||||
case AXORQ:
|
||||
case AXORW:
|
||||
case AMOVB:
|
||||
case AMOVW:
|
||||
|
||||
case AADDSD:
|
||||
case AADDSS:
|
||||
case ACMPSD:
|
||||
case ACMPSS:
|
||||
case ADIVSD:
|
||||
case ADIVSS:
|
||||
case AMAXSD:
|
||||
case AMAXSS:
|
||||
case AMINSD:
|
||||
case AMINSS:
|
||||
case AMULSD:
|
||||
case AMULSS:
|
||||
case ARCPSS:
|
||||
case ARSQRTSS:
|
||||
case ASQRTSD:
|
||||
case ASQRTSS:
|
||||
case ASUBSD:
|
||||
case ASUBSS:
|
||||
case AXORPD:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case ACMPL: /* read only */
|
||||
case ACMPW:
|
||||
case ACMPB:
|
||||
case ACMPQ:
|
||||
|
||||
case ACOMISD:
|
||||
case ACOMISS:
|
||||
case AUCOMISD:
|
||||
case AUCOMISS:
|
||||
caseread:
|
||||
if(s != A) {
|
||||
if(copysub(&p->from, v, s, 1))
|
||||
return 1;
|
||||
return copysub(&p->to, v, s, 1);
|
||||
}
|
||||
if(copyau(&p->from, v))
|
||||
return 1;
|
||||
if(copyau(&p->to, v))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case AJGE: /* no reference */
|
||||
case AJNE:
|
||||
case AJLE:
|
||||
case AJEQ:
|
||||
case AJHI:
|
||||
case AJLS:
|
||||
case AJMI:
|
||||
case AJPL:
|
||||
case AJGT:
|
||||
case AJLT:
|
||||
case AJCC:
|
||||
case AJCS:
|
||||
|
||||
case AADJSP:
|
||||
case AWAIT:
|
||||
case ACLD:
|
||||
break;
|
||||
|
||||
case AIMULL:
|
||||
case AIMULQ:
|
||||
case AIMULW:
|
||||
if(p->to.type != D_NONE) {
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
goto caseread;
|
||||
}
|
||||
|
||||
case ADIVB:
|
||||
case ADIVL:
|
||||
case ADIVQ:
|
||||
case ADIVW:
|
||||
case AIDIVB:
|
||||
case AIDIVL:
|
||||
case AIDIVQ:
|
||||
case AIDIVW:
|
||||
case AIMULB:
|
||||
case AMULB:
|
||||
case AMULL:
|
||||
case AMULQ:
|
||||
case AMULW:
|
||||
|
||||
case ACWD:
|
||||
case ACDQ:
|
||||
case ACQO:
|
||||
if(v->type == D_AX || v->type == D_DX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AMOVSL:
|
||||
case AMOVSQ:
|
||||
case AREP:
|
||||
case AREPN:
|
||||
if(v->type == D_CX || v->type == D_DI || v->type == D_SI)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AJMP: /* funny */
|
||||
if(s != A) {
|
||||
if(copysub(&p->to, v, s, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(copyau(&p->to, v))
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
case ARET: /* funny */
|
||||
if(v->type == REGRET || v->type == FREGRET)
|
||||
return 2;
|
||||
if(s != A)
|
||||
return 1;
|
||||
return 3;
|
||||
|
||||
case ACALL: /* funny */
|
||||
if(REGEXT && v->type <= REGEXT && v->type > exregoffset)
|
||||
return 2;
|
||||
if(REGARG && v->type == REGARG)
|
||||
return 2;
|
||||
|
||||
if(s != A) {
|
||||
if(copysub(&p->to, v, s, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(copyau(&p->to, v))
|
||||
return 4;
|
||||
return 3;
|
||||
|
||||
case ATEXT: /* funny */
|
||||
if(REGARG && v->type == REGARG)
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* direct reference,
|
||||
* could be set/use depending on
|
||||
* semantics
|
||||
*/
|
||||
int
|
||||
copyas(Adr *a, Adr *v)
|
||||
{
|
||||
if(a->type != v->type)
|
||||
return 0;
|
||||
if(regtyp(v))
|
||||
return 1;
|
||||
if(v->type == D_AUTO || v->type == D_PARAM)
|
||||
if(v->offset == a->offset)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* either direct or indirect
|
||||
*/
|
||||
int
|
||||
copyau(Adr *a, Adr *v)
|
||||
{
|
||||
|
||||
if(copyas(a, v))
|
||||
return 1;
|
||||
if(regtyp(v)) {
|
||||
if(a->type-D_INDIR == v->type)
|
||||
return 1;
|
||||
if(a->index == v->type)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* substitute s for v in a
|
||||
* return failure to substitute
|
||||
*/
|
||||
int
|
||||
copysub(Adr *a, Adr *v, Adr *s, int f)
|
||||
{
|
||||
int t;
|
||||
|
||||
if(copyas(a, v)) {
|
||||
t = s->type;
|
||||
if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
|
||||
if(f)
|
||||
a->type = t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(regtyp(v)) {
|
||||
t = v->type;
|
||||
if(a->type == t+D_INDIR) {
|
||||
if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
|
||||
return 1; /* can't use BP-base with index */
|
||||
if(f)
|
||||
a->type = s->type+D_INDIR;
|
||||
// return 0;
|
||||
}
|
||||
if(a->index == t) {
|
||||
if(f)
|
||||
a->index = s->type;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
550
src/cmd/6c/pgen.c
Normal file
550
src/cmd/6c/pgen.c
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
// Inferno utils/6c/sgen.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
codgen(Node *n, Node *nn)
|
||||
{
|
||||
Prog *sp;
|
||||
Node *n1, nod, nod1;
|
||||
|
||||
cursafe = 0;
|
||||
curarg = 0;
|
||||
maxargsafe = 0;
|
||||
|
||||
/*
|
||||
* isolate name
|
||||
*/
|
||||
for(n1 = nn;; n1 = n1->left) {
|
||||
if(n1 == Z) {
|
||||
diag(nn, "cant find function name");
|
||||
return;
|
||||
}
|
||||
if(n1->op == ONAME)
|
||||
break;
|
||||
}
|
||||
nearln = nn->lineno;
|
||||
gpseudo(ATEXT, n1->sym, nodconst(stkoff));
|
||||
sp = p;
|
||||
|
||||
/*
|
||||
* isolate first argument
|
||||
*/
|
||||
if(REGARG) {
|
||||
if(typecmplx[thisfn->link->etype]) {
|
||||
nod1 = *nodret->left;
|
||||
nodreg(&nod, &nod1, REGARG);
|
||||
gmove(&nod, &nod1);
|
||||
} else
|
||||
if(firstarg && typeword[firstargtype->etype]) {
|
||||
nod1 = *nodret->left;
|
||||
nod1.sym = firstarg;
|
||||
nod1.type = firstargtype;
|
||||
nod1.xoffset = align(0, firstargtype, Aarg1);
|
||||
nod1.etype = firstargtype->etype;
|
||||
nodreg(&nod, &nod1, REGARG);
|
||||
gmove(&nod, &nod1);
|
||||
}
|
||||
}
|
||||
|
||||
canreach = 1;
|
||||
warnreach = 1;
|
||||
gen(n);
|
||||
if(canreach && thisfn->link->etype != TVOID)
|
||||
warn(Z, "no return at end of function: %s", n1->sym->name);
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
|
||||
if(!debug['N'] || debug['R'] || debug['P'])
|
||||
regopt(sp);
|
||||
|
||||
if(thechar=='6' || thechar=='7') /* [sic] */
|
||||
maxargsafe = xround(maxargsafe, 8);
|
||||
sp->to.offset += maxargsafe;
|
||||
}
|
||||
|
||||
void
|
||||
supgen(Node *n)
|
||||
{
|
||||
int owarn;
|
||||
long spc;
|
||||
Prog *sp;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
suppress++;
|
||||
owarn = warnreach;
|
||||
warnreach = 0;
|
||||
spc = pc;
|
||||
sp = lastp;
|
||||
gen(n);
|
||||
lastp = sp;
|
||||
pc = spc;
|
||||
sp->link = nil;
|
||||
suppress--;
|
||||
warnreach = owarn;
|
||||
}
|
||||
|
||||
void
|
||||
gen(Node *n)
|
||||
{
|
||||
Node *l, nod;
|
||||
Prog *sp, *spc, *spb;
|
||||
Case *cn;
|
||||
long sbc, scc;
|
||||
int snbreak, sncontin;
|
||||
int f, o, oldreach;
|
||||
|
||||
loop:
|
||||
if(n == Z)
|
||||
return;
|
||||
nearln = n->lineno;
|
||||
o = n->op;
|
||||
if(debug['G'])
|
||||
if(o != OLIST)
|
||||
print("%L %O\n", nearln, o);
|
||||
|
||||
if(!canreach) {
|
||||
switch(o) {
|
||||
case OLABEL:
|
||||
case OCASE:
|
||||
case OLIST:
|
||||
case OBREAK:
|
||||
case OFOR:
|
||||
case OWHILE:
|
||||
case ODWHILE:
|
||||
/* all handled specially - see switch body below */
|
||||
break;
|
||||
default:
|
||||
if(warnreach) {
|
||||
warn(n, "unreachable code %O", o);
|
||||
warnreach = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(o) {
|
||||
|
||||
default:
|
||||
complex(n);
|
||||
cgen(n, Z);
|
||||
break;
|
||||
|
||||
case OLIST:
|
||||
gen(n->left);
|
||||
|
||||
rloop:
|
||||
n = n->right;
|
||||
goto loop;
|
||||
|
||||
case ORETURN:
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
complex(n);
|
||||
if(n->type == T)
|
||||
break;
|
||||
l = n->left;
|
||||
if(l == Z) {
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
}
|
||||
if(typecmplx[n->type->etype]) {
|
||||
sugen(l, nodret, n->type->width);
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
}
|
||||
regret(&nod, n);
|
||||
cgen(l, &nod);
|
||||
regfree(&nod);
|
||||
if(typefd[n->type->etype])
|
||||
noretval(1);
|
||||
else
|
||||
noretval(2);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
|
||||
case OLABEL:
|
||||
canreach = 1;
|
||||
l = n->left;
|
||||
if(l) {
|
||||
l->pc = pc;
|
||||
if(l->label)
|
||||
patch(l->label, pc);
|
||||
}
|
||||
gbranch(OGOTO); /* prevent self reference in reg */
|
||||
patch(p, pc);
|
||||
goto rloop;
|
||||
|
||||
case OGOTO:
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
n = n->left;
|
||||
if(n == Z)
|
||||
return;
|
||||
if(n->complex == 0) {
|
||||
diag(Z, "label undefined: %s", n->sym->name);
|
||||
return;
|
||||
}
|
||||
if(suppress)
|
||||
return;
|
||||
gbranch(OGOTO);
|
||||
if(n->pc) {
|
||||
patch(p, n->pc);
|
||||
return;
|
||||
}
|
||||
if(n->label)
|
||||
patch(n->label, pc-1);
|
||||
n->label = p;
|
||||
return;
|
||||
|
||||
case OCASE:
|
||||
canreach = 1;
|
||||
l = n->left;
|
||||
if(cases == C)
|
||||
diag(n, "case/default outside a switch");
|
||||
if(l == Z) {
|
||||
cas();
|
||||
cases->val = 0;
|
||||
cases->def = 1;
|
||||
cases->label = pc;
|
||||
cases->isv = 0;
|
||||
goto rloop;
|
||||
}
|
||||
complex(l);
|
||||
if(l->type == T)
|
||||
goto rloop;
|
||||
if(l->op == OCONST)
|
||||
if(typeword[l->type->etype] && l->type->etype != TIND) {
|
||||
cas();
|
||||
cases->val = l->vconst;
|
||||
cases->def = 0;
|
||||
cases->label = pc;
|
||||
cases->isv = typev[l->type->etype];
|
||||
goto rloop;
|
||||
}
|
||||
diag(n, "case expression must be integer constant");
|
||||
goto rloop;
|
||||
|
||||
case OSWITCH:
|
||||
l = n->left;
|
||||
complex(l);
|
||||
if(l->type == T)
|
||||
break;
|
||||
if(!typeword[l->type->etype] || l->type->etype == TIND) {
|
||||
diag(n, "switch expression must be integer");
|
||||
break;
|
||||
}
|
||||
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
cn = cases;
|
||||
cases = C;
|
||||
cas();
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
gen(n->right); /* body */
|
||||
if(canreach){
|
||||
gbranch(OGOTO);
|
||||
patch(p, breakpc);
|
||||
nbreak++;
|
||||
}
|
||||
|
||||
patch(sp, pc);
|
||||
regalloc(&nod, l, Z);
|
||||
/* always signed */
|
||||
if(typev[l->type->etype])
|
||||
nod.type = types[TVLONG];
|
||||
else
|
||||
nod.type = types[TLONG];
|
||||
cgen(l, &nod);
|
||||
doswit(&nod);
|
||||
regfree(&nod);
|
||||
patch(spb, pc);
|
||||
|
||||
cases = cn;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
break;
|
||||
|
||||
case OWHILE:
|
||||
case ODWHILE:
|
||||
l = n->left;
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
scc = continpc;
|
||||
continpc = pc;
|
||||
gbranch(OGOTO);
|
||||
spc = p;
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
patch(spc, pc);
|
||||
if(n->op == OWHILE)
|
||||
patch(sp, pc);
|
||||
bcomplex(l, Z); /* test */
|
||||
patch(p, breakpc);
|
||||
if(l->op != OCONST || vconst(l) == 0)
|
||||
nbreak++;
|
||||
|
||||
if(n->op == ODWHILE)
|
||||
patch(sp, pc);
|
||||
gen(n->right); /* body */
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
|
||||
patch(spb, pc);
|
||||
continpc = scc;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
break;
|
||||
|
||||
case OFOR:
|
||||
l = n->left;
|
||||
if(!canreach && l->right->left && warnreach) {
|
||||
warn(n, "unreachable code FOR");
|
||||
warnreach = 0;
|
||||
}
|
||||
gen(l->right->left); /* init */
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
/*
|
||||
* if there are no incoming labels in the
|
||||
* body and the top's not reachable, warn
|
||||
*/
|
||||
if(!canreach && warnreach && deadheads(n)) {
|
||||
warn(n, "unreachable code %O", o);
|
||||
warnreach = 0;
|
||||
}
|
||||
|
||||
scc = continpc;
|
||||
continpc = pc;
|
||||
gbranch(OGOTO);
|
||||
spc = p;
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
sncontin = ncontin;
|
||||
ncontin = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
patch(spc, pc);
|
||||
gen(l->right->right); /* inc */
|
||||
patch(sp, pc);
|
||||
if(l->left != Z) { /* test */
|
||||
bcomplex(l->left, Z);
|
||||
patch(p, breakpc);
|
||||
if(l->left->op != OCONST || vconst(l->left) == 0)
|
||||
nbreak++;
|
||||
}
|
||||
canreach = 1;
|
||||
gen(n->right); /* body */
|
||||
if(canreach){
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
ncontin++;
|
||||
}
|
||||
if(!ncontin && l->right->right && warnreach) {
|
||||
warn(l->right->right, "unreachable FOR inc");
|
||||
warnreach = 0;
|
||||
}
|
||||
|
||||
patch(spb, pc);
|
||||
continpc = scc;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
ncontin = sncontin;
|
||||
break;
|
||||
|
||||
case OCONTINUE:
|
||||
if(continpc < 0) {
|
||||
diag(n, "continue not in a loop");
|
||||
break;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
ncontin++;
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
break;
|
||||
|
||||
case OBREAK:
|
||||
if(breakpc < 0) {
|
||||
diag(n, "break not in a loop");
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Don't complain about unreachable break statements.
|
||||
* There are breaks hidden in yacc's output and some people
|
||||
* write return; break; in their switch statements out of habit.
|
||||
* However, don't confuse the analysis by inserting an
|
||||
* unreachable reference to breakpc either.
|
||||
*/
|
||||
if(!canreach)
|
||||
break;
|
||||
gbranch(OGOTO);
|
||||
patch(p, breakpc);
|
||||
nbreak++;
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
break;
|
||||
|
||||
case OIF:
|
||||
l = n->left;
|
||||
if(bcomplex(l, n->right)) {
|
||||
if(typefd[l->type->etype])
|
||||
f = !l->fconst;
|
||||
else
|
||||
f = !l->vconst;
|
||||
if(debug['c'])
|
||||
print("%L const if %s\n", nearln, f ? "false" : "true");
|
||||
if(f) {
|
||||
canreach = 1;
|
||||
supgen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
gen(n->right->right);
|
||||
/*
|
||||
* treat constant ifs as regular ifs for
|
||||
* reachability warnings.
|
||||
*/
|
||||
if(!canreach && oldreach && debug['w'] < 2)
|
||||
warnreach = 0;
|
||||
}
|
||||
else {
|
||||
canreach = 1;
|
||||
gen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
supgen(n->right->right);
|
||||
/*
|
||||
* treat constant ifs as regular ifs for
|
||||
* reachability warnings.
|
||||
*/
|
||||
if(!oldreach && canreach && debug['w'] < 2)
|
||||
warnreach = 0;
|
||||
canreach = oldreach;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sp = p;
|
||||
canreach = 1;
|
||||
if(n->right->left != Z)
|
||||
gen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
if(n->right->right != Z) {
|
||||
gbranch(OGOTO);
|
||||
patch(sp, pc);
|
||||
sp = p;
|
||||
gen(n->right->right);
|
||||
}
|
||||
patch(sp, pc);
|
||||
canreach = canreach || oldreach;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSET:
|
||||
case OUSED:
|
||||
usedset(n->left, o);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usedset(Node *n, int o)
|
||||
{
|
||||
if(n->op == OLIST) {
|
||||
usedset(n->left, o);
|
||||
usedset(n->right, o);
|
||||
return;
|
||||
}
|
||||
complex(n);
|
||||
switch(n->op) {
|
||||
case OADDR: /* volatile */
|
||||
gins(ANOP, n, Z);
|
||||
break;
|
||||
case ONAME:
|
||||
if(o == OSET)
|
||||
gins(ANOP, Z, n);
|
||||
else
|
||||
gins(ANOP, n, Z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bcomplex(Node *n, Node *c)
|
||||
{
|
||||
|
||||
complex(n);
|
||||
if(n->type != T)
|
||||
if(tcompat(n, T, n->type, tnot))
|
||||
n->type = T;
|
||||
if(n->type == T) {
|
||||
gbranch(OGOTO);
|
||||
return 0;
|
||||
}
|
||||
if(c != Z && n->op == OCONST && deadheads(c))
|
||||
return 1;
|
||||
bool64(n);
|
||||
boolgen(n, 1, Z);
|
||||
return 0;
|
||||
}
|
||||
168
src/cmd/6c/pswt.c
Normal file
168
src/cmd/6c/pswt.c
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
// Inferno utils/6c/swt.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
int
|
||||
swcmp(const void *a1, const void *a2)
|
||||
{
|
||||
C1 *p1, *p2;
|
||||
|
||||
p1 = (C1*)a1;
|
||||
p2 = (C1*)a2;
|
||||
if(p1->val < p2->val)
|
||||
return -1;
|
||||
return p1->val > p2->val;
|
||||
}
|
||||
|
||||
void
|
||||
doswit(Node *n)
|
||||
{
|
||||
Case *c;
|
||||
C1 *q, *iq;
|
||||
long def, nc, i, isv;
|
||||
|
||||
def = 0;
|
||||
nc = 0;
|
||||
isv = 0;
|
||||
for(c = cases; c->link != C; c = c->link) {
|
||||
if(c->def) {
|
||||
if(def)
|
||||
diag(n, "more than one default in switch");
|
||||
def = c->label;
|
||||
continue;
|
||||
}
|
||||
isv |= c->isv;
|
||||
nc++;
|
||||
}
|
||||
if(isv && !typev[n->type->etype])
|
||||
warn(n, "32-bit switch expression with 64-bit case constant");
|
||||
|
||||
iq = alloc(nc*sizeof(C1));
|
||||
q = iq;
|
||||
for(c = cases; c->link != C; c = c->link) {
|
||||
if(c->def)
|
||||
continue;
|
||||
q->label = c->label;
|
||||
if(isv)
|
||||
q->val = c->val;
|
||||
else
|
||||
q->val = (long)c->val; /* cast ensures correct value for 32-bit switch on 64-bit architecture */
|
||||
q++;
|
||||
}
|
||||
qsort(iq, nc, sizeof(C1), swcmp);
|
||||
if(debug['W'])
|
||||
for(i=0; i<nc; i++)
|
||||
print("case %2ld: = %.8llux\n", i, (vlong)iq[i].val);
|
||||
for(i=0; i<nc-1; i++)
|
||||
if(iq[i].val == iq[i+1].val)
|
||||
diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val);
|
||||
if(def == 0) {
|
||||
def = breakpc;
|
||||
nbreak++;
|
||||
}
|
||||
swit1(iq, nc, def, n);
|
||||
}
|
||||
|
||||
void
|
||||
cas(void)
|
||||
{
|
||||
Case *c;
|
||||
|
||||
c = alloc(sizeof(*c));
|
||||
c->link = cases;
|
||||
cases = c;
|
||||
}
|
||||
|
||||
long
|
||||
outlstring(ushort *s, long n)
|
||||
{
|
||||
char buf[2];
|
||||
int c;
|
||||
long r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
while(nstring & 1)
|
||||
outstring("", 1);
|
||||
r = nstring;
|
||||
while(n > 0) {
|
||||
c = *s++;
|
||||
if(align(0, types[TCHAR], Aarg1)) {
|
||||
buf[0] = c>>8;
|
||||
buf[1] = c;
|
||||
} else {
|
||||
buf[0] = c;
|
||||
buf[1] = c>>8;
|
||||
}
|
||||
outstring(buf, 2);
|
||||
n -= sizeof(ushort);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
nullwarn(Node *l, Node *r)
|
||||
{
|
||||
warn(Z, "result of operation not used");
|
||||
if(l != Z)
|
||||
cgen(l, Z);
|
||||
if(r != Z)
|
||||
cgen(r, Z);
|
||||
}
|
||||
|
||||
void
|
||||
ieeedtod(Ieee *ieee, double native)
|
||||
{
|
||||
double fr, ho, f;
|
||||
int exp;
|
||||
|
||||
if(native < 0) {
|
||||
ieeedtod(ieee, -native);
|
||||
ieee->h |= 0x80000000L;
|
||||
return;
|
||||
}
|
||||
if(native == 0) {
|
||||
ieee->l = 0;
|
||||
ieee->h = 0;
|
||||
return;
|
||||
}
|
||||
fr = frexp(native, &exp);
|
||||
f = 2097152L; /* shouldnt use fp constants here */
|
||||
fr = modf(fr*f, &ho);
|
||||
ieee->h = ho;
|
||||
ieee->h &= 0xfffffL;
|
||||
ieee->h |= (exp+1022L) << 20;
|
||||
f = 65536L;
|
||||
fr = modf(fr*f, &ho);
|
||||
ieee->l = ho;
|
||||
ieee->l <<= 16;
|
||||
ieee->l |= (long)(fr*f);
|
||||
}
|
||||
1386
src/cmd/6c/reg.c
Normal file
1386
src/cmd/6c/reg.c
Normal file
File diff suppressed because it is too large
Load diff
465
src/cmd/6c/sgen.c
Normal file
465
src/cmd/6c/sgen.c
Normal file
|
|
@ -0,0 +1,465 @@
|
|||
// Inferno utils/6c/sgen.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
noretval(int n)
|
||||
{
|
||||
|
||||
if(n & 1) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = REGRET;
|
||||
}
|
||||
if(n & 2) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = FREGRET;
|
||||
}
|
||||
}
|
||||
|
||||
/* welcome to commute */
|
||||
static void
|
||||
commute(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(r->complex > l->complex) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
indexshift(Node *n)
|
||||
{
|
||||
int g;
|
||||
|
||||
if(!typechlpv[n->type->etype])
|
||||
return;
|
||||
simplifyshift(n);
|
||||
if(n->op == OASHL && n->right->op == OCONST){
|
||||
g = vconst(n->right);
|
||||
if(g >= 0 && g <= 3)
|
||||
n->addable = 7;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate addressability as follows
|
||||
* NAME ==> 10/11 name+value(SB/SP)
|
||||
* REGISTER ==> 12 register
|
||||
* CONST ==> 20 $value
|
||||
* *(20) ==> 21 value
|
||||
* &(10) ==> 13 $name+value(SB)
|
||||
* &(11) ==> 1 $name+value(SP)
|
||||
* (13) + (20) ==> 13 fold constants
|
||||
* (1) + (20) ==> 1 fold constants
|
||||
* *(13) ==> 10 back to name
|
||||
* *(1) ==> 11 back to name
|
||||
*
|
||||
* (20) * (X) ==> 7 multiplier in indexing
|
||||
* (X,7) + (13,1) ==> 8 adder in indexing (addresses)
|
||||
* (8) ==> &9(OINDEX) index, almost addressable
|
||||
*
|
||||
* calculate complexity (number of registers)
|
||||
*/
|
||||
void
|
||||
xcom(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
int g;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
n->complex = 0;
|
||||
n->addable = 0;
|
||||
switch(n->op) {
|
||||
case OCONST:
|
||||
n->addable = 20;
|
||||
break;
|
||||
|
||||
case ONAME:
|
||||
n->addable = 10;
|
||||
if(n->class == CPARAM || n->class == CAUTO)
|
||||
n->addable = 11;
|
||||
break;
|
||||
|
||||
case OREGISTER:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OINDREG:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
xcom(l);
|
||||
if(l->addable == 10)
|
||||
n->addable = 13;
|
||||
else
|
||||
if(l->addable == 11)
|
||||
n->addable = 1;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
if(n->type->etype != TIND)
|
||||
break;
|
||||
|
||||
switch(r->addable) {
|
||||
case 20:
|
||||
switch(l->addable) {
|
||||
case 1:
|
||||
case 13:
|
||||
commadd:
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
l = new(0, Z, Z);
|
||||
*l = *(n->left);
|
||||
l->xoffset += r->vconst;
|
||||
n->left = l;
|
||||
r = n->right;
|
||||
goto brk;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 13:
|
||||
case 10:
|
||||
case 11:
|
||||
/* l is the base, r is the index */
|
||||
if(l->addable != 20)
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
switch(l->addable) {
|
||||
case 20:
|
||||
switch(r->addable) {
|
||||
case 13:
|
||||
case 1:
|
||||
r = n->left;
|
||||
l = n->right;
|
||||
n->left = l;
|
||||
n->right = r;
|
||||
goto commadd;
|
||||
}
|
||||
break;
|
||||
|
||||
case 13:
|
||||
case 1:
|
||||
case 10:
|
||||
case 11:
|
||||
/* r is the base, l is the index */
|
||||
if(r->addable != 20)
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
if(n->addable == 8 && !side(n)) {
|
||||
indx(n);
|
||||
l = new1(OINDEX, idx.basetree, idx.regtree);
|
||||
l->scale = idx.scale;
|
||||
l->addable = 9;
|
||||
l->complex = l->right->complex;
|
||||
l->type = l->left->type;
|
||||
n->op = OADDR;
|
||||
n->left = l;
|
||||
n->right = Z;
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OINDEX:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
n->addable = 9;
|
||||
break;
|
||||
|
||||
case OIND:
|
||||
xcom(l);
|
||||
if(l->op == OADDR) {
|
||||
l = l->left;
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
return;
|
||||
}
|
||||
switch(l->addable) {
|
||||
case 20:
|
||||
n->addable = 21;
|
||||
break;
|
||||
case 1:
|
||||
n->addable = 11;
|
||||
break;
|
||||
case 13:
|
||||
n->addable = 10;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASHL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
indexshift(n);
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(l);
|
||||
if(g >= 0) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
l = r;
|
||||
r = n->right;
|
||||
}
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASHL;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
indexshift(n);
|
||||
break;
|
||||
}
|
||||
commute(n);
|
||||
break;
|
||||
|
||||
case OASLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASLSHR;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OLSHR;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
indexshift(n);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASASHL;
|
||||
r->vconst = g;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
indexshift(n);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(l != Z)
|
||||
xcom(l);
|
||||
if(r != Z)
|
||||
xcom(r);
|
||||
break;
|
||||
}
|
||||
brk:
|
||||
if(n->addable >= 10)
|
||||
return;
|
||||
if(l != Z)
|
||||
n->complex = l->complex;
|
||||
if(r != Z) {
|
||||
if(r->complex == n->complex)
|
||||
n->complex = r->complex+1;
|
||||
else
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
}
|
||||
if(n->complex == 0)
|
||||
n->complex++;
|
||||
|
||||
switch(n->op) {
|
||||
|
||||
case OFUNC:
|
||||
n->complex = FNX;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
if(l->type->etype == TUVLONG && typefd[n->type->etype])
|
||||
n->complex += 2;
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
case OMOD:
|
||||
case OLMUL:
|
||||
case OLDIV:
|
||||
case OMUL:
|
||||
case ODIV:
|
||||
case OASLMUL:
|
||||
case OASLDIV:
|
||||
case OASLMOD:
|
||||
case OASMUL:
|
||||
case OASDIV:
|
||||
case OASMOD:
|
||||
if(r->complex >= l->complex) {
|
||||
n->complex = l->complex + 3;
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
} else {
|
||||
n->complex = r->complex + 3;
|
||||
if(l->complex > n->complex)
|
||||
n->complex = l->complex;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
case OASLSHR:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
if(r->complex >= l->complex) {
|
||||
n->complex = l->complex + 2;
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
} else {
|
||||
n->complex = r->complex + 2;
|
||||
if(l->complex > n->complex)
|
||||
n->complex = l->complex;
|
||||
}
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OXOR:
|
||||
case OAND:
|
||||
case OOR:
|
||||
/*
|
||||
* immediate operators, make const on right
|
||||
*/
|
||||
if(l->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OGT:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
/*
|
||||
* compare operators, make const on left
|
||||
*/
|
||||
if(r->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
n->op = invrel[relindex(n->op)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
indx(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
if(debug['x'])
|
||||
prtree(n, "indx");
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
|
||||
n->right = l;
|
||||
n->left = r;
|
||||
l = r;
|
||||
r = n->right;
|
||||
}
|
||||
if(l->addable != 7) {
|
||||
idx.regtree = l;
|
||||
idx.scale = 1;
|
||||
} else
|
||||
if(l->right->addable == 20) {
|
||||
idx.regtree = l->left;
|
||||
idx.scale = 1 << l->right->vconst;
|
||||
} else
|
||||
if(l->left->addable == 20) {
|
||||
idx.regtree = l->right;
|
||||
idx.scale = 1 << l->left->vconst;
|
||||
} else
|
||||
diag(n, "bad index");
|
||||
|
||||
idx.basetree = r;
|
||||
if(debug['x']) {
|
||||
print("scale = %d\n", idx.scale);
|
||||
prtree(idx.regtree, "index");
|
||||
prtree(idx.basetree, "base");
|
||||
}
|
||||
}
|
||||
566
src/cmd/6c/swt.c
Normal file
566
src/cmd/6c/swt.c
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
// Inferno utils/6c/swt.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
swit1(C1 *q, int nc, long def, Node *n)
|
||||
{
|
||||
C1 *r;
|
||||
int i;
|
||||
Prog *sp;
|
||||
|
||||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8llux\n", q->val);
|
||||
gcmp(OEQ, n, q->val);
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, def);
|
||||
return;
|
||||
}
|
||||
i = nc / 2;
|
||||
r = q+i;
|
||||
if(debug['W'])
|
||||
print("case > %.8llux\n", r->val);
|
||||
gcmp(OGT, n, r->val);
|
||||
sp = p;
|
||||
gbranch(OGOTO);
|
||||
p->as = AJEQ;
|
||||
patch(p, r->label);
|
||||
swit1(q, i, def, n);
|
||||
|
||||
if(debug['W'])
|
||||
print("case < %.8llux\n", r->val);
|
||||
patch(sp, pc);
|
||||
swit1(r+1, nc-i-1, def, n);
|
||||
}
|
||||
|
||||
void
|
||||
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int sh;
|
||||
long v;
|
||||
Node *l;
|
||||
|
||||
/*
|
||||
* n1 gets adjusted/masked value
|
||||
* n2 gets address of cell
|
||||
* n3 gets contents of cell
|
||||
*/
|
||||
l = b->left;
|
||||
if(n2 != Z) {
|
||||
regalloc(n1, l, nn);
|
||||
reglcgen(n2, l, Z);
|
||||
regalloc(n3, l, Z);
|
||||
gmove(n2, n3);
|
||||
gmove(n3, n1);
|
||||
} else {
|
||||
regalloc(n1, l, nn);
|
||||
cgen(l, n1);
|
||||
}
|
||||
if(b->type->shift == 0 && typeu[b->type->etype]) {
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, tfield, nodconst(v), n1);
|
||||
} else {
|
||||
sh = 32 - b->type->shift - b->type->nbits;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, tfield, nodconst(sh), n1);
|
||||
sh += b->type->shift;
|
||||
if(sh > 0)
|
||||
if(typeu[b->type->etype])
|
||||
gopcode(OLSHR, tfield, nodconst(sh), n1);
|
||||
else
|
||||
gopcode(OASHR, tfield, nodconst(sh), n1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
long v;
|
||||
Node nod;
|
||||
int sh;
|
||||
|
||||
regalloc(&nod, b->left, Z);
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, types[TLONG], nodconst(v), n1);
|
||||
gmove(n1, &nod);
|
||||
if(nn != Z)
|
||||
gmove(n1, nn);
|
||||
sh = b->type->shift;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
|
||||
v <<= sh;
|
||||
gopcode(OAND, types[TLONG], nodconst(~v), n3);
|
||||
gopcode(OOR, types[TLONG], n3, &nod);
|
||||
gmove(&nod, n2);
|
||||
|
||||
regfree(&nod);
|
||||
regfree(n1);
|
||||
regfree(n2);
|
||||
regfree(n3);
|
||||
}
|
||||
|
||||
long
|
||||
outstring(char *s, long n)
|
||||
{
|
||||
long r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
r = nstring;
|
||||
while(n) {
|
||||
string[mnstring] = *s++;
|
||||
mnstring++;
|
||||
nstring++;
|
||||
if(mnstring >= NSNAME) {
|
||||
gpseudo(ADATA, symstring, nodconst(0L));
|
||||
p->from.offset += nstring - NSNAME;
|
||||
p->from.scale = NSNAME;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.sval, string, NSNAME);
|
||||
mnstring = 0;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
sextern(Sym *s, Node *a, long o, long w)
|
||||
{
|
||||
long e, lw;
|
||||
|
||||
for(e=0; e<w; e+=NSNAME) {
|
||||
lw = NSNAME;
|
||||
if(w-e < lw)
|
||||
lw = w-e;
|
||||
gpseudo(ADATA, s, nodconst(0L));
|
||||
p->from.offset += o+e;
|
||||
p->from.scale = lw;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.sval, a->cstring+e, lw);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gextern(Sym *s, Node *a, long o, long w)
|
||||
{
|
||||
if(0 && a->op == OCONST && typev[a->type->etype]) {
|
||||
gpseudo(ADATA, s, lo64(a));
|
||||
p->from.offset += o;
|
||||
p->from.scale = 4;
|
||||
gpseudo(ADATA, s, hi64(a));
|
||||
p->from.offset += o + 4;
|
||||
p->from.scale = 4;
|
||||
return;
|
||||
}
|
||||
gpseudo(ADATA, s, a);
|
||||
p->from.offset += o;
|
||||
p->from.scale = w;
|
||||
switch(p->to.type) {
|
||||
default:
|
||||
p->to.index = p->to.type;
|
||||
p->to.type = D_ADDR;
|
||||
case D_CONST:
|
||||
case D_FCONST:
|
||||
case D_ADDR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void zname(Biobuf*, Sym*, int);
|
||||
void zaddr(Biobuf*, Adr*, int);
|
||||
void outhist(Biobuf*);
|
||||
|
||||
void
|
||||
outcode(void)
|
||||
{
|
||||
struct { Sym *sym; short type; } h[NSYM];
|
||||
Prog *p;
|
||||
Sym *s;
|
||||
int f, sf, st, t, sym;
|
||||
Biobuf b;
|
||||
|
||||
if(debug['S']) {
|
||||
for(p = firstp; p != P; p = p->link)
|
||||
if(p->as != ADATA && p->as != AGLOBL)
|
||||
pc--;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
print("%P\n", p);
|
||||
if(p->as != ADATA && p->as != AGLOBL)
|
||||
pc++;
|
||||
}
|
||||
}
|
||||
|
||||
f = open(outfile, OWRITE);
|
||||
if(f < 0) {
|
||||
diag(Z, "cannot open %s", outfile);
|
||||
return;
|
||||
}
|
||||
Binit(&b, f, OWRITE);
|
||||
|
||||
Bprint(&b, "x86-64\n");
|
||||
Bprint(&b, "!\n");
|
||||
|
||||
outhist(&b);
|
||||
for(sym=0; sym<NSYM; sym++) {
|
||||
h[sym].sym = S;
|
||||
h[sym].type = 0;
|
||||
}
|
||||
sym = 1;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
jackpot:
|
||||
sf = 0;
|
||||
s = p->from.sym;
|
||||
while(s != S) {
|
||||
sf = s->sym;
|
||||
if(sf < 0 || sf >= NSYM)
|
||||
sf = 0;
|
||||
t = p->from.type;
|
||||
if(t == D_ADDR)
|
||||
t = p->from.index;
|
||||
if(h[sf].type == t)
|
||||
if(h[sf].sym == s)
|
||||
break;
|
||||
s->sym = sym;
|
||||
zname(&b, s, t);
|
||||
h[sym].sym = s;
|
||||
h[sym].type = t;
|
||||
sf = sym;
|
||||
sym++;
|
||||
if(sym >= NSYM)
|
||||
sym = 1;
|
||||
break;
|
||||
}
|
||||
st = 0;
|
||||
s = p->to.sym;
|
||||
while(s != S) {
|
||||
st = s->sym;
|
||||
if(st < 0 || st >= NSYM)
|
||||
st = 0;
|
||||
t = p->to.type;
|
||||
if(t == D_ADDR)
|
||||
t = p->to.index;
|
||||
if(h[st].type == t)
|
||||
if(h[st].sym == s)
|
||||
break;
|
||||
s->sym = sym;
|
||||
zname(&b, s, t);
|
||||
h[sym].sym = s;
|
||||
h[sym].type = t;
|
||||
st = sym;
|
||||
sym++;
|
||||
if(sym >= NSYM)
|
||||
sym = 1;
|
||||
if(st == sf)
|
||||
goto jackpot;
|
||||
break;
|
||||
}
|
||||
Bputc(&b, p->as);
|
||||
Bputc(&b, p->as>>8);
|
||||
Bputc(&b, p->lineno);
|
||||
Bputc(&b, p->lineno>>8);
|
||||
Bputc(&b, p->lineno>>16);
|
||||
Bputc(&b, p->lineno>>24);
|
||||
zaddr(&b, &p->from, sf);
|
||||
zaddr(&b, &p->to, st);
|
||||
}
|
||||
Bflush(&b);
|
||||
close(f);
|
||||
firstp = P;
|
||||
lastp = P;
|
||||
}
|
||||
|
||||
void
|
||||
outhist(Biobuf *b)
|
||||
{
|
||||
Hist *h;
|
||||
char *p, *q, *op, c;
|
||||
Prog pg;
|
||||
int n;
|
||||
|
||||
pg = zprog;
|
||||
pg.as = AHISTORY;
|
||||
c = pathchar();
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
op = 0;
|
||||
/* on windows skip drive specifier in pathname */
|
||||
if(systemtype(Windows) && p && p[1] == ':'){
|
||||
p += 2;
|
||||
c = *p;
|
||||
}
|
||||
if(p && p[0] != c && h->offset == 0 && pathname){
|
||||
/* on windows skip drive specifier in pathname */
|
||||
if(systemtype(Windows) && pathname[1] == ':') {
|
||||
op = p;
|
||||
p = pathname+2;
|
||||
c = *p;
|
||||
} else if(pathname[0] == c){
|
||||
op = p;
|
||||
p = pathname;
|
||||
}
|
||||
}
|
||||
while(p) {
|
||||
q = utfrune(p, c);
|
||||
if(q) {
|
||||
n = q-p;
|
||||
if(n == 0){
|
||||
n = 1; /* leading "/" */
|
||||
*p = '/'; /* don't emit "\" on windows */
|
||||
}
|
||||
q++;
|
||||
} else {
|
||||
n = strlen(p);
|
||||
q = 0;
|
||||
}
|
||||
if(n) {
|
||||
Bputc(b, ANAME);
|
||||
Bputc(b, ANAME>>8);
|
||||
Bputc(b, D_FILE);
|
||||
Bputc(b, 1);
|
||||
Bputc(b, '<');
|
||||
Bwrite(b, p, n);
|
||||
Bputc(b, 0);
|
||||
}
|
||||
p = q;
|
||||
if(p == 0 && op) {
|
||||
p = op;
|
||||
op = 0;
|
||||
}
|
||||
}
|
||||
pg.lineno = h->line;
|
||||
pg.to.type = zprog.to.type;
|
||||
pg.to.offset = h->offset;
|
||||
if(h->offset)
|
||||
pg.to.type = D_CONST;
|
||||
|
||||
Bputc(b, pg.as);
|
||||
Bputc(b, pg.as>>8);
|
||||
Bputc(b, pg.lineno);
|
||||
Bputc(b, pg.lineno>>8);
|
||||
Bputc(b, pg.lineno>>16);
|
||||
Bputc(b, pg.lineno>>24);
|
||||
zaddr(b, &pg.from, 0);
|
||||
zaddr(b, &pg.to, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
zname(Biobuf *b, Sym *s, int t)
|
||||
{
|
||||
char *n;
|
||||
ulong sig;
|
||||
|
||||
if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
|
||||
sig = sign(s);
|
||||
Bputc(b, ASIGNAME);
|
||||
Bputc(b, ASIGNAME>>8);
|
||||
Bputc(b, sig);
|
||||
Bputc(b, sig>>8);
|
||||
Bputc(b, sig>>16);
|
||||
Bputc(b, sig>>24);
|
||||
s->sig = SIGDONE;
|
||||
}
|
||||
else{
|
||||
Bputc(b, ANAME); /* as */
|
||||
Bputc(b, ANAME>>8); /* as */
|
||||
}
|
||||
Bputc(b, t); /* type */
|
||||
Bputc(b, s->sym); /* sym */
|
||||
n = s->name;
|
||||
while(*n) {
|
||||
Bputc(b, *n);
|
||||
n++;
|
||||
}
|
||||
Bputc(b, 0);
|
||||
}
|
||||
|
||||
void
|
||||
zaddr(Biobuf *b, Adr *a, int s)
|
||||
{
|
||||
long l;
|
||||
int i, t;
|
||||
char *n;
|
||||
Ieee e;
|
||||
|
||||
t = 0;
|
||||
if(a->index != D_NONE || a->scale != 0)
|
||||
t |= T_INDEX;
|
||||
if(s != 0)
|
||||
t |= T_SYM;
|
||||
|
||||
switch(a->type) {
|
||||
default:
|
||||
t |= T_TYPE;
|
||||
case D_NONE:
|
||||
if(a->offset != 0) {
|
||||
t |= T_OFFSET;
|
||||
l = a->offset;
|
||||
if((vlong)l != a->offset)
|
||||
t |= T_64;
|
||||
}
|
||||
break;
|
||||
case D_FCONST:
|
||||
t |= T_FCONST;
|
||||
break;
|
||||
case D_SCONST:
|
||||
t |= T_SCONST;
|
||||
break;
|
||||
}
|
||||
Bputc(b, t);
|
||||
|
||||
if(t & T_INDEX) { /* implies index, scale */
|
||||
Bputc(b, a->index);
|
||||
Bputc(b, a->scale);
|
||||
}
|
||||
if(t & T_OFFSET) { /* implies offset */
|
||||
l = a->offset;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
if(t & T_64) {
|
||||
l = a->offset>>32;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
}
|
||||
}
|
||||
if(t & T_SYM) /* implies sym */
|
||||
Bputc(b, s);
|
||||
if(t & T_FCONST) {
|
||||
ieeedtod(&e, a->dval);
|
||||
l = e.l;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
l = e.h;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
return;
|
||||
}
|
||||
if(t & T_SCONST) {
|
||||
n = a->sval;
|
||||
for(i=0; i<NSNAME; i++) {
|
||||
Bputc(b, *n);
|
||||
n++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(t & T_TYPE)
|
||||
Bputc(b, a->type);
|
||||
}
|
||||
|
||||
long
|
||||
align(long i, Type *t, int op)
|
||||
{
|
||||
long o;
|
||||
Type *v;
|
||||
int w;
|
||||
|
||||
o = i;
|
||||
w = 1;
|
||||
switch(op) {
|
||||
default:
|
||||
diag(Z, "unknown align opcode %d", op);
|
||||
break;
|
||||
|
||||
case Asu2: /* padding at end of a struct */
|
||||
w = SZ_VLONG;
|
||||
if(packflg)
|
||||
w = packflg;
|
||||
break;
|
||||
|
||||
case Ael1: /* initial align of struct element */
|
||||
for(v=t; v->etype==TARRAY; v=v->link)
|
||||
;
|
||||
w = ewidth[v->etype];
|
||||
if(w <= 0 || w >= SZ_VLONG)
|
||||
w = SZ_VLONG;
|
||||
if(packflg)
|
||||
w = packflg;
|
||||
break;
|
||||
|
||||
case Ael2: /* width of a struct element */
|
||||
o += t->width;
|
||||
break;
|
||||
|
||||
case Aarg0: /* initial passbyptr argument in arg list */
|
||||
if(typesu[t->etype]) {
|
||||
o = align(o, types[TIND], Aarg1);
|
||||
o = align(o, types[TIND], Aarg2);
|
||||
}
|
||||
break;
|
||||
|
||||
case Aarg1: /* initial align of parameter */
|
||||
w = ewidth[t->etype];
|
||||
if(w <= 0 || w >= SZ_VLONG) {
|
||||
w = SZ_VLONG;
|
||||
break;
|
||||
}
|
||||
w = 1; /* little endian no adjustment */
|
||||
break;
|
||||
|
||||
case Aarg2: /* width of a parameter */
|
||||
o += t->width;
|
||||
w = t->width;
|
||||
if(w > SZ_VLONG)
|
||||
w = SZ_VLONG;
|
||||
break;
|
||||
|
||||
case Aaut3: /* total allign of automatic */
|
||||
o = align(o, t, Ael1);
|
||||
o = align(o, t, Ael2);
|
||||
break;
|
||||
}
|
||||
o = xround(o, w);
|
||||
if(debug['A'])
|
||||
print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
|
||||
return o;
|
||||
}
|
||||
|
||||
long
|
||||
maxround(long max, long v)
|
||||
{
|
||||
v += SZ_VLONG-1;
|
||||
if(v > max)
|
||||
max = xround(v, SZ_VLONG);
|
||||
return max;
|
||||
}
|
||||
1546
src/cmd/6c/txt.c
Normal file
1546
src/cmd/6c/txt.c
Normal file
File diff suppressed because it is too large
Load diff
210
src/cmd/6g/align.c
Normal file
210
src/cmd/6g/align.c
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "gg.h"
|
||||
|
||||
/*
|
||||
* machine size and rounding
|
||||
* alignment is dictated around
|
||||
* the size of a pointer.
|
||||
* the size of the generic types
|
||||
* are pulled from the typedef table.
|
||||
*/
|
||||
|
||||
static int wptr = 8; // width of a pointer
|
||||
static int wmax = 8; // max rounding
|
||||
|
||||
static char*
|
||||
typedefs[] =
|
||||
{
|
||||
"short", "int16", // shorts
|
||||
"ushort", "uint16",
|
||||
|
||||
"int", "int32", // ints
|
||||
"uint", "uint32",
|
||||
"rune", "uint32",
|
||||
|
||||
"long", "int64", // longs
|
||||
"ulong", "uint64",
|
||||
|
||||
"vlong", "int64", // vlongs
|
||||
"uvlong", "uint64",
|
||||
|
||||
"float", "float32", // floats
|
||||
"double", "float64",
|
||||
|
||||
};
|
||||
|
||||
ulong
|
||||
rnd(ulong o, ulong r)
|
||||
{
|
||||
if(r > wmax)
|
||||
r = wmax;
|
||||
if(r != 0)
|
||||
while(o%r != 0)
|
||||
o++;
|
||||
return o;
|
||||
}
|
||||
|
||||
void
|
||||
offmod(Type *t)
|
||||
{
|
||||
Type *f;
|
||||
long o;
|
||||
|
||||
o = 0;
|
||||
for(f=t->type; f!=T; f=f->down) {
|
||||
if(f->etype != TFIELD)
|
||||
fatal("widstruct: not TFIELD: %lT", f);
|
||||
if(f->type->etype != TFUNC)
|
||||
continue;
|
||||
f->width = o;
|
||||
o += wptr;
|
||||
}
|
||||
}
|
||||
|
||||
ulong
|
||||
widstruct(Type *t, ulong o, int flag)
|
||||
{
|
||||
Type *f;
|
||||
long w;
|
||||
|
||||
for(f=t->type; f!=T; f=f->down) {
|
||||
if(f->etype != TFIELD)
|
||||
fatal("widstruct: not TFIELD: %lT", f);
|
||||
dowidth(f->type);
|
||||
w = f->type->width;
|
||||
o = rnd(o, w);
|
||||
f->width = o; // really offset for TFIELD
|
||||
o += w;
|
||||
}
|
||||
// final width is rounded
|
||||
if(flag)
|
||||
o = rnd(o, maxround);
|
||||
t->width = o;
|
||||
return o;
|
||||
}
|
||||
|
||||
void
|
||||
dowidth(Type *t)
|
||||
{
|
||||
ulong w;
|
||||
|
||||
w = 0;
|
||||
if(t == T)
|
||||
return;
|
||||
|
||||
switch(t->etype) {
|
||||
default:
|
||||
fatal("dowidth: unknown type: %E", t->etype);
|
||||
break;
|
||||
|
||||
case TINT8:
|
||||
case TUINT8:
|
||||
case TBOOL: // bool is int8
|
||||
w = 1;
|
||||
break;
|
||||
case TINT16:
|
||||
case TUINT16:
|
||||
w = 2;
|
||||
break;
|
||||
case TINT32:
|
||||
case TUINT32:
|
||||
case TFLOAT32:
|
||||
case TPTR32:
|
||||
w = 4;
|
||||
break;
|
||||
case TINT64:
|
||||
case TUINT64:
|
||||
case TFLOAT64:
|
||||
case TPTR64:
|
||||
w = 8;
|
||||
break;
|
||||
case TFLOAT80:
|
||||
w = 10;
|
||||
break;
|
||||
case TINTER: // implemented as 2 pointers
|
||||
offmod(t);
|
||||
w = 2*wptr;
|
||||
break;
|
||||
case TCHAN: // implemented as pointer
|
||||
dowidth(t->type);
|
||||
dowidth(t->down);
|
||||
w = wptr;
|
||||
break;
|
||||
case TMAP: // implemented as pointer
|
||||
dowidth(t->type);
|
||||
w = wptr;
|
||||
break;
|
||||
case TFORW: // implemented as pointer
|
||||
w = wptr;
|
||||
break;
|
||||
case TANY: // implemented as pointer
|
||||
w = wptr;
|
||||
break;
|
||||
case TSTRING: // implemented as pointer
|
||||
w = wptr;
|
||||
break;
|
||||
case TARRAY:
|
||||
case TDARRAY:
|
||||
if(t->type == T)
|
||||
break;
|
||||
dowidth(t->type);
|
||||
w = t->bound * t->type->width;
|
||||
break;
|
||||
|
||||
case TSTRUCT:
|
||||
w = widstruct(t, 0, 1);
|
||||
offmod(t);
|
||||
break;
|
||||
|
||||
case TFUNC:
|
||||
// function is 3 cated structures
|
||||
w = widstruct(*getthis(t), 0, 0);
|
||||
w = widstruct(*getinarg(t), w, 0);
|
||||
w = widstruct(*getoutarg(t), w, 1);
|
||||
w = 0;
|
||||
break;
|
||||
}
|
||||
t->width = w;
|
||||
}
|
||||
|
||||
void
|
||||
besetptr(void)
|
||||
{
|
||||
maxround = wmax;
|
||||
widthptr = wptr;
|
||||
|
||||
types[TPTR32] = typ(TPTR32);
|
||||
dowidth(types[TPTR32]);
|
||||
|
||||
types[TPTR64] = typ(TPTR64);
|
||||
dowidth(types[TPTR64]);
|
||||
|
||||
tptr = TPTR32;
|
||||
if(wptr == 8)
|
||||
tptr = TPTR64;
|
||||
}
|
||||
|
||||
void
|
||||
belexinit(int lextype)
|
||||
{
|
||||
int i;
|
||||
Sym *s0, *s1;
|
||||
|
||||
for(i=0; i<nelem(typedefs); i+=2) {
|
||||
s1 = lookup(typedefs[i+1]);
|
||||
if(s1->lexical != lextype)
|
||||
yyerror("need %s to define %s",
|
||||
typedefs[i+1], typedefs[i+0]);
|
||||
s0 = lookup(typedefs[i+0]);
|
||||
s0->lexical = s1->lexical;
|
||||
s0->otype = s1->otype;
|
||||
}
|
||||
|
||||
symstringo = lookup(".stringo"); // strings
|
||||
|
||||
listinit();
|
||||
buildtxt();
|
||||
}
|
||||
638
src/cmd/6g/cgen.c
Normal file
638
src/cmd/6g/cgen.c
Normal file
|
|
@ -0,0 +1,638 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "gg.h"
|
||||
|
||||
void
|
||||
cgen(Node *n, Node *res)
|
||||
{
|
||||
long lno;
|
||||
Node *nl, *nr, *r;
|
||||
Node n1, tmp;
|
||||
int a;
|
||||
Prog *p1, *p2, *p3;
|
||||
|
||||
if(debug['g']) {
|
||||
dump("\ncgen-l", res);
|
||||
dump("cgen-r", n);
|
||||
}
|
||||
if(n == N || n->type == T)
|
||||
return;
|
||||
if(res == N || res->type == T)
|
||||
fatal("cgen: res nil");
|
||||
|
||||
lno = dynlineno;
|
||||
if(n->op != ONAME)
|
||||
dynlineno = n->lineno; // for diagnostics
|
||||
|
||||
if(isfat(n->type)) {
|
||||
sgen(n, res, n->type->width);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if(!res->addable) {
|
||||
igen(res, &n1, N);
|
||||
cgen(n, &n1);
|
||||
regfree(&n1);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if(n->addable) {
|
||||
gmove(n, res);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
nl = n->left;
|
||||
nr = n->right;
|
||||
if(nl != N && nl->ullman >= UINF)
|
||||
if(nr != N && nr->ullman >= UINF) {
|
||||
fatal("cgen: both sides functions");
|
||||
goto ret;
|
||||
}
|
||||
|
||||
switch(n->op) {
|
||||
default:
|
||||
dump("cgen", n);
|
||||
fatal("cgen: unknown op %N", n);
|
||||
break;
|
||||
|
||||
// these call bgen to get a bool value
|
||||
case OOROR:
|
||||
case OANDAND:
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLT:
|
||||
case OLE:
|
||||
case OGE:
|
||||
case OGT:
|
||||
case ONOT:
|
||||
p1 = gbranch(AJMP, T);
|
||||
p2 = pc;
|
||||
gmove(booltrue, res);
|
||||
p3 = gbranch(AJMP, T);
|
||||
patch(p1, pc);
|
||||
bgen(n, 1, p2);
|
||||
gmove(boolfalse, res);
|
||||
patch(p3, pc);
|
||||
goto ret;
|
||||
|
||||
case OPLUS:
|
||||
cgen(nl, res);
|
||||
goto ret;
|
||||
|
||||
// unary
|
||||
case OMINUS:
|
||||
case OCOM:
|
||||
a = optoas(n->op, nl->type);
|
||||
goto uop;
|
||||
|
||||
// symmetric binary
|
||||
case OAND:
|
||||
case OOR:
|
||||
case OXOR:
|
||||
case OADD:
|
||||
case OMUL:
|
||||
a = optoas(n->op, nl->type);
|
||||
goto sbop;
|
||||
|
||||
// asymmetric binary
|
||||
case OMOD:
|
||||
case OSUB:
|
||||
case ODIV:
|
||||
case OLSH:
|
||||
case ORSH:
|
||||
a = optoas(n->op, nl->type);
|
||||
goto abop;
|
||||
|
||||
case OCONV:
|
||||
if(eqtype(n->type, nl->type, 0)) {
|
||||
cgen(nl, res);
|
||||
break;
|
||||
}
|
||||
regalloc(&n1, nl->type, res);
|
||||
cgen(nl, &n1);
|
||||
gmove(&n1, res);
|
||||
regfree(&n1);
|
||||
break;
|
||||
|
||||
// case OINDEXPTRSTR:
|
||||
// nl = n->left;
|
||||
// nr = n->right;
|
||||
// if(nl->addable) {
|
||||
// cgen(nr);
|
||||
// cgen(nl);
|
||||
// gopcode(P_LOADI, T_ADDR, N);
|
||||
// gopcodet(P_INDEXZ, nr->type, N);
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
|
||||
// case OINDEXSTR:
|
||||
// nl = n->left;
|
||||
// nr = n->right;
|
||||
// if(nl->addable) {
|
||||
// cgen(nr);
|
||||
// gopcodet(P_INDEXZ, nr->type, nl);
|
||||
// break;
|
||||
// }
|
||||
// cgen(nl);
|
||||
// r = tempname(nl->type);
|
||||
// gopcodet(P_STORE, nl->type, r);
|
||||
// cgen(nr);
|
||||
// gopcodet(P_INDEXZ, nr->type, r);
|
||||
// break;
|
||||
|
||||
// case OSLICESTR:
|
||||
// case OSLICEPTRSTR:
|
||||
// nl = n->left; // name
|
||||
// nr = n->right;
|
||||
//
|
||||
// r = nr->right; // index2
|
||||
// if(!r->addable) {
|
||||
// cgen(r);
|
||||
// r = tempname(r->type);
|
||||
// gopcodet(P_STORE, r->type, r);
|
||||
// }
|
||||
//
|
||||
// // string into T_ADDR
|
||||
// if(!nl->addable) {
|
||||
// cgen(nl);
|
||||
// gconv(T_ADDR, nl->type->etype);
|
||||
// } else
|
||||
// gopcode(P_LOAD, T_ADDR, nl);
|
||||
//
|
||||
// if(n->op == OSLICEPTRSTR)
|
||||
// gopcode(P_LOADI, T_ADDR, N);
|
||||
//
|
||||
// // offset in int reg
|
||||
// cgen(nr->left);
|
||||
//
|
||||
// // index 2 addressed
|
||||
// gopcodet(P_SLICE, r->type, r);
|
||||
// break;
|
||||
|
||||
case OS2I:
|
||||
case OI2I:
|
||||
case OI2S:
|
||||
|
||||
case OINDEXPTR:
|
||||
case OINDEX:
|
||||
case ODOT:
|
||||
case ODOTPTR:
|
||||
case OIND:
|
||||
igen(n, &n1, res);
|
||||
gmove(&n1, res);
|
||||
regfree(&n1);
|
||||
break;
|
||||
|
||||
case OLEN:
|
||||
if(isptrto(nl->type, TSTRING)) {
|
||||
regalloc(&n1, types[tptr], res);
|
||||
cgen(nl, res);
|
||||
n1.op = OINDREG;
|
||||
n1.type = types[TINT32];
|
||||
gmove(&n1, res);
|
||||
regfree(&n1);
|
||||
break;
|
||||
}
|
||||
fatal("cgen: OLEN: unknown type %lT", nl->type);
|
||||
break;
|
||||
|
||||
// case ODOTMETH:
|
||||
// case ODOTINTER:
|
||||
// cgen(n->left);
|
||||
// break;
|
||||
|
||||
case OADDR:
|
||||
agen(nl, res);
|
||||
break;
|
||||
|
||||
case OCALLMETH:
|
||||
cgen_callmeth(n);
|
||||
cgen_callret(n, res);
|
||||
break;
|
||||
|
||||
case OCALLINTER:
|
||||
cgen_callinter(n, res);
|
||||
cgen_callret(n, res);
|
||||
break;
|
||||
|
||||
case OCALL:
|
||||
cgen_call(n);
|
||||
cgen_callret(n, res);
|
||||
break;
|
||||
}
|
||||
goto ret;
|
||||
|
||||
sbop: // symmetric binary
|
||||
if(nl->ullman < nr->ullman) {
|
||||
r = nl;
|
||||
nl = nr;
|
||||
nr = r;
|
||||
}
|
||||
|
||||
abop: // asymmetric binary
|
||||
if(nr->addable) {
|
||||
regalloc(&n1, nl->type, res);
|
||||
cgen(nl, &n1);
|
||||
gins(a, nr, &n1);
|
||||
gmove(&n1, res);
|
||||
regfree(&n1);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
tempname(&tmp, nr->type);
|
||||
regalloc(&n1, nr->type, res);
|
||||
cgen(nr, &n1);
|
||||
gmove(&n1, &tmp);
|
||||
regfree(&n1);
|
||||
|
||||
regalloc(&n1, nl->type, res);
|
||||
cgen(nl, &n1);
|
||||
gins(a, &tmp, &n1);
|
||||
gmove(&n1, res);
|
||||
regfree(&n1);
|
||||
goto ret;
|
||||
|
||||
uop: // unary
|
||||
regalloc(&n1, nl->type, res);
|
||||
cgen(nl, &n1);
|
||||
gins(a, N, &n1);
|
||||
gmove(&n1, res);
|
||||
regfree(&n1);
|
||||
goto ret;
|
||||
|
||||
ret:
|
||||
dynlineno = lno;
|
||||
}
|
||||
|
||||
void
|
||||
agen(Node *n, Node *res)
|
||||
{
|
||||
Node *nl, *nr;
|
||||
Node n1, n2, n3, tmp;
|
||||
ulong w;
|
||||
Type *t;
|
||||
|
||||
if(n == N || n->type == T)
|
||||
return;
|
||||
|
||||
if(!isptr[res->type->etype])
|
||||
fatal("agen: not tptr: %T", res->type);
|
||||
|
||||
if(n->addable) {
|
||||
regalloc(&n1, types[tptr], res);
|
||||
gins(ALEAQ, n, &n1);
|
||||
gmove(&n1, res);
|
||||
regfree(&n1);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(n->op) {
|
||||
default:
|
||||
fatal("agen: unknown op %N", n);
|
||||
break;
|
||||
|
||||
// case ONAME:
|
||||
// regalloc(&n1, types[tptr], res);
|
||||
// gins(optoas(OADDR, types[tptr]), n, &n1);
|
||||
// gmove(&n1, res);
|
||||
// regfree(&n1);
|
||||
// break;
|
||||
|
||||
case OINDEXPTR:
|
||||
nl = n->left;
|
||||
nr = n->right;
|
||||
w = n->type->width;
|
||||
if(nr->addable)
|
||||
goto iprad;
|
||||
if(nl->addable) {
|
||||
regalloc(&n1, nr->type, N);
|
||||
cgen(nr, &n1);
|
||||
cgen(nl, res);
|
||||
goto index;
|
||||
}
|
||||
cgen(nr, res);
|
||||
tempname(&tmp, nr->type);
|
||||
gmove(res, &tmp);
|
||||
|
||||
iprad:
|
||||
cgen(nl, res);
|
||||
regalloc(&n1, nr->type, N);
|
||||
cgen(nr, &n1);
|
||||
goto index;
|
||||
|
||||
case OS2I:
|
||||
case OI2I:
|
||||
case OI2S:
|
||||
agen_inter(n, res);
|
||||
break;
|
||||
|
||||
// case OINDREG:
|
||||
|
||||
case OINDEX:
|
||||
nl = n->left;
|
||||
nr = n->right;
|
||||
w = n->type->width;
|
||||
if(nr->addable)
|
||||
goto irad;
|
||||
if(nl->addable) {
|
||||
regalloc(&n1, nr->type, N);
|
||||
cgen(nr, &n1);
|
||||
agen(nl, res);
|
||||
goto index;
|
||||
}
|
||||
cgen(nr, res);
|
||||
tempname(&tmp, nr->type);
|
||||
gmove(res, &tmp);
|
||||
|
||||
irad:
|
||||
agen(nl, res);
|
||||
regalloc(&n1, nr->type, N);
|
||||
cgen(nr, &n1);
|
||||
goto index;
|
||||
|
||||
index:
|
||||
// &a is in res
|
||||
// i is in &n1
|
||||
// w is width
|
||||
if(issigned[n1.type->etype]) {
|
||||
nodconst(&n3, types[TINT64], w); // w/tint64
|
||||
regalloc(&n2, types[TINT64], &n1); // i/int64
|
||||
gmove(&n1, &n2);
|
||||
gins(optoas(OMUL, types[TINT64]), &n3, &n2);
|
||||
gins(optoas(OADD, types[tptr]), &n2, res);
|
||||
regfree(&n1);
|
||||
regfree(&n2);
|
||||
break;
|
||||
}
|
||||
// unsigned multiply is a pain in the ass
|
||||
fatal("agen: unsigned index");
|
||||
break;
|
||||
|
||||
// case OIND:
|
||||
// nl = n->left;
|
||||
// if(nl->addable) {
|
||||
// gopcode(P_LOAD, T_ADDR, nl);
|
||||
// break;
|
||||
// }
|
||||
// cgen(nl);
|
||||
// gconv(T_ADDR, nl->type->etype);
|
||||
// break;
|
||||
|
||||
case ODOT:
|
||||
nl = n->left;
|
||||
t = nl->type;
|
||||
agen(nl, res);
|
||||
if(n->xoffset != 0) {
|
||||
nodconst(&n1, types[TINT64], n->xoffset);
|
||||
gins(optoas(OADD, types[tptr]), &n1, res);
|
||||
}
|
||||
break;
|
||||
|
||||
case ODOTPTR:
|
||||
nl = n->left;
|
||||
t = nl->type;
|
||||
if(!isptr[t->etype])
|
||||
fatal("agen: not ptr %N", n);
|
||||
cgen(nl, res);
|
||||
if(n->xoffset != 0) {
|
||||
nodconst(&n1, types[TINT64], n->xoffset);
|
||||
gins(optoas(OADD, types[tptr]), &n1, res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vlong
|
||||
fieldoffset(Type *t, Node *n)
|
||||
{
|
||||
if(t->etype != TSTRUCT)
|
||||
fatal("fieldoffset: not struct %lT", t);
|
||||
if(n->op != ONAME)
|
||||
fatal("fieldoffset: not field name %N", n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
igen(Node *n, Node *a, Node *res)
|
||||
{
|
||||
regalloc(a, types[tptr], res);
|
||||
agen(n, a);
|
||||
a->op = OINDREG;
|
||||
a->type = n->type;
|
||||
}
|
||||
|
||||
void
|
||||
bgen(Node *n, int true, Prog *to)
|
||||
{
|
||||
long lno;
|
||||
int et, a, b;
|
||||
Node *nl, *nr, *r;
|
||||
Node n1, n2, tmp;
|
||||
Prog *p1, *p2;
|
||||
|
||||
if(n == N)
|
||||
n = booltrue;
|
||||
|
||||
lno = dynlineno;
|
||||
if(n->op != ONAME)
|
||||
dynlineno = n->lineno; // for diagnostics
|
||||
|
||||
if(n->type == T) {
|
||||
convlit(n, types[TBOOL]);
|
||||
if(n->type == T)
|
||||
goto ret;
|
||||
}
|
||||
|
||||
et = n->type->etype;
|
||||
if(et != TBOOL) {
|
||||
yyerror("cgen: bad type %T for %O", n->type, n->op);
|
||||
patch(gins(AEND, N, N), to);
|
||||
goto ret;
|
||||
}
|
||||
nl = N;
|
||||
nr = N;
|
||||
|
||||
switch(n->op) {
|
||||
default:
|
||||
regalloc(&n1, n->type, N);
|
||||
cgen(n, &n1);
|
||||
nodconst(&n2, n->type, 0);
|
||||
gins(optoas(OCMP, n->type), &n1, &n2);
|
||||
a = AJNE;
|
||||
if(!true)
|
||||
a = AJEQ;
|
||||
patch(gbranch(a, n->type), to);
|
||||
regfree(&n1);
|
||||
goto ret;
|
||||
|
||||
case OLITERAL:
|
||||
if(!true == !n->val.vval)
|
||||
patch(gbranch(AJMP, T), to);
|
||||
goto ret;
|
||||
|
||||
case ONAME:
|
||||
nodconst(&n1, n->type, 0);
|
||||
gins(optoas(OCMP, n->type), n, &n1);
|
||||
a = AJNE;
|
||||
if(!true)
|
||||
a = AJEQ;
|
||||
patch(gbranch(a, n->type), to);
|
||||
goto ret;
|
||||
|
||||
case OANDAND:
|
||||
if(!true)
|
||||
goto caseor;
|
||||
|
||||
caseand:
|
||||
p1 = gbranch(AJMP, T);
|
||||
p2 = gbranch(AJMP, T);
|
||||
patch(p1, pc);
|
||||
bgen(n->left, !true, p2);
|
||||
bgen(n->right, !true, p2);
|
||||
p1 = gbranch(AJMP, T);
|
||||
patch(p1, to);
|
||||
patch(p2, pc);
|
||||
goto ret;
|
||||
|
||||
case OOROR:
|
||||
if(!true)
|
||||
goto caseand;
|
||||
|
||||
caseor:
|
||||
bgen(n->left, true, to);
|
||||
bgen(n->right, true, to);
|
||||
goto ret;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLT:
|
||||
case OGT:
|
||||
case OLE:
|
||||
case OGE:
|
||||
nr = n->right;
|
||||
if(nr == N || nr->type == T)
|
||||
goto ret;
|
||||
|
||||
case ONOT: // unary
|
||||
nl = n->left;
|
||||
if(nl == N || nl->type == T)
|
||||
goto ret;
|
||||
}
|
||||
|
||||
switch(n->op) {
|
||||
|
||||
case ONOT:
|
||||
bgen(nl, !true, to);
|
||||
goto ret;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLT:
|
||||
case OGT:
|
||||
case OLE:
|
||||
case OGE:
|
||||
a = n->op;
|
||||
if(!true)
|
||||
a = brcom(a);
|
||||
|
||||
// make simplest on right
|
||||
if(nl->ullman < nr->ullman) {
|
||||
a = brrev(a);
|
||||
r = nl;
|
||||
nl = nr;
|
||||
nr = r;
|
||||
}
|
||||
a = optoas(a, nr->type);
|
||||
|
||||
if(nr->addable) {
|
||||
regalloc(&n1, nl->type, N);
|
||||
cgen(nl, &n1);
|
||||
b = optoas(OCMP, nr->type);
|
||||
|
||||
switch(b) {
|
||||
case ACMPQ:
|
||||
if(nr->op == OLITERAL)
|
||||
if(nr->val.vval >= (1LL<<32))
|
||||
goto dolit;
|
||||
|
||||
case AUCOMISS:
|
||||
if(nr->op == OLITERAL)
|
||||
goto dolit;
|
||||
if(nr->op == ONAME)
|
||||
goto dolit;
|
||||
}
|
||||
|
||||
gins(b, &n1, nr);
|
||||
patch(gbranch(a, nr->type), to);
|
||||
regfree(&n1);
|
||||
break;
|
||||
|
||||
dolit:
|
||||
regalloc(&n2, nr->type, N);
|
||||
cgen(nr, &n2);
|
||||
gins(b, &n1, &n2);
|
||||
patch(gbranch(a, nr->type), to);
|
||||
regfree(&n2);
|
||||
regfree(&n1);
|
||||
break;
|
||||
}
|
||||
|
||||
tempname(&tmp, nr->type);
|
||||
cgen(nr, &tmp);
|
||||
|
||||
regalloc(&n1, nl->type, N);
|
||||
cgen(nl, &n1);
|
||||
|
||||
gins(optoas(OCMP, nr->type), &n1, &tmp);
|
||||
patch(gbranch(a, nr->type), to);
|
||||
regfree(&n1);
|
||||
break;
|
||||
}
|
||||
goto ret;
|
||||
|
||||
ret:
|
||||
dynlineno = lno;
|
||||
}
|
||||
|
||||
void
|
||||
sgen(Node *n, Node *ns, ulong w)
|
||||
{
|
||||
Node nodl, nodr;
|
||||
long c;
|
||||
|
||||
if(w == 0)
|
||||
return;
|
||||
if(n->ullman >= UINF && ns->ullman >= UINF) {
|
||||
fatal("sgen UINF");
|
||||
}
|
||||
|
||||
nodreg(&nodl, types[tptr], D_DI);
|
||||
nodreg(&nodr, types[tptr], D_SI);
|
||||
|
||||
if(n->ullman >= ns->ullman) {
|
||||
agen(n, &nodr);
|
||||
agen(ns, &nodl);
|
||||
} else {
|
||||
agen(ns, &nodl);
|
||||
agen(n, &nodr);
|
||||
}
|
||||
|
||||
gins(ACLD, N, N); // clear direction flag
|
||||
|
||||
c = w / 8;
|
||||
if(c > 0) {
|
||||
gconreg(AMOVQ, c, D_CX);
|
||||
gins(AREP, N, N); // repeat
|
||||
gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
|
||||
}
|
||||
|
||||
c = w % 8;
|
||||
if(c > 0) {
|
||||
gconreg(AMOVQ, c, D_CX);
|
||||
gins(AREP, N, N); // repeat
|
||||
gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+
|
||||
}
|
||||
}
|
||||
820
src/cmd/6g/gen.c
Normal file
820
src/cmd/6g/gen.c
Normal file
|
|
@ -0,0 +1,820 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
||||
#undef EXTERN
|
||||
#define EXTERN
|
||||
#include "gg.h"
|
||||
|
||||
enum
|
||||
{
|
||||
// random unused opcode
|
||||
AJMPX = AADDPD,
|
||||
};
|
||||
|
||||
static Node* curfn;
|
||||
|
||||
void
|
||||
compile(Node *fn)
|
||||
{
|
||||
Plist *pl;
|
||||
Node nod1;
|
||||
Prog *ptxt;
|
||||
|
||||
if(fn->nbody == N)
|
||||
return;
|
||||
|
||||
curfn = fn;
|
||||
dowidth(curfn->type);
|
||||
|
||||
if(nerrors != 0) {
|
||||
walk(curfn);
|
||||
return;
|
||||
}
|
||||
|
||||
if(debug['w'])
|
||||
dump("--- pre walk ---", curfn->nbody);
|
||||
|
||||
maxarg = 0;
|
||||
stksize = 0;
|
||||
|
||||
walk(curfn);
|
||||
if(nerrors != 0)
|
||||
return;
|
||||
|
||||
if(debug['w'])
|
||||
dump("--- post walk ---", curfn->nbody);
|
||||
|
||||
allocparams();
|
||||
|
||||
continpc = P;
|
||||
breakpc = P;
|
||||
|
||||
pl = newplist();
|
||||
pl->name = curfn->nname;
|
||||
pl->locals = autodcl;
|
||||
|
||||
nodconst(&nod1, types[TINT32], 0);
|
||||
ptxt = gins(ATEXT, curfn->nname, &nod1);
|
||||
|
||||
// inarggen();
|
||||
|
||||
ginit();
|
||||
gen(curfn->nbody);
|
||||
gclean();
|
||||
|
||||
// if(curfn->type->outtuple != 0)
|
||||
// gins(AGOK, N, N);
|
||||
|
||||
pc->as = ARET; // overwrite AEND
|
||||
|
||||
// fill in final stack size
|
||||
ptxt->to.offset = rnd(stksize+maxarg, maxround);
|
||||
|
||||
if(debug['f'])
|
||||
frame(0);
|
||||
}
|
||||
|
||||
void
|
||||
allocparams(void)
|
||||
{
|
||||
Dcl *d;
|
||||
Iter list;
|
||||
Type *t;
|
||||
Node *n;
|
||||
ulong w;
|
||||
|
||||
/*
|
||||
* allocate (set xoffset) the stack
|
||||
* slots for this, inargs, outargs
|
||||
* these are allocated positavely
|
||||
* from 0 up.
|
||||
* note that this uses the 'width'
|
||||
* field, which, in the OFIELD of the
|
||||
* parameters, is the offset in the
|
||||
* parameter list.
|
||||
*/
|
||||
d = autodcl;
|
||||
t = funcfirst(&list, curfn->type);
|
||||
while(t != T) {
|
||||
if(d == D)
|
||||
fatal("allocparams: this nil");
|
||||
if(d->op != ONAME) {
|
||||
d = d->forw;
|
||||
continue;
|
||||
}
|
||||
|
||||
n = d->dnode;
|
||||
if(n->class != PPARAM)
|
||||
fatal("allocparams: this class");
|
||||
|
||||
n->xoffset = t->width;
|
||||
d = d->forw;
|
||||
t = funcnext(&list);
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (set xoffset) the stack
|
||||
* slots for all automatics.
|
||||
* allocated starting at -w down.
|
||||
*/
|
||||
for(d=autodcl; d!=D; d=d->forw) {
|
||||
if(d->op != ONAME)
|
||||
continue;
|
||||
|
||||
n = d->dnode;
|
||||
if(n->class != PAUTO)
|
||||
continue;
|
||||
|
||||
dowidth(n->type);
|
||||
w = n->type->width;
|
||||
stksize += w;
|
||||
stksize = rnd(stksize, w);
|
||||
|
||||
n->xoffset = -stksize;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* compile statements
|
||||
*/
|
||||
void
|
||||
gen(Node *n)
|
||||
{
|
||||
long lno;
|
||||
Prog *scontin, *sbreak;
|
||||
Prog *p1, *p2, *p3;
|
||||
Sym *s;
|
||||
|
||||
lno = dynlineno;
|
||||
|
||||
loop:
|
||||
if(n == N)
|
||||
goto ret;
|
||||
dynlineno = n->lineno; // for diagnostics
|
||||
|
||||
switch(n->op) {
|
||||
default:
|
||||
fatal("gen: unknown op %N", n);
|
||||
break;
|
||||
|
||||
case OLIST:
|
||||
gen(n->left);
|
||||
n = n->right;
|
||||
goto loop;
|
||||
|
||||
case OPANIC:
|
||||
genpanic();
|
||||
break;
|
||||
|
||||
case OCASE:
|
||||
case OFALL:
|
||||
case OXCASE:
|
||||
case OXFALL:
|
||||
case OEMPTY:
|
||||
break;
|
||||
|
||||
case OLABEL:
|
||||
// before declaration, s->label points at
|
||||
// a link list of PXGOTO instructions.
|
||||
// after declaration, s->label points
|
||||
// at a AJMP to .+1
|
||||
|
||||
s = n->left->sym;
|
||||
p1 = (Prog*)s->label;
|
||||
|
||||
if(p1 != P) {
|
||||
if(p1->as == AJMP) {
|
||||
yyerror("label redeclared: %S", s);
|
||||
break;
|
||||
}
|
||||
while(p1 != P) {
|
||||
if(p1->as != AJMPX)
|
||||
fatal("bad label pointer: %S", s);
|
||||
p1->as = AJMP;
|
||||
p2 = p1->to.branch;
|
||||
patch(p1, pc);
|
||||
p1 = p2;
|
||||
}
|
||||
}
|
||||
|
||||
s->label = pc;
|
||||
p1 = gbranch(AJMP, T);
|
||||
patch(p1, pc);
|
||||
break;
|
||||
|
||||
case OGOTO:
|
||||
s = n->left->sym;
|
||||
p1 = (Prog*)s->label;
|
||||
if(p1 != P && p1->as == AJMP) {
|
||||
// already declared
|
||||
p2 = gbranch(AJMP, T);
|
||||
patch(p2, p1->to.branch);
|
||||
break;
|
||||
}
|
||||
|
||||
// link thru to.branch
|
||||
p2 = gbranch(AJMPX, T);
|
||||
p2->to.branch = p1;
|
||||
s->label = p2;
|
||||
break;
|
||||
|
||||
case OBREAK:
|
||||
if(breakpc == P) {
|
||||
yyerror("gen: break is not in a loop");
|
||||
break;
|
||||
}
|
||||
patch(gbranch(AJMP, T), breakpc);
|
||||
break;
|
||||
|
||||
case OCONTINUE:
|
||||
if(continpc == P) {
|
||||
yyerror("gen: continue is not in a loop");
|
||||
break;
|
||||
}
|
||||
patch(gbranch(AJMP, T), continpc);
|
||||
break;
|
||||
|
||||
case OFOR:
|
||||
gen(n->ninit); // init
|
||||
p1 = gbranch(AJMP, T); // goto test
|
||||
sbreak = breakpc;
|
||||
breakpc = gbranch(AJMP, T); // break: goto done
|
||||
scontin = continpc;
|
||||
continpc = pc;
|
||||
gen(n->nincr); // contin: incr
|
||||
patch(p1, pc); // test:
|
||||
bgen(n->ntest, 0, breakpc); // if(!test) goto break
|
||||
gen(n->nbody); // body
|
||||
patch(gbranch(AJMP, T), continpc); // goto contin
|
||||
patch(breakpc, pc); // done:
|
||||
continpc = scontin;
|
||||
breakpc = sbreak;
|
||||
break;
|
||||
|
||||
case OIF:
|
||||
gen(n->ninit); // init
|
||||
p1 = gbranch(AJMP, T); // goto test
|
||||
p2 = gbranch(AJMP, T); // p2: goto else
|
||||
patch(p1, pc); // test:
|
||||
bgen(n->ntest, 0, p2); // if(!test) goto p2
|
||||
gen(n->nbody); // then
|
||||
p3 = gbranch(AJMP, T); // goto done
|
||||
patch(p2, pc); // else:
|
||||
gen(n->nelse); // else
|
||||
patch(p3, pc); // done:
|
||||
break;
|
||||
|
||||
case OSWITCH:
|
||||
gen(n->ninit); // init
|
||||
p1 = gbranch(AJMP, T); // goto test
|
||||
sbreak = breakpc;
|
||||
breakpc = gbranch(AJMP, T); // break: goto done
|
||||
patch(p1, pc); // test:
|
||||
swgen(n); // switch(test) body
|
||||
patch(breakpc, pc); // done:
|
||||
breakpc = sbreak;
|
||||
break;
|
||||
|
||||
case OASOP:
|
||||
cgen_asop(n->left, n->right, n->etype);
|
||||
break;
|
||||
|
||||
case OAS:
|
||||
cgen_as(n->left, n->right, n->op);
|
||||
break;
|
||||
|
||||
case OCALLMETH:
|
||||
cgen_callmeth(n);
|
||||
break;
|
||||
|
||||
case OCALLINTER:
|
||||
cgen_callinter(n, N);
|
||||
break;
|
||||
|
||||
case OCALL:
|
||||
cgen_call(n);
|
||||
break;
|
||||
|
||||
case ORETURN:
|
||||
cgen_ret(n);
|
||||
break;
|
||||
}
|
||||
|
||||
ret:
|
||||
dynlineno = lno;
|
||||
}
|
||||
|
||||
void
|
||||
agen_inter(Node *n, Node *res)
|
||||
{
|
||||
Node nodo, nodr, nodt;
|
||||
Sym *s;
|
||||
char *e;
|
||||
long o;
|
||||
|
||||
// stack offset
|
||||
memset(&nodo, 0, sizeof(nodo));
|
||||
nodo.op = OINDREG;
|
||||
nodo.val.vval = D_SP;
|
||||
nodo.addable = 1;
|
||||
nodo.type = types[tptr];
|
||||
|
||||
// pointer register
|
||||
regalloc(&nodr, types[tptr], res);
|
||||
|
||||
switch(n->op) {
|
||||
default:
|
||||
fatal("agen_inter %O\n", n->op);
|
||||
|
||||
case OS2I:
|
||||
// ifaces2i(*sigi, *sigs, i.map, i.s)
|
||||
// i.s is input
|
||||
// (i.map, i.s) is output
|
||||
|
||||
cgen(n->left, &nodr);
|
||||
nodo.xoffset = 3*widthptr;
|
||||
cgen_as(&nodo, &nodr, 0);
|
||||
|
||||
nodtypesig(&nodt, n->type);
|
||||
agen(&nodt, &nodr);
|
||||
nodo.xoffset = 0*widthptr;
|
||||
cgen_as(&nodo, &nodr, 0);
|
||||
|
||||
nodtypesig(&nodt, n->left->type);
|
||||
agen(&nodt, &nodr);
|
||||
nodo.xoffset = 1*widthptr;
|
||||
cgen_as(&nodo, &nodr, 0);
|
||||
|
||||
e = "ifaces2i";
|
||||
if(maxarg < 4*widthptr)
|
||||
maxarg = 4*widthptr;
|
||||
o = 2*widthptr;
|
||||
break;
|
||||
|
||||
case OI2I:
|
||||
// ifacei2i(*sigi, i.map, i.s)
|
||||
// (i.map, i.s) is input
|
||||
// (i.map, i.s) is output
|
||||
|
||||
nodo.xoffset = 1*widthptr;
|
||||
if(!n->left->addable) {
|
||||
agen(n->left, &nodr);
|
||||
gmove(&nodr, &nodo);
|
||||
fatal("agen_inter i2i");
|
||||
} else {
|
||||
cgen(n->left, &nodo);
|
||||
}
|
||||
|
||||
nodtypesig(&nodt, n->type);
|
||||
agen(&nodt, &nodr);
|
||||
nodo.xoffset = 0*widthptr;
|
||||
cgen_as(&nodo, &nodr, 0);
|
||||
|
||||
e = "ifacei2i";
|
||||
if(maxarg < 3*widthptr)
|
||||
maxarg = 3*widthptr;
|
||||
o = 1*widthptr;
|
||||
break;
|
||||
|
||||
case OI2S:
|
||||
// ifacei2s(*sigs, i.map, i.s)
|
||||
// (i.map, i.s) is input
|
||||
// i.s is output
|
||||
|
||||
nodo.xoffset = 1*widthptr;
|
||||
if(!n->left->addable) {
|
||||
agen(n->left, &nodr);
|
||||
gmove(&nodr, &nodo);
|
||||
fatal("agen_inter i2s");
|
||||
} else
|
||||
gmove(n->left, &nodo);
|
||||
|
||||
nodtypesig(&nodt, n->type);
|
||||
agen(&nodt, &nodr);
|
||||
nodo.xoffset = 0*widthptr;
|
||||
cgen_as(&nodo, &nodr, 0);
|
||||
|
||||
e = "ifacei2s";
|
||||
if(maxarg < 3*widthptr)
|
||||
maxarg = 3*widthptr;
|
||||
o = 2*widthptr;
|
||||
break;
|
||||
}
|
||||
|
||||
s = pkglookup(e, "sys");
|
||||
if(s->oname == N) {
|
||||
s->oname = newname(s);
|
||||
s->oname->class = PEXTERN;
|
||||
}
|
||||
gins(ACALL, N, s->oname);
|
||||
|
||||
nodo.xoffset = o;
|
||||
gins(ALEAQ, &nodo, res);
|
||||
|
||||
regfree(&nodr);
|
||||
}
|
||||
|
||||
void
|
||||
swgen(Node *n)
|
||||
{
|
||||
Node *c1, *c2;
|
||||
Node n1, tmp;
|
||||
Case *s0, *se, *s;
|
||||
Prog *p1, *dflt;
|
||||
long lno;
|
||||
int any;
|
||||
Iter save1, save2;
|
||||
|
||||
// botch - put most of this code in
|
||||
// walk. gen binary search for
|
||||
// sequence of constant cases
|
||||
|
||||
lno = dynlineno;
|
||||
|
||||
p1 = gbranch(AJMP, T);
|
||||
s0 = C;
|
||||
se = C;
|
||||
|
||||
// walk thru the body placing breaks
|
||||
// and labels into the case statements
|
||||
|
||||
any = 0;
|
||||
dflt = P;
|
||||
c1 = listfirst(&save1, &n->nbody);
|
||||
while(c1 != N) {
|
||||
dynlineno = c1->lineno; // for diagnostics
|
||||
if(c1->op != OCASE) {
|
||||
if(s0 == C)
|
||||
yyerror("unreachable statements in a switch");
|
||||
gen(c1);
|
||||
|
||||
any = 1;
|
||||
if(c1->op == OFALL)
|
||||
any = 0;
|
||||
c1 = listnext(&save1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// put in the break between cases
|
||||
if(any) {
|
||||
patch(gbranch(AJMP, T), breakpc);
|
||||
any = 0;
|
||||
}
|
||||
|
||||
// over case expressions
|
||||
c2 = listfirst(&save2, &c1->left);
|
||||
if(c2 == N)
|
||||
dflt = pc;
|
||||
|
||||
while(c2 != N) {
|
||||
|
||||
s = mal(sizeof(*s));
|
||||
if(s0 == C)
|
||||
s0 = s;
|
||||
else
|
||||
se->slink = s;
|
||||
se = s;
|
||||
|
||||
s->scase = c2; // case expression
|
||||
s->sprog = pc; // where to go
|
||||
|
||||
c2 = listnext(&save2);
|
||||
}
|
||||
|
||||
c1 = listnext(&save1);
|
||||
}
|
||||
|
||||
if(any)
|
||||
patch(gbranch(AJMP, T), breakpc);
|
||||
|
||||
patch(p1, pc);
|
||||
|
||||
tempname(&tmp, n->ntest->type);
|
||||
cgen(n->ntest, &tmp);
|
||||
|
||||
for(s=s0; s!=C; s=s->slink) {
|
||||
memset(&n1, 0, sizeof(n1));
|
||||
n1.op = OEQ;
|
||||
n1.left = &tmp;
|
||||
n1.right = s->scase;
|
||||
walktype(&n1, 0);
|
||||
bgen(&n1, 1, s->sprog);
|
||||
}
|
||||
if(dflt != P) {
|
||||
patch(gbranch(AJMP, T), dflt);
|
||||
goto ret;
|
||||
}
|
||||
patch(gbranch(AJMP, T), breakpc);
|
||||
|
||||
ret:
|
||||
dynlineno = lno;
|
||||
}
|
||||
|
||||
void
|
||||
inarggen(void)
|
||||
{
|
||||
fatal("inarggen");
|
||||
}
|
||||
|
||||
void
|
||||
genpanic(void)
|
||||
{
|
||||
Node n1, n2;
|
||||
Prog *p;
|
||||
|
||||
nodconst(&n1, types[TINT64], 0xf0);
|
||||
nodreg(&n2, types[TINT64], D_AX);
|
||||
gins(AMOVL, &n1, &n2);
|
||||
p = pc;
|
||||
gins(AMOVQ, &n2, N);
|
||||
p->to.type = D_INDIR+D_AX;
|
||||
}
|
||||
|
||||
void
|
||||
cgen_callinter(Node *n, Node *res)
|
||||
{
|
||||
Node *i, *f;
|
||||
Node tmpi, nodo, nodr, nodsp;
|
||||
|
||||
i = n->left;
|
||||
if(i->op != ODOTINTER)
|
||||
fatal("cgen_callinter: not ODOTINTER %O", i->op);
|
||||
|
||||
f = i->right; // field
|
||||
if(f->op != ONAME)
|
||||
fatal("cgen_callinter: not ONAME %O", f->op);
|
||||
|
||||
i = i->left; // interface
|
||||
|
||||
if(!i->addable) {
|
||||
tempname(&tmpi, i->type);
|
||||
cgen(i, &tmpi);
|
||||
i = &tmpi;
|
||||
}
|
||||
|
||||
gen(n->right); // args
|
||||
|
||||
regalloc(&nodr, types[tptr], res);
|
||||
regalloc(&nodo, types[tptr], &nodr);
|
||||
nodo.op = OINDREG;
|
||||
|
||||
agen(i, &nodr); // REG = &inter
|
||||
|
||||
nodindreg(&nodsp, types[tptr], D_SP);
|
||||
nodo.xoffset += widthptr;
|
||||
cgen(&nodo, &nodsp); // 0(SP) = 8(REG) -- i.s
|
||||
|
||||
nodo.xoffset -= widthptr;
|
||||
cgen(&nodo, &nodr); // REG = 0(REG) -- i.m
|
||||
|
||||
//print("field = %N\n", f);
|
||||
//print("offset = %ld\n", n->left->xoffset);
|
||||
|
||||
nodo.xoffset = n->left->xoffset + 4*widthptr;
|
||||
cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.m->fun[f]
|
||||
|
||||
gins(ACALL, N, &nodr);
|
||||
regfree(&nodr);
|
||||
regfree(&nodr);
|
||||
|
||||
setmaxarg(n->left->type);
|
||||
}
|
||||
|
||||
void
|
||||
cgen_callmeth(Node *n)
|
||||
{
|
||||
Node *l;
|
||||
|
||||
// generate a rewrite for method call
|
||||
// (p.f)(...) goes to (f)(p,...)
|
||||
|
||||
l = n->left;
|
||||
|
||||
n->op = OCALL;
|
||||
n->left = n->left->right;
|
||||
n->left->type = l->type;
|
||||
|
||||
if(n->left->op == ONAME)
|
||||
n->left->class = PEXTERN;
|
||||
cgen_call(n);
|
||||
}
|
||||
|
||||
void
|
||||
cgen_call(Node *n)
|
||||
{
|
||||
Type *t;
|
||||
Node nod, afun;
|
||||
|
||||
if(n == N)
|
||||
return;
|
||||
|
||||
if(n->left->ullman >= UINF) {
|
||||
// if name involves a fn call
|
||||
// precompute the address of the fn
|
||||
tempname(&afun, types[tptr]);
|
||||
if(isptr[n->left->type->etype])
|
||||
cgen(n->left, &afun);
|
||||
else
|
||||
agen(n->left, &afun);
|
||||
}
|
||||
|
||||
gen(n->right); // assign the args
|
||||
t = n->left->type;
|
||||
if(isptr[t->etype])
|
||||
t = t->type;
|
||||
|
||||
setmaxarg(t);
|
||||
|
||||
// call tempname pointer
|
||||
if(n->left->ullman >= UINF) {
|
||||
regalloc(&nod, types[tptr], N);
|
||||
cgen_as(&nod, &afun, 0);
|
||||
gins(ACALL, N, &nod);
|
||||
regfree(&nod);
|
||||
return;
|
||||
}
|
||||
|
||||
// call pointer
|
||||
if(isptr[n->left->type->etype]) {
|
||||
regalloc(&nod, types[tptr], N);
|
||||
cgen_as(&nod, n->left, 0);
|
||||
gins(ACALL, N, &nod);
|
||||
regfree(&nod);
|
||||
return;
|
||||
}
|
||||
|
||||
// call direct
|
||||
gins(ACALL, N, n->left);
|
||||
}
|
||||
|
||||
void
|
||||
cgen_callret(Node *n, Node *res)
|
||||
{
|
||||
Node nod;
|
||||
Type *fp, *t;
|
||||
Iter flist;
|
||||
|
||||
t = n->left->type;
|
||||
if(t->etype == TPTR32 || t->etype == TPTR64)
|
||||
t = t->type;
|
||||
|
||||
fp = structfirst(&flist, getoutarg(t));
|
||||
if(fp == T)
|
||||
fatal("cgen_callret: nil");
|
||||
|
||||
memset(&nod, 0, sizeof(nod));
|
||||
nod.op = OINDREG;
|
||||
nod.val.vval = D_SP;
|
||||
nod.addable = 1;
|
||||
|
||||
nod.xoffset = fp->width;
|
||||
nod.type = fp->type;
|
||||
cgen_as(res, &nod, 0);
|
||||
}
|
||||
|
||||
void
|
||||
cgen_ret(Node *n)
|
||||
{
|
||||
gen(n->left); // copy out args
|
||||
gins(ARET, N, N);
|
||||
}
|
||||
|
||||
void
|
||||
cgen_asop(Node *nl, Node *nr, int op)
|
||||
{
|
||||
Node n1, n2;
|
||||
int a;
|
||||
|
||||
// botch compare ullman numbers
|
||||
// and use temp for functions
|
||||
|
||||
a = optoas(op, nl->type);
|
||||
regalloc(&n1, nl->type, N);
|
||||
if(nl->addable) {
|
||||
cgen(nr, &n1);
|
||||
gins(a, nl, &n1);
|
||||
gmove(&n1, nl);
|
||||
regfree(&n1);
|
||||
return;
|
||||
}
|
||||
|
||||
igen(nl, &n2, N);
|
||||
cgen(nr, &n1);
|
||||
gins(a, &n2, &n1);
|
||||
gmove(&n1, &n2);
|
||||
regfree(&n1);
|
||||
regfree(&n2);
|
||||
}
|
||||
|
||||
void
|
||||
cgen_as(Node *nl, Node *nr, int op)
|
||||
{
|
||||
Node nc, n1;
|
||||
Type *tl;
|
||||
ulong w, c;
|
||||
|
||||
if(nl == N)
|
||||
return;
|
||||
|
||||
tl = nl->type;
|
||||
if(tl == T)
|
||||
return;
|
||||
|
||||
if(nr == N) {
|
||||
if(isfat(tl)) {
|
||||
/* clear a fat object */
|
||||
if(debug['g'])
|
||||
dump("\nclearfat", nl);
|
||||
|
||||
w = nl->type->width;
|
||||
if(w > 0)
|
||||
gconreg(AMOVQ, 0, D_AX);
|
||||
|
||||
if(w > 0) {
|
||||
nodreg(&n1, types[tptr], D_DI);
|
||||
agen(nl, &n1);
|
||||
gins(ACLD, N, N); // clear direction flag
|
||||
}
|
||||
|
||||
c = w / 8;
|
||||
if(c > 0) {
|
||||
gconreg(AMOVQ, c, D_CX);
|
||||
gins(AREP, N, N); // repeat
|
||||
gins(ASTOSQ, N, N); // STOQ AL,*(DI)+
|
||||
}
|
||||
|
||||
c = w % 8;
|
||||
if(c > 0) {
|
||||
gconreg(AMOVQ, c, D_CX);
|
||||
gins(AREP, N, N); // repeat
|
||||
gins(ASTOSB, N, N); // STOB AL,*(DI)+
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* invent a "zero" for the rhs */
|
||||
nr = &nc;
|
||||
memset(nr, 0, sizeof(*nr));
|
||||
switch(tl->etype) {
|
||||
default:
|
||||
fatal("cgen_as: tl %T", tl);
|
||||
break;
|
||||
|
||||
case TINT8:
|
||||
case TUINT8:
|
||||
case TINT16:
|
||||
case TUINT16:
|
||||
case TINT32:
|
||||
case TUINT32:
|
||||
case TINT64:
|
||||
case TUINT64:
|
||||
nr->val.ctype = CTINT;
|
||||
nr->val.vval = 0;
|
||||
break;
|
||||
|
||||
case TFLOAT32:
|
||||
case TFLOAT64:
|
||||
case TFLOAT80:
|
||||
nr->val.ctype = CTFLT;
|
||||
nr->val.dval = 0.0;
|
||||
break;
|
||||
|
||||
case TBOOL:
|
||||
nr->val.ctype = CTBOOL;
|
||||
nr->val.vval = 0;
|
||||
break;
|
||||
|
||||
case TPTR32:
|
||||
case TPTR64:
|
||||
if(isptrto(nl->type, TSTRING)) {
|
||||
nr->val.ctype = CTSTR;
|
||||
nr->val.sval = &emptystring;
|
||||
break;
|
||||
}
|
||||
nr->val.ctype = CTNIL;
|
||||
nr->val.vval = 0;
|
||||
break;
|
||||
|
||||
// case TINTER:
|
||||
// nodreg(&n1, types[tptr], D_DI);
|
||||
// agen(nl, &n1);
|
||||
// n1.op = OINDREG;
|
||||
//
|
||||
// nodreg(&nc, types[tptr], D_AX);
|
||||
// gconreg(AMOVQ, 0, D_AX);
|
||||
//
|
||||
// gins(AMOVQ, &nc, &n1);
|
||||
// n1.xoffset += widthptr;
|
||||
// gins(AMOVQ, &nc, &n1);
|
||||
// return;
|
||||
|
||||
}
|
||||
nr->op = OLITERAL;
|
||||
nr->type = tl;
|
||||
nr->addable = 1;
|
||||
ullmancalc(nr);
|
||||
}
|
||||
cgen(nr, nl);
|
||||
}
|
||||
203
src/cmd/6g/gg.h
Normal file
203
src/cmd/6g/gg.h
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
#include "../gc/go.h"
|
||||
#include "../6l/6.out.h"
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef struct Prog Prog;
|
||||
typedef struct Addr Addr;
|
||||
|
||||
struct Addr
|
||||
{
|
||||
vlong offset;
|
||||
double dval;
|
||||
Prog* branch;
|
||||
char sval[NSNAME];
|
||||
|
||||
Sym* sym;
|
||||
uchar type;
|
||||
uchar index;
|
||||
uchar etype;
|
||||
uchar scale; /* doubles as width in DATA op */
|
||||
};
|
||||
#define A ((Addr*)0)
|
||||
|
||||
struct Prog
|
||||
{
|
||||
short as; // opcode
|
||||
ulong loc; // pc offset in this func
|
||||
ulong lineno; // source line that generated this
|
||||
Addr from; // src address
|
||||
Addr to; // dst address
|
||||
Prog* link; // next instruction in this func
|
||||
};
|
||||
#define P ((Prog*)0)
|
||||
|
||||
typedef struct Plist Plist;
|
||||
struct Plist
|
||||
{
|
||||
Node* name;
|
||||
Dcl* locals;
|
||||
Prog* firstpc;
|
||||
int recur;
|
||||
Plist* link;
|
||||
};
|
||||
|
||||
typedef struct Sig Sig;
|
||||
struct Sig
|
||||
{
|
||||
char* name;
|
||||
Sym* sym;
|
||||
ulong hash;
|
||||
long offset;
|
||||
Sig* link;
|
||||
};
|
||||
|
||||
typedef struct Case Case;
|
||||
struct Case
|
||||
{
|
||||
Prog* sprog;
|
||||
Node* scase;
|
||||
Case* slink;
|
||||
};
|
||||
#define C ((Case*)0)
|
||||
|
||||
typedef struct Pool Pool;
|
||||
struct Pool
|
||||
{
|
||||
String* sval;
|
||||
Pool* link;
|
||||
};
|
||||
|
||||
EXTERN Prog* continpc;
|
||||
EXTERN Prog* breakpc;
|
||||
EXTERN Prog* pc;
|
||||
EXTERN Prog* firstpc;
|
||||
EXTERN Plist* plist;
|
||||
EXTERN Plist* plast;
|
||||
EXTERN Pool* poolist;
|
||||
EXTERN Pool* poolast;
|
||||
EXTERN Biobuf* bout;
|
||||
EXTERN long dynloc;
|
||||
EXTERN uchar reg[D_NONE];
|
||||
EXTERN ushort txt[NTYPE*NTYPE];
|
||||
EXTERN long maxround;
|
||||
EXTERN long widthptr;
|
||||
EXTERN long maxarg;
|
||||
EXTERN long stksize;
|
||||
EXTERN Sym* symstringo; // string objects
|
||||
EXTERN long stringo; // size of string objects
|
||||
EXTERN long pcloc; // instruction counter
|
||||
EXTERN String emptystring;
|
||||
extern char* anames[];
|
||||
|
||||
/*
|
||||
* gen.c
|
||||
*/
|
||||
void compile(Node*);
|
||||
void proglist(void);
|
||||
void gen(Node*);
|
||||
void swgen(Node*);
|
||||
Node* lookdot(Node*, Node*, int);
|
||||
void inarggen(void);
|
||||
void agen_inter(Node*, Node*);
|
||||
void cgen_as(Node*, Node*, int);
|
||||
void cgen_asop(Node*, Node*, int);
|
||||
void cgen_ret(Node*);
|
||||
void cgen_call(Node*);
|
||||
void cgen_callmeth(Node*);
|
||||
void cgen_callinter(Node*, Node*);
|
||||
void cgen_callret(Node*, Node*);
|
||||
void genpanic(void);
|
||||
int needconvert(Type*, Type*);
|
||||
void genconv(Type*, Type*);
|
||||
void allocparams(void);
|
||||
|
||||
/*
|
||||
* cgen
|
||||
*/
|
||||
void cgen(Node*, Node*);
|
||||
void agen(Node*, Node*);
|
||||
void igen(Node*, Node*, Node*);
|
||||
vlong fieldoffset(Type*, Node*);
|
||||
void bgen(Node*, int, Prog*);
|
||||
void sgen(Node*, Node*, ulong);
|
||||
void gmove(Node*, Node*);
|
||||
Prog* gins(int, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void naddr(Node*, Addr*);
|
||||
|
||||
/*
|
||||
* gsubr.c
|
||||
*/
|
||||
void clearp(Prog*);
|
||||
void proglist(void);
|
||||
Prog* gbranch(int, Type*);
|
||||
void patch(Prog*, Prog*);
|
||||
Prog* prog(int);
|
||||
void gaddoffset(Node*);
|
||||
void gconv(int, int);
|
||||
int conv2pt(Type*);
|
||||
void belexinit(int);
|
||||
vlong convvtox(vlong, int);
|
||||
int brcom(int);
|
||||
int brrev(int);
|
||||
void fnparam(Type*, int, int);
|
||||
Sig* lsort(Sig*, int(*)(Sig*, Sig*));
|
||||
Prog* gop(int, Node*, Node*, Node*);
|
||||
void setconst(Addr*, vlong);
|
||||
void setaddr(Addr*, Node*);
|
||||
int optoas(int, Type*);
|
||||
void ginit(void);
|
||||
void gclean(void);
|
||||
void regalloc(Node*, Type*, Node*);
|
||||
void regfree(Node*);
|
||||
void regsalloc(Node*, Type*); // replace w tmpvar
|
||||
void regret(Node*, Type*);
|
||||
Node* nodarg(Type*, int);
|
||||
void nodreg(Node*, Type*, int);
|
||||
void nodindreg(Node*, Type*, int);
|
||||
void nodconst(Node*, Type*, vlong);
|
||||
Sym* signame(Type*);
|
||||
void nodtypesig(Node*, Type*);
|
||||
void gconreg(int, vlong, int);
|
||||
void buildtxt(void);
|
||||
void stringpool(Node*);
|
||||
void tempname(Node*, Type*);
|
||||
Plist* newplist(void);
|
||||
int isfat(Type*);
|
||||
void setmaxarg(Type*);
|
||||
|
||||
/*
|
||||
* list.c
|
||||
*/
|
||||
int Aconv(Fmt*);
|
||||
int Dconv(Fmt*);
|
||||
int Pconv(Fmt*);
|
||||
int Rconv(Fmt*);
|
||||
int Yconv(Fmt*);
|
||||
void listinit(void);
|
||||
|
||||
/*
|
||||
* obj
|
||||
*/
|
||||
void zname(Biobuf*, Sym*, int);
|
||||
void zaddr(Biobuf*, Addr*, int);
|
||||
void ieeedtod(Ieee*, double);
|
||||
void dumpstrings(void);
|
||||
void dumpsignatures(void);
|
||||
|
||||
/*
|
||||
* align
|
||||
*/
|
||||
void dowidth(Type*);
|
||||
ulong rnd(ulong, ulong);
|
||||
1649
src/cmd/6g/gsubr.c
Normal file
1649
src/cmd/6g/gsubr.c
Normal file
File diff suppressed because it is too large
Load diff
336
src/cmd/6g/list.c
Normal file
336
src/cmd/6g/list.c
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
// Derived from Inferno utils/6c/list.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gg.h"
|
||||
|
||||
static int sconsize;
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
|
||||
fmtinstall('A', Aconv); // as
|
||||
fmtinstall('P', Pconv); // Prog*
|
||||
fmtinstall('D', Dconv); // Addr*
|
||||
fmtinstall('R', Rconv); // reg
|
||||
fmtinstall('Y', Yconv); // sconst
|
||||
}
|
||||
|
||||
int
|
||||
Pconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Prog *p;
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
sconsize = 8;
|
||||
if(p->as == ADATA) {
|
||||
sconsize = p->from.scale;
|
||||
snprint(str, sizeof(str), "%.4ld %-7A %D/%d,%D",
|
||||
p->loc, p->as, &p->from, sconsize, &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
snprint(str, sizeof(str), "%.4ld %-7A %D,%D",
|
||||
p->loc, p->as, &p->from, &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[40], s[20];
|
||||
Addr *a;
|
||||
int i;
|
||||
|
||||
a = va_arg(fp->args, Addr*);
|
||||
i = a->type;
|
||||
if(i >= D_INDIR) {
|
||||
if(a->offset)
|
||||
sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
|
||||
else
|
||||
sprint(str, "(%R)", i-D_INDIR);
|
||||
goto brk;
|
||||
}
|
||||
switch(i) {
|
||||
|
||||
default:
|
||||
if(a->offset)
|
||||
sprint(str, "$%lld,%R", a->offset, i);
|
||||
else
|
||||
sprint(str, "%R", i);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
str[0] = 0;
|
||||
break;
|
||||
|
||||
case D_BRANCH:
|
||||
snprint(str, sizeof(str), "%ld", a->branch->loc);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
sprint(str, "%S+%lld(SB)", a->sym, a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
sprint(str, "%S<>+%lld(SB)", a->sym, a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
sprint(str, "%S+%lld(SP)", a->sym, a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
sprint(str, "%S+%lld(FP)", a->sym, a->offset);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
sprint(str, "$%lld", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
sprint(str, "$(%.17e)", a->dval);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
sprint(str, "$\"%Y\"", a->sval);
|
||||
break;
|
||||
|
||||
case D_ADDR:
|
||||
a->type = a->index;
|
||||
a->index = D_NONE;
|
||||
sprint(str, "$%D", a);
|
||||
a->index = a->type;
|
||||
a->type = D_ADDR;
|
||||
goto conv;
|
||||
}
|
||||
brk:
|
||||
if(a->index != D_NONE) {
|
||||
sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
|
||||
strcat(str, s);
|
||||
}
|
||||
conv:
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
static char* regstr[] =
|
||||
{
|
||||
"AL", /* [D_AL] */
|
||||
"CL",
|
||||
"DL",
|
||||
"BL",
|
||||
"SPB",
|
||||
"BPB",
|
||||
"SIB",
|
||||
"DIB",
|
||||
"R8B",
|
||||
"R9B",
|
||||
"R10B",
|
||||
"R11B",
|
||||
"R12B",
|
||||
"R13B",
|
||||
"R14B",
|
||||
"R15B",
|
||||
|
||||
"AX", /* [D_AX] */
|
||||
"CX",
|
||||
"DX",
|
||||
"BX",
|
||||
"SP",
|
||||
"BP",
|
||||
"SI",
|
||||
"DI",
|
||||
"R8",
|
||||
"R9",
|
||||
"R10",
|
||||
"R11",
|
||||
"R12",
|
||||
"R13",
|
||||
"R14",
|
||||
"R15",
|
||||
|
||||
"AH",
|
||||
"CH",
|
||||
"DH",
|
||||
"BH",
|
||||
|
||||
"F0", /* [D_F0] */
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
|
||||
"M0",
|
||||
"M1",
|
||||
"M2",
|
||||
"M3",
|
||||
"M4",
|
||||
"M5",
|
||||
"M6",
|
||||
"M7",
|
||||
|
||||
"X0",
|
||||
"X1",
|
||||
"X2",
|
||||
"X3",
|
||||
"X4",
|
||||
"X5",
|
||||
"X6",
|
||||
"X7",
|
||||
"X8",
|
||||
"X9",
|
||||
"X10",
|
||||
"X11",
|
||||
"X12",
|
||||
"X13",
|
||||
"X14",
|
||||
"X15",
|
||||
|
||||
"CS", /* [D_CS] */
|
||||
"SS",
|
||||
"DS",
|
||||
"ES",
|
||||
"FS",
|
||||
"GS",
|
||||
|
||||
"GDTR", /* [D_GDTR] */
|
||||
"IDTR", /* [D_IDTR] */
|
||||
"LDTR", /* [D_LDTR] */
|
||||
"MSW", /* [D_MSW] */
|
||||
"TASK", /* [D_TASK] */
|
||||
|
||||
"CR0", /* [D_CR] */
|
||||
"CR1",
|
||||
"CR2",
|
||||
"CR3",
|
||||
"CR4",
|
||||
"CR5",
|
||||
"CR6",
|
||||
"CR7",
|
||||
"CR8",
|
||||
"CR9",
|
||||
"CR10",
|
||||
"CR11",
|
||||
"CR12",
|
||||
"CR13",
|
||||
"CR14",
|
||||
"CR15",
|
||||
|
||||
"DR0", /* [D_DR] */
|
||||
"DR1",
|
||||
"DR2",
|
||||
"DR3",
|
||||
"DR4",
|
||||
"DR5",
|
||||
"DR6",
|
||||
"DR7",
|
||||
|
||||
"TR0", /* [D_TR] */
|
||||
"TR1",
|
||||
"TR2",
|
||||
"TR3",
|
||||
"TR4",
|
||||
"TR5",
|
||||
"TR6",
|
||||
"TR7",
|
||||
|
||||
"NONE", /* [D_NONE] */
|
||||
};
|
||||
|
||||
int
|
||||
Rconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
int r;
|
||||
|
||||
r = va_arg(fp->args, int);
|
||||
if(r < 0 || r >= nelem(regstr) || regstr[r] == nil) {
|
||||
snprint(str, sizeof(str), "BAD_R(%d)", r);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
return fmtstrcpy(fp, regstr[r]);
|
||||
}
|
||||
|
||||
int
|
||||
Aconv(Fmt *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = va_arg(fp->args, int);
|
||||
return fmtstrcpy(fp, anames[i]);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Yconv(Fmt *fp)
|
||||
{
|
||||
int i, c;
|
||||
char str[30], *p, *a;
|
||||
|
||||
a = va_arg(fp->args, char*);
|
||||
p = str;
|
||||
for(i=0; i<sconsize; i++) {
|
||||
c = a[i] & 0xff;
|
||||
if(c >= 'a' && c <= 'z' ||
|
||||
c >= 'A' && c <= 'Z' ||
|
||||
c >= '0' && c <= '9') {
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
*p++ = '\\';
|
||||
switch(c) {
|
||||
default:
|
||||
if(c < 040 || c >= 0177)
|
||||
break; /* not portable */
|
||||
p[-1] = c;
|
||||
continue;
|
||||
case 0:
|
||||
*p++ = 'z';
|
||||
continue;
|
||||
case '\\':
|
||||
case '"':
|
||||
*p++ = c;
|
||||
continue;
|
||||
case '\n':
|
||||
*p++ = 'n';
|
||||
continue;
|
||||
case '\t':
|
||||
*p++ = 't';
|
||||
continue;
|
||||
}
|
||||
*p++ = (c>>6) + '0';
|
||||
*p++ = ((c>>3) & 7) + '0';
|
||||
*p++ = (c & 7) + '0';
|
||||
}
|
||||
*p = 0;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
604
src/cmd/6g/obj.c
Normal file
604
src/cmd/6g/obj.c
Normal file
|
|
@ -0,0 +1,604 @@
|
|||
// Derived from Inferno utils/6c/swt.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gg.h"
|
||||
|
||||
void
|
||||
dumpobj(void)
|
||||
{
|
||||
Plist *pl;
|
||||
Prog *p;
|
||||
Dcl *d;
|
||||
Sym *s;
|
||||
Node *n;
|
||||
struct { Sym *sym; short type; } h[NSYM];
|
||||
int sf, st, t, sym;
|
||||
Node n1;
|
||||
|
||||
// add nil plist w AEND
|
||||
newplist();
|
||||
|
||||
bout = Bopen(outfile, OWRITE);
|
||||
if(bout == nil)
|
||||
fatal("cant open %s", outfile);
|
||||
|
||||
Bprint(bout, "x86-64\n");
|
||||
Bprint(bout, " exports automatically generated from\n");
|
||||
Bprint(bout, " %s in package \"%s\"\n", curio.infile, package);
|
||||
dumpexport();
|
||||
Bprint(bout, "\n!\n");
|
||||
|
||||
// add globals
|
||||
nodconst(&n1, types[TINT32], 0);
|
||||
for(d=externdcl; d!=D; d=d->forw) {
|
||||
if(d->op != ONAME)
|
||||
continue;
|
||||
|
||||
s = d->dsym;
|
||||
if(s == S)
|
||||
fatal("external nil");
|
||||
n = d->dnode;
|
||||
if(n == N || n->type == T)
|
||||
fatal("external %S nil\n", s);
|
||||
|
||||
if(n->type->etype == TFUNC)
|
||||
continue;
|
||||
|
||||
dowidth(n->type);
|
||||
n1.val.vval = n->type->width;
|
||||
|
||||
p = pc;
|
||||
gins(AGLOBL, s->oname, &n1);
|
||||
p->lineno = s->oname->lineno;
|
||||
}
|
||||
|
||||
dumpstrings();
|
||||
dumpsignatures();
|
||||
|
||||
for(sym=0; sym<NSYM; sym++) {
|
||||
h[sym].sym = S;
|
||||
h[sym].type = 0;
|
||||
}
|
||||
sym = 1;
|
||||
|
||||
// put out functions
|
||||
for(pl=plist; pl!=nil; pl=pl->link) {
|
||||
|
||||
if(debug['S']) {
|
||||
s = S;
|
||||
if(pl->name != N)
|
||||
s = pl->name->sym;
|
||||
print("\n--- prog list \"%S\" ---\n", s);
|
||||
for(p=pl->firstpc; p!=P; p=p->link)
|
||||
print("%P\n", p);
|
||||
}
|
||||
|
||||
for(p=pl->firstpc; p!=P; p=p->link) {
|
||||
jackpot:
|
||||
sf = 0;
|
||||
s = p->from.sym;
|
||||
while(s != S) {
|
||||
sf = s->sym;
|
||||
if(sf < 0 || sf >= NSYM)
|
||||
sf = 0;
|
||||
t = p->from.type;
|
||||
if(t == D_ADDR)
|
||||
t = p->from.index;
|
||||
if(h[sf].type == t)
|
||||
if(h[sf].sym == s)
|
||||
break;
|
||||
s->sym = sym;
|
||||
zname(bout, s, t);
|
||||
h[sym].sym = s;
|
||||
h[sym].type = t;
|
||||
sf = sym;
|
||||
sym++;
|
||||
if(sym >= NSYM)
|
||||
sym = 1;
|
||||
break;
|
||||
}
|
||||
st = 0;
|
||||
s = p->to.sym;
|
||||
while(s != S) {
|
||||
st = s->sym;
|
||||
if(st < 0 || st >= NSYM)
|
||||
st = 0;
|
||||
t = p->to.type;
|
||||
if(t == D_ADDR)
|
||||
t = p->to.index;
|
||||
if(h[st].type == t)
|
||||
if(h[st].sym == s)
|
||||
break;
|
||||
s->sym = sym;
|
||||
zname(bout, s, t);
|
||||
h[sym].sym = s;
|
||||
h[sym].type = t;
|
||||
st = sym;
|
||||
sym++;
|
||||
if(sym >= NSYM)
|
||||
sym = 1;
|
||||
if(st == sf)
|
||||
goto jackpot;
|
||||
break;
|
||||
}
|
||||
Bputc(bout, p->as);
|
||||
Bputc(bout, p->as>>8);
|
||||
Bputc(bout, p->lineno);
|
||||
Bputc(bout, p->lineno>>8);
|
||||
Bputc(bout, p->lineno>>16);
|
||||
Bputc(bout, p->lineno>>24);
|
||||
zaddr(bout, &p->from, sf);
|
||||
zaddr(bout, &p->to, st);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
zname(Biobuf *b, Sym *s, int t)
|
||||
{
|
||||
char *n;
|
||||
|
||||
Bputc(b, ANAME); /* as */
|
||||
Bputc(b, ANAME>>8); /* as */
|
||||
Bputc(b, t); /* type */
|
||||
Bputc(b, s->sym); /* sym */
|
||||
|
||||
for(n=s->opackage; *n; n++)
|
||||
Bputc(b, *n);
|
||||
Bputc(b, '_');
|
||||
for(n=s->name; *n; n++)
|
||||
Bputc(b, *n);
|
||||
Bputc(b, 0);
|
||||
}
|
||||
|
||||
void
|
||||
zaddr(Biobuf *b, Addr *a, int s)
|
||||
{
|
||||
long l;
|
||||
int i, t;
|
||||
char *n;
|
||||
Ieee e;
|
||||
|
||||
t = 0;
|
||||
if(a->index != D_NONE || a->scale != 0)
|
||||
t |= T_INDEX;
|
||||
if(s != 0)
|
||||
t |= T_SYM;
|
||||
|
||||
switch(a->type) {
|
||||
default:
|
||||
t |= T_TYPE;
|
||||
case D_NONE:
|
||||
if(a->offset != 0) {
|
||||
t |= T_OFFSET;
|
||||
l = a->offset;
|
||||
if((vlong)l != a->offset)
|
||||
t |= T_64;
|
||||
}
|
||||
break;
|
||||
case D_FCONST:
|
||||
t |= T_FCONST;
|
||||
break;
|
||||
case D_SCONST:
|
||||
t |= T_SCONST;
|
||||
break;
|
||||
}
|
||||
Bputc(b, t);
|
||||
|
||||
if(t & T_INDEX) { /* implies index, scale */
|
||||
Bputc(b, a->index);
|
||||
Bputc(b, a->scale);
|
||||
}
|
||||
if(t & T_OFFSET) { /* implies offset */
|
||||
l = a->offset;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
if(t & T_64) {
|
||||
l = a->offset>>32;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
}
|
||||
}
|
||||
if(t & T_SYM) /* implies sym */
|
||||
Bputc(b, s);
|
||||
if(t & T_FCONST) {
|
||||
ieeedtod(&e, a->dval);
|
||||
l = e.l;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
l = e.h;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
return;
|
||||
}
|
||||
if(t & T_SCONST) {
|
||||
n = a->sval;
|
||||
for(i=0; i<NSNAME; i++) {
|
||||
Bputc(b, *n);
|
||||
n++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(t & T_TYPE)
|
||||
Bputc(b, a->type);
|
||||
}
|
||||
|
||||
void
|
||||
ieeedtod(Ieee *ieee, double native)
|
||||
{
|
||||
double fr, ho, f;
|
||||
int exp;
|
||||
|
||||
if(native < 0) {
|
||||
ieeedtod(ieee, -native);
|
||||
ieee->h |= 0x80000000L;
|
||||
return;
|
||||
}
|
||||
if(native == 0) {
|
||||
ieee->l = 0;
|
||||
ieee->h = 0;
|
||||
return;
|
||||
}
|
||||
fr = frexp(native, &exp);
|
||||
f = 2097152L; /* shouldnt use fp constants here */
|
||||
fr = modf(fr*f, &ho);
|
||||
ieee->h = ho;
|
||||
ieee->h &= 0xfffffL;
|
||||
ieee->h |= (exp+1022L) << 20;
|
||||
f = 65536L;
|
||||
fr = modf(fr*f, &ho);
|
||||
ieee->l = ho;
|
||||
ieee->l <<= 16;
|
||||
ieee->l |= (long)(fr*f);
|
||||
}
|
||||
|
||||
void
|
||||
datastring(char *s, int len)
|
||||
{
|
||||
int w;
|
||||
Prog *p;
|
||||
Addr ac, ao;
|
||||
|
||||
// string
|
||||
memset(&ao, 0, sizeof(ao));
|
||||
ao.type = D_STATIC;
|
||||
ao.index = D_NONE;
|
||||
ao.etype = TINT32;
|
||||
ao.sym = symstringo;
|
||||
ao.offset = 0; // fill in
|
||||
|
||||
// constant
|
||||
memset(&ac, 0, sizeof(ac));
|
||||
ac.type = D_CONST;
|
||||
ac.index = D_NONE;
|
||||
ac.offset = 0; // fill in
|
||||
|
||||
for(w=0; w<len; w+=8) {
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
|
||||
// .stringo<>+oo, [NSNAME], $"xxx"
|
||||
p->from = ao;
|
||||
p->from.offset = stringo;
|
||||
|
||||
p->from.scale = NSNAME;
|
||||
if(w+8 > len)
|
||||
p->from.scale = len-w;
|
||||
|
||||
p->to = ac;
|
||||
p->to.type = D_SCONST;
|
||||
p->to.offset = len;
|
||||
memmove(p->to.sval, s+w, p->from.scale);
|
||||
stringo += p->from.scale;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dumpstrings(void)
|
||||
{
|
||||
Pool *l;
|
||||
Prog *p;
|
||||
Addr ac, ao;
|
||||
long wi;
|
||||
|
||||
if(poolist == nil)
|
||||
return;
|
||||
|
||||
memset(&ac, 0, sizeof(ac));
|
||||
memset(&ao, 0, sizeof(ao));
|
||||
|
||||
// constant
|
||||
ac.type = D_CONST;
|
||||
ac.index = D_NONE;
|
||||
ac.offset = 0; // fill in
|
||||
|
||||
// string len+ptr
|
||||
ao.type = D_STATIC;
|
||||
ao.index = D_NONE;
|
||||
ao.etype = TINT32;
|
||||
ao.sym = symstringo;
|
||||
ao.offset = 0; // fill in
|
||||
|
||||
wi = types[TINT32]->width;
|
||||
|
||||
// lay out (count+string)
|
||||
for(l=poolist; l!=nil; l=l->link) {
|
||||
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
|
||||
// .stringo<>+xx, wi, $len
|
||||
stringo = rnd(stringo, wi);
|
||||
p->from = ao;
|
||||
p->from.offset = stringo;
|
||||
p->from.scale = wi;
|
||||
p->to = ac;
|
||||
p->to.offset = l->sval->len;
|
||||
stringo += wi;
|
||||
|
||||
datastring(l->sval->s, l->sval->len);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sigcmp(Sig *a, Sig *b)
|
||||
{
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
void
|
||||
dumpsignatures(void)
|
||||
{
|
||||
Dcl *d;
|
||||
Type *t, *f;
|
||||
Sym *s1, *s;
|
||||
int et, o, wi, ot;
|
||||
Sig *a, *b;
|
||||
Addr at, ao, ac, ad;
|
||||
Prog *p;
|
||||
char *sp;
|
||||
|
||||
/*
|
||||
* put all the names into a linked
|
||||
* list so that it may be generated in sorted order.
|
||||
* the runtime will be linear rather than quadradic
|
||||
*/
|
||||
|
||||
memset(&at, 0, sizeof(at));
|
||||
memset(&ao, 0, sizeof(ao));
|
||||
memset(&ac, 0, sizeof(ac));
|
||||
memset(&ad, 0, sizeof(ad));
|
||||
|
||||
// sig structure
|
||||
at.type = D_EXTERN;
|
||||
at.index = D_NONE;
|
||||
at.sym = S; // fill in
|
||||
at.offset = 0; // fill in
|
||||
|
||||
// $string
|
||||
ao.type = D_ADDR;
|
||||
ao.index = D_STATIC;
|
||||
ao.etype = TINT32;
|
||||
ao.sym = symstringo;
|
||||
ao.offset = 0; // fill in
|
||||
|
||||
// constant
|
||||
ac.type = D_CONST;
|
||||
ac.index = D_NONE;
|
||||
ac.offset = 0; // fill in
|
||||
|
||||
// $method
|
||||
ad.type = D_ADDR;
|
||||
ad.index = D_EXTERN;
|
||||
ad.sym = S; // fill in
|
||||
ad.offset = 0;
|
||||
|
||||
wi = types[TINT32]->width;
|
||||
|
||||
for(d=externdcl; d!=D; d=d->forw) {
|
||||
if(d->op != OTYPE)
|
||||
continue;
|
||||
|
||||
t = d->dtype;
|
||||
et = t->etype;
|
||||
if(et != TSTRUCT && et != TINTER)
|
||||
continue;
|
||||
|
||||
s = d->dsym;
|
||||
if(s == S)
|
||||
continue;
|
||||
|
||||
if(s->name[0] == '_')
|
||||
continue;
|
||||
|
||||
if(strcmp(s->opackage, package) != 0)
|
||||
continue;
|
||||
|
||||
at.sym = signame(t);
|
||||
|
||||
a = nil;
|
||||
o = 0;
|
||||
for(f=t->type; f!=T; f=f->down) {
|
||||
if(f->type->etype != TFUNC)
|
||||
continue;
|
||||
|
||||
if(f->etype != TFIELD)
|
||||
fatal("dumpsignatures: not field");
|
||||
|
||||
s1 = f->sym;
|
||||
if(s1 == nil)
|
||||
continue;
|
||||
if(s1->name[0] == '_')
|
||||
continue;
|
||||
|
||||
b = mal(sizeof(*b));
|
||||
b->link = a;
|
||||
a = b;
|
||||
|
||||
a->name = s1->name;
|
||||
sp = strchr(s1->name, '_');
|
||||
if(sp != nil)
|
||||
a->name = sp+1;
|
||||
|
||||
a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
|
||||
a->sym = f->sym;
|
||||
a->offset = o;
|
||||
o++;
|
||||
}
|
||||
|
||||
a = lsort(a, sigcmp);
|
||||
ot = 0;
|
||||
|
||||
if(et == TINTER) {
|
||||
o = 0;
|
||||
for(b=a; b!=nil; b=b->link)
|
||||
o++;
|
||||
|
||||
// sigi[0].name = ""
|
||||
ot = rnd(ot, maxround);
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = ot;
|
||||
p->from.scale = widthptr;
|
||||
p->to = ao;
|
||||
p->to.offset = stringo;
|
||||
ot += widthptr;
|
||||
|
||||
// sigi[0].hash = 0
|
||||
ot = rnd(ot, wi);
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = ot;
|
||||
p->from.scale = wi;
|
||||
p->to = ac;
|
||||
p->to.offset = 0;
|
||||
ot += wi;
|
||||
|
||||
// sigi[0].offset = count
|
||||
ot = rnd(ot, wi);
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = ot;
|
||||
p->from.scale = wi;
|
||||
p->to = ac;
|
||||
p->to.offset = o;
|
||||
ot += wi;
|
||||
|
||||
datastring("", 1);
|
||||
|
||||
}
|
||||
|
||||
for(b=a; b!=nil; b=b->link) {
|
||||
|
||||
// sigx[++].name = "fieldname"
|
||||
ot = rnd(ot, maxround);
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = ot;
|
||||
p->from.scale = widthptr;
|
||||
p->to = ao;
|
||||
p->to.offset = stringo;
|
||||
ot += widthptr;
|
||||
|
||||
// sigx[++].hash = hashcode
|
||||
ot = rnd(ot, wi);
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = ot;
|
||||
p->from.scale = wi;
|
||||
p->to = ac;
|
||||
p->to.offset = b->hash;
|
||||
ot += wi;
|
||||
|
||||
if(et == TINTER) {
|
||||
// sigi[++].offset = offset of method
|
||||
ot = rnd(ot, wi);
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = ot;
|
||||
p->from.scale = wi;
|
||||
p->to = ac;
|
||||
p->to.offset = b->offset;
|
||||
ot += wi;
|
||||
} else {
|
||||
// sigs[++].fun = &method
|
||||
ot = rnd(ot, widthptr);
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = ot;
|
||||
p->from.scale = widthptr;
|
||||
p->to = ad;
|
||||
p->to.sym = b->sym;
|
||||
ot += widthptr;
|
||||
}
|
||||
datastring(b->name, strlen(b->name)+1);
|
||||
}
|
||||
|
||||
// nil field name at end
|
||||
ot = rnd(ot, maxround);
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = ot;
|
||||
p->from.scale = widthptr;
|
||||
p->to = ac;
|
||||
p->to.offset = 0;
|
||||
ot += widthptr;
|
||||
|
||||
p = pc;
|
||||
gins(AGLOBL, N, N);
|
||||
p->from = at;
|
||||
p->to = ac;
|
||||
p->to.offset = ot;
|
||||
}
|
||||
|
||||
if(stringo > 0) {
|
||||
p = pc;
|
||||
gins(AGLOBL, N, N);
|
||||
p->from = ao;
|
||||
p->to = ac;
|
||||
p->to.offset = stringo;
|
||||
}
|
||||
}
|
||||
595
src/cmd/6g/runtime.c
Normal file
595
src/cmd/6g/runtime.c
Normal file
|
|
@ -0,0 +1,595 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "runtime.h"
|
||||
|
||||
int32 debug = 0;
|
||||
|
||||
void
|
||||
sys_printbool(bool v)
|
||||
{
|
||||
if(v) {
|
||||
sys_write(1, (byte*)"true", 4);
|
||||
return;
|
||||
}
|
||||
sys_write(1, (byte*)"false", 5);
|
||||
}
|
||||
|
||||
void
|
||||
sys_printfloat(float64 v)
|
||||
{
|
||||
sys_write(1, "printfloat", 10);
|
||||
}
|
||||
|
||||
void
|
||||
sys_printint(int64 v)
|
||||
{
|
||||
byte buf[100];
|
||||
int32 i, s;
|
||||
|
||||
s = 0;
|
||||
if(v < 0) {
|
||||
v = -v;
|
||||
s = 1;
|
||||
if(v < 0) {
|
||||
sys_write(1, (byte*)"-oo", 3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=nelem(buf)-1; i>0; i--) {
|
||||
buf[i] = v%10 + '0';
|
||||
if(v < 10)
|
||||
break;
|
||||
v = v/10;
|
||||
}
|
||||
if(s) {
|
||||
i--;
|
||||
buf[i] = '-';
|
||||
}
|
||||
sys_write(1, buf+i, nelem(buf)-i);
|
||||
}
|
||||
|
||||
void
|
||||
sys_printpointer(void *p)
|
||||
{
|
||||
uint64 v;
|
||||
byte buf[100];
|
||||
int32 i;
|
||||
|
||||
v = (int64)p;
|
||||
for(i=nelem(buf)-1; i>0; i--) {
|
||||
buf[i] = v%16 + '0';
|
||||
if(buf[i] > '9')
|
||||
buf[i] += 'a'-'0'-10;
|
||||
if(v < 16)
|
||||
break;
|
||||
v = v/16;
|
||||
}
|
||||
sys_write(1, buf+i, nelem(buf)-i);
|
||||
}
|
||||
|
||||
void
|
||||
sys_panicl(int32 lno)
|
||||
{
|
||||
prints("\npanic on line ");
|
||||
sys_printint(lno);
|
||||
prints("\n");
|
||||
*(int32*)0 = 0;
|
||||
}
|
||||
|
||||
void
|
||||
sys_printstring(string v)
|
||||
{
|
||||
sys_write(1, v->str, v->len);
|
||||
}
|
||||
|
||||
int32
|
||||
strlen(int8 *s)
|
||||
{
|
||||
int32 l;
|
||||
|
||||
for(l=0; s[l]!=0; l++)
|
||||
;
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
prints(int8 *s)
|
||||
{
|
||||
sys_write(1, s, strlen(s));
|
||||
}
|
||||
|
||||
dump(byte *p, int32 n)
|
||||
{
|
||||
uint32 v;
|
||||
int32 i;
|
||||
|
||||
for(i=0; i<n; i++) {
|
||||
sys_printpointer((byte*)(p[i]>>4));
|
||||
sys_printpointer((byte*)(p[i]&0xf));
|
||||
if((i&15) == 15)
|
||||
prints("\n");
|
||||
else
|
||||
prints(" ");
|
||||
}
|
||||
if(n & 15)
|
||||
prints("\n");
|
||||
}
|
||||
|
||||
static uint8* hunk;
|
||||
static uint32 nhunk;
|
||||
static uint64 nmmap;
|
||||
static uint64 nmal;
|
||||
enum
|
||||
{
|
||||
NHUNK = 20<<20,
|
||||
|
||||
PROT_NONE = 0x00,
|
||||
PROT_READ = 0x01,
|
||||
PROT_WRITE = 0x02,
|
||||
PROT_EXEC = 0x04,
|
||||
|
||||
MAP_FILE = 0x0000,
|
||||
MAP_SHARED = 0x0001,
|
||||
MAP_PRIVATE = 0x0002,
|
||||
MAP_FIXED = 0x0010,
|
||||
MAP_ANON = 0x1000,
|
||||
};
|
||||
|
||||
static void
|
||||
throw(int8 *s)
|
||||
{
|
||||
prints("throw: ");
|
||||
prints(s);
|
||||
prints("\n");
|
||||
sys_exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
mcpy(byte *t, byte *f, uint32 n)
|
||||
{
|
||||
while(n > 0) {
|
||||
*t = *f;
|
||||
t++;
|
||||
f++;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
static byte*
|
||||
brk(uint32 n)
|
||||
{
|
||||
byte* v;
|
||||
|
||||
v = sys_mmap(nil, NHUNK, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0);
|
||||
sys_memclr(v, n);
|
||||
nmmap += n;
|
||||
return v;
|
||||
}
|
||||
|
||||
static void*
|
||||
mal(uint32 n)
|
||||
{
|
||||
byte* v;
|
||||
|
||||
// round to keep everything 64-bit alligned
|
||||
while(n & 7)
|
||||
n++;
|
||||
|
||||
nmal += n;
|
||||
|
||||
// do we have enough in contiguous hunk
|
||||
if(n > nhunk) {
|
||||
|
||||
// if it is big allocate it separately
|
||||
if(n > NHUNK)
|
||||
return brk(n);
|
||||
|
||||
// allocate a new contiguous hunk
|
||||
hunk = brk(NHUNK);
|
||||
nhunk = NHUNK;
|
||||
}
|
||||
|
||||
// allocate from the contiguous hunk
|
||||
v = hunk;
|
||||
hunk += n;
|
||||
nhunk -= n;
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
sys_mal(uint32 n, uint8 *ret)
|
||||
{
|
||||
ret = mal(n);
|
||||
FLUSH(&ret);
|
||||
}
|
||||
|
||||
void
|
||||
sys_catstring(string s1, string s2, string s3)
|
||||
{
|
||||
uint32 l;
|
||||
|
||||
if(s1->len == 0) {
|
||||
s3 = s2;
|
||||
goto out;
|
||||
}
|
||||
if(s2->len == 0) {
|
||||
s3 = s1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
l = s1->len + s2->len;
|
||||
|
||||
s3 = mal(sizeof(s3->len)+l);
|
||||
s3->len = l;
|
||||
mcpy(s3->str, s1->str, s1->len);
|
||||
mcpy(s3->str+s1->len, s2->str, s2->len);
|
||||
|
||||
out:
|
||||
FLUSH(&s3);
|
||||
}
|
||||
|
||||
void
|
||||
sys_cmpstring(string s1, string s2, int32 v)
|
||||
{
|
||||
uint32 i, l;
|
||||
byte c1, c2;
|
||||
|
||||
l = s1->len;
|
||||
if(s2->len < l)
|
||||
l = s2->len;
|
||||
for(i=0; i<l; i++) {
|
||||
c1 = s1->str[i];
|
||||
c2 = s2->str[i];
|
||||
if(c1 < c2) {
|
||||
v = -1;
|
||||
goto out;
|
||||
}
|
||||
if(c1 > c2) {
|
||||
v = +1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if(s1->len < s2->len) {
|
||||
v = -1;
|
||||
goto out;
|
||||
}
|
||||
if(s1->len > s2->len) {
|
||||
v = +1;
|
||||
goto out;
|
||||
}
|
||||
v = 0;
|
||||
|
||||
out:
|
||||
FLUSH(&v);
|
||||
}
|
||||
|
||||
static int32
|
||||
strcmp(byte *s1, byte *s2)
|
||||
{
|
||||
uint32 i;
|
||||
byte c1, c2;
|
||||
|
||||
for(i=0;; i++) {
|
||||
c1 = s1[i];
|
||||
c2 = s2[i];
|
||||
if(c1 < c2)
|
||||
return -1;
|
||||
if(c1 > c2)
|
||||
return +1;
|
||||
if(c1 == 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
prbounds(int8* s, int32 a, int32 b, int32 c)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
prints(s);
|
||||
prints(" ");
|
||||
sys_printint(a);
|
||||
prints("<");
|
||||
sys_printint(b);
|
||||
prints(">");
|
||||
sys_printint(c);
|
||||
prints("\n");
|
||||
throw("bounds");
|
||||
}
|
||||
|
||||
void
|
||||
sys_slicestring(string si, int32 lindex, int32 hindex, string so)
|
||||
{
|
||||
string s, str;
|
||||
int32 l;
|
||||
|
||||
if(lindex < 0 || lindex > si->len ||
|
||||
hindex < lindex || hindex > si->len)
|
||||
prbounds("slice", lindex, si->len, hindex);
|
||||
|
||||
l = hindex-lindex;
|
||||
so = mal(sizeof(so->len)+l);
|
||||
so->len = l;
|
||||
mcpy(so->str, si->str+lindex, l);
|
||||
FLUSH(&so);
|
||||
}
|
||||
|
||||
void
|
||||
sys_indexstring(string s, int32 i, byte b)
|
||||
{
|
||||
if(i < 0 || i >= s->len)
|
||||
prbounds("index", 0, i, s->len);
|
||||
|
||||
b = s->str[i];
|
||||
FLUSH(&b);
|
||||
}
|
||||
|
||||
/*
|
||||
* this is the plan9 runetochar
|
||||
* extended for 36 bits in 7 bytes
|
||||
* note that it truncates to 32 bits
|
||||
* through the argument passing.
|
||||
*/
|
||||
static int32
|
||||
runetochar(byte *str, uint32 c)
|
||||
{
|
||||
int32 i, n;
|
||||
uint32 mask, mark;
|
||||
|
||||
/*
|
||||
* one character in 7 bits
|
||||
*/
|
||||
if(c <= 0x07FUL) {
|
||||
str[0] = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* every new character picks up 5 bits
|
||||
* one less in the first byte and
|
||||
* six more in an extension byte
|
||||
*/
|
||||
mask = 0x7ffUL;
|
||||
mark = 0xC0UL;
|
||||
for(n=1;; n++) {
|
||||
if(c <= mask)
|
||||
break;
|
||||
mask = (mask<<5) | 0x1fUL;
|
||||
mark = (mark>>1) | 0x80UL;
|
||||
}
|
||||
|
||||
/*
|
||||
* lay down the bytes backwards
|
||||
* n is the number of extension bytes
|
||||
* mask is the max codepoint
|
||||
* mark is the zeroth byte indicator
|
||||
*/
|
||||
for(i=n; i>0; i--) {
|
||||
str[i] = 0x80UL | (c&0x3fUL);
|
||||
c >>= 6;
|
||||
}
|
||||
|
||||
str[0] = mark|c;
|
||||
return n+1;
|
||||
}
|
||||
|
||||
void
|
||||
sys_intstring(int64 v, string s)
|
||||
{
|
||||
int32 l;
|
||||
|
||||
s = mal(sizeof(s->len)+8);
|
||||
s->len = runetochar(s->str, v);
|
||||
FLUSH(&s);
|
||||
}
|
||||
|
||||
void
|
||||
sys_byteastring(byte *a, int32 l, string s)
|
||||
{
|
||||
s = mal(sizeof(s->len)+l);
|
||||
s->len = l;
|
||||
mcpy(s->str, a, l);
|
||||
FLUSH(&s);
|
||||
}
|
||||
|
||||
static Map* hash[1009];
|
||||
|
||||
static Map*
|
||||
hashmap(Sigi *si, Sigs *ss)
|
||||
{
|
||||
int32 ns, ni;
|
||||
uint32 ihash, h;
|
||||
byte *sname, *iname;
|
||||
Map *m;
|
||||
|
||||
h = ((uint32)si + (uint32)ss) % nelem(hash);
|
||||
for(m=hash[h]; m!=nil; m=m->link) {
|
||||
if(m->si == si && m->ss == ss) {
|
||||
if(m->bad) {
|
||||
throw("bad hashmap");
|
||||
m = nil;
|
||||
}
|
||||
// prints("old hashmap\n");
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
ni = si[0].offset; // first word has size
|
||||
m = mal(sizeof(*m) + ni*sizeof(m->fun[0]));
|
||||
m->si = si;
|
||||
m->ss = ss;
|
||||
|
||||
ni = 1; // skip first word
|
||||
ns = 0;
|
||||
|
||||
loop1:
|
||||
// pick up next name from
|
||||
// interface signature
|
||||
iname = si[ni].name;
|
||||
if(iname == nil) {
|
||||
m->link = hash[h];
|
||||
hash[h] = m;
|
||||
// prints("new hashmap\n");
|
||||
return m;
|
||||
}
|
||||
ihash = si[ni].hash;
|
||||
|
||||
loop2:
|
||||
// pick up and comapre next name
|
||||
// from structure signature
|
||||
sname = ss[ns].name;
|
||||
if(sname == nil) {
|
||||
prints((int8*)iname);
|
||||
prints(": ");
|
||||
throw("hashmap: failed to find method");
|
||||
m->bad = 1;
|
||||
m->link = hash[h];
|
||||
hash[h] = m;
|
||||
return nil;
|
||||
}
|
||||
if(ihash != ss[ns].hash ||
|
||||
strcmp(sname, iname) != 0) {
|
||||
ns++;
|
||||
goto loop2;
|
||||
}
|
||||
|
||||
m->fun[si[ni].offset] = ss[ns].fun;
|
||||
ni++;
|
||||
goto loop1;
|
||||
}
|
||||
|
||||
void
|
||||
sys_ifaces2i(Sigi *si, Sigs *ss, Map *m, void *s)
|
||||
{
|
||||
|
||||
if(debug) {
|
||||
prints("s2i sigi=");
|
||||
sys_printpointer(si);
|
||||
prints(" sigs=");
|
||||
sys_printpointer(ss);
|
||||
prints(" s=");
|
||||
sys_printpointer(s);
|
||||
}
|
||||
|
||||
if(s == nil) {
|
||||
throw("ifaces2i: nil pointer");
|
||||
m = nil;
|
||||
FLUSH(&m);
|
||||
return;
|
||||
}
|
||||
|
||||
m = hashmap(si, ss);
|
||||
|
||||
if(debug) {
|
||||
prints(" returning m=");
|
||||
sys_printpointer(m);
|
||||
prints(" s=");
|
||||
sys_printpointer(s);
|
||||
prints("\n");
|
||||
dump((byte*)m, 64);
|
||||
}
|
||||
|
||||
FLUSH(&m);
|
||||
}
|
||||
|
||||
void
|
||||
sys_ifacei2i(Sigi *si, Map *m, void *s)
|
||||
{
|
||||
|
||||
if(debug) {
|
||||
prints("i2i sigi=");
|
||||
sys_printpointer(si);
|
||||
prints(" m=");
|
||||
sys_printpointer(m);
|
||||
prints(" s=");
|
||||
sys_printpointer(s);
|
||||
}
|
||||
|
||||
if(m == nil) {
|
||||
throw("ifacei2i: nil map");
|
||||
s = nil;
|
||||
FLUSH(&s);
|
||||
return;
|
||||
}
|
||||
|
||||
if(m->si == nil) {
|
||||
throw("ifacei2i: nil pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
if(m->si != si) {
|
||||
m = hashmap(si, m->ss);
|
||||
FLUSH(&m);
|
||||
}
|
||||
|
||||
if(debug) {
|
||||
prints(" returning m=");
|
||||
sys_printpointer(m);
|
||||
prints(" s=");
|
||||
sys_printpointer(s);
|
||||
prints("\n");
|
||||
dump((byte*)m, 64);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sys_ifacei2s(Sigs *ss, Map *m, void *s)
|
||||
{
|
||||
|
||||
if(debug) {
|
||||
prints("i2s m=");
|
||||
sys_printpointer(m);
|
||||
prints(" s=");
|
||||
sys_printpointer(s);
|
||||
prints("\n");
|
||||
}
|
||||
|
||||
if(m == nil) {
|
||||
throw("ifacei2s: nil map");
|
||||
s = nil;
|
||||
FLUSH(&s);
|
||||
return;
|
||||
}
|
||||
|
||||
if(m->ss != ss) {
|
||||
dump((byte*)m, 64);
|
||||
throw("ifacei2s: wrong pointer");
|
||||
s = nil;
|
||||
FLUSH(&s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
check(void)
|
||||
{
|
||||
int8 a;
|
||||
uint8 b;
|
||||
int16 c;
|
||||
uint16 d;
|
||||
int32 e;
|
||||
uint32 f;
|
||||
int64 g;
|
||||
uint64 h;
|
||||
float32 i;
|
||||
float64 j;
|
||||
void* k;
|
||||
uint16* l;
|
||||
|
||||
if(sizeof(a) != 1) throw("bad a");
|
||||
if(sizeof(b) != 1) throw("bad b");
|
||||
if(sizeof(c) != 2) throw("bad c");
|
||||
if(sizeof(d) != 2) throw("bad d");
|
||||
if(sizeof(e) != 4) throw("bad e");
|
||||
if(sizeof(f) != 4) throw("bad f");
|
||||
if(sizeof(g) != 8) throw("bad g");
|
||||
if(sizeof(h) != 8) throw("bad h");
|
||||
if(sizeof(i) != 4) throw("bad i");
|
||||
if(sizeof(j) != 8) throw("bad j");
|
||||
if(sizeof(k) != 8) throw("bad k");
|
||||
if(sizeof(l) != 8) throw("bad l");
|
||||
// prints(1"check ok\n");
|
||||
}
|
||||
107
src/cmd/6g/runtime.h
Normal file
107
src/cmd/6g/runtime.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
||||
/*
|
||||
* basic types
|
||||
*/
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed long long int int64;
|
||||
typedef unsigned long long int uint64;
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
|
||||
/*
|
||||
* get rid of C types
|
||||
*/
|
||||
#define unsigned XXunsigned
|
||||
#define signed XXsigned
|
||||
#define char XXchar
|
||||
#define short XXshort
|
||||
#define int XXint
|
||||
#define long XXlong
|
||||
#define float XXfloat
|
||||
#define double XXdouble
|
||||
|
||||
/*
|
||||
* defined types
|
||||
*/
|
||||
typedef uint8 bool;
|
||||
typedef uint8 byte;
|
||||
typedef struct
|
||||
{
|
||||
int32 len;
|
||||
byte str[1];
|
||||
} *string;
|
||||
typedef struct
|
||||
{
|
||||
byte* name;
|
||||
uint32 hash;
|
||||
void (*fun)(void);
|
||||
} Sigs;
|
||||
typedef struct
|
||||
{
|
||||
byte* name;
|
||||
uint32 hash;
|
||||
uint32 offset;
|
||||
} Sigi;
|
||||
typedef struct Map Map;
|
||||
struct Map
|
||||
{
|
||||
Sigi* si;
|
||||
Sigs* ss;
|
||||
Map* link;
|
||||
int32 bad;
|
||||
int32 unused;
|
||||
void (*fun[])(void);
|
||||
};
|
||||
|
||||
/*
|
||||
* defined constants
|
||||
*/
|
||||
enum
|
||||
{
|
||||
true = 1,
|
||||
false = 0,
|
||||
};
|
||||
|
||||
/*
|
||||
* defined macros
|
||||
* you need super-goru privilege
|
||||
* to add this list.
|
||||
*/
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#define nil ((void*)0)
|
||||
|
||||
/*
|
||||
* very low level
|
||||
*/
|
||||
void FLUSH(void*);
|
||||
void prints(int8*);
|
||||
void sys_exit(int32);
|
||||
void sys_write(int32, void*, int32);
|
||||
void sys_breakpoint(void);
|
||||
uint8* sys_mmap(byte*, uint32, int32, int32, int32, uint32);
|
||||
void sys_memclr(byte*, uint32);
|
||||
|
||||
/*
|
||||
* runtime
|
||||
*/
|
||||
void sys_printbool(bool);
|
||||
void sys_printfloat(float64);
|
||||
void sys_printint(int64);
|
||||
void sys_printstring(string);
|
||||
void sys_catstring(string, string, string);
|
||||
void sys_cmpstring(string, string, int32);
|
||||
void sys_slicestring(string, int32, int32, string);
|
||||
void sys_indexstring(string, int32, byte);
|
||||
void sys_intstring(int64, string);
|
||||
void sys_ifaces2i(Sigi*, Sigs*, Map*, void*);
|
||||
void sys_ifacei2i(Sigi*, Map*, void*);
|
||||
void sys_ifacei2s(Sigs*, Map*, void*);
|
||||
857
src/cmd/6l/6.out.h
Normal file
857
src/cmd/6l/6.out.h
Normal file
|
|
@ -0,0 +1,857 @@
|
|||
// Inferno utils/6c/6.out.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/6.out.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#define NSYM 50
|
||||
#define NSNAME 8
|
||||
#define NOPROF (1<<0)
|
||||
#define DUPOK (1<<1)
|
||||
|
||||
/*
|
||||
* amd64
|
||||
*/
|
||||
|
||||
enum as
|
||||
{
|
||||
AXXX,
|
||||
AAAA,
|
||||
AAAD,
|
||||
AAAM,
|
||||
AAAS,
|
||||
AADCB,
|
||||
AADCL,
|
||||
AADCW,
|
||||
AADDB,
|
||||
AADDL,
|
||||
AADDW,
|
||||
AADJSP,
|
||||
AANDB,
|
||||
AANDL,
|
||||
AANDW,
|
||||
AARPL,
|
||||
ABOUNDL,
|
||||
ABOUNDW,
|
||||
ABSFL,
|
||||
ABSFW,
|
||||
ABSRL,
|
||||
ABSRW,
|
||||
ABTL,
|
||||
ABTW,
|
||||
ABTCL,
|
||||
ABTCW,
|
||||
ABTRL,
|
||||
ABTRW,
|
||||
ABTSL,
|
||||
ABTSW,
|
||||
ABYTE,
|
||||
ACALL,
|
||||
ACLC,
|
||||
ACLD,
|
||||
ACLI,
|
||||
ACLTS,
|
||||
ACMC,
|
||||
ACMPB,
|
||||
ACMPL,
|
||||
ACMPW,
|
||||
ACMPSB,
|
||||
ACMPSL,
|
||||
ACMPSW,
|
||||
ADAA,
|
||||
ADAS,
|
||||
ADATA,
|
||||
ADECB,
|
||||
ADECL,
|
||||
ADECQ,
|
||||
ADECW,
|
||||
ADIVB,
|
||||
ADIVL,
|
||||
ADIVW,
|
||||
AENTER,
|
||||
AGLOBL,
|
||||
AGOK,
|
||||
AHISTORY,
|
||||
AHLT,
|
||||
AIDIVB,
|
||||
AIDIVL,
|
||||
AIDIVW,
|
||||
AIMULB,
|
||||
AIMULL,
|
||||
AIMULW,
|
||||
AINB,
|
||||
AINL,
|
||||
AINW,
|
||||
AINCB,
|
||||
AINCL,
|
||||
AINCQ,
|
||||
AINCW,
|
||||
AINSB,
|
||||
AINSL,
|
||||
AINSW,
|
||||
AINT,
|
||||
AINTO,
|
||||
AIRETL,
|
||||
AIRETW,
|
||||
AJCC,
|
||||
AJCS,
|
||||
AJCXZ,
|
||||
AJEQ,
|
||||
AJGE,
|
||||
AJGT,
|
||||
AJHI,
|
||||
AJLE,
|
||||
AJLS,
|
||||
AJLT,
|
||||
AJMI,
|
||||
AJMP,
|
||||
AJNE,
|
||||
AJOC,
|
||||
AJOS,
|
||||
AJPC,
|
||||
AJPL,
|
||||
AJPS,
|
||||
ALAHF,
|
||||
ALARL,
|
||||
ALARW,
|
||||
ALEAL,
|
||||
ALEAW,
|
||||
ALEAVEL,
|
||||
ALEAVEW,
|
||||
ALOCK,
|
||||
ALODSB,
|
||||
ALODSL,
|
||||
ALODSW,
|
||||
ALONG,
|
||||
ALOOP,
|
||||
ALOOPEQ,
|
||||
ALOOPNE,
|
||||
ALSLL,
|
||||
ALSLW,
|
||||
AMOVB,
|
||||
AMOVL,
|
||||
AMOVW,
|
||||
AMOVBLSX,
|
||||
AMOVBLZX,
|
||||
AMOVBQSX,
|
||||
AMOVBQZX,
|
||||
AMOVBWSX,
|
||||
AMOVBWZX,
|
||||
AMOVWLSX,
|
||||
AMOVWLZX,
|
||||
AMOVWQSX,
|
||||
AMOVWQZX,
|
||||
AMOVSB,
|
||||
AMOVSL,
|
||||
AMOVSW,
|
||||
AMULB,
|
||||
AMULL,
|
||||
AMULW,
|
||||
ANAME,
|
||||
ANEGB,
|
||||
ANEGL,
|
||||
ANEGW,
|
||||
ANOP,
|
||||
ANOTB,
|
||||
ANOTL,
|
||||
ANOTW,
|
||||
AORB,
|
||||
AORL,
|
||||
AORW,
|
||||
AOUTB,
|
||||
AOUTL,
|
||||
AOUTW,
|
||||
AOUTSB,
|
||||
AOUTSL,
|
||||
AOUTSW,
|
||||
APOPAL,
|
||||
APOPAW,
|
||||
APOPFL,
|
||||
APOPFW,
|
||||
APOPL,
|
||||
APOPW,
|
||||
APUSHAL,
|
||||
APUSHAW,
|
||||
APUSHFL,
|
||||
APUSHFW,
|
||||
APUSHL,
|
||||
APUSHW,
|
||||
ARCLB,
|
||||
ARCLL,
|
||||
ARCLW,
|
||||
ARCRB,
|
||||
ARCRL,
|
||||
ARCRW,
|
||||
AREP,
|
||||
AREPN,
|
||||
ARET,
|
||||
AROLB,
|
||||
AROLL,
|
||||
AROLW,
|
||||
ARORB,
|
||||
ARORL,
|
||||
ARORW,
|
||||
ASAHF,
|
||||
ASALB,
|
||||
ASALL,
|
||||
ASALW,
|
||||
ASARB,
|
||||
ASARL,
|
||||
ASARW,
|
||||
ASBBB,
|
||||
ASBBL,
|
||||
ASBBW,
|
||||
ASCASB,
|
||||
ASCASL,
|
||||
ASCASW,
|
||||
ASETCC,
|
||||
ASETCS,
|
||||
ASETEQ,
|
||||
ASETGE,
|
||||
ASETGT,
|
||||
ASETHI,
|
||||
ASETLE,
|
||||
ASETLS,
|
||||
ASETLT,
|
||||
ASETMI,
|
||||
ASETNE,
|
||||
ASETOC,
|
||||
ASETOS,
|
||||
ASETPC,
|
||||
ASETPL,
|
||||
ASETPS,
|
||||
ACDQ,
|
||||
ACWD,
|
||||
ASHLB,
|
||||
ASHLL,
|
||||
ASHLW,
|
||||
ASHRB,
|
||||
ASHRL,
|
||||
ASHRW,
|
||||
ASTC,
|
||||
ASTD,
|
||||
ASTI,
|
||||
ASTOSB,
|
||||
ASTOSL,
|
||||
ASTOSW,
|
||||
ASUBB,
|
||||
ASUBL,
|
||||
ASUBW,
|
||||
ASYSCALL,
|
||||
ATESTB,
|
||||
ATESTL,
|
||||
ATESTW,
|
||||
ATEXT,
|
||||
AVERR,
|
||||
AVERW,
|
||||
AWAIT,
|
||||
AWORD,
|
||||
AXCHGB,
|
||||
AXCHGL,
|
||||
AXCHGW,
|
||||
AXLAT,
|
||||
AXORB,
|
||||
AXORL,
|
||||
AXORW,
|
||||
|
||||
AFMOVB,
|
||||
AFMOVBP,
|
||||
AFMOVD,
|
||||
AFMOVDP,
|
||||
AFMOVF,
|
||||
AFMOVFP,
|
||||
AFMOVL,
|
||||
AFMOVLP,
|
||||
AFMOVV,
|
||||
AFMOVVP,
|
||||
AFMOVW,
|
||||
AFMOVWP,
|
||||
AFMOVX,
|
||||
AFMOVXP,
|
||||
|
||||
AFCOMB,
|
||||
AFCOMBP,
|
||||
AFCOMD,
|
||||
AFCOMDP,
|
||||
AFCOMDPP,
|
||||
AFCOMF,
|
||||
AFCOMFP,
|
||||
AFCOML,
|
||||
AFCOMLP,
|
||||
AFCOMW,
|
||||
AFCOMWP,
|
||||
AFUCOM,
|
||||
AFUCOMP,
|
||||
AFUCOMPP,
|
||||
|
||||
AFADDDP,
|
||||
AFADDW,
|
||||
AFADDL,
|
||||
AFADDF,
|
||||
AFADDD,
|
||||
|
||||
AFMULDP,
|
||||
AFMULW,
|
||||
AFMULL,
|
||||
AFMULF,
|
||||
AFMULD,
|
||||
|
||||
AFSUBDP,
|
||||
AFSUBW,
|
||||
AFSUBL,
|
||||
AFSUBF,
|
||||
AFSUBD,
|
||||
|
||||
AFSUBRDP,
|
||||
AFSUBRW,
|
||||
AFSUBRL,
|
||||
AFSUBRF,
|
||||
AFSUBRD,
|
||||
|
||||
AFDIVDP,
|
||||
AFDIVW,
|
||||
AFDIVL,
|
||||
AFDIVF,
|
||||
AFDIVD,
|
||||
|
||||
AFDIVRDP,
|
||||
AFDIVRW,
|
||||
AFDIVRL,
|
||||
AFDIVRF,
|
||||
AFDIVRD,
|
||||
|
||||
AFXCHD,
|
||||
AFFREE,
|
||||
|
||||
AFLDCW,
|
||||
AFLDENV,
|
||||
AFRSTOR,
|
||||
AFSAVE,
|
||||
AFSTCW,
|
||||
AFSTENV,
|
||||
AFSTSW,
|
||||
|
||||
AF2XM1,
|
||||
AFABS,
|
||||
AFCHS,
|
||||
AFCLEX,
|
||||
AFCOS,
|
||||
AFDECSTP,
|
||||
AFINCSTP,
|
||||
AFINIT,
|
||||
AFLD1,
|
||||
AFLDL2E,
|
||||
AFLDL2T,
|
||||
AFLDLG2,
|
||||
AFLDLN2,
|
||||
AFLDPI,
|
||||
AFLDZ,
|
||||
AFNOP,
|
||||
AFPATAN,
|
||||
AFPREM,
|
||||
AFPREM1,
|
||||
AFPTAN,
|
||||
AFRNDINT,
|
||||
AFSCALE,
|
||||
AFSIN,
|
||||
AFSINCOS,
|
||||
AFSQRT,
|
||||
AFTST,
|
||||
AFXAM,
|
||||
AFXTRACT,
|
||||
AFYL2X,
|
||||
AFYL2XP1,
|
||||
|
||||
AEND,
|
||||
|
||||
ADYNT,
|
||||
AINIT,
|
||||
|
||||
ASIGNAME,
|
||||
|
||||
/* extra 32-bit operations */
|
||||
ACMPXCHGB,
|
||||
ACMPXCHGL,
|
||||
ACMPXCHGW,
|
||||
ACMPXCHG8B,
|
||||
ACPUID,
|
||||
AINVD,
|
||||
AINVLPG,
|
||||
ALFENCE,
|
||||
AMFENCE,
|
||||
AMOVNTIL,
|
||||
ARDMSR,
|
||||
ARDPMC,
|
||||
ARDTSC,
|
||||
ARSM,
|
||||
ASFENCE,
|
||||
ASYSRET,
|
||||
AWBINVD,
|
||||
AWRMSR,
|
||||
AXADDB,
|
||||
AXADDL,
|
||||
AXADDW,
|
||||
|
||||
/* conditional move */
|
||||
ACMOVLCC,
|
||||
ACMOVLCS,
|
||||
ACMOVLEQ,
|
||||
ACMOVLGE,
|
||||
ACMOVLGT,
|
||||
ACMOVLHI,
|
||||
ACMOVLLE,
|
||||
ACMOVLLS,
|
||||
ACMOVLLT,
|
||||
ACMOVLMI,
|
||||
ACMOVLNE,
|
||||
ACMOVLOC,
|
||||
ACMOVLOS,
|
||||
ACMOVLPC,
|
||||
ACMOVLPL,
|
||||
ACMOVLPS,
|
||||
ACMOVQCC,
|
||||
ACMOVQCS,
|
||||
ACMOVQEQ,
|
||||
ACMOVQGE,
|
||||
ACMOVQGT,
|
||||
ACMOVQHI,
|
||||
ACMOVQLE,
|
||||
ACMOVQLS,
|
||||
ACMOVQLT,
|
||||
ACMOVQMI,
|
||||
ACMOVQNE,
|
||||
ACMOVQOC,
|
||||
ACMOVQOS,
|
||||
ACMOVQPC,
|
||||
ACMOVQPL,
|
||||
ACMOVQPS,
|
||||
ACMOVWCC,
|
||||
ACMOVWCS,
|
||||
ACMOVWEQ,
|
||||
ACMOVWGE,
|
||||
ACMOVWGT,
|
||||
ACMOVWHI,
|
||||
ACMOVWLE,
|
||||
ACMOVWLS,
|
||||
ACMOVWLT,
|
||||
ACMOVWMI,
|
||||
ACMOVWNE,
|
||||
ACMOVWOC,
|
||||
ACMOVWOS,
|
||||
ACMOVWPC,
|
||||
ACMOVWPL,
|
||||
ACMOVWPS,
|
||||
|
||||
/* 64-bit */
|
||||
AADCQ,
|
||||
AADDQ,
|
||||
AANDQ,
|
||||
ABSFQ,
|
||||
ABSRQ,
|
||||
ABTCQ,
|
||||
ABTQ,
|
||||
ABTRQ,
|
||||
ABTSQ,
|
||||
ACMPQ,
|
||||
ACMPSQ,
|
||||
ACMPXCHGQ,
|
||||
ACQO,
|
||||
ADIVQ,
|
||||
AIDIVQ,
|
||||
AIMULQ,
|
||||
AIRETQ,
|
||||
ALEAQ,
|
||||
ALEAVEQ,
|
||||
ALODSQ,
|
||||
AMOVQ,
|
||||
AMOVLQSX,
|
||||
AMOVLQZX,
|
||||
AMOVNTIQ,
|
||||
AMOVSQ,
|
||||
AMULQ,
|
||||
ANEGQ,
|
||||
ANOTQ,
|
||||
AORQ,
|
||||
APOPFQ,
|
||||
APOPQ,
|
||||
APUSHFQ,
|
||||
APUSHQ,
|
||||
ARCLQ,
|
||||
ARCRQ,
|
||||
AROLQ,
|
||||
ARORQ,
|
||||
AQUAD,
|
||||
ASALQ,
|
||||
ASARQ,
|
||||
ASBBQ,
|
||||
ASCASQ,
|
||||
ASHLQ,
|
||||
ASHRQ,
|
||||
ASTOSQ,
|
||||
ASUBQ,
|
||||
ATESTQ,
|
||||
AXADDQ,
|
||||
AXCHGQ,
|
||||
AXORQ,
|
||||
|
||||
/* media */
|
||||
AADDPD,
|
||||
AADDPS,
|
||||
AADDSD,
|
||||
AADDSS,
|
||||
AANDNPD,
|
||||
AANDNPS,
|
||||
AANDPD,
|
||||
AANDPS,
|
||||
ACMPPD,
|
||||
ACMPPS,
|
||||
ACMPSD,
|
||||
ACMPSS,
|
||||
ACOMISD,
|
||||
ACOMISS,
|
||||
ACVTPD2PL,
|
||||
ACVTPD2PS,
|
||||
ACVTPL2PD,
|
||||
ACVTPL2PS,
|
||||
ACVTPS2PD,
|
||||
ACVTPS2PL,
|
||||
ACVTSD2SL,
|
||||
ACVTSD2SQ,
|
||||
ACVTSD2SS,
|
||||
ACVTSL2SD,
|
||||
ACVTSL2SS,
|
||||
ACVTSQ2SD,
|
||||
ACVTSQ2SS,
|
||||
ACVTSS2SD,
|
||||
ACVTSS2SL,
|
||||
ACVTSS2SQ,
|
||||
ACVTTPD2PL,
|
||||
ACVTTPS2PL,
|
||||
ACVTTSD2SL,
|
||||
ACVTTSD2SQ,
|
||||
ACVTTSS2SL,
|
||||
ACVTTSS2SQ,
|
||||
ADIVPD,
|
||||
ADIVPS,
|
||||
ADIVSD,
|
||||
ADIVSS,
|
||||
AEMMS,
|
||||
AFXRSTOR,
|
||||
AFXRSTOR64,
|
||||
AFXSAVE,
|
||||
AFXSAVE64,
|
||||
ALDMXCSR,
|
||||
AMASKMOVOU,
|
||||
AMASKMOVQ,
|
||||
AMAXPD,
|
||||
AMAXPS,
|
||||
AMAXSD,
|
||||
AMAXSS,
|
||||
AMINPD,
|
||||
AMINPS,
|
||||
AMINSD,
|
||||
AMINSS,
|
||||
AMOVAPD,
|
||||
AMOVAPS,
|
||||
AMOVOU,
|
||||
AMOVHLPS,
|
||||
AMOVHPD,
|
||||
AMOVHPS,
|
||||
AMOVLHPS,
|
||||
AMOVLPD,
|
||||
AMOVLPS,
|
||||
AMOVMSKPD,
|
||||
AMOVMSKPS,
|
||||
AMOVNTO,
|
||||
AMOVNTPD,
|
||||
AMOVNTPS,
|
||||
AMOVNTQ,
|
||||
AMOVO,
|
||||
AMOVQOZX,
|
||||
AMOVSD,
|
||||
AMOVSS,
|
||||
AMOVUPD,
|
||||
AMOVUPS,
|
||||
AMULPD,
|
||||
AMULPS,
|
||||
AMULSD,
|
||||
AMULSS,
|
||||
AORPD,
|
||||
AORPS,
|
||||
APACKSSLW,
|
||||
APACKSSWB,
|
||||
APACKUSWB,
|
||||
APADDB,
|
||||
APADDL,
|
||||
APADDQ,
|
||||
APADDSB,
|
||||
APADDSW,
|
||||
APADDUSB,
|
||||
APADDUSW,
|
||||
APADDW,
|
||||
APANDB,
|
||||
APANDL,
|
||||
APANDSB,
|
||||
APANDSW,
|
||||
APANDUSB,
|
||||
APANDUSW,
|
||||
APANDW,
|
||||
APAND,
|
||||
APANDN,
|
||||
APAVGB,
|
||||
APAVGW,
|
||||
APCMPEQB,
|
||||
APCMPEQL,
|
||||
APCMPEQW,
|
||||
APCMPGTB,
|
||||
APCMPGTL,
|
||||
APCMPGTW,
|
||||
APEXTRW,
|
||||
APFACC,
|
||||
APFADD,
|
||||
APFCMPEQ,
|
||||
APFCMPGE,
|
||||
APFCMPGT,
|
||||
APFMAX,
|
||||
APFMIN,
|
||||
APFMUL,
|
||||
APFNACC,
|
||||
APFPNACC,
|
||||
APFRCP,
|
||||
APFRCPIT1,
|
||||
APFRCPI2T,
|
||||
APFRSQIT1,
|
||||
APFRSQRT,
|
||||
APFSUB,
|
||||
APFSUBR,
|
||||
APINSRW,
|
||||
APMADDWL,
|
||||
APMAXSW,
|
||||
APMAXUB,
|
||||
APMINSW,
|
||||
APMINUB,
|
||||
APMOVMSKB,
|
||||
APMULHRW,
|
||||
APMULHUW,
|
||||
APMULHW,
|
||||
APMULLW,
|
||||
APMULULQ,
|
||||
APOR,
|
||||
APSADBW,
|
||||
APSHUFHW,
|
||||
APSHUFL,
|
||||
APSHUFLW,
|
||||
APSHUFW,
|
||||
APSLLO,
|
||||
APSLLL,
|
||||
APSLLQ,
|
||||
APSLLW,
|
||||
APSRAL,
|
||||
APSRAW,
|
||||
APSRLO,
|
||||
APSRLL,
|
||||
APSRLQ,
|
||||
APSRLW,
|
||||
APSUBB,
|
||||
APSUBL,
|
||||
APSUBQ,
|
||||
APSUBSB,
|
||||
APSUBSW,
|
||||
APSUBUSB,
|
||||
APSUBUSW,
|
||||
APSUBW,
|
||||
APSWAPL,
|
||||
APUNPCKHBW,
|
||||
APUNPCKHLQ,
|
||||
APUNPCKHQDQ,
|
||||
APUNPCKHWL,
|
||||
APUNPCKLBW,
|
||||
APUNPCKLLQ,
|
||||
APUNPCKLQDQ,
|
||||
APUNPCKLWL,
|
||||
APXOR,
|
||||
ARCPPS,
|
||||
ARCPSS,
|
||||
ARSQRTPS,
|
||||
ARSQRTSS,
|
||||
ASHUFPD,
|
||||
ASHUFPS,
|
||||
ASQRTPD,
|
||||
ASQRTPS,
|
||||
ASQRTSD,
|
||||
ASQRTSS,
|
||||
ASTMXCSR,
|
||||
ASUBPD,
|
||||
ASUBPS,
|
||||
ASUBSD,
|
||||
ASUBSS,
|
||||
AUCOMISD,
|
||||
AUCOMISS,
|
||||
AUNPCKHPD,
|
||||
AUNPCKHPS,
|
||||
AUNPCKLPD,
|
||||
AUNPCKLPS,
|
||||
AXORPD,
|
||||
AXORPS,
|
||||
|
||||
APF2IW,
|
||||
APF2IL,
|
||||
API2FW,
|
||||
API2FL,
|
||||
ARETFW,
|
||||
ARETFL,
|
||||
ARETFQ,
|
||||
ASWAPGS,
|
||||
|
||||
AMODE,
|
||||
|
||||
ALAST
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
D_AL = 0,
|
||||
D_CL,
|
||||
D_DL,
|
||||
D_BL,
|
||||
D_SPB,
|
||||
D_BPB,
|
||||
D_SIB,
|
||||
D_DIB,
|
||||
D_R8B,
|
||||
D_R9B,
|
||||
D_R10B,
|
||||
D_R11B,
|
||||
D_R12B,
|
||||
D_R13B,
|
||||
D_R14B,
|
||||
D_R15B,
|
||||
|
||||
D_AX = 16,
|
||||
D_CX,
|
||||
D_DX,
|
||||
D_BX,
|
||||
D_SP,
|
||||
D_BP,
|
||||
D_SI,
|
||||
D_DI,
|
||||
D_R8,
|
||||
D_R9,
|
||||
D_R10,
|
||||
D_R11,
|
||||
D_R12,
|
||||
D_R13,
|
||||
D_R14,
|
||||
D_R15,
|
||||
|
||||
D_AH = 32,
|
||||
D_CH,
|
||||
D_DH,
|
||||
D_BH,
|
||||
|
||||
D_F0 = 36,
|
||||
|
||||
D_M0 = 44,
|
||||
|
||||
D_X0 = 52,
|
||||
D_X1,
|
||||
D_X2,
|
||||
D_X3,
|
||||
D_X4,
|
||||
D_X5,
|
||||
D_X6,
|
||||
D_X7,
|
||||
|
||||
D_CS = 68,
|
||||
D_SS,
|
||||
D_DS,
|
||||
D_ES,
|
||||
D_FS,
|
||||
D_GS,
|
||||
|
||||
D_GDTR, /* global descriptor table register */
|
||||
D_IDTR, /* interrupt descriptor table register */
|
||||
D_LDTR, /* local descriptor table register */
|
||||
D_MSW, /* machine status word */
|
||||
D_TASK, /* task register */
|
||||
|
||||
D_CR = 79,
|
||||
D_DR = 95,
|
||||
D_TR = 103,
|
||||
|
||||
D_NONE = 111,
|
||||
|
||||
D_BRANCH = 112,
|
||||
D_EXTERN = 113,
|
||||
D_STATIC = 114,
|
||||
D_AUTO = 115,
|
||||
D_PARAM = 116,
|
||||
D_CONST = 117,
|
||||
D_FCONST = 118,
|
||||
D_SCONST = 119,
|
||||
D_ADDR = 120,
|
||||
|
||||
D_FILE,
|
||||
D_FILE1,
|
||||
|
||||
D_INDIR, /* additive */
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
T_FCONST = 1<<3,
|
||||
T_SYM = 1<<4,
|
||||
T_SCONST = 1<<5,
|
||||
T_64 = 1<<6,
|
||||
|
||||
REGARG = 0,
|
||||
REGRET = D_AX,
|
||||
FREGRET = D_X0,
|
||||
REGSP = D_SP,
|
||||
REGTMP = D_DI,
|
||||
REGEXT = D_R15, /* compiler allocates external registers R15 down */
|
||||
FREGMIN = D_X0+5, /* first register variable */
|
||||
FREGEXT = D_X0+7 /* first external register */
|
||||
};
|
||||
|
||||
/*
|
||||
* this is the ranlib header
|
||||
*/
|
||||
#define SYMDEF "__.SYMDEF"
|
||||
|
||||
/*
|
||||
* this is the simulated IEEE floating point
|
||||
*/
|
||||
typedef struct ieee Ieee;
|
||||
struct ieee
|
||||
{
|
||||
long l; /* contains ls-man 0xffffffff */
|
||||
long h; /* contains sign 0x80000000
|
||||
exp 0x7ff00000
|
||||
ms-man 0x000fffff */
|
||||
};
|
||||
617
src/cmd/6l/asm.c
Normal file
617
src/cmd/6l/asm.c
Normal file
|
|
@ -0,0 +1,617 @@
|
|||
// Inferno utils/6l/asm.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6l/asm.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "l.h"
|
||||
|
||||
#define Dbufslop 100
|
||||
|
||||
#define PADDR(a) ((ulong)(a) & ~0x80000000)
|
||||
|
||||
vlong
|
||||
entryvalue(void)
|
||||
{
|
||||
char *a;
|
||||
Sym *s;
|
||||
|
||||
a = INITENTRY;
|
||||
if(*a >= '0' && *a <= '9')
|
||||
return atolwhex(a);
|
||||
s = lookup(a, 0);
|
||||
if(s->type == 0)
|
||||
return INITTEXT;
|
||||
switch(s->type) {
|
||||
case STEXT:
|
||||
break;
|
||||
case SDATA:
|
||||
if(dlm)
|
||||
return s->value+INITDAT;
|
||||
default:
|
||||
diag("entry not text: %s", s->name);
|
||||
}
|
||||
return s->value;
|
||||
}
|
||||
|
||||
void
|
||||
wputl(ushort w)
|
||||
{
|
||||
cput(w);
|
||||
cput(w>>8);
|
||||
}
|
||||
|
||||
void
|
||||
wput(ushort w)
|
||||
{
|
||||
cput(w>>8);
|
||||
cput(w);
|
||||
}
|
||||
|
||||
void
|
||||
lput(long l)
|
||||
{
|
||||
cput(l>>24);
|
||||
cput(l>>16);
|
||||
cput(l>>8);
|
||||
cput(l);
|
||||
}
|
||||
|
||||
void
|
||||
llput(vlong v)
|
||||
{
|
||||
lput(v>>32);
|
||||
lput(v);
|
||||
}
|
||||
|
||||
void
|
||||
lputl(long l)
|
||||
{
|
||||
cput(l);
|
||||
cput(l>>8);
|
||||
cput(l>>16);
|
||||
cput(l>>24);
|
||||
}
|
||||
|
||||
void
|
||||
strnput(char *s, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<n; i++) {
|
||||
cput(*s);
|
||||
if(*s != 0)
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
asmb(void)
|
||||
{
|
||||
Prog *p;
|
||||
long v, magic, w;
|
||||
int a;
|
||||
uchar *op1;
|
||||
vlong vl, va;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
seek(cout, HEADR, 0);
|
||||
pc = INITTEXT;
|
||||
curp = firstp;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(p->pc != pc) {
|
||||
if(!debug['a'])
|
||||
print("%P\n", curp);
|
||||
diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
|
||||
pc = p->pc;
|
||||
}
|
||||
curp = p;
|
||||
asmins(p);
|
||||
a = (andptr - and);
|
||||
if(cbc < a)
|
||||
cflush();
|
||||
if(debug['a']) {
|
||||
Bprint(&bso, pcstr, pc);
|
||||
for(op1 = and; op1 < andptr; op1++)
|
||||
Bprint(&bso, "%.2ux", *op1);
|
||||
for(; op1 < and+Maxand; op1++)
|
||||
Bprint(&bso, " ");
|
||||
Bprint(&bso, "%P\n", curp);
|
||||
}
|
||||
if(dlm) {
|
||||
if(p->as == ATEXT)
|
||||
reloca = nil;
|
||||
else if(reloca != nil)
|
||||
diag("reloc failure: %P", curp);
|
||||
}
|
||||
memmove(cbp, and, a);
|
||||
cbp += a;
|
||||
pc += a;
|
||||
cbc -= a;
|
||||
}
|
||||
cflush();
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
diag("unknown header type %ld", HEADTYPE);
|
||||
case 2:
|
||||
case 5:
|
||||
seek(cout, HEADR+textsize, 0);
|
||||
break;
|
||||
case 6:
|
||||
v = HEADR+textsize;
|
||||
myseek(cout, v);
|
||||
v = rnd(v, 4096) - v;
|
||||
while(v > 0) {
|
||||
cput(0);
|
||||
v--;
|
||||
}
|
||||
cflush();
|
||||
break;
|
||||
}
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f datblk\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
if(dlm){
|
||||
char buf[8];
|
||||
|
||||
write(cout, buf, INITDAT-textsize);
|
||||
textsize = INITDAT;
|
||||
}
|
||||
|
||||
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
|
||||
if(datsize-v > sizeof(buf)-Dbufslop)
|
||||
datblk(v, sizeof(buf)-Dbufslop);
|
||||
else
|
||||
datblk(v, datsize-v);
|
||||
}
|
||||
|
||||
symsize = 0;
|
||||
spsize = 0;
|
||||
lcsize = 0;
|
||||
if(!debug['s']) {
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f sym\n", cputime());
|
||||
Bflush(&bso);
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
case 2:
|
||||
case 5:
|
||||
seek(cout, HEADR+textsize+datsize, 0);
|
||||
break;
|
||||
case 6:
|
||||
debug['s'] = 1;
|
||||
break;
|
||||
}
|
||||
if(!debug['s'])
|
||||
asmsym();
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f sp\n", cputime());
|
||||
Bflush(&bso);
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f pc\n", cputime());
|
||||
Bflush(&bso);
|
||||
if(!debug['s'])
|
||||
asmlc();
|
||||
if(dlm)
|
||||
asmdyn();
|
||||
cflush();
|
||||
}
|
||||
else if(dlm){
|
||||
seek(cout, HEADR+textsize+datsize, 0);
|
||||
asmdyn();
|
||||
cflush();
|
||||
}
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f headr\n", cputime());
|
||||
Bflush(&bso);
|
||||
seek(cout, 0L, 0);
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
case 2: /* plan9 */
|
||||
magic = 4*26*26+7;
|
||||
magic |= 0x00008000; /* fat header */
|
||||
if(dlm)
|
||||
magic |= 0x80000000; /* dlm */
|
||||
lput(magic); /* magic */
|
||||
lput(textsize); /* sizes */
|
||||
lput(datsize);
|
||||
lput(bsssize);
|
||||
lput(symsize); /* nsyms */
|
||||
vl = entryvalue();
|
||||
lput(PADDR(vl)); /* va of entry */
|
||||
lput(spsize); /* sp offsets */
|
||||
lput(lcsize); /* line offsets */
|
||||
llput(vl); /* va of entry */
|
||||
break;
|
||||
case 3: /* plan9 */
|
||||
magic = 4*26*26+7;
|
||||
if(dlm)
|
||||
magic |= 0x80000000;
|
||||
lput(magic); /* magic */
|
||||
lput(textsize); /* sizes */
|
||||
lput(datsize);
|
||||
lput(bsssize);
|
||||
lput(symsize); /* nsyms */
|
||||
lput(entryvalue()); /* va of entry */
|
||||
lput(spsize); /* sp offsets */
|
||||
lput(lcsize); /* line offsets */
|
||||
break;
|
||||
case 5:
|
||||
strnput("\177ELF", 4); /* e_ident */
|
||||
cput(1); /* class = 32 bit */
|
||||
cput(1); /* data = LSB */
|
||||
cput(1); /* version = CURRENT */
|
||||
strnput("", 9);
|
||||
wputl(2); /* type = EXEC */
|
||||
wputl(62); /* machine = AMD64 */
|
||||
lputl(1L); /* version = CURRENT */
|
||||
lputl(PADDR(entryvalue())); /* entry vaddr */
|
||||
lputl(52L); /* offset to first phdr */
|
||||
lputl(0L); /* offset to first shdr */
|
||||
lputl(0L); /* processor specific flags */
|
||||
wputl(52); /* Ehdr size */
|
||||
wputl(32); /* Phdr size */
|
||||
wputl(3); /* # of Phdrs */
|
||||
wputl(0); /* Shdr size */
|
||||
wputl(0); /* # of Shdrs */
|
||||
wputl(0); /* Shdr string size */
|
||||
|
||||
lputl(1L); /* text - type = PT_LOAD */
|
||||
lputl(HEADR); /* file offset */
|
||||
lputl(INITTEXT); /* vaddr */
|
||||
lputl(PADDR(INITTEXT)); /* paddr */
|
||||
lputl(textsize); /* file size */
|
||||
lputl(textsize); /* memory size */
|
||||
lputl(0x05L); /* protections = RX */
|
||||
lputl(INITRND); /* alignment */
|
||||
|
||||
lputl(1L); /* data - type = PT_LOAD */
|
||||
lputl(HEADR+textsize); /* file offset */
|
||||
lputl(INITDAT); /* vaddr */
|
||||
lputl(PADDR(INITDAT)); /* paddr */
|
||||
lputl(datsize); /* file size */
|
||||
lputl(datsize+bsssize); /* memory size */
|
||||
lputl(0x06L); /* protections = RW */
|
||||
lputl(INITRND); /* alignment */
|
||||
|
||||
lputl(0L); /* data - type = PT_NULL */
|
||||
lputl(HEADR+textsize+datsize); /* file offset */
|
||||
lputl(0L);
|
||||
lputl(0L);
|
||||
lputl(symsize); /* symbol table size */
|
||||
lputl(lcsize); /* line number size */
|
||||
lputl(0x04L); /* protections = R */
|
||||
lputl(0x04L); /* alignment */
|
||||
break;
|
||||
case 6:
|
||||
/* apple MACH */
|
||||
va = 4096;
|
||||
|
||||
lputl(0xfeedfacf); /* 64-bit */
|
||||
lputl((1<<24)|7); /* cputype - x86/ABI64 */
|
||||
lputl(3); /* subtype - x86 */
|
||||
lputl(2); /* file type - mach executable */
|
||||
lputl(4); /* number of loads */
|
||||
lputl(machheadr()-32); /* size of loads */
|
||||
lputl(1); /* flags - no undefines */
|
||||
lputl(0); /* reserved */
|
||||
|
||||
machseg("__PAGEZERO",
|
||||
0,va, /* vaddr vsize */
|
||||
0,0, /* fileoffset filesize */
|
||||
0,0, /* protects */
|
||||
0,0); /* sections flags */
|
||||
|
||||
v = rnd(HEADR+textsize, INITRND);
|
||||
machseg("__TEXT",
|
||||
va, /* vaddr */
|
||||
v, /* vsize */
|
||||
0,v, /* fileoffset filesize */
|
||||
7,5, /* protects */
|
||||
1,0); /* sections flags */
|
||||
machsect("__text", "__TEXT",
|
||||
va+HEADR,v-HEADR, /* addr size */
|
||||
HEADR,0,0,0, /* offset align reloc nreloc */
|
||||
0|0x400); /* flag - some instructions */
|
||||
|
||||
w = datsize+bsssize;
|
||||
machseg("__DATA",
|
||||
va+v, /* vaddr */
|
||||
w, /* vsize */
|
||||
v,datsize, /* fileoffset filesize */
|
||||
7,3, /* protects */
|
||||
2,0); /* sections flags */
|
||||
machsect("__data", "__DATA",
|
||||
va+v,datsize, /* addr size */
|
||||
v,0,0,0, /* offset align reloc nreloc */
|
||||
0); /* flag */
|
||||
machsect("__bss", "__DATA",
|
||||
va+v+datsize,bsssize, /* addr size */
|
||||
0,0,0,0, /* offset align reloc nreloc */
|
||||
1); /* flag - zero fill */
|
||||
machstack(va+HEADR);
|
||||
break;
|
||||
}
|
||||
cflush();
|
||||
}
|
||||
|
||||
void
|
||||
cflush(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = sizeof(buf.cbuf) - cbc;
|
||||
if(n)
|
||||
write(cout, buf.cbuf, n);
|
||||
cbp = buf.cbuf;
|
||||
cbc = sizeof(buf.cbuf);
|
||||
}
|
||||
|
||||
void
|
||||
outa(int n, uchar *cast, uchar *map, vlong l)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
Bprint(&bso, pcstr, l);
|
||||
for(i=0; i<n; i++) {
|
||||
j = i;
|
||||
if(map != nil)
|
||||
j = map[j];
|
||||
Bprint(&bso, "%.2ux", cast[j]);
|
||||
}
|
||||
for(; i<Maxand; i++)
|
||||
Bprint(&bso, " ");
|
||||
Bprint(&bso, "%P\n", curp);
|
||||
}
|
||||
|
||||
void
|
||||
datblk(long s, long n)
|
||||
{
|
||||
Prog *p;
|
||||
uchar *cast;
|
||||
long l, fl, j;
|
||||
vlong o;
|
||||
int i, c;
|
||||
|
||||
memset(buf.dbuf, 0, n+Dbufslop);
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
curp = p;
|
||||
l = p->from.sym->value + p->from.offset - s;
|
||||
c = p->from.scale;
|
||||
i = 0;
|
||||
if(l < 0) {
|
||||
if(l+c <= 0)
|
||||
continue;
|
||||
while(l < 0) {
|
||||
l++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if(l >= n)
|
||||
continue;
|
||||
if(p->as != AINIT && p->as != ADYNT) {
|
||||
for(j=l+(c-i)-1; j>=l; j--)
|
||||
if(buf.dbuf[j]) {
|
||||
print("%P\n", p);
|
||||
diag("multiple initialization");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(p->to.type) {
|
||||
case D_FCONST:
|
||||
switch(c) {
|
||||
default:
|
||||
case 4:
|
||||
fl = ieeedtof(&p->to.ieee);
|
||||
cast = (uchar*)&fl;
|
||||
if(debug['a'] && i == 0)
|
||||
outa(c, cast, fnuxi4, l+s+INITDAT);
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[fnuxi4[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
cast = (uchar*)&p->to.ieee;
|
||||
if(debug['a'] && i == 0)
|
||||
outa(c, cast, fnuxi8, l+s+INITDAT);
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[fnuxi8[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
if(debug['a'] && i == 0)
|
||||
outa(c, (uchar*)p->to.scon, nil, l+s+INITDAT);
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = p->to.scon[i];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
o = p->to.offset;
|
||||
if(p->to.type == D_ADDR) {
|
||||
if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
|
||||
diag("DADDR type%P", p);
|
||||
if(p->to.sym) {
|
||||
if(p->to.sym->type == SUNDEF)
|
||||
ckoff(p->to.sym, o);
|
||||
o += p->to.sym->value;
|
||||
if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
|
||||
o += INITDAT;
|
||||
if(dlm)
|
||||
dynreloc(p->to.sym, l+s+INITDAT, 1);
|
||||
}
|
||||
}
|
||||
fl = o;
|
||||
cast = (uchar*)&fl;
|
||||
switch(c) {
|
||||
default:
|
||||
diag("bad nuxi %d %d\n%P", c, i, curp);
|
||||
break;
|
||||
case 1:
|
||||
if(debug['a'] && i == 0)
|
||||
outa(c, cast, inuxi1, l+s+INITDAT);
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi1[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(debug['a'] && i == 0)
|
||||
outa(c, cast, inuxi2, l+s+INITDAT);
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi2[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(debug['a'] && i == 0)
|
||||
outa(c, cast, inuxi4, l+s+INITDAT);
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi4[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
cast = (uchar*)&o;
|
||||
if(debug['a'] && i == 0)
|
||||
outa(c, cast, inuxi8, l+s+INITDAT);
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi8[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
write(cout, buf.dbuf, n);
|
||||
}
|
||||
|
||||
vlong
|
||||
rnd(vlong v, vlong r)
|
||||
{
|
||||
vlong c;
|
||||
|
||||
if(r <= 0)
|
||||
return v;
|
||||
v += r - 1;
|
||||
c = v % r;
|
||||
if(c < 0)
|
||||
c += r;
|
||||
v -= c;
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
vputl(vlong v)
|
||||
{
|
||||
lputl(v);
|
||||
lputl(v>>32);
|
||||
}
|
||||
|
||||
void
|
||||
machseg(char *name, vlong vaddr, vlong vsize, vlong foff, vlong fsize,
|
||||
ulong prot1, ulong prot2, ulong nsect, ulong flag)
|
||||
{
|
||||
lputl(25); // section
|
||||
lputl(72 + 80*nsect);
|
||||
strnput(name, 16);
|
||||
vputl(vaddr);
|
||||
vputl(vsize);
|
||||
vputl(foff);
|
||||
vputl(fsize);
|
||||
lputl(prot1);
|
||||
lputl(prot2);
|
||||
lputl(nsect);
|
||||
lputl(flag);
|
||||
}
|
||||
|
||||
void
|
||||
machsect(char *name, char *seg, vlong addr, vlong size, ulong off,
|
||||
ulong align, ulong reloc, ulong nreloc, ulong flag)
|
||||
{
|
||||
strnput(name, 16);
|
||||
strnput(seg, 16);
|
||||
vputl(addr);
|
||||
vputl(size);
|
||||
lputl(off);
|
||||
lputl(align);
|
||||
lputl(reloc);
|
||||
lputl(nreloc);
|
||||
lputl(flag);
|
||||
lputl(0); /* reserved */
|
||||
lputl(0); /* reserved */
|
||||
lputl(0); /* reserved */
|
||||
}
|
||||
|
||||
void
|
||||
machstack(vlong e)
|
||||
{
|
||||
int i;
|
||||
|
||||
lputl(5); /* unix thread */
|
||||
lputl((42+4)*4); /* total byte count */
|
||||
|
||||
lputl(4); /* thread type */
|
||||
lputl(42); /* word count */
|
||||
|
||||
for(i=0; i<32; i++)
|
||||
lputl(0);
|
||||
vputl(e);
|
||||
for(i=0; i<8; i++)
|
||||
lputl(0);
|
||||
}
|
||||
|
||||
ulong
|
||||
machheadr(void)
|
||||
{
|
||||
ulong a;
|
||||
|
||||
a = 8; /* a.out header */
|
||||
a += 18; /* page zero seg */
|
||||
a += 18; /* text seg */
|
||||
a += 20; /* text sect */
|
||||
a += 18; /* data seg */
|
||||
a += 20; /* data sect */
|
||||
a += 20; /* bss sect */
|
||||
a += 46; /* stack sect */
|
||||
|
||||
return a*4;
|
||||
}
|
||||
430
src/cmd/6l/l.h
Normal file
430
src/cmd/6l/l.h
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
// Inferno utils/6l/l.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "../6l/6.out.h"
|
||||
#include "compat.h"
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define P ((Prog*)0)
|
||||
#define S ((Sym*)0)
|
||||
#define TNAME (curtext?curtext->from.sym->name:noname)
|
||||
#define cput(c)\
|
||||
{ *cbp++ = c;\
|
||||
if(--cbc <= 0)\
|
||||
cflush(); }
|
||||
|
||||
typedef struct Adr Adr;
|
||||
typedef struct Prog Prog;
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Auto Auto;
|
||||
typedef struct Optab Optab;
|
||||
typedef struct Movtab Movtab;
|
||||
|
||||
struct Adr
|
||||
{
|
||||
union
|
||||
{
|
||||
vlong u0offset;
|
||||
char u0scon[8];
|
||||
Prog *u0cond; /* not used, but should be D_BRANCH */
|
||||
Ieee u0ieee;
|
||||
} u0;
|
||||
union
|
||||
{
|
||||
Auto* u1autom;
|
||||
Sym* u1sym;
|
||||
} u1;
|
||||
short type;
|
||||
char index;
|
||||
char scale;
|
||||
};
|
||||
|
||||
#define offset u0.u0offset
|
||||
#define scon u0.u0scon
|
||||
#define cond u0.u0cond
|
||||
#define ieee u0.u0ieee
|
||||
|
||||
#define autom u1.u1autom
|
||||
#define sym u1.u1sym
|
||||
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
Adr to;
|
||||
Prog *forwd;
|
||||
Prog* link;
|
||||
Prog* pcond; /* work on this */
|
||||
vlong pc;
|
||||
long line;
|
||||
uchar mark; /* work on these */
|
||||
uchar back;
|
||||
|
||||
short as;
|
||||
char width; /* fake for DATA */
|
||||
char mode; /* 16, 32, or 64 */
|
||||
};
|
||||
struct Auto
|
||||
{
|
||||
Sym* asym;
|
||||
Auto* link;
|
||||
long aoffset;
|
||||
short type;
|
||||
};
|
||||
struct Sym
|
||||
{
|
||||
char *name;
|
||||
short type;
|
||||
short version;
|
||||
short become;
|
||||
short frame;
|
||||
uchar subtype;
|
||||
ushort file;
|
||||
vlong value;
|
||||
long sig;
|
||||
Sym* link;
|
||||
};
|
||||
struct Optab
|
||||
{
|
||||
short as;
|
||||
uchar* ytab;
|
||||
uchar prefix;
|
||||
uchar op[20];
|
||||
};
|
||||
struct Movtab
|
||||
{
|
||||
short as;
|
||||
uchar ft;
|
||||
uchar tt;
|
||||
uchar code;
|
||||
uchar op[4];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
STEXT = 1,
|
||||
SDATA,
|
||||
SBSS,
|
||||
SDATA1,
|
||||
SXREF,
|
||||
SFILE,
|
||||
SCONST,
|
||||
SUNDEF,
|
||||
|
||||
SIMPORT,
|
||||
SEXPORT,
|
||||
|
||||
NHASH = 10007,
|
||||
NHUNK = 100000,
|
||||
MINSIZ = 8,
|
||||
STRINGSZ = 200,
|
||||
MINLC = 1,
|
||||
MAXIO = 8192,
|
||||
MAXHIST = 20, /* limit of path elements for history symbols */
|
||||
|
||||
Yxxx = 0,
|
||||
Ynone,
|
||||
Yi0,
|
||||
Yi1,
|
||||
Yi8,
|
||||
Ys32,
|
||||
Yi32,
|
||||
Yi64,
|
||||
Yiauto,
|
||||
Yal,
|
||||
Ycl,
|
||||
Yax,
|
||||
Ycx,
|
||||
Yrb,
|
||||
Yrl,
|
||||
Yrf,
|
||||
Yf0,
|
||||
Yrx,
|
||||
Ymb,
|
||||
Yml,
|
||||
Ym,
|
||||
Ybr,
|
||||
Ycol,
|
||||
|
||||
Ycs, Yss, Yds, Yes, Yfs, Ygs,
|
||||
Ygdtr, Yidtr, Yldtr, Ymsw, Ytask,
|
||||
Ycr0, Ycr1, Ycr2, Ycr3, Ycr4, Ycr5, Ycr6, Ycr7, Ycr8,
|
||||
Ydr0, Ydr1, Ydr2, Ydr3, Ydr4, Ydr5, Ydr6, Ydr7,
|
||||
Ytr0, Ytr1, Ytr2, Ytr3, Ytr4, Ytr5, Ytr6, Ytr7, Yrl32, Yrl64,
|
||||
Ymr, Ymm,
|
||||
Yxr, Yxm,
|
||||
Ymax,
|
||||
|
||||
Zxxx = 0,
|
||||
|
||||
Zlit,
|
||||
Z_rp,
|
||||
Zbr,
|
||||
Zcall,
|
||||
Zib_,
|
||||
Zib_rp,
|
||||
Zibo_m,
|
||||
Zibo_m_xm,
|
||||
Zil_,
|
||||
Zil_rp,
|
||||
Ziq_rp,
|
||||
Zilo_m,
|
||||
Ziqo_m,
|
||||
Zjmp,
|
||||
Zloop,
|
||||
Zo_iw,
|
||||
Zm_o,
|
||||
Zm_r,
|
||||
Zm_r_xm,
|
||||
Zm_r_i_xm,
|
||||
Zm_r_3d,
|
||||
Zm_r_xm_nr,
|
||||
Zr_m_xm_nr,
|
||||
Zibm_r, /* mmx1,mmx2/mem64,imm8 */
|
||||
Zmb_r,
|
||||
Zaut_r,
|
||||
Zo_m,
|
||||
Zo_m64,
|
||||
Zpseudo,
|
||||
Zr_m,
|
||||
Zr_m_xm,
|
||||
Zr_m_i_xm,
|
||||
Zrp_,
|
||||
Z_ib,
|
||||
Z_il,
|
||||
Zm_ibo,
|
||||
Zm_ilo,
|
||||
Zib_rr,
|
||||
Zil_rr,
|
||||
Zclr,
|
||||
Zbyte,
|
||||
Zmax,
|
||||
|
||||
Px = 0,
|
||||
P32 = 0x32, /* 32-bit only */
|
||||
Pe = 0x66, /* operand escape */
|
||||
Pm = 0x0f, /* 2byte opcode escape */
|
||||
Pq = 0xff, /* both escape */
|
||||
Pb = 0xfe, /* byte operands */
|
||||
Pf2 = 0xf2, /* xmm escape 1 */
|
||||
Pf3 = 0xf3, /* xmm escape 2 */
|
||||
Pw = 0x48, /* Rex.w */
|
||||
Py = 0x80, /* defaults to 64-bit mode */
|
||||
|
||||
Rxf = 1<<9, /* internal flag for Rxr on from */
|
||||
Rxt = 1<<8, /* internal flag for Rxr on to */
|
||||
Rxw = 1<<3, /* =1, 64-bit operand size */
|
||||
Rxr = 1<<2, /* extend modrm reg */
|
||||
Rxx = 1<<1, /* extend sib index */
|
||||
Rxb = 1<<0, /* extend modrm r/m, sib base, or opcode reg */
|
||||
|
||||
Roffset = 22, /* no. bits for offset in relocation address */
|
||||
Rindex = 10, /* no. bits for index in relocation address */
|
||||
Maxand = 10, /* in -a output width of the byte codes */
|
||||
};
|
||||
|
||||
EXTERN union
|
||||
{
|
||||
struct
|
||||
{
|
||||
char obuf[MAXIO]; /* output buffer */
|
||||
uchar ibuf[MAXIO]; /* input buffer */
|
||||
} u;
|
||||
char dbuf[1];
|
||||
} buf;
|
||||
|
||||
#define cbuf u.obuf
|
||||
#define xbuf u.ibuf
|
||||
|
||||
#pragma varargck type "A" uint
|
||||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
#pragma varargck type "S" char*
|
||||
|
||||
EXTERN long HEADR;
|
||||
EXTERN long HEADTYPE;
|
||||
EXTERN vlong INITDAT;
|
||||
EXTERN long INITRND;
|
||||
EXTERN vlong INITTEXT;
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN Biobuf bso;
|
||||
EXTERN long bsssize;
|
||||
EXTERN int cbc;
|
||||
EXTERN char* cbp;
|
||||
EXTERN char* pcstr;
|
||||
EXTERN int cout;
|
||||
EXTERN Auto* curauto;
|
||||
EXTERN Auto* curhist;
|
||||
EXTERN Prog* curp;
|
||||
EXTERN Prog* curtext;
|
||||
EXTERN Prog* datap;
|
||||
EXTERN Prog* edatap;
|
||||
EXTERN vlong datsize;
|
||||
EXTERN char debug[128];
|
||||
EXTERN char literal[32];
|
||||
EXTERN Prog* etextp;
|
||||
EXTERN Prog* firstp;
|
||||
EXTERN uchar fnuxi8[8];
|
||||
EXTERN uchar fnuxi4[4];
|
||||
EXTERN Sym* hash[NHASH];
|
||||
EXTERN Sym* histfrog[MAXHIST];
|
||||
EXTERN int histfrogp;
|
||||
EXTERN int histgen;
|
||||
EXTERN char* library[50];
|
||||
EXTERN char* libraryobj[50];
|
||||
EXTERN int libraryp;
|
||||
EXTERN int xrefresolv;
|
||||
EXTERN char* hunk;
|
||||
EXTERN uchar inuxi1[1];
|
||||
EXTERN uchar inuxi2[2];
|
||||
EXTERN uchar inuxi4[4];
|
||||
EXTERN uchar inuxi8[8];
|
||||
EXTERN char ycover[Ymax*Ymax];
|
||||
EXTERN uchar* andptr;
|
||||
EXTERN uchar* rexptr;
|
||||
EXTERN uchar and[30];
|
||||
EXTERN int reg[D_NONE];
|
||||
EXTERN int regrex[D_NONE+1];
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN long lcsize;
|
||||
EXTERN int nerrors;
|
||||
EXTERN long nhunk;
|
||||
EXTERN long nsymbol;
|
||||
EXTERN char* noname;
|
||||
EXTERN char* outfile;
|
||||
EXTERN vlong pc;
|
||||
EXTERN long spsize;
|
||||
EXTERN Sym* symlist;
|
||||
EXTERN long symsize;
|
||||
EXTERN Prog* textp;
|
||||
EXTERN vlong textsize;
|
||||
EXTERN long thunk;
|
||||
EXTERN int version;
|
||||
EXTERN Prog zprg;
|
||||
EXTERN int dtype;
|
||||
EXTERN char* paramspace;
|
||||
|
||||
EXTERN Adr* reloca;
|
||||
EXTERN int doexp, dlm;
|
||||
EXTERN int imports, nimports;
|
||||
EXTERN int exports, nexports;
|
||||
EXTERN char* EXPTAB;
|
||||
EXTERN Prog undefp;
|
||||
|
||||
#define UP (&undefp)
|
||||
|
||||
extern Optab optab[];
|
||||
extern Optab* opindex[];
|
||||
extern char* anames[];
|
||||
|
||||
int Aconv(Fmt*);
|
||||
int Dconv(Fmt*);
|
||||
int Pconv(Fmt*);
|
||||
int Rconv(Fmt*);
|
||||
int Sconv(Fmt*);
|
||||
void addhist(long, int);
|
||||
Prog* appendp(Prog*);
|
||||
void asmb(void);
|
||||
void asmdyn(void);
|
||||
void asmins(Prog*);
|
||||
void asmlc(void);
|
||||
void asmsp(void);
|
||||
void asmsym(void);
|
||||
vlong atolwhex(char*);
|
||||
Prog* brchain(Prog*);
|
||||
Prog* brloop(Prog*);
|
||||
void buildop(void);
|
||||
void cflush(void);
|
||||
void ckoff(Sym*, long);
|
||||
Prog* copyp(Prog*);
|
||||
double cputime(void);
|
||||
void datblk(long, long);
|
||||
void diag(char*, ...);
|
||||
void dodata(void);
|
||||
void doinit(void);
|
||||
void doprof1(void);
|
||||
void doprof2(void);
|
||||
void dostkoff(void);
|
||||
void dynreloc(Sym*, ulong, int);
|
||||
vlong entryvalue(void);
|
||||
void errorexit(void);
|
||||
void export(void);
|
||||
int find1(long, int);
|
||||
int find2(long, int);
|
||||
void follow(void);
|
||||
void gethunk(void);
|
||||
void histtoauto(void);
|
||||
double ieeedtod(Ieee*);
|
||||
long ieeedtof(Ieee*);
|
||||
void import(void);
|
||||
void ldobj(int, long, char*);
|
||||
void loadlib(void);
|
||||
void listinit(void);
|
||||
Sym* lookup(char*, int);
|
||||
void lput(long);
|
||||
void lputl(long);
|
||||
void main(int, char*[]);
|
||||
void mkfwd(void);
|
||||
void* mysbrk(ulong);
|
||||
void nuxiinit(void);
|
||||
void objfile(char*);
|
||||
int opsize(Prog*);
|
||||
void patch(void);
|
||||
Prog* prg(void);
|
||||
void readundefs(char*, int);
|
||||
int relinv(int);
|
||||
long reuse(Prog*, Sym*);
|
||||
vlong rnd(vlong, vlong);
|
||||
void span(void);
|
||||
void undef(void);
|
||||
void undefsym(Sym*);
|
||||
vlong vaddr(Adr*);
|
||||
void wput(ushort);
|
||||
void xdefine(char*, int, vlong);
|
||||
void xfol(Prog*);
|
||||
int zaddr(uchar*, Adr*, Sym*[]);
|
||||
void zerosig(char*);
|
||||
|
||||
void machseg(char*, vlong, vlong, vlong, vlong, ulong, ulong, ulong, ulong);
|
||||
void machsect(char*, char*, vlong, vlong, ulong, ulong, ulong, ulong, ulong);
|
||||
void machstack(vlong);
|
||||
ulong machheadr(void);
|
||||
|
||||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck argpos diag 1
|
||||
397
src/cmd/6l/list.c
Normal file
397
src/cmd/6l/list.c
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
// Inferno utils/6l/list.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6l/list.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "l.h"
|
||||
|
||||
static Prog* bigP;
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
|
||||
fmtinstall('R', Rconv);
|
||||
fmtinstall('A', Aconv);
|
||||
fmtinstall('D', Dconv);
|
||||
fmtinstall('S', Sconv);
|
||||
fmtinstall('P', Pconv);
|
||||
}
|
||||
|
||||
int
|
||||
Pconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ], str1[STRINGSZ];
|
||||
Prog *p;
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
bigP = p;
|
||||
|
||||
sprint(str1, "(%ld)", p->line);
|
||||
switch(p->as) {
|
||||
case ATEXT:
|
||||
if(p->from.scale) {
|
||||
sprint(str, "%-7s %-7A %D,%d,%D",
|
||||
str1, p->as, &p->from, p->from.scale, &p->to);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
sprint(str, "%-7s %-7A %D,%D",
|
||||
str1, p->as, &p->from, &p->to);
|
||||
break;
|
||||
|
||||
case ADATA:
|
||||
case AINIT:
|
||||
case ADYNT:
|
||||
sprint(str, "%-7s %-7A %D/%d,%D",
|
||||
str1, p->as, &p->from, p->from.scale, &p->to);
|
||||
break;
|
||||
}
|
||||
bigP = P;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Aconv(Fmt *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = va_arg(fp->args, int);
|
||||
return fmtstrcpy(fp, anames[i]);
|
||||
}
|
||||
|
||||
int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[40], s[20];
|
||||
Adr *a;
|
||||
int i;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
i = a->type;
|
||||
if(i >= D_INDIR) {
|
||||
if(a->offset)
|
||||
sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
|
||||
else
|
||||
sprint(str, "(%R)", i-D_INDIR);
|
||||
goto brk;
|
||||
}
|
||||
switch(i) {
|
||||
|
||||
default:
|
||||
if(a->offset)
|
||||
sprint(str, "$%lld,%R", a->offset, i);
|
||||
else
|
||||
sprint(str, "%R", i);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
str[0] = 0;
|
||||
break;
|
||||
|
||||
case D_BRANCH:
|
||||
if(bigP != P && bigP->pcond != P)
|
||||
if(a->sym != S)
|
||||
sprint(str, "%llux+%s", bigP->pcond->pc,
|
||||
a->sym->name);
|
||||
else
|
||||
sprint(str, "%llux", bigP->pcond->pc);
|
||||
else
|
||||
sprint(str, "%lld(PC)", a->offset);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
if(a->sym) {
|
||||
sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
|
||||
break;
|
||||
}
|
||||
sprint(str, "!!noname!!+%lld(SB)", a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
if(a->sym) {
|
||||
sprint(str, "%s<%d>+%lld(SB)", a->sym->name,
|
||||
a->sym->version, a->offset);
|
||||
break;
|
||||
}
|
||||
sprint(str, "!!noname!!<999>+%lld(SB)", a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
if(a->sym) {
|
||||
sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
|
||||
break;
|
||||
}
|
||||
sprint(str, "!!noname!!+%lld(SP)", a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
if(a->sym) {
|
||||
sprint(str, "%s+%lld(%s)", a->sym->name, a->offset, paramspace);
|
||||
break;
|
||||
}
|
||||
sprint(str, "!!noname!!+%lld(%s)", a->offset, paramspace);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
sprint(str, "$%lld", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
sprint(str, "$(%.8lux,%.8lux)", a->ieee.h, a->ieee.l);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
sprint(str, "$\"%S\"", a->scon);
|
||||
break;
|
||||
|
||||
case D_ADDR:
|
||||
a->type = a->index;
|
||||
a->index = D_NONE;
|
||||
sprint(str, "$%D", a);
|
||||
a->index = a->type;
|
||||
a->type = D_ADDR;
|
||||
goto conv;
|
||||
}
|
||||
brk:
|
||||
if(a->index != D_NONE) {
|
||||
sprint(s, "(%R*%d)", a->index, a->scale);
|
||||
strcat(str, s);
|
||||
}
|
||||
conv:
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
char* regstr[] =
|
||||
{
|
||||
"AL", /* [D_AL] */
|
||||
"CL",
|
||||
"DL",
|
||||
"BL",
|
||||
"SPB",
|
||||
"BPB",
|
||||
"SIB",
|
||||
"DIB",
|
||||
"R8B",
|
||||
"R9B",
|
||||
"R10B",
|
||||
"R11B",
|
||||
"R12B",
|
||||
"R13B",
|
||||
"R14B",
|
||||
"R15B",
|
||||
|
||||
"AX", /* [D_AX] */
|
||||
"CX",
|
||||
"DX",
|
||||
"BX",
|
||||
"SP",
|
||||
"BP",
|
||||
"SI",
|
||||
"DI",
|
||||
"R8",
|
||||
"R9",
|
||||
"R10",
|
||||
"R11",
|
||||
"R12",
|
||||
"R13",
|
||||
"R14",
|
||||
"R15",
|
||||
|
||||
"AH",
|
||||
"CH",
|
||||
"DH",
|
||||
"BH",
|
||||
|
||||
"F0", /* [D_F0] */
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
|
||||
"M0",
|
||||
"M1",
|
||||
"M2",
|
||||
"M3",
|
||||
"M4",
|
||||
"M5",
|
||||
"M6",
|
||||
"M7",
|
||||
|
||||
"X0",
|
||||
"X1",
|
||||
"X2",
|
||||
"X3",
|
||||
"X4",
|
||||
"X5",
|
||||
"X6",
|
||||
"X7",
|
||||
"X8",
|
||||
"X9",
|
||||
"X10",
|
||||
"X11",
|
||||
"X12",
|
||||
"X13",
|
||||
"X14",
|
||||
"X15",
|
||||
|
||||
"CS", /* [D_CS] */
|
||||
"SS",
|
||||
"DS",
|
||||
"ES",
|
||||
"FS",
|
||||
"GS",
|
||||
|
||||
"GDTR", /* [D_GDTR] */
|
||||
"IDTR", /* [D_IDTR] */
|
||||
"LDTR", /* [D_LDTR] */
|
||||
"MSW", /* [D_MSW] */
|
||||
"TASK", /* [D_TASK] */
|
||||
|
||||
"CR0", /* [D_CR] */
|
||||
"CR1",
|
||||
"CR2",
|
||||
"CR3",
|
||||
"CR4",
|
||||
"CR5",
|
||||
"CR6",
|
||||
"CR7",
|
||||
"CR8",
|
||||
"CR9",
|
||||
"CR10",
|
||||
"CR11",
|
||||
"CR12",
|
||||
"CR13",
|
||||
"CR14",
|
||||
"CR15",
|
||||
|
||||
"DR0", /* [D_DR] */
|
||||
"DR1",
|
||||
"DR2",
|
||||
"DR3",
|
||||
"DR4",
|
||||
"DR5",
|
||||
"DR6",
|
||||
"DR7",
|
||||
|
||||
"TR0", /* [D_TR] */
|
||||
"TR1",
|
||||
"TR2",
|
||||
"TR3",
|
||||
"TR4",
|
||||
"TR5",
|
||||
"TR6",
|
||||
"TR7",
|
||||
|
||||
"NONE", /* [D_NONE] */
|
||||
};
|
||||
|
||||
int
|
||||
Rconv(Fmt *fp)
|
||||
{
|
||||
char str[20];
|
||||
int r;
|
||||
|
||||
r = va_arg(fp->args, int);
|
||||
if(r >= D_AL && r <= D_NONE)
|
||||
sprint(str, "%s", regstr[r-D_AL]);
|
||||
else
|
||||
sprint(str, "gok(%d)", r);
|
||||
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Sconv(Fmt *fp)
|
||||
{
|
||||
int i, c;
|
||||
char str[30], *p, *a;
|
||||
|
||||
a = va_arg(fp->args, char*);
|
||||
p = str;
|
||||
for(i=0; i<sizeof(double); i++) {
|
||||
c = a[i] & 0xff;
|
||||
if(c >= 'a' && c <= 'z' ||
|
||||
c >= 'A' && c <= 'Z' ||
|
||||
c >= '0' && c <= '9') {
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
*p++ = '\\';
|
||||
switch(c) {
|
||||
default:
|
||||
if(c < 040 || c >= 0177)
|
||||
break; /* not portable */
|
||||
p[-1] = c;
|
||||
continue;
|
||||
case 0:
|
||||
*p++ = 'z';
|
||||
continue;
|
||||
case '\\':
|
||||
case '"':
|
||||
*p++ = c;
|
||||
continue;
|
||||
case '\n':
|
||||
*p++ = 'n';
|
||||
continue;
|
||||
case '\t':
|
||||
*p++ = 't';
|
||||
continue;
|
||||
}
|
||||
*p++ = (c>>6) + '0';
|
||||
*p++ = ((c>>3) & 7) + '0';
|
||||
*p++ = (c & 7) + '0';
|
||||
}
|
||||
*p = 0;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
void
|
||||
diag(char *fmt, ...)
|
||||
{
|
||||
char buf[STRINGSZ], *tn;
|
||||
va_list arg;
|
||||
|
||||
tn = "??none??";
|
||||
if(curtext != P && curtext->from.sym != S)
|
||||
tn = curtext->from.sym->name;
|
||||
va_start(arg, fmt);
|
||||
vseprint(buf, buf+sizeof(buf), fmt, arg);
|
||||
va_end(arg);
|
||||
print("%s: %s\n", tn, buf);
|
||||
|
||||
nerrors++;
|
||||
if(nerrors > 20) {
|
||||
print("too many errors\n");
|
||||
errorexit();
|
||||
}
|
||||
}
|
||||
45
src/cmd/6l/mkenam
Normal file
45
src/cmd/6l/mkenam
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Inferno utils/6c/mkenam
|
||||
# http://code.google.com/p/inferno-os/source/browse/utils/6c/mkenam
|
||||
#
|
||||
# Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
# Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
# Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
# Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
# Portions Copyright © 2004,2006 Bruce Ellis
|
||||
# Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
# Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
# Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
ed - ../6l/6.out.h <<'!'
|
||||
v/^ A/d
|
||||
,s/^ A/ "/
|
||||
g/ .*$/s///
|
||||
,s/,*$/",/
|
||||
1i
|
||||
char* anames[] =
|
||||
{
|
||||
.
|
||||
$a
|
||||
};
|
||||
.
|
||||
w enam.c
|
||||
Q
|
||||
!
|
||||
1595
src/cmd/6l/obj.c
Normal file
1595
src/cmd/6l/obj.c
Normal file
File diff suppressed because it is too large
Load diff
1213
src/cmd/6l/optab.c
Normal file
1213
src/cmd/6l/optab.c
Normal file
File diff suppressed because it is too large
Load diff
820
src/cmd/6l/pass.c
Normal file
820
src/cmd/6l/pass.c
Normal file
|
|
@ -0,0 +1,820 @@
|
|||
// Inferno utils/6l/pass.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "l.h"
|
||||
|
||||
void
|
||||
dodata(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
Prog *p;
|
||||
long t, u;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f dodata\n", cputime());
|
||||
Bflush(&bso);
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
s = p->from.sym;
|
||||
if(p->as == ADYNT || p->as == AINIT)
|
||||
s->value = dtype;
|
||||
if(s->type == SBSS)
|
||||
s->type = SDATA;
|
||||
if(s->type != SDATA)
|
||||
diag("initialize non-data (%d): %s\n%P",
|
||||
s->type, s->name, p);
|
||||
t = p->from.offset + p->width;
|
||||
if(t > s->value)
|
||||
diag("initialize bounds (%lld): %s\n%P",
|
||||
s->value, s->name, p);
|
||||
}
|
||||
/* allocate small guys */
|
||||
datsize = 0;
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SDATA)
|
||||
if(s->type != SBSS)
|
||||
continue;
|
||||
t = s->value;
|
||||
if(t == 0) {
|
||||
diag("%s: no size", s->name);
|
||||
t = 1;
|
||||
}
|
||||
t = rnd(t, 4);
|
||||
s->value = t;
|
||||
if(t > MINSIZ)
|
||||
continue;
|
||||
if(t >= 8)
|
||||
datsize = rnd(datsize, 8);
|
||||
s->value = datsize;
|
||||
datsize += t;
|
||||
s->type = SDATA1;
|
||||
}
|
||||
|
||||
/* allocate the rest of the data */
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SDATA) {
|
||||
if(s->type == SDATA1)
|
||||
s->type = SDATA;
|
||||
continue;
|
||||
}
|
||||
t = s->value;
|
||||
if(t >= 8)
|
||||
datsize = rnd(datsize, 8);
|
||||
s->value = datsize;
|
||||
datsize += t;
|
||||
}
|
||||
if(datsize)
|
||||
datsize = rnd(datsize, 8);
|
||||
|
||||
if(debug['j']) {
|
||||
/*
|
||||
* pad data with bss that fits up to next
|
||||
* 8k boundary, then push data to 8k
|
||||
*/
|
||||
u = rnd(datsize, 8192);
|
||||
u -= datsize;
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SBSS)
|
||||
continue;
|
||||
t = s->value;
|
||||
if(t > u)
|
||||
continue;
|
||||
u -= t;
|
||||
s->value = datsize;
|
||||
s->type = SDATA;
|
||||
datsize += t;
|
||||
}
|
||||
datsize += u;
|
||||
}
|
||||
|
||||
/* now the bss */
|
||||
bsssize = 0;
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SBSS)
|
||||
continue;
|
||||
t = s->value;
|
||||
if(t >= 8)
|
||||
bsssize = rnd(bsssize, 8);
|
||||
s->value = bsssize + datsize;
|
||||
bsssize += t;
|
||||
}
|
||||
xdefine("edata", SBSS, datsize);
|
||||
xdefine("end", SBSS, bsssize + datsize);
|
||||
}
|
||||
|
||||
Prog*
|
||||
brchain(Prog *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<20; i++) {
|
||||
if(p == P || p->as != AJMP)
|
||||
return p;
|
||||
p = p->pcond;
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
void
|
||||
follow(void)
|
||||
{
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f follow\n", cputime());
|
||||
Bflush(&bso);
|
||||
firstp = prg();
|
||||
lastp = firstp;
|
||||
xfol(textp);
|
||||
lastp->link = P;
|
||||
firstp = firstp->link;
|
||||
}
|
||||
|
||||
void
|
||||
xfol(Prog *p)
|
||||
{
|
||||
Prog *q;
|
||||
int i;
|
||||
enum as a;
|
||||
|
||||
loop:
|
||||
if(p == P)
|
||||
return;
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(p->as == AJMP)
|
||||
if((q = p->pcond) != P) {
|
||||
p->mark = 1;
|
||||
p = q;
|
||||
if(p->mark == 0)
|
||||
goto loop;
|
||||
}
|
||||
if(p->mark) {
|
||||
/* copy up to 4 instructions to avoid branch */
|
||||
for(i=0,q=p; i<4; i++,q=q->link) {
|
||||
if(q == P)
|
||||
break;
|
||||
if(q == lastp)
|
||||
break;
|
||||
a = q->as;
|
||||
if(a == ANOP) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
switch(a) {
|
||||
case AJMP:
|
||||
case ARET:
|
||||
case AIRETL:
|
||||
case AIRETQ:
|
||||
case AIRETW:
|
||||
case ARETFL:
|
||||
case ARETFQ:
|
||||
case ARETFW:
|
||||
|
||||
case APUSHL:
|
||||
case APUSHFL:
|
||||
case APUSHQ:
|
||||
case APUSHFQ:
|
||||
case APUSHW:
|
||||
case APUSHFW:
|
||||
case APOPL:
|
||||
case APOPFL:
|
||||
case APOPQ:
|
||||
case APOPFQ:
|
||||
case APOPW:
|
||||
case APOPFW:
|
||||
goto brk;
|
||||
}
|
||||
if(q->pcond == P || q->pcond->mark)
|
||||
continue;
|
||||
if(a == ACALL || a == ALOOP)
|
||||
continue;
|
||||
for(;;) {
|
||||
if(p->as == ANOP) {
|
||||
p = p->link;
|
||||
continue;
|
||||
}
|
||||
q = copyp(p);
|
||||
p = p->link;
|
||||
q->mark = 1;
|
||||
lastp->link = q;
|
||||
lastp = q;
|
||||
if(q->as != a || q->pcond == P || q->pcond->mark)
|
||||
continue;
|
||||
|
||||
q->as = relinv(q->as);
|
||||
p = q->pcond;
|
||||
q->pcond = q->link;
|
||||
q->link = p;
|
||||
xfol(q->link);
|
||||
p = q->link;
|
||||
if(p->mark)
|
||||
return;
|
||||
goto loop;
|
||||
}
|
||||
} /* */
|
||||
brk:;
|
||||
q = prg();
|
||||
q->as = AJMP;
|
||||
q->line = p->line;
|
||||
q->to.type = D_BRANCH;
|
||||
q->to.offset = p->pc;
|
||||
q->pcond = p;
|
||||
p = q;
|
||||
}
|
||||
p->mark = 1;
|
||||
lastp->link = p;
|
||||
lastp = p;
|
||||
a = p->as;
|
||||
if(a == AJMP || a == ARET || a == AIRETL || a == AIRETQ || a == AIRETW ||
|
||||
a == ARETFL || a == ARETFQ || a == ARETFW)
|
||||
return;
|
||||
if(p->pcond != P)
|
||||
if(a != ACALL) {
|
||||
q = brchain(p->link);
|
||||
if(q != P && q->mark)
|
||||
if(a != ALOOP) {
|
||||
p->as = relinv(a);
|
||||
p->link = p->pcond;
|
||||
p->pcond = q;
|
||||
}
|
||||
xfol(p->link);
|
||||
q = brchain(p->pcond);
|
||||
if(q->mark) {
|
||||
p->pcond = q;
|
||||
return;
|
||||
}
|
||||
p = q;
|
||||
goto loop;
|
||||
}
|
||||
p = p->link;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
relinv(int a)
|
||||
{
|
||||
|
||||
switch(a) {
|
||||
case AJEQ: return AJNE;
|
||||
case AJNE: return AJEQ;
|
||||
case AJLE: return AJGT;
|
||||
case AJLS: return AJHI;
|
||||
case AJLT: return AJGE;
|
||||
case AJMI: return AJPL;
|
||||
case AJGE: return AJLT;
|
||||
case AJPL: return AJMI;
|
||||
case AJGT: return AJLE;
|
||||
case AJHI: return AJLS;
|
||||
case AJCS: return AJCC;
|
||||
case AJCC: return AJCS;
|
||||
case AJPS: return AJPC;
|
||||
case AJPC: return AJPS;
|
||||
case AJOS: return AJOC;
|
||||
case AJOC: return AJOS;
|
||||
}
|
||||
diag("unknown relation: %s in %s", anames[a], TNAME);
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
doinit(void)
|
||||
{
|
||||
Sym *s;
|
||||
Prog *p;
|
||||
int x;
|
||||
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
x = p->to.type;
|
||||
if(x != D_EXTERN && x != D_STATIC)
|
||||
continue;
|
||||
s = p->to.sym;
|
||||
if(s->type == 0 || s->type == SXREF)
|
||||
diag("undefined %s initializer of %s",
|
||||
s->name, p->from.sym->name);
|
||||
p->to.offset += s->value;
|
||||
p->to.type = D_CONST;
|
||||
if(s->type == SDATA || s->type == SBSS)
|
||||
p->to.offset += INITDAT;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
patch(void)
|
||||
{
|
||||
long c;
|
||||
Prog *p, *q;
|
||||
Sym *s;
|
||||
long vexit;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f mkfwd\n", cputime());
|
||||
Bflush(&bso);
|
||||
mkfwd();
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f patch\n", cputime());
|
||||
Bflush(&bso);
|
||||
s = lookup("exit", 0);
|
||||
vexit = s->value;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(p->as == ACALL || p->as == ARET) {
|
||||
s = p->to.sym;
|
||||
if(s) {
|
||||
if(debug['c'])
|
||||
Bprint(&bso, "%s calls %s\n", TNAME, s->name);
|
||||
switch(s->type) {
|
||||
default:
|
||||
diag("undefined: %s in %s", s->name, TNAME);
|
||||
s->type = STEXT;
|
||||
s->value = vexit;
|
||||
break; /* or fall through to set offset? */
|
||||
case STEXT:
|
||||
p->to.offset = s->value;
|
||||
break;
|
||||
case SUNDEF:
|
||||
p->pcond = UP;
|
||||
p->to.offset = 0;
|
||||
break;
|
||||
}
|
||||
p->to.type = D_BRANCH;
|
||||
}
|
||||
}
|
||||
if(p->to.type != D_BRANCH || p->pcond == UP)
|
||||
continue;
|
||||
c = p->to.offset;
|
||||
for(q = firstp; q != P;) {
|
||||
if(q->forwd != P)
|
||||
if(c >= q->forwd->pc) {
|
||||
q = q->forwd;
|
||||
continue;
|
||||
}
|
||||
if(c == q->pc)
|
||||
break;
|
||||
q = q->link;
|
||||
}
|
||||
if(q == P) {
|
||||
diag("branch out of range in %s\n%P", TNAME, p);
|
||||
p->to.type = D_NONE;
|
||||
}
|
||||
p->pcond = q;
|
||||
}
|
||||
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
p->mark = 0; /* initialization for follow */
|
||||
if(p->pcond != P && p->pcond != UP) {
|
||||
p->pcond = brloop(p->pcond);
|
||||
if(p->pcond != P)
|
||||
if(p->to.type == D_BRANCH)
|
||||
p->to.offset = p->pcond->pc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define LOG 5
|
||||
void
|
||||
mkfwd(void)
|
||||
{
|
||||
Prog *p;
|
||||
int i;
|
||||
long dwn[LOG], cnt[LOG];
|
||||
Prog *lst[LOG];
|
||||
|
||||
for(i=0; i<LOG; i++) {
|
||||
if(i == 0)
|
||||
cnt[i] = 1; else
|
||||
cnt[i] = LOG * cnt[i-1];
|
||||
dwn[i] = 1;
|
||||
lst[i] = P;
|
||||
}
|
||||
i = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
i--;
|
||||
if(i < 0)
|
||||
i = LOG-1;
|
||||
p->forwd = P;
|
||||
dwn[i]--;
|
||||
if(dwn[i] <= 0) {
|
||||
dwn[i] = cnt[i];
|
||||
if(lst[i] != P)
|
||||
lst[i]->forwd = p;
|
||||
lst[i] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Prog*
|
||||
brloop(Prog *p)
|
||||
{
|
||||
int c;
|
||||
Prog *q;
|
||||
|
||||
c = 0;
|
||||
for(q = p; q != P; q = q->pcond) {
|
||||
if(q->as != AJMP)
|
||||
break;
|
||||
c++;
|
||||
if(c >= 5000)
|
||||
return P;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
void
|
||||
dostkoff(void)
|
||||
{
|
||||
Prog *p, *q;
|
||||
long autoffset, deltasp;
|
||||
int a, f, curframe, curbecome, maxbecome, pcsize;
|
||||
|
||||
curframe = 0;
|
||||
curbecome = 0;
|
||||
maxbecome = 0;
|
||||
curtext = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
|
||||
/* find out how much arg space is used in this TEXT */
|
||||
if(p->to.type == (D_INDIR+D_SP))
|
||||
if(p->to.offset > curframe)
|
||||
curframe = p->to.offset;
|
||||
|
||||
switch(p->as) {
|
||||
case ATEXT:
|
||||
if(curtext && curtext->from.sym) {
|
||||
curtext->from.sym->frame = curframe;
|
||||
curtext->from.sym->become = curbecome;
|
||||
if(curbecome > maxbecome)
|
||||
maxbecome = curbecome;
|
||||
}
|
||||
curframe = 0;
|
||||
curbecome = 0;
|
||||
|
||||
curtext = p;
|
||||
break;
|
||||
|
||||
case ARET:
|
||||
/* special form of RET is BECOME */
|
||||
if(p->from.type == D_CONST)
|
||||
if(p->from.offset > curbecome)
|
||||
curbecome = p->from.offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(curtext && curtext->from.sym) {
|
||||
curtext->from.sym->frame = curframe;
|
||||
curtext->from.sym->become = curbecome;
|
||||
if(curbecome > maxbecome)
|
||||
maxbecome = curbecome;
|
||||
}
|
||||
|
||||
if(debug['b'])
|
||||
print("max become = %d\n", maxbecome);
|
||||
xdefine("ALEFbecome", STEXT, maxbecome);
|
||||
|
||||
curtext = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
switch(p->as) {
|
||||
case ATEXT:
|
||||
curtext = p;
|
||||
break;
|
||||
case ACALL:
|
||||
if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
|
||||
f = maxbecome - curtext->from.sym->frame;
|
||||
if(f <= 0)
|
||||
break;
|
||||
/* calling a become or calling a variable */
|
||||
if(p->to.sym == S || p->to.sym->become) {
|
||||
curtext->to.offset += f;
|
||||
if(debug['b']) {
|
||||
curp = p;
|
||||
print("%D calling %D increase %d\n",
|
||||
&curtext->from, &p->to, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
autoffset = 0;
|
||||
deltasp = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT) {
|
||||
curtext = p;
|
||||
autoffset = p->to.offset;
|
||||
if(autoffset < 0)
|
||||
autoffset = 0;
|
||||
if(autoffset) {
|
||||
p = appendp(p);
|
||||
p->as = AADJSP;
|
||||
p->from.type = D_CONST;
|
||||
p->from.offset = autoffset;
|
||||
}
|
||||
deltasp = autoffset;
|
||||
}
|
||||
pcsize = p->mode/8;
|
||||
a = p->from.type;
|
||||
if(a == D_AUTO)
|
||||
p->from.offset += deltasp;
|
||||
if(a == D_PARAM)
|
||||
p->from.offset += deltasp + pcsize;
|
||||
a = p->to.type;
|
||||
if(a == D_AUTO)
|
||||
p->to.offset += deltasp;
|
||||
if(a == D_PARAM)
|
||||
p->to.offset += deltasp + pcsize;
|
||||
|
||||
switch(p->as) {
|
||||
default:
|
||||
continue;
|
||||
case APUSHL:
|
||||
case APUSHFL:
|
||||
deltasp += 4;
|
||||
continue;
|
||||
case APUSHQ:
|
||||
case APUSHFQ:
|
||||
deltasp += 8;
|
||||
continue;
|
||||
case APUSHW:
|
||||
case APUSHFW:
|
||||
deltasp += 2;
|
||||
continue;
|
||||
case APOPL:
|
||||
case APOPFL:
|
||||
deltasp -= 4;
|
||||
continue;
|
||||
case APOPQ:
|
||||
case APOPFQ:
|
||||
deltasp -= 8;
|
||||
continue;
|
||||
case APOPW:
|
||||
case APOPFW:
|
||||
deltasp -= 2;
|
||||
continue;
|
||||
case ARET:
|
||||
break;
|
||||
}
|
||||
|
||||
if(autoffset != deltasp)
|
||||
diag("unbalanced PUSH/POP");
|
||||
if(p->from.type == D_CONST)
|
||||
goto become;
|
||||
|
||||
if(autoffset) {
|
||||
q = p;
|
||||
p = appendp(p);
|
||||
p->as = ARET;
|
||||
|
||||
q->as = AADJSP;
|
||||
q->from.type = D_CONST;
|
||||
q->from.offset = -autoffset;
|
||||
}
|
||||
continue;
|
||||
|
||||
become:
|
||||
q = p;
|
||||
p = appendp(p);
|
||||
p->as = AJMP;
|
||||
p->to = q->to;
|
||||
p->pcond = q->pcond;
|
||||
|
||||
q->as = AADJSP;
|
||||
q->from = zprg.from;
|
||||
q->from.type = D_CONST;
|
||||
q->from.offset = -autoffset;
|
||||
q->to = zprg.to;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
vlong
|
||||
atolwhex(char *s)
|
||||
{
|
||||
vlong n;
|
||||
int f;
|
||||
|
||||
n = 0;
|
||||
f = 0;
|
||||
while(*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
if(*s == '-' || *s == '+') {
|
||||
if(*s++ == '-')
|
||||
f = 1;
|
||||
while(*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
}
|
||||
if(s[0]=='0' && s[1]){
|
||||
if(s[1]=='x' || s[1]=='X'){
|
||||
s += 2;
|
||||
for(;;){
|
||||
if(*s >= '0' && *s <= '9')
|
||||
n = n*16 + *s++ - '0';
|
||||
else if(*s >= 'a' && *s <= 'f')
|
||||
n = n*16 + *s++ - 'a' + 10;
|
||||
else if(*s >= 'A' && *s <= 'F')
|
||||
n = n*16 + *s++ - 'A' + 10;
|
||||
else
|
||||
break;
|
||||
}
|
||||
} else
|
||||
while(*s >= '0' && *s <= '7')
|
||||
n = n*8 + *s++ - '0';
|
||||
} else
|
||||
while(*s >= '0' && *s <= '9')
|
||||
n = n*10 + *s++ - '0';
|
||||
if(f)
|
||||
n = -n;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
undef(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->type == SXREF)
|
||||
diag("%s: not defined", s->name);
|
||||
}
|
||||
|
||||
void
|
||||
import(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
|
||||
if(s->value != 0)
|
||||
diag("value != 0 on SXREF");
|
||||
undefsym(s);
|
||||
Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, s->value);
|
||||
if(debug['S'])
|
||||
s->sig = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ckoff(Sym *s, long v)
|
||||
{
|
||||
if(v < 0 || v >= 1<<Roffset)
|
||||
diag("relocation offset %ld for %s out of range", v, s->name);
|
||||
}
|
||||
|
||||
static Prog*
|
||||
newdata(Sym *s, int o, int w, int t)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = prg();
|
||||
if(edatap == P)
|
||||
datap = p;
|
||||
else
|
||||
edatap->link = p;
|
||||
edatap = p;
|
||||
p->as = ADATA;
|
||||
p->width = w;
|
||||
p->from.scale = w;
|
||||
p->from.type = t;
|
||||
p->from.sym = s;
|
||||
p->from.offset = o;
|
||||
p->to.type = D_CONST;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
export(void)
|
||||
{
|
||||
int i, j, n, off, nb, sv, ne;
|
||||
Sym *s, *et, *str, **esyms;
|
||||
Prog *p;
|
||||
char buf[NSNAME], *t;
|
||||
|
||||
n = 0;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
|
||||
n++;
|
||||
esyms = malloc(n*sizeof(Sym*));
|
||||
ne = n;
|
||||
n = 0;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
|
||||
esyms[n++] = s;
|
||||
for(i = 0; i < ne-1; i++)
|
||||
for(j = i+1; j < ne; j++)
|
||||
if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
|
||||
s = esyms[i];
|
||||
esyms[i] = esyms[j];
|
||||
esyms[j] = s;
|
||||
}
|
||||
|
||||
nb = 0;
|
||||
off = 0;
|
||||
et = lookup(EXPTAB, 0);
|
||||
if(et->type != 0 && et->type != SXREF)
|
||||
diag("%s already defined", EXPTAB);
|
||||
et->type = SDATA;
|
||||
str = lookup(".string", 0);
|
||||
if(str->type == 0)
|
||||
str->type = SDATA;
|
||||
sv = str->value;
|
||||
for(i = 0; i < ne; i++){
|
||||
s = esyms[i];
|
||||
if(debug['S'])
|
||||
s->sig = 0;
|
||||
/* Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); */
|
||||
|
||||
/* signature */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.offset = s->sig;
|
||||
|
||||
/* address */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.type = D_ADDR;
|
||||
p->to.index = D_EXTERN;
|
||||
p->to.sym = s;
|
||||
|
||||
/* string */
|
||||
t = s->name;
|
||||
n = strlen(t)+1;
|
||||
for(;;){
|
||||
buf[nb++] = *t;
|
||||
sv++;
|
||||
if(nb >= NSNAME){
|
||||
p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.scon, buf, NSNAME);
|
||||
nb = 0;
|
||||
}
|
||||
if(*t++ == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* name */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.type = D_ADDR;
|
||||
p->to.index = D_STATIC;
|
||||
p->to.sym = str;
|
||||
p->to.offset = sv-n;
|
||||
}
|
||||
|
||||
if(nb > 0){
|
||||
p = newdata(str, sv-nb, nb, D_STATIC);
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.scon, buf, nb);
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++){
|
||||
newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
}
|
||||
et->value = off;
|
||||
if(sv == 0)
|
||||
sv = 1;
|
||||
str->value = sv;
|
||||
exports = ne;
|
||||
free(esyms);
|
||||
}
|
||||
1776
src/cmd/6l/span.c
Normal file
1776
src/cmd/6l/span.c
Normal file
File diff suppressed because it is too large
Load diff
331
src/cmd/cc/acid.c
Normal file
331
src/cmd/cc/acid.c
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
// Inferno utils/cc/acid.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/acid.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
static char *kwd[] =
|
||||
{
|
||||
"$adt", "$aggr", "$append", "$complex", "$defn",
|
||||
"$delete", "$do", "$else", "$eval", "$head", "$if",
|
||||
"$local", "$loop", "$return", "$tail", "$then",
|
||||
"$union", "$whatis", "$while",
|
||||
};
|
||||
|
||||
char*
|
||||
amap(char *s)
|
||||
{
|
||||
int i, bot, top, new;
|
||||
|
||||
bot = 0;
|
||||
top = bot + nelem(kwd) - 1;
|
||||
while(bot <= top){
|
||||
new = bot + (top - bot)/2;
|
||||
i = strcmp(kwd[new]+1, s);
|
||||
if(i == 0)
|
||||
return kwd[new];
|
||||
|
||||
if(i < 0)
|
||||
bot = new + 1;
|
||||
else
|
||||
top = new - 1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Sym*
|
||||
acidsue(Type *t)
|
||||
{
|
||||
int h;
|
||||
Sym *s;
|
||||
|
||||
if(t != T)
|
||||
for(h=0; h<nelem(hash); h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->suetag && s->suetag->link == t)
|
||||
return s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sym*
|
||||
acidfun(Type *t)
|
||||
{
|
||||
int h;
|
||||
Sym *s;
|
||||
|
||||
for(h=0; h<nelem(hash); h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->type == t)
|
||||
return s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char acidchar[NTYPE];
|
||||
Init acidcinit[] =
|
||||
{
|
||||
TCHAR, 'C', 0,
|
||||
TUCHAR, 'b', 0,
|
||||
TSHORT, 'd', 0,
|
||||
TUSHORT, 'u', 0,
|
||||
TLONG, 'D', 0,
|
||||
TULONG, 'U', 0,
|
||||
TVLONG, 'V', 0,
|
||||
TUVLONG, 'W', 0,
|
||||
TFLOAT, 'f', 0,
|
||||
TDOUBLE, 'F', 0,
|
||||
TARRAY, 'a', 0,
|
||||
TIND, 'X', 0,
|
||||
-1, 0, 0,
|
||||
};
|
||||
|
||||
static void
|
||||
acidinit(void)
|
||||
{
|
||||
Init *p;
|
||||
|
||||
for(p=acidcinit; p->code >= 0; p++)
|
||||
acidchar[p->code] = p->value;
|
||||
|
||||
acidchar[TINT] = acidchar[TLONG];
|
||||
acidchar[TUINT] = acidchar[TULONG];
|
||||
if(types[TINT]->width != types[TLONG]->width) {
|
||||
acidchar[TINT] = acidchar[TSHORT];
|
||||
acidchar[TUINT] = acidchar[TUSHORT];
|
||||
if(types[TINT]->width != types[TSHORT]->width)
|
||||
warn(Z, "acidmember int not long or short");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
acidmember(Type *t, long off, int flag)
|
||||
{
|
||||
Sym *s, *s1;
|
||||
Type *l;
|
||||
static int acidcharinit = 0;
|
||||
|
||||
if(acidcharinit == 0) {
|
||||
acidinit();
|
||||
acidcharinit = 1;
|
||||
}
|
||||
s = t->sym;
|
||||
switch(t->etype) {
|
||||
default:
|
||||
Bprint(&outbuf, " T%d\n", t->etype);
|
||||
break;
|
||||
|
||||
case TIND:
|
||||
if(s == S)
|
||||
break;
|
||||
if(flag) {
|
||||
for(l=t; l->etype==TIND; l=l->link)
|
||||
;
|
||||
if(typesu[l->etype]) {
|
||||
s1 = acidsue(l->link);
|
||||
if(s1 != S) {
|
||||
Bprint(&outbuf, " 'A' %s %ld %s;\n",
|
||||
amap(s1->name),
|
||||
t->offset+off, amap(s->name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Bprint(&outbuf,
|
||||
"\tprint(\"\t%s\t\", addr.%s\\X, \"\\n\");\n",
|
||||
amap(s->name), amap(s->name));
|
||||
break;
|
||||
}
|
||||
|
||||
case TINT:
|
||||
case TUINT:
|
||||
case TCHAR:
|
||||
case TUCHAR:
|
||||
case TSHORT:
|
||||
case TUSHORT:
|
||||
case TLONG:
|
||||
case TULONG:
|
||||
case TVLONG:
|
||||
case TUVLONG:
|
||||
case TFLOAT:
|
||||
case TDOUBLE:
|
||||
case TARRAY:
|
||||
if(s == S)
|
||||
break;
|
||||
if(flag) {
|
||||
Bprint(&outbuf, " '%c' %ld %s;\n",
|
||||
acidchar[t->etype], t->offset+off, amap(s->name));
|
||||
} else {
|
||||
Bprint(&outbuf, "\tprint(\"\t%s\t\", addr.%s, \"\\n\");\n",
|
||||
amap(s->name), amap(s->name));
|
||||
}
|
||||
break;
|
||||
|
||||
case TSTRUCT:
|
||||
case TUNION:
|
||||
s1 = acidsue(t->link);
|
||||
if(s1 == S)
|
||||
break;
|
||||
if(flag) {
|
||||
if(s == S) {
|
||||
Bprint(&outbuf, " {\n");
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
acidmember(l, t->offset+off, flag);
|
||||
Bprint(&outbuf, " };\n");
|
||||
} else {
|
||||
Bprint(&outbuf, " %s %ld %s;\n",
|
||||
amap(s1->name),
|
||||
t->offset+off, amap(s->name));
|
||||
}
|
||||
} else {
|
||||
if(s != S) {
|
||||
Bprint(&outbuf, "\tprint(\"%s %s {\\n\");\n",
|
||||
amap(s1->name), amap(s->name));
|
||||
Bprint(&outbuf, "\t%s(addr.%s);\n",
|
||||
amap(s1->name), amap(s->name));
|
||||
Bprint(&outbuf, "\tprint(\"}\\n\");\n");
|
||||
} else {
|
||||
Bprint(&outbuf, "\tprint(\"%s {\\n\");\n",
|
||||
amap(s1->name));
|
||||
Bprint(&outbuf, "\t\t%s(addr+%ld);\n",
|
||||
amap(s1->name), t->offset+off);
|
||||
Bprint(&outbuf, "\tprint(\"}\\n\");\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
acidtype(Type *t)
|
||||
{
|
||||
Sym *s;
|
||||
Type *l;
|
||||
Io *i;
|
||||
int n;
|
||||
char *an;
|
||||
|
||||
if(!debug['a'])
|
||||
return;
|
||||
if(debug['a'] > 1) {
|
||||
n = 0;
|
||||
for(i=iostack; i; i=i->link)
|
||||
n++;
|
||||
if(n > 1)
|
||||
return;
|
||||
}
|
||||
s = acidsue(t->link);
|
||||
if(s == S)
|
||||
return;
|
||||
switch(t->etype) {
|
||||
default:
|
||||
Bprint(&outbuf, "T%d\n", t->etype);
|
||||
return;
|
||||
|
||||
case TUNION:
|
||||
case TSTRUCT:
|
||||
if(debug['s'])
|
||||
goto asmstr;
|
||||
an = amap(s->name);
|
||||
Bprint(&outbuf, "sizeof%s = %ld;\n", an, t->width);
|
||||
Bprint(&outbuf, "aggr %s\n{\n", an);
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
acidmember(l, 0, 1);
|
||||
Bprint(&outbuf, "};\n\n");
|
||||
|
||||
Bprint(&outbuf, "defn\n%s(addr) {\n\tcomplex %s addr;\n", an, an);
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
acidmember(l, 0, 0);
|
||||
Bprint(&outbuf, "};\n\n");
|
||||
break;
|
||||
asmstr:
|
||||
if(s == S)
|
||||
break;
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
if(l->sym != S)
|
||||
Bprint(&outbuf, "#define\t%s.%s\t%ld\n",
|
||||
s->name,
|
||||
l->sym->name,
|
||||
l->offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
acidvar(Sym *s)
|
||||
{
|
||||
int n;
|
||||
Io *i;
|
||||
Type *t;
|
||||
Sym *s1, *s2;
|
||||
|
||||
if(!debug['a'] || debug['s'])
|
||||
return;
|
||||
if(debug['a'] > 1) {
|
||||
n = 0;
|
||||
for(i=iostack; i; i=i->link)
|
||||
n++;
|
||||
if(n > 1)
|
||||
return;
|
||||
}
|
||||
t = s->type;
|
||||
while(t && t->etype == TIND)
|
||||
t = t->link;
|
||||
if(t == T)
|
||||
return;
|
||||
if(t->etype == TENUM) {
|
||||
Bprint(&outbuf, "%s = ", amap(s->name));
|
||||
if(!typefd[t->etype])
|
||||
Bprint(&outbuf, "%lld;\n", s->vconst);
|
||||
else
|
||||
Bprint(&outbuf, "%f\n;", s->fconst);
|
||||
return;
|
||||
}
|
||||
if(!typesu[t->etype])
|
||||
return;
|
||||
s1 = acidsue(t->link);
|
||||
if(s1 == S)
|
||||
return;
|
||||
switch(s->class) {
|
||||
case CAUTO:
|
||||
case CPARAM:
|
||||
s2 = acidfun(thisfn);
|
||||
if(s2)
|
||||
Bprint(&outbuf, "complex %s %s:%s;\n",
|
||||
amap(s1->name), amap(s2->name), amap(s->name));
|
||||
break;
|
||||
|
||||
case CSTATIC:
|
||||
case CEXTERN:
|
||||
case CGLOBL:
|
||||
case CLOCAL:
|
||||
Bprint(&outbuf, "complex %s %s;\n",
|
||||
amap(s1->name), amap(s->name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
119
src/cmd/cc/bits.c
Normal file
119
src/cmd/cc/bits.c
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
// Inferno utils/cc/bits.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/bits.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
Bits
|
||||
bor(Bits a, Bits b)
|
||||
{
|
||||
Bits c;
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
c.b[i] = a.b[i] | b.b[i];
|
||||
return c;
|
||||
}
|
||||
|
||||
Bits
|
||||
band(Bits a, Bits b)
|
||||
{
|
||||
Bits c;
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
c.b[i] = a.b[i] & b.b[i];
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
Bits
|
||||
bnot(Bits a)
|
||||
{
|
||||
Bits c;
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
c.b[i] = ~a.b[i];
|
||||
return c;
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
bany(Bits *a)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
if(a->b[i])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
beq(Bits a, Bits b)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
if(a.b[i] != b.b[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
bnum(Bits a)
|
||||
{
|
||||
int i;
|
||||
long b;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
if(b = a.b[i])
|
||||
return 32*i + bitno(b);
|
||||
diag(Z, "bad in bnum");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bits
|
||||
blsh(uint n)
|
||||
{
|
||||
Bits c;
|
||||
|
||||
c = zbits;
|
||||
c.b[n/32] = 1L << (n%32);
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
bset(Bits a, uint n)
|
||||
{
|
||||
if(a.b[n/32] & (1L << (n%32)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
795
src/cmd/cc/cc.h
Normal file
795
src/cmd/cc/cc.h
Normal file
|
|
@ -0,0 +1,795 @@
|
|||
// Inferno utils/cc/cc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/cc.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <ctype.h>
|
||||
#include "compat.h"
|
||||
|
||||
#pragma lib "../cc/cc.a$O"
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef struct Node Node;
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Type Type;
|
||||
typedef struct Funct Funct;
|
||||
typedef struct Decl Decl;
|
||||
typedef struct Io Io;
|
||||
typedef struct Hist Hist;
|
||||
typedef struct Term Term;
|
||||
typedef struct Init Init;
|
||||
typedef struct Bits Bits;
|
||||
|
||||
#define NHUNK 50000L
|
||||
#define BUFSIZ 8192
|
||||
#define NSYMB 500
|
||||
#define NHASH 1024
|
||||
#define STRINGSZ 200
|
||||
#define HISTSZ 20
|
||||
#define YYMAXDEPTH 500
|
||||
#define NTERM 10
|
||||
#define MAXALIGN 7
|
||||
|
||||
#define SIGN(n) ((vlong)1<<(n-1))
|
||||
#define MASK(n) (SIGN(n)|(SIGN(n)-1))
|
||||
|
||||
#define BITS 5
|
||||
#define NVAR (BITS*sizeof(ulong)*8)
|
||||
struct Bits
|
||||
{
|
||||
ulong b[BITS];
|
||||
};
|
||||
|
||||
struct Node
|
||||
{
|
||||
Node* left;
|
||||
Node* right;
|
||||
void* label;
|
||||
long pc;
|
||||
int reg;
|
||||
long xoffset;
|
||||
double fconst; /* fp constant */
|
||||
vlong vconst; /* non fp const */
|
||||
char* cstring; /* character string */
|
||||
ushort* rstring; /* rune string */
|
||||
|
||||
Sym* sym;
|
||||
Type* type;
|
||||
long lineno;
|
||||
uchar op;
|
||||
uchar oldop;
|
||||
uchar xcast;
|
||||
uchar class;
|
||||
uchar etype;
|
||||
uchar complex;
|
||||
uchar addable;
|
||||
uchar scale;
|
||||
uchar garb;
|
||||
};
|
||||
#define Z ((Node*)0)
|
||||
|
||||
struct Sym
|
||||
{
|
||||
Sym* link;
|
||||
Type* type;
|
||||
Type* suetag;
|
||||
Type* tenum;
|
||||
char* macro;
|
||||
long varlineno;
|
||||
long offset;
|
||||
vlong vconst;
|
||||
double fconst;
|
||||
Node* label;
|
||||
ushort lexical;
|
||||
char *name;
|
||||
ushort block;
|
||||
ushort sueblock;
|
||||
uchar class;
|
||||
uchar sym;
|
||||
uchar aused;
|
||||
uchar sig;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
|
||||
enum{
|
||||
SIGNONE = 0,
|
||||
SIGDONE = 1,
|
||||
SIGINTERN = 2,
|
||||
|
||||
SIGNINTERN = 1729*325*1729,
|
||||
};
|
||||
|
||||
struct Decl
|
||||
{
|
||||
Decl* link;
|
||||
Sym* sym;
|
||||
Type* type;
|
||||
long varlineno;
|
||||
long offset;
|
||||
short val;
|
||||
ushort block;
|
||||
uchar class;
|
||||
uchar aused;
|
||||
};
|
||||
#define D ((Decl*)0)
|
||||
|
||||
struct Type
|
||||
{
|
||||
Sym* sym;
|
||||
Sym* tag;
|
||||
Funct* funct;
|
||||
Type* link;
|
||||
Type* down;
|
||||
long width;
|
||||
long offset;
|
||||
long lineno;
|
||||
uchar shift;
|
||||
uchar nbits;
|
||||
uchar etype;
|
||||
uchar garb;
|
||||
};
|
||||
|
||||
#define T ((Type*)0)
|
||||
#define NODECL ((void(*)(int, Type*, Sym*))0)
|
||||
|
||||
struct Init /* general purpose initialization */
|
||||
{
|
||||
int code;
|
||||
ulong value;
|
||||
char* s;
|
||||
};
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
char* p;
|
||||
int c;
|
||||
} fi;
|
||||
|
||||
struct Io
|
||||
{
|
||||
Io* link;
|
||||
char* p;
|
||||
char b[BUFSIZ];
|
||||
short c;
|
||||
short f;
|
||||
};
|
||||
#define I ((Io*)0)
|
||||
|
||||
struct Hist
|
||||
{
|
||||
Hist* link;
|
||||
char* name;
|
||||
long line;
|
||||
long offset;
|
||||
};
|
||||
#define H ((Hist*)0)
|
||||
EXTERN Hist* hist;
|
||||
|
||||
struct Term
|
||||
{
|
||||
vlong mult;
|
||||
Node *node;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Axxx,
|
||||
Ael1,
|
||||
Ael2,
|
||||
Asu2,
|
||||
Aarg0,
|
||||
Aarg1,
|
||||
Aarg2,
|
||||
Aaut3,
|
||||
NALIGN,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DMARK,
|
||||
DAUTO,
|
||||
DSUE,
|
||||
DLABEL,
|
||||
};
|
||||
enum
|
||||
{
|
||||
OXXX,
|
||||
OADD,
|
||||
OADDR,
|
||||
OAND,
|
||||
OANDAND,
|
||||
OARRAY,
|
||||
OAS,
|
||||
OASI,
|
||||
OASADD,
|
||||
OASAND,
|
||||
OASASHL,
|
||||
OASASHR,
|
||||
OASDIV,
|
||||
OASHL,
|
||||
OASHR,
|
||||
OASLDIV,
|
||||
OASLMOD,
|
||||
OASLMUL,
|
||||
OASLSHR,
|
||||
OASMOD,
|
||||
OASMUL,
|
||||
OASOR,
|
||||
OASSUB,
|
||||
OASXOR,
|
||||
OBIT,
|
||||
OBREAK,
|
||||
OCASE,
|
||||
OCAST,
|
||||
OCOMMA,
|
||||
OCOND,
|
||||
OCONST,
|
||||
OCONTINUE,
|
||||
ODIV,
|
||||
ODOT,
|
||||
ODOTDOT,
|
||||
ODWHILE,
|
||||
OENUM,
|
||||
OEQ,
|
||||
OFOR,
|
||||
OFUNC,
|
||||
OGE,
|
||||
OGOTO,
|
||||
OGT,
|
||||
OHI,
|
||||
OHS,
|
||||
OIF,
|
||||
OIND,
|
||||
OINDREG,
|
||||
OINIT,
|
||||
OLABEL,
|
||||
OLDIV,
|
||||
OLE,
|
||||
OLIST,
|
||||
OLMOD,
|
||||
OLMUL,
|
||||
OLO,
|
||||
OLS,
|
||||
OLSHR,
|
||||
OLT,
|
||||
OMOD,
|
||||
OMUL,
|
||||
ONAME,
|
||||
ONE,
|
||||
ONOT,
|
||||
OOR,
|
||||
OOROR,
|
||||
OPOSTDEC,
|
||||
OPOSTINC,
|
||||
OPREDEC,
|
||||
OPREINC,
|
||||
OPROTO,
|
||||
OREGISTER,
|
||||
ORETURN,
|
||||
OSET,
|
||||
OSIGN,
|
||||
OSIZE,
|
||||
OSTRING,
|
||||
OLSTRING,
|
||||
OSTRUCT,
|
||||
OSUB,
|
||||
OSWITCH,
|
||||
OUNION,
|
||||
OUSED,
|
||||
OWHILE,
|
||||
OXOR,
|
||||
ONEG,
|
||||
OCOM,
|
||||
OPOS,
|
||||
OELEM,
|
||||
|
||||
OTST, /* used in some compilers */
|
||||
OINDEX,
|
||||
OFAS,
|
||||
OREGPAIR,
|
||||
|
||||
OEND
|
||||
};
|
||||
enum
|
||||
{
|
||||
TXXX,
|
||||
TCHAR,
|
||||
TUCHAR,
|
||||
TSHORT,
|
||||
TUSHORT,
|
||||
TINT,
|
||||
TUINT,
|
||||
TLONG,
|
||||
TULONG,
|
||||
TVLONG,
|
||||
TUVLONG,
|
||||
TFLOAT,
|
||||
TDOUBLE,
|
||||
TIND,
|
||||
TFUNC,
|
||||
TARRAY,
|
||||
TVOID,
|
||||
TSTRUCT,
|
||||
TUNION,
|
||||
TENUM,
|
||||
NTYPE,
|
||||
|
||||
TAUTO = NTYPE,
|
||||
TEXTERN,
|
||||
TSTATIC,
|
||||
TTYPEDEF,
|
||||
TTYPESTR,
|
||||
TREGISTER,
|
||||
TCONSTNT,
|
||||
TVOLATILE,
|
||||
TUNSIGNED,
|
||||
TSIGNED,
|
||||
TDOT,
|
||||
TFILE,
|
||||
TOLD,
|
||||
NALLTYPES,
|
||||
};
|
||||
enum
|
||||
{
|
||||
CXXX,
|
||||
CAUTO,
|
||||
CEXTERN,
|
||||
CGLOBL,
|
||||
CSTATIC,
|
||||
CLOCAL,
|
||||
CTYPEDEF,
|
||||
CTYPESTR,
|
||||
CPARAM,
|
||||
CSELEM,
|
||||
CLABEL,
|
||||
CEXREG,
|
||||
NCTYPES,
|
||||
};
|
||||
enum
|
||||
{
|
||||
GXXX = 0,
|
||||
GCONSTNT = 1<<0,
|
||||
GVOLATILE = 1<<1,
|
||||
NGTYPES = 1<<2,
|
||||
|
||||
GINCOMPLETE = 1<<2,
|
||||
};
|
||||
enum
|
||||
{
|
||||
BCHAR = 1L<<TCHAR,
|
||||
BUCHAR = 1L<<TUCHAR,
|
||||
BSHORT = 1L<<TSHORT,
|
||||
BUSHORT = 1L<<TUSHORT,
|
||||
BINT = 1L<<TINT,
|
||||
BUINT = 1L<<TUINT,
|
||||
BLONG = 1L<<TLONG,
|
||||
BULONG = 1L<<TULONG,
|
||||
BVLONG = 1L<<TVLONG,
|
||||
BUVLONG = 1L<<TUVLONG,
|
||||
BFLOAT = 1L<<TFLOAT,
|
||||
BDOUBLE = 1L<<TDOUBLE,
|
||||
BIND = 1L<<TIND,
|
||||
BFUNC = 1L<<TFUNC,
|
||||
BARRAY = 1L<<TARRAY,
|
||||
BVOID = 1L<<TVOID,
|
||||
BSTRUCT = 1L<<TSTRUCT,
|
||||
BUNION = 1L<<TUNION,
|
||||
BENUM = 1L<<TENUM,
|
||||
BFILE = 1L<<TFILE,
|
||||
BDOT = 1L<<TDOT,
|
||||
BCONSTNT = 1L<<TCONSTNT,
|
||||
BVOLATILE = 1L<<TVOLATILE,
|
||||
BUNSIGNED = 1L<<TUNSIGNED,
|
||||
BSIGNED = 1L<<TSIGNED,
|
||||
BAUTO = 1L<<TAUTO,
|
||||
BEXTERN = 1L<<TEXTERN,
|
||||
BSTATIC = 1L<<TSTATIC,
|
||||
BTYPEDEF = 1L<<TTYPEDEF,
|
||||
BTYPESTR = 1L<<TTYPESTR,
|
||||
BREGISTER = 1L<<TREGISTER,
|
||||
|
||||
BINTEGER = BCHAR|BUCHAR|BSHORT|BUSHORT|BINT|BUINT|
|
||||
BLONG|BULONG|BVLONG|BUVLONG,
|
||||
BNUMBER = BINTEGER|BFLOAT|BDOUBLE,
|
||||
|
||||
/* these can be overloaded with complex types */
|
||||
|
||||
BCLASS = BAUTO|BEXTERN|BSTATIC|BTYPEDEF|BTYPESTR|BREGISTER,
|
||||
BGARB = BCONSTNT|BVOLATILE,
|
||||
};
|
||||
|
||||
struct Funct
|
||||
{
|
||||
Sym* sym[OEND];
|
||||
Sym* castto[NTYPE];
|
||||
Sym* castfr[NTYPE];
|
||||
};
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
Type* tenum; /* type of entire enum */
|
||||
Type* cenum; /* type of current enum run */
|
||||
vlong lastenum; /* value of current enum */
|
||||
double floatenum; /* value of current enum */
|
||||
} en;
|
||||
|
||||
EXTERN int autobn;
|
||||
EXTERN long autoffset;
|
||||
EXTERN int blockno;
|
||||
EXTERN Decl* dclstack;
|
||||
EXTERN char debug[256];
|
||||
EXTERN Hist* ehist;
|
||||
EXTERN long firstbit;
|
||||
EXTERN Sym* firstarg;
|
||||
EXTERN Type* firstargtype;
|
||||
EXTERN Decl* firstdcl;
|
||||
EXTERN int fperror;
|
||||
EXTERN Sym* hash[NHASH];
|
||||
EXTERN char* hunk;
|
||||
EXTERN char* include[20];
|
||||
EXTERN Io* iofree;
|
||||
EXTERN Io* ionext;
|
||||
EXTERN Io* iostack;
|
||||
EXTERN long lastbit;
|
||||
EXTERN char lastclass;
|
||||
EXTERN Type* lastdcl;
|
||||
EXTERN long lastfield;
|
||||
EXTERN Type* lasttype;
|
||||
EXTERN long lineno;
|
||||
EXTERN long nearln;
|
||||
EXTERN int nerrors;
|
||||
EXTERN int newflag;
|
||||
EXTERN long nhunk;
|
||||
EXTERN int ninclude;
|
||||
EXTERN Node* nodproto;
|
||||
EXTERN Node* nodcast;
|
||||
EXTERN Biobuf outbuf;
|
||||
EXTERN Biobuf diagbuf;
|
||||
EXTERN char* outfile;
|
||||
EXTERN char* pathname;
|
||||
EXTERN int peekc;
|
||||
EXTERN long stkoff;
|
||||
EXTERN Type* strf;
|
||||
EXTERN Type* strl;
|
||||
EXTERN char symb[NSYMB];
|
||||
EXTERN Sym* symstring;
|
||||
EXTERN int taggen;
|
||||
EXTERN Type* tfield;
|
||||
EXTERN Type* tufield;
|
||||
EXTERN int thechar;
|
||||
EXTERN char* thestring;
|
||||
EXTERN Type* thisfn;
|
||||
EXTERN long thunk;
|
||||
EXTERN Type* types[NTYPE];
|
||||
EXTERN Type* fntypes[NTYPE];
|
||||
EXTERN Node* initlist;
|
||||
EXTERN Term term[NTERM];
|
||||
EXTERN int nterm;
|
||||
EXTERN int packflg;
|
||||
EXTERN int fproundflg;
|
||||
EXTERN int profileflg;
|
||||
EXTERN int ncontin;
|
||||
EXTERN int canreach;
|
||||
EXTERN int warnreach;
|
||||
EXTERN Bits zbits;
|
||||
|
||||
extern char *onames[], *tnames[], *gnames[];
|
||||
extern char *cnames[], *qnames[], *bnames[];
|
||||
extern uchar tab[NTYPE][NTYPE];
|
||||
extern uchar comrel[], invrel[], logrel[];
|
||||
extern long ncast[], tadd[], tand[];
|
||||
extern long targ[], tasadd[], tasign[], tcast[];
|
||||
extern long tdot[], tfunct[], tindir[], tmul[];
|
||||
extern long tnot[], trel[], tsub[];
|
||||
|
||||
extern uchar typeaf[];
|
||||
extern uchar typefd[];
|
||||
extern uchar typei[];
|
||||
extern uchar typesu[];
|
||||
extern uchar typesuv[];
|
||||
extern uchar typeu[];
|
||||
extern uchar typev[];
|
||||
extern uchar typec[];
|
||||
extern uchar typeh[];
|
||||
extern uchar typeil[];
|
||||
extern uchar typeilp[];
|
||||
extern uchar typechl[];
|
||||
extern uchar typechlv[];
|
||||
extern uchar typechlvp[];
|
||||
extern uchar typechlp[];
|
||||
extern uchar typechlpfd[];
|
||||
|
||||
EXTERN uchar* typeword;
|
||||
EXTERN uchar* typecmplx;
|
||||
|
||||
extern ulong thash1;
|
||||
extern ulong thash2;
|
||||
extern ulong thash3;
|
||||
extern ulong thash[];
|
||||
|
||||
/*
|
||||
* compat.c/unix.c/windows.c
|
||||
*/
|
||||
int mywait(int*);
|
||||
int mycreat(char*, int);
|
||||
int systemtype(int);
|
||||
int pathchar(void);
|
||||
int myaccess(char*);
|
||||
char* mygetwd(char*, int);
|
||||
int myexec(char*, char*[]);
|
||||
int mydup(int, int);
|
||||
int myfork(void);
|
||||
int mypipe(int*);
|
||||
void* mysbrk(ulong);
|
||||
|
||||
/*
|
||||
* parser
|
||||
*/
|
||||
int yyparse(void);
|
||||
int mpatov(char*, vlong*);
|
||||
|
||||
/*
|
||||
* lex.c
|
||||
*/
|
||||
void* allocn(void*, long, long);
|
||||
void* alloc(long);
|
||||
void cinit(void);
|
||||
int compile(char*, char**, int);
|
||||
void errorexit(void);
|
||||
int filbuf(void);
|
||||
int getc(void);
|
||||
long getr(void);
|
||||
int getnsc(void);
|
||||
Sym* lookup(void);
|
||||
void main(int, char*[]);
|
||||
void newfile(char*, int);
|
||||
void newio(void);
|
||||
void pushio(void);
|
||||
long escchar(long, int, int);
|
||||
Sym* slookup(char*);
|
||||
void syminit(Sym*);
|
||||
void unget(int);
|
||||
long yylex(void);
|
||||
int Lconv(Fmt*);
|
||||
int Tconv(Fmt*);
|
||||
int FNconv(Fmt*);
|
||||
int Oconv(Fmt*);
|
||||
int Qconv(Fmt*);
|
||||
int VBconv(Fmt*);
|
||||
void setinclude(char*);
|
||||
|
||||
/*
|
||||
* mac.c
|
||||
*/
|
||||
void dodefine(char*);
|
||||
void domacro(void);
|
||||
Sym* getsym(void);
|
||||
long getnsn(void);
|
||||
void linehist(char*, int);
|
||||
void macdef(void);
|
||||
void macprag(void);
|
||||
void macend(void);
|
||||
void macexpand(Sym*, char*);
|
||||
void macif(int);
|
||||
void macinc(void);
|
||||
void maclin(void);
|
||||
void macund(void);
|
||||
|
||||
/*
|
||||
* dcl.c
|
||||
*/
|
||||
Node* doinit(Sym*, Type*, long, Node*);
|
||||
Type* tcopy(Type*);
|
||||
Node* init1(Sym*, Type*, long, int);
|
||||
Node* newlist(Node*, Node*);
|
||||
void adecl(int, Type*, Sym*);
|
||||
int anyproto(Node*);
|
||||
void argmark(Node*, int);
|
||||
void dbgdecl(Sym*);
|
||||
Node* dcllabel(Sym*, int);
|
||||
Node* dodecl(void(*)(int, Type*, Sym*), int, Type*, Node*);
|
||||
Sym* mkstatic(Sym*);
|
||||
void doenum(Sym*, Node*);
|
||||
void snap(Type*);
|
||||
Type* dotag(Sym*, int, int);
|
||||
void edecl(int, Type*, Sym*);
|
||||
Type* fnproto(Node*);
|
||||
Type* fnproto1(Node*);
|
||||
void markdcl(void);
|
||||
Type* paramconv(Type*, int);
|
||||
void pdecl(int, Type*, Sym*);
|
||||
Decl* push(void);
|
||||
Decl* push1(Sym*);
|
||||
Node* revertdcl(void);
|
||||
long xround(long, int);
|
||||
int rsametype(Type*, Type*, int, int);
|
||||
int sametype(Type*, Type*);
|
||||
ulong sign(Sym*);
|
||||
ulong signature(Type*);
|
||||
void suallign(Type*);
|
||||
void tmerge(Type*, Sym*);
|
||||
void walkparam(Node*, int);
|
||||
void xdecl(int, Type*, Sym*);
|
||||
Node* contig(Sym*, Node*, long);
|
||||
|
||||
/*
|
||||
* com.c
|
||||
*/
|
||||
void ccom(Node*);
|
||||
void complex(Node*);
|
||||
int tcom(Node*);
|
||||
int tcoma(Node*, Node*, Type*, int);
|
||||
int tcomd(Node*);
|
||||
int tcomo(Node*, int);
|
||||
int tcomx(Node*);
|
||||
int tlvalue(Node*);
|
||||
void constas(Node*, Type*, Type*);
|
||||
|
||||
/*
|
||||
* con.c
|
||||
*/
|
||||
void acom(Node*);
|
||||
void acom1(vlong, Node*);
|
||||
void acom2(Node*, Type*);
|
||||
int acomcmp1(const void*, const void*);
|
||||
int acomcmp2(const void*, const void*);
|
||||
int addo(Node*);
|
||||
void evconst(Node*);
|
||||
|
||||
/*
|
||||
* funct.c
|
||||
*/
|
||||
int isfunct(Node*);
|
||||
void dclfunct(Type*, Sym*);
|
||||
|
||||
/*
|
||||
* sub.c
|
||||
*/
|
||||
void arith(Node*, int);
|
||||
int deadheads(Node*);
|
||||
Type* dotsearch(Sym*, Type*, Node*, long*);
|
||||
long dotoffset(Type*, Type*, Node*);
|
||||
void gethunk(void);
|
||||
Node* invert(Node*);
|
||||
int bitno(long);
|
||||
void makedot(Node*, Type*, long);
|
||||
int mixedasop(Type*, Type*);
|
||||
Node* new(int, Node*, Node*);
|
||||
Node* new1(int, Node*, Node*);
|
||||
int nilcast(Type*, Type*);
|
||||
int nocast(Type*, Type*);
|
||||
void prtree(Node*, char*);
|
||||
void prtree1(Node*, int, int);
|
||||
void relcon(Node*, Node*);
|
||||
int relindex(int);
|
||||
int simpleg(long);
|
||||
Type* garbt(Type*, long);
|
||||
int simplec(long);
|
||||
Type* simplet(long);
|
||||
int stcompat(Node*, Type*, Type*, long[]);
|
||||
int tcompat(Node*, Type*, Type*, long[]);
|
||||
void tinit(void);
|
||||
Type* typ(int, Type*);
|
||||
Type* copytyp(Type*);
|
||||
void typeext(Type*, Node*);
|
||||
void typeext1(Type*, Node*);
|
||||
int side(Node*);
|
||||
int vconst(Node*);
|
||||
int xlog2(uvlong);
|
||||
int vlog(Node*);
|
||||
int topbit(ulong);
|
||||
void simplifyshift(Node*);
|
||||
long typebitor(long, long);
|
||||
void diag(Node*, char*, ...);
|
||||
void warn(Node*, char*, ...);
|
||||
void yyerror(char*, ...);
|
||||
void fatal(Node*, char*, ...);
|
||||
|
||||
/*
|
||||
* acid.c
|
||||
*/
|
||||
void acidtype(Type*);
|
||||
void acidvar(Sym*);
|
||||
|
||||
/*
|
||||
* pickle.c
|
||||
*/
|
||||
void pickletype(Type*);
|
||||
|
||||
/*
|
||||
* bits.c
|
||||
*/
|
||||
Bits bor(Bits, Bits);
|
||||
Bits band(Bits, Bits);
|
||||
Bits bnot(Bits);
|
||||
int bany(Bits*);
|
||||
int bnum(Bits);
|
||||
Bits blsh(uint);
|
||||
int beq(Bits, Bits);
|
||||
int bset(Bits, uint);
|
||||
|
||||
/*
|
||||
* dpchk.c
|
||||
*/
|
||||
void dpcheck(Node*);
|
||||
void arginit(void);
|
||||
void pragvararg(void);
|
||||
void pragpack(void);
|
||||
void pragfpround(void);
|
||||
void pragprofile(void);
|
||||
void pragincomplete(void);
|
||||
|
||||
/*
|
||||
* calls to machine depend part
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gclean(void);
|
||||
void gextern(Sym*, Node*, long, long);
|
||||
void ginit(void);
|
||||
long outstring(char*, long);
|
||||
long outlstring(ushort*, long);
|
||||
void sextern(Sym*, Node*, long, long);
|
||||
void xcom(Node*);
|
||||
long exreg(Type*);
|
||||
long align(long, Type*, int);
|
||||
long maxround(long, long);
|
||||
|
||||
extern schar ewidth[];
|
||||
|
||||
/*
|
||||
* com64
|
||||
*/
|
||||
int com64(Node*);
|
||||
void com64init(void);
|
||||
void bool64(Node*);
|
||||
double convvtof(vlong);
|
||||
vlong convftov(double);
|
||||
double convftox(double, int);
|
||||
vlong convvtox(vlong, int);
|
||||
|
||||
/*
|
||||
* machcap
|
||||
*/
|
||||
int machcap(Node*);
|
||||
|
||||
#pragma varargck argpos warn 2
|
||||
#pragma varargck argpos diag 2
|
||||
#pragma varargck argpos yyerror 1
|
||||
|
||||
#pragma varargck type "F" Node*
|
||||
#pragma varargck type "L" long
|
||||
#pragma varargck type "Q" long
|
||||
#pragma varargck type "O" int
|
||||
#pragma varargck type "T" Type*
|
||||
#pragma varargck type "|" int
|
||||
1205
src/cmd/cc/cc.y
Normal file
1205
src/cmd/cc/cc.y
Normal file
File diff suppressed because it is too large
Load diff
1378
src/cmd/cc/com.c
Normal file
1378
src/cmd/cc/com.c
Normal file
File diff suppressed because it is too large
Load diff
643
src/cmd/cc/com64.c
Normal file
643
src/cmd/cc/com64.c
Normal file
|
|
@ -0,0 +1,643 @@
|
|||
// Inferno utils/cc/com64.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/com64.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
/*
|
||||
* this is machine depend, but it is totally
|
||||
* common on all of the 64-bit symulating machines.
|
||||
*/
|
||||
|
||||
#define FNX 100 /* botch -- redefinition */
|
||||
|
||||
Node* nodaddv;
|
||||
Node* nodsubv;
|
||||
Node* nodmulv;
|
||||
Node* noddivv;
|
||||
Node* noddivvu;
|
||||
Node* nodmodv;
|
||||
Node* nodmodvu;
|
||||
Node* nodlshv;
|
||||
Node* nodrshav;
|
||||
Node* nodrshlv;
|
||||
Node* nodandv;
|
||||
Node* nodorv;
|
||||
Node* nodxorv;
|
||||
Node* nodnegv;
|
||||
Node* nodcomv;
|
||||
|
||||
Node* nodtestv;
|
||||
Node* nodeqv;
|
||||
Node* nodnev;
|
||||
Node* nodlev;
|
||||
Node* nodltv;
|
||||
Node* nodgev;
|
||||
Node* nodgtv;
|
||||
Node* nodhiv;
|
||||
Node* nodhsv;
|
||||
Node* nodlov;
|
||||
Node* nodlsv;
|
||||
|
||||
Node* nodf2v;
|
||||
Node* nodd2v;
|
||||
Node* nodp2v;
|
||||
Node* nodsi2v;
|
||||
Node* nodui2v;
|
||||
Node* nodsl2v;
|
||||
Node* nodul2v;
|
||||
Node* nodsh2v;
|
||||
Node* noduh2v;
|
||||
Node* nodsc2v;
|
||||
Node* noduc2v;
|
||||
|
||||
Node* nodv2f;
|
||||
Node* nodv2d;
|
||||
Node* nodv2ui;
|
||||
Node* nodv2si;
|
||||
Node* nodv2ul;
|
||||
Node* nodv2sl;
|
||||
Node* nodv2uh;
|
||||
Node* nodv2sh;
|
||||
Node* nodv2uc;
|
||||
Node* nodv2sc;
|
||||
|
||||
Node* nodvpp;
|
||||
Node* nodppv;
|
||||
Node* nodvmm;
|
||||
Node* nodmmv;
|
||||
|
||||
Node* nodvasop;
|
||||
|
||||
char etconv[NTYPE]; /* for _vasop */
|
||||
Init initetconv[] =
|
||||
{
|
||||
TCHAR, 1, 0,
|
||||
TUCHAR, 2, 0,
|
||||
TSHORT, 3, 0,
|
||||
TUSHORT, 4, 0,
|
||||
TLONG, 5, 0,
|
||||
TULONG, 6, 0,
|
||||
TVLONG, 7, 0,
|
||||
TUVLONG, 8, 0,
|
||||
TINT, 9, 0,
|
||||
TUINT, 10, 0,
|
||||
-1, 0, 0,
|
||||
};
|
||||
|
||||
Node*
|
||||
fvn(char *name, int type)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = new(ONAME, Z, Z);
|
||||
n->sym = slookup(name);
|
||||
n->sym->sig = SIGINTERN;
|
||||
if(fntypes[type] == 0)
|
||||
fntypes[type] = typ(TFUNC, types[type]);
|
||||
n->type = fntypes[type];
|
||||
n->etype = type;
|
||||
n->class = CGLOBL;
|
||||
n->addable = 10;
|
||||
n->complex = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
com64init(void)
|
||||
{
|
||||
Init *p;
|
||||
|
||||
nodaddv = fvn("_addv", TVLONG);
|
||||
nodsubv = fvn("_subv", TVLONG);
|
||||
nodmulv = fvn("_mulv", TVLONG);
|
||||
noddivv = fvn("_divv", TVLONG);
|
||||
noddivvu = fvn("_divvu", TVLONG);
|
||||
nodmodv = fvn("_modv", TVLONG);
|
||||
nodmodvu = fvn("_modvu", TVLONG);
|
||||
nodlshv = fvn("_lshv", TVLONG);
|
||||
nodrshav = fvn("_rshav", TVLONG);
|
||||
nodrshlv = fvn("_rshlv", TVLONG);
|
||||
nodandv = fvn("_andv", TVLONG);
|
||||
nodorv = fvn("_orv", TVLONG);
|
||||
nodxorv = fvn("_xorv", TVLONG);
|
||||
nodnegv = fvn("_negv", TVLONG);
|
||||
nodcomv = fvn("_comv", TVLONG);
|
||||
|
||||
nodtestv = fvn("_testv", TLONG);
|
||||
nodeqv = fvn("_eqv", TLONG);
|
||||
nodnev = fvn("_nev", TLONG);
|
||||
nodlev = fvn("_lev", TLONG);
|
||||
nodltv = fvn("_ltv", TLONG);
|
||||
nodgev = fvn("_gev", TLONG);
|
||||
nodgtv = fvn("_gtv", TLONG);
|
||||
nodhiv = fvn("_hiv", TLONG);
|
||||
nodhsv = fvn("_hsv", TLONG);
|
||||
nodlov = fvn("_lov", TLONG);
|
||||
nodlsv = fvn("_lsv", TLONG);
|
||||
|
||||
nodf2v = fvn("_f2v", TVLONG);
|
||||
nodd2v = fvn("_d2v", TVLONG);
|
||||
nodp2v = fvn("_p2v", TVLONG);
|
||||
nodsi2v = fvn("_si2v", TVLONG);
|
||||
nodui2v = fvn("_ui2v", TVLONG);
|
||||
nodsl2v = fvn("_sl2v", TVLONG);
|
||||
nodul2v = fvn("_ul2v", TVLONG);
|
||||
nodsh2v = fvn("_sh2v", TVLONG);
|
||||
noduh2v = fvn("_uh2v", TVLONG);
|
||||
nodsc2v = fvn("_sc2v", TVLONG);
|
||||
noduc2v = fvn("_uc2v", TVLONG);
|
||||
|
||||
nodv2f = fvn("_v2f", TFLOAT);
|
||||
nodv2d = fvn("_v2d", TDOUBLE);
|
||||
nodv2sl = fvn("_v2sl", TLONG);
|
||||
nodv2ul = fvn("_v2ul", TULONG);
|
||||
nodv2si = fvn("_v2si", TINT);
|
||||
nodv2ui = fvn("_v2ui", TUINT);
|
||||
nodv2sh = fvn("_v2sh", TSHORT);
|
||||
nodv2uh = fvn("_v2ul", TUSHORT);
|
||||
nodv2sc = fvn("_v2sc", TCHAR);
|
||||
nodv2uc = fvn("_v2uc", TUCHAR);
|
||||
|
||||
nodvpp = fvn("_vpp", TVLONG);
|
||||
nodppv = fvn("_ppv", TVLONG);
|
||||
nodvmm = fvn("_vmm", TVLONG);
|
||||
nodmmv = fvn("_mmv", TVLONG);
|
||||
|
||||
nodvasop = fvn("_vasop", TVLONG);
|
||||
|
||||
for(p = initetconv; p->code >= 0; p++)
|
||||
etconv[p->code] = p->value;
|
||||
}
|
||||
|
||||
int
|
||||
com64(Node *n)
|
||||
{
|
||||
Node *l, *r, *a, *t;
|
||||
int lv, rv;
|
||||
|
||||
if(n->type == 0)
|
||||
return 0;
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
|
||||
lv = 0;
|
||||
if(l && l->type && typev[l->type->etype])
|
||||
lv = 1;
|
||||
rv = 0;
|
||||
if(r && r->type && typev[r->type->etype])
|
||||
rv = 1;
|
||||
|
||||
if(lv) {
|
||||
switch(n->op) {
|
||||
case OEQ:
|
||||
a = nodeqv;
|
||||
goto setbool;
|
||||
case ONE:
|
||||
a = nodnev;
|
||||
goto setbool;
|
||||
case OLE:
|
||||
a = nodlev;
|
||||
goto setbool;
|
||||
case OLT:
|
||||
a = nodltv;
|
||||
goto setbool;
|
||||
case OGE:
|
||||
a = nodgev;
|
||||
goto setbool;
|
||||
case OGT:
|
||||
a = nodgtv;
|
||||
goto setbool;
|
||||
case OHI:
|
||||
a = nodhiv;
|
||||
goto setbool;
|
||||
case OHS:
|
||||
a = nodhsv;
|
||||
goto setbool;
|
||||
case OLO:
|
||||
a = nodlov;
|
||||
goto setbool;
|
||||
case OLS:
|
||||
a = nodlsv;
|
||||
goto setbool;
|
||||
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
|
||||
if(rv) {
|
||||
r = new(OFUNC, nodtestv, r);
|
||||
n->right = r;
|
||||
r->complex = FNX;
|
||||
r->op = OFUNC;
|
||||
r->type = types[TLONG];
|
||||
}
|
||||
|
||||
case OCOND:
|
||||
case ONOT:
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
|
||||
l = new(OFUNC, nodtestv, l);
|
||||
n->left = l;
|
||||
l->complex = FNX;
|
||||
l->op = OFUNC;
|
||||
l->type = types[TLONG];
|
||||
n->complex = FNX;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(rv) {
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
switch(n->op) {
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
r = new(OFUNC, nodtestv, r);
|
||||
n->right = r;
|
||||
r->complex = FNX;
|
||||
r->op = OFUNC;
|
||||
r->type = types[TLONG];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(typev[n->type->etype]) {
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
switch(n->op) {
|
||||
default:
|
||||
diag(n, "unknown vlong %O", n->op);
|
||||
case OFUNC:
|
||||
n->complex = FNX;
|
||||
case ORETURN:
|
||||
case OAS:
|
||||
case OIND:
|
||||
return 1;
|
||||
case OADD:
|
||||
a = nodaddv;
|
||||
goto setbop;
|
||||
case OSUB:
|
||||
a = nodsubv;
|
||||
goto setbop;
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
a = nodmulv;
|
||||
goto setbop;
|
||||
case ODIV:
|
||||
a = noddivv;
|
||||
goto setbop;
|
||||
case OLDIV:
|
||||
a = noddivvu;
|
||||
goto setbop;
|
||||
case OMOD:
|
||||
a = nodmodv;
|
||||
goto setbop;
|
||||
case OLMOD:
|
||||
a = nodmodvu;
|
||||
goto setbop;
|
||||
case OASHL:
|
||||
a = nodlshv;
|
||||
goto setbop;
|
||||
case OASHR:
|
||||
a = nodrshav;
|
||||
goto setbop;
|
||||
case OLSHR:
|
||||
a = nodrshlv;
|
||||
goto setbop;
|
||||
case OAND:
|
||||
a = nodandv;
|
||||
goto setbop;
|
||||
case OOR:
|
||||
a = nodorv;
|
||||
goto setbop;
|
||||
case OXOR:
|
||||
a = nodxorv;
|
||||
goto setbop;
|
||||
case OPOSTINC:
|
||||
a = nodvpp;
|
||||
goto setvinc;
|
||||
case OPOSTDEC:
|
||||
a = nodvmm;
|
||||
goto setvinc;
|
||||
case OPREINC:
|
||||
a = nodppv;
|
||||
goto setvinc;
|
||||
case OPREDEC:
|
||||
a = nodmmv;
|
||||
goto setvinc;
|
||||
case ONEG:
|
||||
a = nodnegv;
|
||||
goto setfnx;
|
||||
case OCOM:
|
||||
a = nodcomv;
|
||||
goto setfnx;
|
||||
case OCAST:
|
||||
switch(l->type->etype) {
|
||||
case TCHAR:
|
||||
a = nodsc2v;
|
||||
goto setfnxl;
|
||||
case TUCHAR:
|
||||
a = noduc2v;
|
||||
goto setfnxl;
|
||||
case TSHORT:
|
||||
a = nodsh2v;
|
||||
goto setfnxl;
|
||||
case TUSHORT:
|
||||
a = noduh2v;
|
||||
goto setfnxl;
|
||||
case TINT:
|
||||
a = nodsi2v;
|
||||
goto setfnx;
|
||||
case TUINT:
|
||||
a = nodui2v;
|
||||
goto setfnx;
|
||||
case TLONG:
|
||||
a = nodsl2v;
|
||||
goto setfnx;
|
||||
case TULONG:
|
||||
a = nodul2v;
|
||||
goto setfnx;
|
||||
case TFLOAT:
|
||||
a = nodf2v;
|
||||
goto setfnx;
|
||||
case TDOUBLE:
|
||||
a = nodd2v;
|
||||
goto setfnx;
|
||||
case TIND:
|
||||
a = nodp2v;
|
||||
goto setfnx;
|
||||
}
|
||||
diag(n, "unknown %T->vlong cast", l->type);
|
||||
return 1;
|
||||
case OASADD:
|
||||
a = nodaddv;
|
||||
goto setasop;
|
||||
case OASSUB:
|
||||
a = nodsubv;
|
||||
goto setasop;
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
a = nodmulv;
|
||||
goto setasop;
|
||||
case OASDIV:
|
||||
a = noddivv;
|
||||
goto setasop;
|
||||
case OASLDIV:
|
||||
a = noddivvu;
|
||||
goto setasop;
|
||||
case OASMOD:
|
||||
a = nodmodv;
|
||||
goto setasop;
|
||||
case OASLMOD:
|
||||
a = nodmodvu;
|
||||
goto setasop;
|
||||
case OASASHL:
|
||||
a = nodlshv;
|
||||
goto setasop;
|
||||
case OASASHR:
|
||||
a = nodrshav;
|
||||
goto setasop;
|
||||
case OASLSHR:
|
||||
a = nodrshlv;
|
||||
goto setasop;
|
||||
case OASAND:
|
||||
a = nodandv;
|
||||
goto setasop;
|
||||
case OASOR:
|
||||
a = nodorv;
|
||||
goto setasop;
|
||||
case OASXOR:
|
||||
a = nodxorv;
|
||||
goto setasop;
|
||||
}
|
||||
}
|
||||
|
||||
if(typefd[n->type->etype] && l && l->op == OFUNC) {
|
||||
switch(n->op) {
|
||||
case OASADD:
|
||||
case OASSUB:
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
case OASDIV:
|
||||
case OASLDIV:
|
||||
case OASMOD:
|
||||
case OASLMOD:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASLSHR:
|
||||
case OASAND:
|
||||
case OASOR:
|
||||
case OASXOR:
|
||||
if(l->right && typev[l->right->etype]) {
|
||||
diag(n, "sorry float <asop> vlong not implemented\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(n->op == OCAST) {
|
||||
if(l->type && typev[l->type->etype]) {
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
switch(n->type->etype) {
|
||||
case TDOUBLE:
|
||||
a = nodv2d;
|
||||
goto setfnx;
|
||||
case TFLOAT:
|
||||
a = nodv2f;
|
||||
goto setfnx;
|
||||
case TLONG:
|
||||
a = nodv2sl;
|
||||
goto setfnx;
|
||||
case TULONG:
|
||||
a = nodv2ul;
|
||||
goto setfnx;
|
||||
case TINT:
|
||||
a = nodv2si;
|
||||
goto setfnx;
|
||||
case TUINT:
|
||||
a = nodv2ui;
|
||||
goto setfnx;
|
||||
case TSHORT:
|
||||
a = nodv2sh;
|
||||
goto setfnx;
|
||||
case TUSHORT:
|
||||
a = nodv2uh;
|
||||
goto setfnx;
|
||||
case TCHAR:
|
||||
a = nodv2sc;
|
||||
goto setfnx;
|
||||
case TUCHAR:
|
||||
a = nodv2uc;
|
||||
goto setfnx;
|
||||
case TIND: // small pun here
|
||||
a = nodv2ul;
|
||||
goto setfnx;
|
||||
}
|
||||
diag(n, "unknown vlong->%T cast", n->type);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
setbop:
|
||||
n->left = a;
|
||||
n->right = new(OLIST, l, r);
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
return 1;
|
||||
|
||||
setfnxl:
|
||||
l = new(OCAST, l, 0);
|
||||
l->type = types[TLONG];
|
||||
l->complex = l->left->complex;
|
||||
|
||||
setfnx:
|
||||
n->left = a;
|
||||
n->right = l;
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
return 1;
|
||||
|
||||
setvinc:
|
||||
n->left = a;
|
||||
l = new(OADDR, l, Z);
|
||||
l->type = typ(TIND, l->left->type);
|
||||
n->right = new(OLIST, l, r);
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
return 1;
|
||||
|
||||
setbool:
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
n->left = a;
|
||||
n->right = new(OLIST, l, r);
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
n->type = types[TLONG];
|
||||
return 1;
|
||||
|
||||
setasop:
|
||||
if(l->op == OFUNC) {
|
||||
l = l->right;
|
||||
goto setasop;
|
||||
}
|
||||
|
||||
t = new(OCONST, 0, 0);
|
||||
t->vconst = etconv[l->type->etype];
|
||||
t->type = types[TLONG];
|
||||
t->addable = 20;
|
||||
r = new(OLIST, t, r);
|
||||
|
||||
t = new(OADDR, a, 0);
|
||||
t->type = typ(TIND, a->type);
|
||||
r = new(OLIST, t, r);
|
||||
|
||||
t = new(OADDR, l, 0);
|
||||
t->type = typ(TIND, l->type);
|
||||
r = new(OLIST, t, r);
|
||||
|
||||
n->left = nodvasop;
|
||||
n->right = r;
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
bool64(Node *n)
|
||||
{
|
||||
Node *n1;
|
||||
|
||||
if(machcap(Z))
|
||||
return;
|
||||
if(typev[n->type->etype]) {
|
||||
n1 = new(OXXX, 0, 0);
|
||||
*n1 = *n;
|
||||
|
||||
n->right = n1;
|
||||
n->left = nodtestv;
|
||||
n->complex = FNX;
|
||||
n->addable = 0;
|
||||
n->op = OFUNC;
|
||||
n->type = types[TLONG];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* more machine depend stuff.
|
||||
* this is common for 8,16,32,64 bit machines.
|
||||
* this is common for ieee machines.
|
||||
*/
|
||||
double
|
||||
convvtof(vlong v)
|
||||
{
|
||||
double d;
|
||||
|
||||
d = v; /* BOTCH */
|
||||
return d;
|
||||
}
|
||||
|
||||
vlong
|
||||
convftov(double d)
|
||||
{
|
||||
vlong v;
|
||||
|
||||
|
||||
v = d; /* BOTCH */
|
||||
return v;
|
||||
}
|
||||
|
||||
double
|
||||
convftox(double d, int et)
|
||||
{
|
||||
|
||||
if(!typefd[et])
|
||||
diag(Z, "bad type in castftox %s", tnames[et]);
|
||||
return d;
|
||||
}
|
||||
|
||||
vlong
|
||||
convvtox(vlong c, int et)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 8 * ewidth[et];
|
||||
c &= MASK(n);
|
||||
if(!typeu[et])
|
||||
if(c & SIGN(n))
|
||||
c |= ~MASK(n);
|
||||
return c;
|
||||
}
|
||||
1664
src/cmd/cc/dcl.c
Normal file
1664
src/cmd/cc/dcl.c
Normal file
File diff suppressed because it is too large
Load diff
524
src/cmd/cc/dpchk.c
Normal file
524
src/cmd/cc/dpchk.c
Normal file
|
|
@ -0,0 +1,524 @@
|
|||
// Inferno utils/cc/dpchk.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/dpchk.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Fnone = 0,
|
||||
Fl,
|
||||
Fvl,
|
||||
Fignor,
|
||||
Fstar,
|
||||
Fadj,
|
||||
|
||||
Fverb = 10,
|
||||
};
|
||||
|
||||
typedef struct Tprot Tprot;
|
||||
struct Tprot
|
||||
{
|
||||
Type* type;
|
||||
Bits flag;
|
||||
Tprot* link;
|
||||
};
|
||||
|
||||
typedef struct Tname Tname;
|
||||
struct Tname
|
||||
{
|
||||
char* name;
|
||||
int param;
|
||||
Tname* link;
|
||||
};
|
||||
|
||||
static Type* indchar;
|
||||
static uchar flagbits[512];
|
||||
static char fmtbuf[100];
|
||||
static int lastadj;
|
||||
static int lastverb;
|
||||
static int nstar;
|
||||
static Tprot* tprot;
|
||||
static Tname* tname;
|
||||
|
||||
void
|
||||
argflag(int c, int v)
|
||||
{
|
||||
|
||||
switch(v) {
|
||||
case Fignor:
|
||||
case Fstar:
|
||||
case Fl:
|
||||
case Fvl:
|
||||
flagbits[c] = v;
|
||||
break;
|
||||
case Fverb:
|
||||
flagbits[c] = lastverb;
|
||||
/*print("flag-v %c %d\n", c, lastadj);*/
|
||||
lastverb++;
|
||||
break;
|
||||
case Fadj:
|
||||
flagbits[c] = lastadj;
|
||||
/*print("flag-l %c %d\n", c, lastadj);*/
|
||||
lastadj++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Bits
|
||||
getflag(char *s)
|
||||
{
|
||||
Bits flag;
|
||||
int f;
|
||||
char *fmt;
|
||||
Rune c;
|
||||
|
||||
fmt = fmtbuf;
|
||||
flag = zbits;
|
||||
nstar = 0;
|
||||
for(;;) {
|
||||
s += chartorune(&c, s);
|
||||
if(c == 0 || c >= nelem(flagbits))
|
||||
break;
|
||||
fmt += runetochar(fmt, &c);
|
||||
f = flagbits[c];
|
||||
switch(f) {
|
||||
case Fnone:
|
||||
argflag(c, Fverb);
|
||||
f = flagbits[c];
|
||||
break;
|
||||
case Fstar:
|
||||
nstar++;
|
||||
case Fignor:
|
||||
continue;
|
||||
case Fl:
|
||||
if(bset(flag, Fl))
|
||||
flag = bor(flag, blsh(Fvl));
|
||||
}
|
||||
flag = bor(flag, blsh(f));
|
||||
if(f >= Fverb)
|
||||
break;
|
||||
}
|
||||
*fmt = 0;
|
||||
return flag;
|
||||
}
|
||||
|
||||
void
|
||||
newprot(Sym *m, Type *t, char *s)
|
||||
{
|
||||
Bits flag;
|
||||
Tprot *l;
|
||||
|
||||
if(t == T) {
|
||||
warn(Z, "%s: newprot: type not defined", m->name);
|
||||
return;
|
||||
}
|
||||
flag = getflag(s);
|
||||
for(l=tprot; l; l=l->link)
|
||||
if(beq(flag, l->flag) && sametype(t, l->type))
|
||||
return;
|
||||
l = alloc(sizeof(*l));
|
||||
l->type = t;
|
||||
l->flag = flag;
|
||||
l->link = tprot;
|
||||
tprot = l;
|
||||
}
|
||||
|
||||
void
|
||||
newname(char *s, int p)
|
||||
{
|
||||
Tname *l;
|
||||
|
||||
for(l=tname; l; l=l->link)
|
||||
if(strcmp(l->name, s) == 0) {
|
||||
if(l->param != p)
|
||||
yyerror("vargck %s already defined\n", s);
|
||||
return;
|
||||
}
|
||||
l = alloc(sizeof(*l));
|
||||
l->name = s;
|
||||
l->param = p;
|
||||
l->link = tname;
|
||||
tname = l;
|
||||
}
|
||||
|
||||
void
|
||||
arginit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* debug['F'] = 1;*/
|
||||
/* debug['w'] = 1;*/
|
||||
|
||||
lastadj = Fadj;
|
||||
lastverb = Fverb;
|
||||
indchar = typ(TIND, types[TCHAR]);
|
||||
|
||||
memset(flagbits, Fnone, sizeof(flagbits));
|
||||
|
||||
for(i='0'; i<='9'; i++)
|
||||
argflag(i, Fignor);
|
||||
argflag('.', Fignor);
|
||||
argflag('#', Fignor);
|
||||
argflag('u', Fignor);
|
||||
argflag('h', Fignor);
|
||||
argflag('+', Fignor);
|
||||
argflag('-', Fignor);
|
||||
|
||||
argflag('*', Fstar);
|
||||
argflag('l', Fl);
|
||||
|
||||
argflag('o', Fverb);
|
||||
flagbits['x'] = flagbits['o'];
|
||||
flagbits['X'] = flagbits['o'];
|
||||
}
|
||||
|
||||
void
|
||||
pragvararg(void)
|
||||
{
|
||||
Sym *s;
|
||||
int n, c;
|
||||
char *t;
|
||||
Rune r;
|
||||
Type *ty;
|
||||
|
||||
if(!debug['F'])
|
||||
goto out;
|
||||
s = getsym();
|
||||
if(s && strcmp(s->name, "argpos") == 0)
|
||||
goto ckpos;
|
||||
if(s && strcmp(s->name, "type") == 0)
|
||||
goto cktype;
|
||||
if(s && strcmp(s->name, "flag") == 0)
|
||||
goto ckflag;
|
||||
yyerror("syntax in #pragma varargck");
|
||||
goto out;
|
||||
|
||||
ckpos:
|
||||
/*#pragma varargck argpos warn 2*/
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
n = getnsn();
|
||||
if(n < 0)
|
||||
goto bad;
|
||||
newname(s->name, n);
|
||||
goto out;
|
||||
|
||||
ckflag:
|
||||
/*#pragma varargck flag 'c'*/
|
||||
c = getnsc();
|
||||
if(c != '\'')
|
||||
goto bad;
|
||||
c = getr();
|
||||
if(c == '\\')
|
||||
c = getr();
|
||||
else if(c == '\'')
|
||||
goto bad;
|
||||
if(c == '\n')
|
||||
goto bad;
|
||||
if(getc() != '\'')
|
||||
goto bad;
|
||||
argflag(c, Fignor);
|
||||
goto out;
|
||||
|
||||
cktype:
|
||||
/*#pragma varargck type O int*/
|
||||
c = getnsc();
|
||||
if(c != '"')
|
||||
goto bad;
|
||||
t = fmtbuf;
|
||||
for(;;) {
|
||||
r = getr();
|
||||
if(r == ' ' || r == '\n')
|
||||
goto bad;
|
||||
if(r == '"')
|
||||
break;
|
||||
t += runetochar(t, &r);
|
||||
}
|
||||
*t = 0;
|
||||
t = strdup(fmtbuf);
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
ty = s->type;
|
||||
while((c = getnsc()) == '*')
|
||||
ty = typ(TIND, ty);
|
||||
unget(c);
|
||||
newprot(s, ty, t);
|
||||
goto out;
|
||||
|
||||
bad:
|
||||
yyerror("syntax in #pragma varargck");
|
||||
|
||||
out:
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
Node*
|
||||
nextarg(Node *n, Node **a)
|
||||
{
|
||||
if(n == Z) {
|
||||
*a = Z;
|
||||
return Z;
|
||||
}
|
||||
if(n->op == OLIST) {
|
||||
*a = n->left;
|
||||
return n->right;
|
||||
}
|
||||
*a = n;
|
||||
return Z;
|
||||
}
|
||||
|
||||
void
|
||||
checkargs(Node *nn, char *s, int pos)
|
||||
{
|
||||
Node *a, *n;
|
||||
Bits flag;
|
||||
Tprot *l;
|
||||
|
||||
if(!debug['F'])
|
||||
return;
|
||||
n = nn;
|
||||
for(;;) {
|
||||
s = strchr(s, '%');
|
||||
if(s == 0) {
|
||||
nextarg(n, &a);
|
||||
if(a != Z)
|
||||
warn(nn, "more arguments than format %T",
|
||||
a->type);
|
||||
return;
|
||||
}
|
||||
s++;
|
||||
flag = getflag(s);
|
||||
while(nstar > 0) {
|
||||
n = nextarg(n, &a);
|
||||
pos++;
|
||||
nstar--;
|
||||
if(a == Z) {
|
||||
warn(nn, "more format than arguments %s",
|
||||
fmtbuf);
|
||||
return;
|
||||
}
|
||||
if(a->type == T)
|
||||
continue;
|
||||
if(!sametype(types[TINT], a->type) &&
|
||||
!sametype(types[TUINT], a->type))
|
||||
warn(nn, "format mismatch '*' in %s %T, arg %d",
|
||||
fmtbuf, a->type, pos);
|
||||
}
|
||||
for(l=tprot; l; l=l->link)
|
||||
if(sametype(types[TVOID], l->type)) {
|
||||
if(beq(flag, l->flag)) {
|
||||
s++;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
n = nextarg(n, &a);
|
||||
pos++;
|
||||
if(a == Z) {
|
||||
warn(nn, "more format than arguments %s",
|
||||
fmtbuf);
|
||||
return;
|
||||
}
|
||||
if(a->type == 0)
|
||||
continue;
|
||||
for(l=tprot; l; l=l->link)
|
||||
if(sametype(a->type, l->type)) {
|
||||
/*print("checking %T/%ulx %T/%ulx\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/
|
||||
if(beq(flag, l->flag))
|
||||
goto loop;
|
||||
}
|
||||
warn(nn, "format mismatch %s %T, arg %d", fmtbuf, a->type, pos);
|
||||
loop:;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dpcheck(Node *n)
|
||||
{
|
||||
char *s;
|
||||
Node *a, *b;
|
||||
Tname *l;
|
||||
int i;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
b = n->left;
|
||||
if(b == Z || b->op != ONAME)
|
||||
return;
|
||||
s = b->sym->name;
|
||||
for(l=tname; l; l=l->link)
|
||||
if(strcmp(s, l->name) == 0)
|
||||
break;
|
||||
if(l == 0)
|
||||
return;
|
||||
|
||||
i = l->param;
|
||||
b = n->right;
|
||||
while(i > 0) {
|
||||
b = nextarg(b, &a);
|
||||
i--;
|
||||
}
|
||||
if(a == Z) {
|
||||
warn(n, "cant find format arg");
|
||||
return;
|
||||
}
|
||||
if(!sametype(indchar, a->type)) {
|
||||
warn(n, "format arg type %T", a->type);
|
||||
return;
|
||||
}
|
||||
if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
|
||||
/* warn(n, "format arg not constant string");*/
|
||||
return;
|
||||
}
|
||||
s = a->left->cstring;
|
||||
checkargs(b, s, l->param);
|
||||
}
|
||||
|
||||
void
|
||||
pragpack(void)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
packflg = 0;
|
||||
s = getsym();
|
||||
if(s) {
|
||||
packflg = atoi(s->name+1);
|
||||
if(strcmp(s->name, "on") == 0 ||
|
||||
strcmp(s->name, "yes") == 0)
|
||||
packflg = 1;
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
if(packflg)
|
||||
print("%4ld: pack %d\n", lineno, packflg);
|
||||
else
|
||||
print("%4ld: pack off\n", lineno);
|
||||
}
|
||||
|
||||
void
|
||||
pragfpround(void)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
fproundflg = 0;
|
||||
s = getsym();
|
||||
if(s) {
|
||||
fproundflg = atoi(s->name+1);
|
||||
if(strcmp(s->name, "on") == 0 ||
|
||||
strcmp(s->name, "yes") == 0)
|
||||
fproundflg = 1;
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
if(fproundflg)
|
||||
print("%4ld: fproundflg %d\n", lineno, fproundflg);
|
||||
else
|
||||
print("%4ld: fproundflg off\n", lineno);
|
||||
}
|
||||
|
||||
void
|
||||
pragprofile(void)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
profileflg = 0;
|
||||
s = getsym();
|
||||
if(s) {
|
||||
profileflg = atoi(s->name+1);
|
||||
if(strcmp(s->name, "on") == 0 ||
|
||||
strcmp(s->name, "yes") == 0)
|
||||
profileflg = 1;
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
if(profileflg)
|
||||
print("%4ld: profileflg %d\n", lineno, profileflg);
|
||||
else
|
||||
print("%4ld: profileflg off\n", lineno);
|
||||
}
|
||||
|
||||
void
|
||||
pragincomplete(void)
|
||||
{
|
||||
Sym *s;
|
||||
Type *t;
|
||||
int istag, w, et;
|
||||
|
||||
istag = 0;
|
||||
s = getsym();
|
||||
if(s == nil)
|
||||
goto out;
|
||||
et = 0;
|
||||
w = s->lexical;
|
||||
if(w == LSTRUCT)
|
||||
et = TSTRUCT;
|
||||
else if(w == LUNION)
|
||||
et = TUNION;
|
||||
if(et != 0){
|
||||
s = getsym();
|
||||
if(s == nil){
|
||||
yyerror("missing struct/union tag in pragma incomplete");
|
||||
goto out;
|
||||
}
|
||||
if(s->lexical != LNAME && s->lexical != LTYPE){
|
||||
yyerror("invalid struct/union tag: %s", s->name);
|
||||
goto out;
|
||||
}
|
||||
dotag(s, et, 0);
|
||||
istag = 1;
|
||||
}else if(strcmp(s->name, "_off_") == 0){
|
||||
debug['T'] = 0;
|
||||
goto out;
|
||||
}else if(strcmp(s->name, "_on_") == 0){
|
||||
debug['T'] = 1;
|
||||
goto out;
|
||||
}
|
||||
t = s->type;
|
||||
if(istag)
|
||||
t = s->suetag;
|
||||
if(t == T)
|
||||
yyerror("unknown type %s in pragma incomplete", s->name);
|
||||
else if(!typesu[t->etype])
|
||||
yyerror("not struct/union type in pragma incomplete: %s", s->name);
|
||||
else
|
||||
t->garb |= GINCOMPLETE;
|
||||
out:
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
print("%s incomplete\n", s->name);
|
||||
}
|
||||
430
src/cmd/cc/funct.c
Normal file
430
src/cmd/cc/funct.c
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
// Inferno utils/cc/funct.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/funct.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
typedef struct Ftab Ftab;
|
||||
struct Ftab
|
||||
{
|
||||
char op;
|
||||
char* name;
|
||||
char typ;
|
||||
};
|
||||
typedef struct Gtab Gtab;
|
||||
struct Gtab
|
||||
{
|
||||
char etype;
|
||||
char* name;
|
||||
};
|
||||
|
||||
Ftab ftabinit[OEND];
|
||||
Gtab gtabinit[NTYPE];
|
||||
|
||||
int
|
||||
isfunct(Node *n)
|
||||
{
|
||||
Type *t, *t1;
|
||||
Funct *f;
|
||||
Node *l;
|
||||
Sym *s;
|
||||
int o;
|
||||
|
||||
o = n->op;
|
||||
if(n->left == Z)
|
||||
goto no;
|
||||
t = n->left->type;
|
||||
if(t == T)
|
||||
goto no;
|
||||
f = t->funct;
|
||||
|
||||
switch(o) {
|
||||
case OAS: // put cast on rhs
|
||||
case OASI:
|
||||
case OASADD:
|
||||
case OASAND:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASDIV:
|
||||
case OASLDIV:
|
||||
case OASLMOD:
|
||||
case OASLMUL:
|
||||
case OASLSHR:
|
||||
case OASMOD:
|
||||
case OASMUL:
|
||||
case OASOR:
|
||||
case OASSUB:
|
||||
case OASXOR:
|
||||
if(n->right == Z)
|
||||
goto no;
|
||||
t1 = n->right->type;
|
||||
if(t1 == T)
|
||||
goto no;
|
||||
if(t1->funct == f)
|
||||
break;
|
||||
|
||||
l = new(OXXX, Z, Z);
|
||||
*l = *n->right;
|
||||
|
||||
n->right->left = l;
|
||||
n->right->right = Z;
|
||||
n->right->type = t;
|
||||
n->right->op = OCAST;
|
||||
|
||||
if(!isfunct(n->right))
|
||||
prtree(n, "isfunc !");
|
||||
break;
|
||||
|
||||
case OCAST: // t f(T) or T f(t)
|
||||
t1 = n->type;
|
||||
if(t1 == T)
|
||||
goto no;
|
||||
if(f != nil) {
|
||||
s = f->castfr[t1->etype];
|
||||
if(s == S)
|
||||
goto no;
|
||||
n->right = n->left;
|
||||
goto build;
|
||||
}
|
||||
f = t1->funct;
|
||||
if(f != nil) {
|
||||
s = f->castto[t->etype];
|
||||
if(s == S)
|
||||
goto no;
|
||||
n->right = n->left;
|
||||
goto build;
|
||||
}
|
||||
goto no;
|
||||
}
|
||||
|
||||
if(f == nil)
|
||||
goto no;
|
||||
s = f->sym[o];
|
||||
if(s == S)
|
||||
goto no;
|
||||
|
||||
/*
|
||||
* the answer is yes,
|
||||
* now we rewrite the node
|
||||
* and give diagnostics
|
||||
*/
|
||||
switch(o) {
|
||||
default:
|
||||
diag(n, "isfunct op missing %O\n", o);
|
||||
goto bad;
|
||||
|
||||
case OADD: // T f(T, T)
|
||||
case OAND:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
case ODIV:
|
||||
case OLDIV:
|
||||
case OLMOD:
|
||||
case OLMUL:
|
||||
case OLSHR:
|
||||
case OMOD:
|
||||
case OMUL:
|
||||
case OOR:
|
||||
case OSUB:
|
||||
case OXOR:
|
||||
|
||||
case OEQ: // int f(T, T)
|
||||
case OGE:
|
||||
case OGT:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLE:
|
||||
case OLO:
|
||||
case OLS:
|
||||
case OLT:
|
||||
case ONE:
|
||||
if(n->right == Z)
|
||||
goto bad;
|
||||
t1 = n->right->type;
|
||||
if(t1 == T)
|
||||
goto bad;
|
||||
if(t1->funct != f)
|
||||
goto bad;
|
||||
n->right = new(OLIST, n->left, n->right);
|
||||
break;
|
||||
|
||||
case OAS: // structure copies done by the compiler
|
||||
case OASI:
|
||||
goto no;
|
||||
|
||||
case OASADD: // T f(T*, T)
|
||||
case OASAND:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASDIV:
|
||||
case OASLDIV:
|
||||
case OASLMOD:
|
||||
case OASLMUL:
|
||||
case OASLSHR:
|
||||
case OASMOD:
|
||||
case OASMUL:
|
||||
case OASOR:
|
||||
case OASSUB:
|
||||
case OASXOR:
|
||||
if(n->right == Z)
|
||||
goto bad;
|
||||
t1 = n->right->type;
|
||||
if(t1 == T)
|
||||
goto bad;
|
||||
if(t1->funct != f)
|
||||
goto bad;
|
||||
n->right = new(OLIST, new(OADDR, n->left, Z), n->right);
|
||||
break;
|
||||
|
||||
case OPOS: // T f(T)
|
||||
case ONEG:
|
||||
case ONOT:
|
||||
case OCOM:
|
||||
n->right = n->left;
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
build:
|
||||
l = new(ONAME, Z, Z);
|
||||
l->sym = s;
|
||||
l->type = s->type;
|
||||
l->etype = s->type->etype;
|
||||
l->xoffset = s->offset;
|
||||
l->class = s->class;
|
||||
tcomo(l, 0);
|
||||
|
||||
n->op = OFUNC;
|
||||
n->left = l;
|
||||
n->type = l->type->link;
|
||||
if(tcompat(n, T, l->type, tfunct))
|
||||
goto bad;
|
||||
if(tcoma(n->left, n->right, l->type->down, 1))
|
||||
goto bad;
|
||||
return 1;
|
||||
|
||||
no:
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
diag(n, "cant rewrite typestr for op %O\n", o);
|
||||
prtree(n, "isfunct");
|
||||
n->type = T;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
dclfunct(Type *t, Sym *s)
|
||||
{
|
||||
Funct *f;
|
||||
Node *n;
|
||||
Type *f1, *f2, *f3, *f4;
|
||||
int o, i, c;
|
||||
char str[100];
|
||||
|
||||
if(t->funct)
|
||||
return;
|
||||
|
||||
// recognize generated tag of dorm _%d_
|
||||
if(t->tag == S)
|
||||
goto bad;
|
||||
for(i=0; c = t->tag->name[i]; i++) {
|
||||
if(c == '_') {
|
||||
if(i == 0 || t->tag->name[i+1] == 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if(c < '0' || c > '9')
|
||||
break;
|
||||
}
|
||||
if(c == 0)
|
||||
goto bad;
|
||||
|
||||
f = alloc(sizeof(*f));
|
||||
for(o=0; o<sizeof(f->sym); o++)
|
||||
f->sym[o] = S;
|
||||
|
||||
t->funct = f;
|
||||
|
||||
f1 = typ(TFUNC, t);
|
||||
f1->down = copytyp(t);
|
||||
f1->down->down = t;
|
||||
|
||||
f2 = typ(TFUNC, types[TINT]);
|
||||
f2->down = copytyp(t);
|
||||
f2->down->down = t;
|
||||
|
||||
f3 = typ(TFUNC, t);
|
||||
f3->down = typ(TIND, t);
|
||||
f3->down->down = t;
|
||||
|
||||
f4 = typ(TFUNC, t);
|
||||
f4->down = t;
|
||||
|
||||
for(i=0;; i++) {
|
||||
o = ftabinit[i].op;
|
||||
if(o == OXXX)
|
||||
break;
|
||||
sprint(str, "%s_%s_", t->tag->name, ftabinit[i].name);
|
||||
n = new(ONAME, Z, Z);
|
||||
n->sym = slookup(str);
|
||||
f->sym[o] = n->sym;
|
||||
switch(ftabinit[i].typ) {
|
||||
default:
|
||||
diag(Z, "dclfunct op missing %d\n", ftabinit[i].typ);
|
||||
break;
|
||||
|
||||
case 1: // T f(T,T) +
|
||||
dodecl(xdecl, CEXTERN, f1, n);
|
||||
break;
|
||||
|
||||
case 2: // int f(T,T) ==
|
||||
dodecl(xdecl, CEXTERN, f2, n);
|
||||
break;
|
||||
|
||||
case 3: // void f(T*,T) +=
|
||||
dodecl(xdecl, CEXTERN, f3, n);
|
||||
break;
|
||||
|
||||
case 4: // T f(T) ~
|
||||
dodecl(xdecl, CEXTERN, f4, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i=0;; i++) {
|
||||
o = gtabinit[i].etype;
|
||||
if(o == TXXX)
|
||||
break;
|
||||
|
||||
/*
|
||||
* OCAST types T1 _T2_T1_(T2)
|
||||
*/
|
||||
sprint(str, "_%s%s_", gtabinit[i].name, t->tag->name);
|
||||
n = new(ONAME, Z, Z);
|
||||
n->sym = slookup(str);
|
||||
f->castto[o] = n->sym;
|
||||
|
||||
f1 = typ(TFUNC, t);
|
||||
f1->down = types[o];
|
||||
dodecl(xdecl, CEXTERN, f1, n);
|
||||
|
||||
sprint(str, "%s_%s_", t->tag->name, gtabinit[i].name);
|
||||
n = new(ONAME, Z, Z);
|
||||
n->sym = slookup(str);
|
||||
f->castfr[o] = n->sym;
|
||||
|
||||
f1 = typ(TFUNC, types[o]);
|
||||
f1->down = t;
|
||||
dodecl(xdecl, CEXTERN, f1, n);
|
||||
}
|
||||
return;
|
||||
bad:
|
||||
diag(Z, "dclfunct bad %T %s\n", t, s->name);
|
||||
}
|
||||
|
||||
Gtab gtabinit[NTYPE] =
|
||||
{
|
||||
TCHAR, "c",
|
||||
TUCHAR, "uc",
|
||||
TSHORT, "h",
|
||||
TUSHORT, "uh",
|
||||
TINT, "i",
|
||||
TUINT, "ui",
|
||||
TLONG, "l",
|
||||
TULONG, "ul",
|
||||
TVLONG, "v",
|
||||
TUVLONG, "uv",
|
||||
TFLOAT, "f",
|
||||
TDOUBLE, "d",
|
||||
TXXX
|
||||
};
|
||||
|
||||
Ftab ftabinit[OEND] =
|
||||
{
|
||||
OADD, "add", 1,
|
||||
OAND, "and", 1,
|
||||
OASHL, "ashl", 1,
|
||||
OASHR, "ashr", 1,
|
||||
ODIV, "div", 1,
|
||||
OLDIV, "ldiv", 1,
|
||||
OLMOD, "lmod", 1,
|
||||
OLMUL, "lmul", 1,
|
||||
OLSHR, "lshr", 1,
|
||||
OMOD, "mod", 1,
|
||||
OMUL, "mul", 1,
|
||||
OOR, "or", 1,
|
||||
OSUB, "sub", 1,
|
||||
OXOR, "xor", 1,
|
||||
|
||||
OEQ, "eq", 2,
|
||||
OGE, "ge", 2,
|
||||
OGT, "gt", 2,
|
||||
OHI, "hi", 2,
|
||||
OHS, "hs", 2,
|
||||
OLE, "le", 2,
|
||||
OLO, "lo", 2,
|
||||
OLS, "ls", 2,
|
||||
OLT, "lt", 2,
|
||||
ONE, "ne", 2,
|
||||
|
||||
OASADD, "asadd", 3,
|
||||
OASAND, "asand", 3,
|
||||
OASASHL, "asashl", 3,
|
||||
OASASHR, "asashr", 3,
|
||||
OASDIV, "asdiv", 3,
|
||||
OASLDIV, "asldiv", 3,
|
||||
OASLMOD, "aslmod", 3,
|
||||
OASLMUL, "aslmul", 3,
|
||||
OASLSHR, "aslshr", 3,
|
||||
OASMOD, "asmod", 3,
|
||||
OASMUL, "asmul", 3,
|
||||
OASOR, "asor", 3,
|
||||
OASSUB, "assub", 3,
|
||||
OASXOR, "asxor", 3,
|
||||
|
||||
OPOS, "pos", 4,
|
||||
ONEG, "neg", 4,
|
||||
OCOM, "com", 4,
|
||||
ONOT, "not", 4,
|
||||
|
||||
// OPOSTDEC,
|
||||
// OPOSTINC,
|
||||
// OPREDEC,
|
||||
// OPREINC,
|
||||
|
||||
OXXX,
|
||||
};
|
||||
|
||||
// Node* nodtestv;
|
||||
|
||||
// Node* nodvpp;
|
||||
// Node* nodppv;
|
||||
// Node* nodvmm;
|
||||
// Node* nodmmv;
|
||||
1542
src/cmd/cc/lex.c
Normal file
1542
src/cmd/cc/lex.c
Normal file
File diff suppressed because it is too large
Load diff
723
src/cmd/cc/lexbody
Normal file
723
src/cmd/cc/lexbody
Normal file
|
|
@ -0,0 +1,723 @@
|
|||
// Inferno utils/cc/lexbody
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/lexbody
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
/*
|
||||
* common code for all the assemblers
|
||||
*/
|
||||
|
||||
void
|
||||
pragpack(void)
|
||||
{
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
pragvararg(void)
|
||||
{
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
pragfpround(void)
|
||||
{
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
pragprofile(void)
|
||||
{
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
pragincomplete(void)
|
||||
{
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
gethunk(void)
|
||||
{
|
||||
hunk = malloc(NHUNK);
|
||||
memset(hunk, 0, NHUNK);
|
||||
nhunk = NHUNK;
|
||||
}
|
||||
|
||||
void*
|
||||
alloc(long n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
while((uintptr)hunk & MAXALIGN) {
|
||||
hunk++;
|
||||
nhunk--;
|
||||
}
|
||||
while(nhunk < n)
|
||||
gethunk();
|
||||
p = hunk;
|
||||
nhunk -= n;
|
||||
hunk += n;
|
||||
return p;
|
||||
}
|
||||
|
||||
void*
|
||||
allocn(void *p, long on, long n)
|
||||
{
|
||||
void *q;
|
||||
|
||||
q = (uchar*)p + on;
|
||||
if(q != hunk || nhunk < n) {
|
||||
while(nhunk < on+n)
|
||||
gethunk();
|
||||
memmove(hunk, p, on);
|
||||
p = hunk;
|
||||
hunk += on;
|
||||
nhunk -= on;
|
||||
}
|
||||
hunk += n;
|
||||
nhunk -= n;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
setinclude(char *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(p == 0)
|
||||
return;
|
||||
for(i=1; i < ninclude; i++)
|
||||
if(strcmp(p, include[i]) == 0)
|
||||
return;
|
||||
|
||||
if(ninclude >= nelem(include)) {
|
||||
yyerror("ninclude too small %d", nelem(include));
|
||||
exits("ninclude");
|
||||
}
|
||||
include[ninclude++] = p;
|
||||
}
|
||||
|
||||
void
|
||||
errorexit(void)
|
||||
{
|
||||
|
||||
if(outfile)
|
||||
remove(outfile);
|
||||
exits("error");
|
||||
}
|
||||
|
||||
void
|
||||
pushio(void)
|
||||
{
|
||||
Io *i;
|
||||
|
||||
i = iostack;
|
||||
if(i == I) {
|
||||
yyerror("botch in pushio");
|
||||
errorexit();
|
||||
}
|
||||
i->p = fi.p;
|
||||
i->c = fi.c;
|
||||
}
|
||||
|
||||
void
|
||||
newio(void)
|
||||
{
|
||||
Io *i;
|
||||
static int pushdepth = 0;
|
||||
|
||||
i = iofree;
|
||||
if(i == I) {
|
||||
pushdepth++;
|
||||
if(pushdepth > 1000) {
|
||||
yyerror("macro/io expansion too deep");
|
||||
errorexit();
|
||||
}
|
||||
i = alloc(sizeof(*i));
|
||||
} else
|
||||
iofree = i->link;
|
||||
i->c = 0;
|
||||
i->f = -1;
|
||||
ionext = i;
|
||||
}
|
||||
|
||||
void
|
||||
newfile(char *s, int f)
|
||||
{
|
||||
Io *i;
|
||||
|
||||
i = ionext;
|
||||
i->link = iostack;
|
||||
iostack = i;
|
||||
i->f = f;
|
||||
if(f < 0)
|
||||
i->f = open(s, 0);
|
||||
if(i->f < 0) {
|
||||
yyerror("%ca: %r: %s", thechar, s);
|
||||
errorexit();
|
||||
}
|
||||
fi.c = 0;
|
||||
linehist(s, 0);
|
||||
}
|
||||
|
||||
Sym*
|
||||
slookup(char *s)
|
||||
{
|
||||
|
||||
strcpy(symb, s);
|
||||
return lookup();
|
||||
}
|
||||
|
||||
Sym*
|
||||
lookup(void)
|
||||
{
|
||||
Sym *s;
|
||||
long h;
|
||||
char *p;
|
||||
int c, l;
|
||||
|
||||
h = 0;
|
||||
for(p=symb; c = *p; p++)
|
||||
h = h+h+h + c;
|
||||
l = (p - symb) + 1;
|
||||
if(h < 0)
|
||||
h = ~h;
|
||||
h %= NHASH;
|
||||
c = symb[0];
|
||||
for(s = hash[h]; s != S; s = s->link) {
|
||||
if(s->name[0] != c)
|
||||
continue;
|
||||
if(memcmp(s->name, symb, l) == 0)
|
||||
return s;
|
||||
}
|
||||
s = alloc(sizeof(*s));
|
||||
s->name = alloc(l);
|
||||
memmove(s->name, symb, l);
|
||||
|
||||
s->link = hash[h];
|
||||
hash[h] = s;
|
||||
syminit(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
long
|
||||
yylex(void)
|
||||
{
|
||||
int c, c1;
|
||||
char *cp;
|
||||
Sym *s;
|
||||
|
||||
c = peekc;
|
||||
if(c != IGN) {
|
||||
peekc = IGN;
|
||||
goto l1;
|
||||
}
|
||||
l0:
|
||||
c = GETC();
|
||||
|
||||
l1:
|
||||
if(c == EOF) {
|
||||
peekc = EOF;
|
||||
return -1;
|
||||
}
|
||||
if(isspace(c)) {
|
||||
if(c == '\n') {
|
||||
lineno++;
|
||||
return ';';
|
||||
}
|
||||
goto l0;
|
||||
}
|
||||
if(isalpha(c))
|
||||
goto talph;
|
||||
if(isdigit(c))
|
||||
goto tnum;
|
||||
switch(c)
|
||||
{
|
||||
case '\n':
|
||||
lineno++;
|
||||
return ';';
|
||||
|
||||
case '#':
|
||||
domacro();
|
||||
goto l0;
|
||||
|
||||
case '.':
|
||||
c = GETC();
|
||||
if(isalpha(c)) {
|
||||
cp = symb;
|
||||
*cp++ = '.';
|
||||
goto aloop;
|
||||
}
|
||||
if(isdigit(c)) {
|
||||
cp = symb;
|
||||
*cp++ = '.';
|
||||
goto casedot;
|
||||
}
|
||||
peekc = c;
|
||||
return '.';
|
||||
|
||||
talph:
|
||||
case '_':
|
||||
case '@':
|
||||
cp = symb;
|
||||
|
||||
aloop:
|
||||
*cp++ = c;
|
||||
c = GETC();
|
||||
if(isalpha(c) || isdigit(c) || c == '_' || c == '$')
|
||||
goto aloop;
|
||||
*cp = 0;
|
||||
peekc = c;
|
||||
s = lookup();
|
||||
if(s->macro) {
|
||||
newio();
|
||||
cp = ionext->b;
|
||||
macexpand(s, cp);
|
||||
pushio();
|
||||
ionext->link = iostack;
|
||||
iostack = ionext;
|
||||
fi.p = cp;
|
||||
fi.c = strlen(cp);
|
||||
if(peekc != IGN) {
|
||||
cp[fi.c++] = peekc;
|
||||
cp[fi.c] = 0;
|
||||
peekc = IGN;
|
||||
}
|
||||
goto l0;
|
||||
}
|
||||
if(s->type == 0)
|
||||
s->type = LNAME;
|
||||
if(s->type == LNAME ||
|
||||
s->type == LVAR ||
|
||||
s->type == LLAB) {
|
||||
yylval.sym = s;
|
||||
return s->type;
|
||||
}
|
||||
yylval.lval = s->value;
|
||||
return s->type;
|
||||
|
||||
tnum:
|
||||
cp = symb;
|
||||
if(c != '0')
|
||||
goto dc;
|
||||
*cp++ = c;
|
||||
c = GETC();
|
||||
c1 = 3;
|
||||
if(c == 'x' || c == 'X') {
|
||||
c1 = 4;
|
||||
c = GETC();
|
||||
} else
|
||||
if(c < '0' || c > '7')
|
||||
goto dc;
|
||||
yylval.lval = 0;
|
||||
for(;;) {
|
||||
if(c >= '0' && c <= '9') {
|
||||
if(c > '7' && c1 == 3)
|
||||
break;
|
||||
yylval.lval <<= c1;
|
||||
yylval.lval += c - '0';
|
||||
c = GETC();
|
||||
continue;
|
||||
}
|
||||
if(c1 == 3)
|
||||
break;
|
||||
if(c >= 'A' && c <= 'F')
|
||||
c += 'a' - 'A';
|
||||
if(c >= 'a' && c <= 'f') {
|
||||
yylval.lval <<= c1;
|
||||
yylval.lval += c - 'a' + 10;
|
||||
c = GETC();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
goto ncu;
|
||||
|
||||
dc:
|
||||
for(;;) {
|
||||
if(!isdigit(c))
|
||||
break;
|
||||
*cp++ = c;
|
||||
c = GETC();
|
||||
}
|
||||
if(c == '.')
|
||||
goto casedot;
|
||||
if(c == 'e' || c == 'E')
|
||||
goto casee;
|
||||
*cp = 0;
|
||||
if(sizeof(yylval.lval) == sizeof(vlong))
|
||||
yylval.lval = strtoll(symb, nil, 10);
|
||||
else
|
||||
yylval.lval = strtol(symb, nil, 10);
|
||||
|
||||
ncu:
|
||||
while(c == 'U' || c == 'u' || c == 'l' || c == 'L')
|
||||
c = GETC();
|
||||
peekc = c;
|
||||
return LCONST;
|
||||
|
||||
casedot:
|
||||
for(;;) {
|
||||
*cp++ = c;
|
||||
c = GETC();
|
||||
if(!isdigit(c))
|
||||
break;
|
||||
}
|
||||
if(c == 'e' || c == 'E')
|
||||
goto casee;
|
||||
goto caseout;
|
||||
|
||||
casee:
|
||||
*cp++ = 'e';
|
||||
c = GETC();
|
||||
if(c == '+' || c == '-') {
|
||||
*cp++ = c;
|
||||
c = GETC();
|
||||
}
|
||||
while(isdigit(c)) {
|
||||
*cp++ = c;
|
||||
c = GETC();
|
||||
}
|
||||
|
||||
caseout:
|
||||
*cp = 0;
|
||||
peekc = c;
|
||||
if(FPCHIP) {
|
||||
yylval.dval = atof(symb);
|
||||
return LFCONST;
|
||||
}
|
||||
yyerror("assembler cannot interpret fp constants");
|
||||
yylval.lval = 1L;
|
||||
return LCONST;
|
||||
|
||||
case '"':
|
||||
memcpy(yylval.sval, nullgen.sval, sizeof(yylval.sval));
|
||||
cp = yylval.sval;
|
||||
c1 = 0;
|
||||
for(;;) {
|
||||
c = escchar('"');
|
||||
if(c == EOF)
|
||||
break;
|
||||
if(c1 < sizeof(yylval.sval))
|
||||
*cp++ = c;
|
||||
c1++;
|
||||
}
|
||||
if(c1 > sizeof(yylval.sval))
|
||||
yyerror("string constant too long");
|
||||
return LSCONST;
|
||||
|
||||
case '\'':
|
||||
c = escchar('\'');
|
||||
if(c == EOF)
|
||||
c = '\'';
|
||||
if(escchar('\'') != EOF)
|
||||
yyerror("missing '");
|
||||
yylval.lval = c;
|
||||
return LCONST;
|
||||
|
||||
case '/':
|
||||
c1 = GETC();
|
||||
if(c1 == '/') {
|
||||
for(;;) {
|
||||
c = GETC();
|
||||
if(c == '\n') {
|
||||
lineno++;
|
||||
goto l1;
|
||||
}
|
||||
if(c == EOF) {
|
||||
yyerror("eof in comment");
|
||||
errorexit();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(c1 == '*') {
|
||||
for(;;) {
|
||||
c = GETC();
|
||||
while(c == '*') {
|
||||
c = GETC();
|
||||
if(c == '/')
|
||||
goto l0;
|
||||
}
|
||||
if(c == EOF) {
|
||||
yyerror("eof in comment");
|
||||
errorexit();
|
||||
}
|
||||
if(c == '\n')
|
||||
lineno++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
peekc = c1;
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
getc(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = peekc;
|
||||
if(c != IGN) {
|
||||
peekc = IGN;
|
||||
return c;
|
||||
}
|
||||
c = GETC();
|
||||
if(c == '\n')
|
||||
lineno++;
|
||||
if(c == EOF) {
|
||||
yyerror("End of file");
|
||||
errorexit();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
getnsc(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
for(;;) {
|
||||
c = getc();
|
||||
if(!isspace(c) || c == '\n')
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
unget(int c)
|
||||
{
|
||||
|
||||
peekc = c;
|
||||
if(c == '\n')
|
||||
lineno--;
|
||||
}
|
||||
|
||||
int
|
||||
escchar(int e)
|
||||
{
|
||||
int c, l;
|
||||
|
||||
loop:
|
||||
c = getc();
|
||||
if(c == '\n') {
|
||||
yyerror("newline in string");
|
||||
return EOF;
|
||||
}
|
||||
if(c != '\\') {
|
||||
if(c == e)
|
||||
return EOF;
|
||||
return c;
|
||||
}
|
||||
c = getc();
|
||||
if(c >= '0' && c <= '7') {
|
||||
l = c - '0';
|
||||
c = getc();
|
||||
if(c >= '0' && c <= '7') {
|
||||
l = l*8 + c-'0';
|
||||
c = getc();
|
||||
if(c >= '0' && c <= '7') {
|
||||
l = l*8 + c-'0';
|
||||
return l;
|
||||
}
|
||||
}
|
||||
peekc = c;
|
||||
return l;
|
||||
}
|
||||
switch(c)
|
||||
{
|
||||
case '\n': goto loop;
|
||||
case 'n': return '\n';
|
||||
case 't': return '\t';
|
||||
case 'b': return '\b';
|
||||
case 'r': return '\r';
|
||||
case 'f': return '\f';
|
||||
case 'a': return 0x07;
|
||||
case 'v': return 0x0b;
|
||||
case 'z': return 0x00;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
pinit(char *f)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
|
||||
lineno = 1;
|
||||
newio();
|
||||
newfile(f, -1);
|
||||
pc = 0;
|
||||
peekc = IGN;
|
||||
sym = 1;
|
||||
for(i=0; i<NSYM; i++) {
|
||||
h[i].type = 0;
|
||||
h[i].sym = S;
|
||||
}
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
s->macro = 0;
|
||||
}
|
||||
|
||||
int
|
||||
filbuf(void)
|
||||
{
|
||||
Io *i;
|
||||
|
||||
loop:
|
||||
i = iostack;
|
||||
if(i == I)
|
||||
return EOF;
|
||||
if(i->f < 0)
|
||||
goto pop;
|
||||
fi.c = read(i->f, i->b, BUFSIZ) - 1;
|
||||
if(fi.c < 0) {
|
||||
close(i->f);
|
||||
linehist(0, 0);
|
||||
goto pop;
|
||||
}
|
||||
fi.p = i->b + 1;
|
||||
return i->b[0];
|
||||
|
||||
pop:
|
||||
iostack = i->link;
|
||||
i->link = iofree;
|
||||
iofree = i;
|
||||
i = iostack;
|
||||
if(i == I)
|
||||
return EOF;
|
||||
fi.p = i->p;
|
||||
fi.c = i->c;
|
||||
if(--fi.c < 0)
|
||||
goto loop;
|
||||
return *fi.p++;
|
||||
}
|
||||
|
||||
void
|
||||
yyerror(char *a, ...)
|
||||
{
|
||||
char buf[200];
|
||||
va_list arg;
|
||||
|
||||
/*
|
||||
* hack to intercept message from yaccpar
|
||||
*/
|
||||
if(strcmp(a, "syntax error") == 0) {
|
||||
yyerror("syntax error, last name: %s", symb);
|
||||
return;
|
||||
}
|
||||
prfile(lineno);
|
||||
va_start(arg, a);
|
||||
vseprint(buf, buf+sizeof(buf), a, arg);
|
||||
va_end(arg);
|
||||
print("%s\n", buf);
|
||||
nerrors++;
|
||||
if(nerrors > 10) {
|
||||
print("too many errors\n");
|
||||
errorexit();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
prfile(long l)
|
||||
{
|
||||
int i, n;
|
||||
Hist a[HISTSZ], *h;
|
||||
long d;
|
||||
|
||||
n = 0;
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
if(l < h->line)
|
||||
break;
|
||||
if(h->name) {
|
||||
if(h->offset == 0) {
|
||||
if(n >= 0 && n < HISTSZ)
|
||||
a[n] = *h;
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
if(n > 0 && n < HISTSZ)
|
||||
if(a[n-1].offset == 0) {
|
||||
a[n] = *h;
|
||||
n++;
|
||||
} else
|
||||
a[n-1] = *h;
|
||||
continue;
|
||||
}
|
||||
n--;
|
||||
if(n >= 0 && n < HISTSZ) {
|
||||
d = h->line - a[n].line;
|
||||
for(i=0; i<n; i++)
|
||||
a[i].line += d;
|
||||
}
|
||||
}
|
||||
if(n > HISTSZ)
|
||||
n = HISTSZ;
|
||||
for(i=0; i<n; i++)
|
||||
print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1));
|
||||
}
|
||||
|
||||
void
|
||||
ieeedtod(Ieee *ieee, double native)
|
||||
{
|
||||
double fr, ho, f;
|
||||
int exp;
|
||||
|
||||
if(native < 0) {
|
||||
ieeedtod(ieee, -native);
|
||||
ieee->h |= 0x80000000L;
|
||||
return;
|
||||
}
|
||||
if(native == 0) {
|
||||
ieee->l = 0;
|
||||
ieee->h = 0;
|
||||
return;
|
||||
}
|
||||
fr = frexp(native, &exp);
|
||||
f = 2097152L; /* shouldnt use fp constants here */
|
||||
fr = modf(fr*f, &ho);
|
||||
ieee->h = ho;
|
||||
ieee->h &= 0xfffffL;
|
||||
ieee->h |= (exp+1022L) << 20;
|
||||
f = 65536L;
|
||||
fr = modf(fr*f, &ho);
|
||||
ieee->l = ho;
|
||||
ieee->l <<= 16;
|
||||
ieee->l |= (long)(fr*f);
|
||||
}
|
||||
33
src/cmd/cc/mac.c
Normal file
33
src/cmd/cc/mac.c
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Inferno utils/cc/mac.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/mac.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
#include "macbody"
|
||||
842
src/cmd/cc/macbody
Normal file
842
src/cmd/cc/macbody
Normal file
|
|
@ -0,0 +1,842 @@
|
|||
// Inferno utils/cc/macbody
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/macbody
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#define VARMAC 0x80
|
||||
|
||||
long
|
||||
getnsn(void)
|
||||
{
|
||||
long n;
|
||||
int c;
|
||||
|
||||
c = getnsc();
|
||||
if(c < '0' || c > '9')
|
||||
return -1;
|
||||
n = 0;
|
||||
while(c >= '0' && c <= '9') {
|
||||
n = n*10 + c-'0';
|
||||
c = getc();
|
||||
}
|
||||
unget(c);
|
||||
return n;
|
||||
}
|
||||
|
||||
Sym*
|
||||
getsym(void)
|
||||
{
|
||||
int c;
|
||||
char *cp;
|
||||
|
||||
c = getnsc();
|
||||
if(!isalpha(c) && c != '_') {
|
||||
unget(c);
|
||||
return S;
|
||||
}
|
||||
for(cp = symb;;) {
|
||||
if(cp <= symb+NSYMB-4)
|
||||
*cp++ = c;
|
||||
c = getc();
|
||||
if(isalnum(c) || c == '_')
|
||||
continue;
|
||||
unget(c);
|
||||
break;
|
||||
}
|
||||
*cp = 0;
|
||||
if(cp > symb+NSYMB-4)
|
||||
yyerror("symbol too large: %s", symb);
|
||||
return lookup();
|
||||
}
|
||||
|
||||
Sym*
|
||||
getsymdots(int *dots)
|
||||
{
|
||||
int c;
|
||||
Sym *s;
|
||||
|
||||
s = getsym();
|
||||
if(s != S)
|
||||
return s;
|
||||
|
||||
c = getnsc();
|
||||
if(c != '.'){
|
||||
unget(c);
|
||||
return S;
|
||||
}
|
||||
if(getc() != '.' || getc() != '.')
|
||||
yyerror("bad dots in macro");
|
||||
*dots = 1;
|
||||
return slookup("__VA_ARGS__");
|
||||
}
|
||||
|
||||
int
|
||||
getcom(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
for(;;) {
|
||||
c = getnsc();
|
||||
if(c != '/')
|
||||
break;
|
||||
c = getc();
|
||||
if(c == '/') {
|
||||
while(c != '\n')
|
||||
c = getc();
|
||||
break;
|
||||
}
|
||||
if(c != '*')
|
||||
break;
|
||||
c = getc();
|
||||
for(;;) {
|
||||
if(c == '*') {
|
||||
c = getc();
|
||||
if(c != '/')
|
||||
continue;
|
||||
c = getc();
|
||||
break;
|
||||
}
|
||||
if(c == '\n') {
|
||||
yyerror("comment across newline");
|
||||
break;
|
||||
}
|
||||
c = getc();
|
||||
}
|
||||
if(c == '\n')
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
dodefine(char *cp)
|
||||
{
|
||||
Sym *s;
|
||||
char *p;
|
||||
long l;
|
||||
|
||||
strcpy(symb, cp);
|
||||
p = strchr(symb, '=');
|
||||
if(p) {
|
||||
*p++ = 0;
|
||||
s = lookup();
|
||||
l = strlen(p) + 2; /* +1 null, +1 nargs */
|
||||
s->macro = alloc(l);
|
||||
strcpy(s->macro+1, p);
|
||||
} else {
|
||||
s = lookup();
|
||||
s->macro = "\0001"; /* \000 is nargs */
|
||||
}
|
||||
if(debug['m'])
|
||||
print("#define (-D) %s %s\n", s->name, s->macro+1);
|
||||
}
|
||||
|
||||
struct
|
||||
{
|
||||
char *macname;
|
||||
void (*macf)(void);
|
||||
} mactab[] =
|
||||
{
|
||||
"ifdef", 0, /* macif(0) */
|
||||
"ifndef", 0, /* macif(1) */
|
||||
"else", 0, /* macif(2) */
|
||||
|
||||
"line", maclin,
|
||||
"define", macdef,
|
||||
"include", macinc,
|
||||
"undef", macund,
|
||||
|
||||
"pragma", macprag,
|
||||
"endif", macend,
|
||||
0
|
||||
};
|
||||
|
||||
void
|
||||
domacro(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
s = slookup("endif");
|
||||
for(i=0; mactab[i].macname; i++)
|
||||
if(strcmp(s->name, mactab[i].macname) == 0) {
|
||||
if(mactab[i].macf)
|
||||
(*mactab[i].macf)();
|
||||
else
|
||||
macif(i);
|
||||
return;
|
||||
}
|
||||
yyerror("unknown #: %s", s->name);
|
||||
macend();
|
||||
}
|
||||
|
||||
void
|
||||
macund(void)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
s = getsym();
|
||||
macend();
|
||||
if(s == S) {
|
||||
yyerror("syntax in #undef");
|
||||
return;
|
||||
}
|
||||
s->macro = 0;
|
||||
}
|
||||
|
||||
#define NARG 25
|
||||
void
|
||||
macdef(void)
|
||||
{
|
||||
Sym *s, *a;
|
||||
char *args[NARG], *np, *base;
|
||||
int n, i, c, len, dots;
|
||||
int ischr;
|
||||
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
if(s->macro)
|
||||
yyerror("macro redefined: %s", s->name);
|
||||
c = getc();
|
||||
n = -1;
|
||||
dots = 0;
|
||||
if(c == '(') {
|
||||
n++;
|
||||
c = getnsc();
|
||||
if(c != ')') {
|
||||
unget(c);
|
||||
for(;;) {
|
||||
a = getsymdots(&dots);
|
||||
if(a == S)
|
||||
goto bad;
|
||||
if(n >= NARG) {
|
||||
yyerror("too many arguments in #define: %s", s->name);
|
||||
goto bad;
|
||||
}
|
||||
args[n++] = a->name;
|
||||
c = getnsc();
|
||||
if(c == ')')
|
||||
break;
|
||||
if(c != ',' || dots)
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
c = getc();
|
||||
}
|
||||
if(isspace(c))
|
||||
if(c != '\n')
|
||||
c = getnsc();
|
||||
base = hunk;
|
||||
len = 1;
|
||||
ischr = 0;
|
||||
for(;;) {
|
||||
if(isalpha(c) || c == '_') {
|
||||
np = symb;
|
||||
*np++ = c;
|
||||
c = getc();
|
||||
while(isalnum(c) || c == '_') {
|
||||
*np++ = c;
|
||||
c = getc();
|
||||
}
|
||||
*np = 0;
|
||||
for(i=0; i<n; i++)
|
||||
if(strcmp(symb, args[i]) == 0)
|
||||
break;
|
||||
if(i >= n) {
|
||||
i = strlen(symb);
|
||||
base = allocn(base, len, i);
|
||||
memcpy(base+len, symb, i);
|
||||
len += i;
|
||||
continue;
|
||||
}
|
||||
base = allocn(base, len, 2);
|
||||
base[len++] = '#';
|
||||
base[len++] = 'a' + i;
|
||||
continue;
|
||||
}
|
||||
if(ischr){
|
||||
if(c == '\\'){
|
||||
base = allocn(base, len, 1);
|
||||
base[len++] = c;
|
||||
c = getc();
|
||||
}else if(c == ischr)
|
||||
ischr = 0;
|
||||
}else{
|
||||
if(c == '"' || c == '\''){
|
||||
base = allocn(base, len, 1);
|
||||
base[len++] = c;
|
||||
ischr = c;
|
||||
c = getc();
|
||||
continue;
|
||||
}
|
||||
if(c == '/') {
|
||||
c = getc();
|
||||
if(c == '/'){
|
||||
c = getc();
|
||||
for(;;) {
|
||||
if(c == '\n')
|
||||
break;
|
||||
c = getc();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(c == '*'){
|
||||
c = getc();
|
||||
for(;;) {
|
||||
if(c == '*') {
|
||||
c = getc();
|
||||
if(c != '/')
|
||||
continue;
|
||||
c = getc();
|
||||
break;
|
||||
}
|
||||
if(c == '\n') {
|
||||
yyerror("comment and newline in define: %s", s->name);
|
||||
break;
|
||||
}
|
||||
c = getc();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
base = allocn(base, len, 1);
|
||||
base[len++] = '/';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(c == '\\') {
|
||||
c = getc();
|
||||
if(c == '\n') {
|
||||
c = getc();
|
||||
continue;
|
||||
}
|
||||
else if(c == '\r') {
|
||||
c = getc();
|
||||
if(c == '\n') {
|
||||
c = getc();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
base = allocn(base, len, 1);
|
||||
base[len++] = '\\';
|
||||
continue;
|
||||
}
|
||||
if(c == '\n')
|
||||
break;
|
||||
if(c == '#')
|
||||
if(n > 0) {
|
||||
base = allocn(base, len, 1);
|
||||
base[len++] = c;
|
||||
}
|
||||
base = allocn(base, len, 1);
|
||||
base[len++] = c;
|
||||
c = ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff));
|
||||
if(c == '\n')
|
||||
lineno++;
|
||||
if(c == -1) {
|
||||
yyerror("eof in a macro: %s", s->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
do {
|
||||
base = allocn(base, len, 1);
|
||||
base[len++] = 0;
|
||||
} while(len & 3);
|
||||
|
||||
*base = n+1;
|
||||
if(dots)
|
||||
*base |= VARMAC;
|
||||
s->macro = base;
|
||||
if(debug['m'])
|
||||
print("#define %s %s\n", s->name, s->macro+1);
|
||||
return;
|
||||
|
||||
bad:
|
||||
if(s == S)
|
||||
yyerror("syntax in #define");
|
||||
else
|
||||
yyerror("syntax in #define: %s", s->name);
|
||||
macend();
|
||||
}
|
||||
|
||||
void
|
||||
macexpand(Sym *s, char *b)
|
||||
{
|
||||
char buf[2000];
|
||||
int n, l, c, nargs;
|
||||
char *arg[NARG], *cp, *ob, *ecp, dots;
|
||||
|
||||
ob = b;
|
||||
if(*s->macro == 0) {
|
||||
strcpy(b, s->macro+1);
|
||||
if(debug['m'])
|
||||
print("#expand %s %s\n", s->name, ob);
|
||||
return;
|
||||
}
|
||||
|
||||
nargs = (char)(*s->macro & ~VARMAC) - 1;
|
||||
dots = *s->macro & VARMAC;
|
||||
|
||||
c = getnsc();
|
||||
if(c != '(')
|
||||
goto bad;
|
||||
n = 0;
|
||||
c = getc();
|
||||
if(c != ')') {
|
||||
unget(c);
|
||||
l = 0;
|
||||
cp = buf;
|
||||
ecp = cp + sizeof(buf)-4;
|
||||
arg[n++] = cp;
|
||||
for(;;) {
|
||||
if(cp >= ecp)
|
||||
goto toobig;
|
||||
c = getc();
|
||||
if(c == '"')
|
||||
for(;;) {
|
||||
if(cp >= ecp)
|
||||
goto toobig;
|
||||
*cp++ = c;
|
||||
c = getc();
|
||||
if(c == '\\') {
|
||||
*cp++ = c;
|
||||
c = getc();
|
||||
continue;
|
||||
}
|
||||
if(c == '\n')
|
||||
goto bad;
|
||||
if(c == '"')
|
||||
break;
|
||||
}
|
||||
if(c == '\'')
|
||||
for(;;) {
|
||||
if(cp >= ecp)
|
||||
goto toobig;
|
||||
*cp++ = c;
|
||||
c = getc();
|
||||
if(c == '\\') {
|
||||
*cp++ = c;
|
||||
c = getc();
|
||||
continue;
|
||||
}
|
||||
if(c == '\n')
|
||||
goto bad;
|
||||
if(c == '\'')
|
||||
break;
|
||||
}
|
||||
if(c == '/') {
|
||||
c = getc();
|
||||
switch(c) {
|
||||
case '*':
|
||||
for(;;) {
|
||||
c = getc();
|
||||
if(c == '*') {
|
||||
c = getc();
|
||||
if(c == '/')
|
||||
break;
|
||||
}
|
||||
}
|
||||
*cp++ = ' ';
|
||||
continue;
|
||||
case '/':
|
||||
while((c = getc()) != '\n')
|
||||
;
|
||||
break;
|
||||
default:
|
||||
unget(c);
|
||||
c = '/';
|
||||
}
|
||||
}
|
||||
if(l == 0) {
|
||||
if(c == ',') {
|
||||
if(n == nargs && dots) {
|
||||
*cp++ = ',';
|
||||
continue;
|
||||
}
|
||||
*cp++ = 0;
|
||||
arg[n++] = cp;
|
||||
if(n > nargs)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(c == ')')
|
||||
break;
|
||||
}
|
||||
if(c == '\n')
|
||||
c = ' ';
|
||||
*cp++ = c;
|
||||
if(c == '(')
|
||||
l++;
|
||||
if(c == ')')
|
||||
l--;
|
||||
}
|
||||
*cp = 0;
|
||||
}
|
||||
if(n != nargs) {
|
||||
yyerror("argument mismatch expanding: %s", s->name);
|
||||
*b = 0;
|
||||
return;
|
||||
}
|
||||
cp = s->macro+1;
|
||||
for(;;) {
|
||||
c = *cp++;
|
||||
if(c == '\n')
|
||||
c = ' ';
|
||||
if(c != '#') {
|
||||
*b++ = c;
|
||||
if(c == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
c = *cp++;
|
||||
if(c == 0)
|
||||
goto bad;
|
||||
if(c == '#') {
|
||||
*b++ = c;
|
||||
continue;
|
||||
}
|
||||
c -= 'a';
|
||||
if(c < 0 || c >= n)
|
||||
continue;
|
||||
strcpy(b, arg[c]);
|
||||
b += strlen(arg[c]);
|
||||
}
|
||||
*b = 0;
|
||||
if(debug['m'])
|
||||
print("#expand %s %s\n", s->name, ob);
|
||||
return;
|
||||
|
||||
bad:
|
||||
yyerror("syntax in macro expansion: %s", s->name);
|
||||
*b = 0;
|
||||
return;
|
||||
|
||||
toobig:
|
||||
yyerror("too much text in macro expansion: %s", s->name);
|
||||
*b = 0;
|
||||
}
|
||||
|
||||
void
|
||||
macinc(void)
|
||||
{
|
||||
int c0, c, i, f;
|
||||
char str[STRINGSZ], *hp;
|
||||
|
||||
c0 = getnsc();
|
||||
if(c0 != '"') {
|
||||
c = c0;
|
||||
if(c0 != '<')
|
||||
goto bad;
|
||||
c0 = '>';
|
||||
}
|
||||
for(hp = str;;) {
|
||||
c = getc();
|
||||
if(c == c0)
|
||||
break;
|
||||
if(c == '\n')
|
||||
goto bad;
|
||||
*hp++ = c;
|
||||
}
|
||||
*hp = 0;
|
||||
|
||||
c = getcom();
|
||||
if(c != '\n')
|
||||
goto bad;
|
||||
|
||||
f = -1;
|
||||
for(i=0; i<ninclude; i++) {
|
||||
if(i == 0 && c0 == '>')
|
||||
continue;
|
||||
strcpy(symb, include[i]);
|
||||
strcat(symb, "/");
|
||||
if(strcmp(symb, "./") == 0)
|
||||
symb[0] = 0;
|
||||
strcat(symb, str);
|
||||
f = myopen(symb);
|
||||
if(f >= 0)
|
||||
break;
|
||||
}
|
||||
if(f < 0)
|
||||
strcpy(symb, str);
|
||||
c = strlen(symb) + 1;
|
||||
hp = alloc(c);
|
||||
memcpy(hp, symb, c);
|
||||
newio();
|
||||
pushio();
|
||||
newfile(hp, f);
|
||||
return;
|
||||
|
||||
bad:
|
||||
unget(c);
|
||||
yyerror("syntax in #include");
|
||||
macend();
|
||||
}
|
||||
|
||||
void
|
||||
maclin(void)
|
||||
{
|
||||
char *cp;
|
||||
int c;
|
||||
long n;
|
||||
|
||||
n = getnsn();
|
||||
c = getc();
|
||||
if(n < 0)
|
||||
goto bad;
|
||||
|
||||
for(;;) {
|
||||
if(c == ' ' || c == '\t') {
|
||||
c = getc();
|
||||
continue;
|
||||
}
|
||||
if(c == '"')
|
||||
break;
|
||||
if(c == '\n') {
|
||||
strcpy(symb, "<noname>");
|
||||
goto nn;
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
cp = symb;
|
||||
for(;;) {
|
||||
c = getc();
|
||||
if(c == '"')
|
||||
break;
|
||||
*cp++ = c;
|
||||
}
|
||||
*cp = 0;
|
||||
c = getcom();
|
||||
if(c != '\n')
|
||||
goto bad;
|
||||
|
||||
nn:
|
||||
c = strlen(symb) + 1;
|
||||
cp = alloc(c);
|
||||
memcpy(cp, symb, c);
|
||||
linehist(cp, n);
|
||||
return;
|
||||
|
||||
bad:
|
||||
unget(c);
|
||||
yyerror("syntax in #line");
|
||||
macend();
|
||||
}
|
||||
|
||||
void
|
||||
macif(int f)
|
||||
{
|
||||
int c, l, bol;
|
||||
Sym *s;
|
||||
|
||||
if(f == 2)
|
||||
goto skip;
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
if(getcom() != '\n')
|
||||
goto bad;
|
||||
if((s->macro != 0) ^ f)
|
||||
return;
|
||||
|
||||
skip:
|
||||
bol = 1;
|
||||
l = 0;
|
||||
for(;;) {
|
||||
c = getc();
|
||||
if(c != '#') {
|
||||
if(!isspace(c))
|
||||
bol = 0;
|
||||
if(c == '\n')
|
||||
bol = 1;
|
||||
continue;
|
||||
}
|
||||
if(!bol)
|
||||
continue;
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
continue;
|
||||
if(strcmp(s->name, "endif") == 0) {
|
||||
if(l) {
|
||||
l--;
|
||||
continue;
|
||||
}
|
||||
macend();
|
||||
return;
|
||||
}
|
||||
if(strcmp(s->name, "ifdef") == 0 || strcmp(s->name, "ifndef") == 0) {
|
||||
l++;
|
||||
continue;
|
||||
}
|
||||
if(l == 0 && f != 2 && strcmp(s->name, "else") == 0) {
|
||||
macend();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bad:
|
||||
yyerror("syntax in #if(n)def");
|
||||
macend();
|
||||
}
|
||||
|
||||
void
|
||||
macprag(void)
|
||||
{
|
||||
Sym *s;
|
||||
int c0, c;
|
||||
char *hp;
|
||||
Hist *h;
|
||||
|
||||
s = getsym();
|
||||
|
||||
if(s && strcmp(s->name, "lib") == 0)
|
||||
goto praglib;
|
||||
if(s && strcmp(s->name, "pack") == 0) {
|
||||
pragpack();
|
||||
return;
|
||||
}
|
||||
if(s && strcmp(s->name, "fpround") == 0) {
|
||||
pragfpround();
|
||||
return;
|
||||
}
|
||||
if(s && strcmp(s->name, "profile") == 0) {
|
||||
pragprofile();
|
||||
return;
|
||||
}
|
||||
if(s && strcmp(s->name, "varargck") == 0) {
|
||||
pragvararg();
|
||||
return;
|
||||
}
|
||||
if(s && strcmp(s->name, "incomplete") == 0) {
|
||||
pragincomplete();
|
||||
return;
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
return;
|
||||
|
||||
praglib:
|
||||
c0 = getnsc();
|
||||
if(c0 != '"') {
|
||||
c = c0;
|
||||
if(c0 != '<')
|
||||
goto bad;
|
||||
c0 = '>';
|
||||
}
|
||||
for(hp = symb;;) {
|
||||
c = getc();
|
||||
if(c == c0)
|
||||
break;
|
||||
if(c == '\n')
|
||||
goto bad;
|
||||
*hp++ = c;
|
||||
}
|
||||
*hp = 0;
|
||||
c = getcom();
|
||||
if(c != '\n')
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* put pragma-line in as a funny history
|
||||
*/
|
||||
c = strlen(symb) + 1;
|
||||
hp = alloc(c);
|
||||
memcpy(hp, symb, c);
|
||||
|
||||
h = alloc(sizeof(Hist));
|
||||
h->name = hp;
|
||||
h->line = lineno;
|
||||
h->offset = -1;
|
||||
h->link = H;
|
||||
if(ehist == H) {
|
||||
hist = h;
|
||||
ehist = h;
|
||||
return;
|
||||
}
|
||||
ehist->link = h;
|
||||
ehist = h;
|
||||
return;
|
||||
|
||||
bad:
|
||||
unget(c);
|
||||
yyerror("syntax in #pragma lib");
|
||||
macend();
|
||||
}
|
||||
|
||||
void
|
||||
macend(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
for(;;) {
|
||||
c = getnsc();
|
||||
if(c < 0 || c == '\n')
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
linehist(char *f, int offset)
|
||||
{
|
||||
Hist *h;
|
||||
|
||||
/*
|
||||
* overwrite the last #line directive if
|
||||
* no alloc has happened since the last one
|
||||
*/
|
||||
if(newflag == 0 && ehist != H && offset != 0 && ehist->offset != 0)
|
||||
if(f && ehist->name && strcmp(f, ehist->name) == 0) {
|
||||
ehist->line = lineno;
|
||||
ehist->offset = offset;
|
||||
return;
|
||||
}
|
||||
|
||||
if(debug['f'])
|
||||
if(f) {
|
||||
if(offset)
|
||||
print("%4ld: %s (#line %d)\n", lineno, f, offset);
|
||||
else
|
||||
print("%4ld: %s\n", lineno, f);
|
||||
} else
|
||||
print("%4ld: <pop>\n", lineno);
|
||||
newflag = 0;
|
||||
|
||||
h = alloc(sizeof(Hist));
|
||||
h->name = f;
|
||||
h->line = lineno;
|
||||
h->offset = offset;
|
||||
h->link = H;
|
||||
if(ehist == H) {
|
||||
hist = h;
|
||||
ehist = h;
|
||||
return;
|
||||
}
|
||||
ehist->link = h;
|
||||
ehist = h;
|
||||
}
|
||||
38
src/cmd/cc/omachcap.c
Normal file
38
src/cmd/cc/omachcap.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Inferno utils/cc/machcap.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/machcap.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
/* default, like old cc */
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
550
src/cmd/cc/pgen.c
Normal file
550
src/cmd/cc/pgen.c
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
// Inferno utils/6c/sgen.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
codgen(Node *n, Node *nn)
|
||||
{
|
||||
Prog *sp;
|
||||
Node *n1, nod, nod1;
|
||||
|
||||
cursafe = 0;
|
||||
curarg = 0;
|
||||
maxargsafe = 0;
|
||||
|
||||
/*
|
||||
* isolate name
|
||||
*/
|
||||
for(n1 = nn;; n1 = n1->left) {
|
||||
if(n1 == Z) {
|
||||
diag(nn, "cant find function name");
|
||||
return;
|
||||
}
|
||||
if(n1->op == ONAME)
|
||||
break;
|
||||
}
|
||||
nearln = nn->lineno;
|
||||
gpseudo(ATEXT, n1->sym, nodconst(stkoff));
|
||||
sp = p;
|
||||
|
||||
/*
|
||||
* isolate first argument
|
||||
*/
|
||||
if(REGARG) {
|
||||
if(typecmplx[thisfn->link->etype]) {
|
||||
nod1 = *nodret->left;
|
||||
nodreg(&nod, &nod1, REGARG);
|
||||
gmove(&nod, &nod1);
|
||||
} else
|
||||
if(firstarg && typeword[firstargtype->etype]) {
|
||||
nod1 = *nodret->left;
|
||||
nod1.sym = firstarg;
|
||||
nod1.type = firstargtype;
|
||||
nod1.xoffset = align(0, firstargtype, Aarg1);
|
||||
nod1.etype = firstargtype->etype;
|
||||
nodreg(&nod, &nod1, REGARG);
|
||||
gmove(&nod, &nod1);
|
||||
}
|
||||
}
|
||||
|
||||
canreach = 1;
|
||||
warnreach = 1;
|
||||
gen(n);
|
||||
if(canreach && thisfn->link->etype != TVOID)
|
||||
warn(Z, "no return at end of function: %s", n1->sym->name);
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
|
||||
if(!debug['N'] || debug['R'] || debug['P'])
|
||||
regopt(sp);
|
||||
|
||||
if(thechar=='6' || thechar=='7') /* [sic] */
|
||||
maxargsafe = xround(maxargsafe, 8);
|
||||
sp->to.offset += maxargsafe;
|
||||
}
|
||||
|
||||
void
|
||||
supgen(Node *n)
|
||||
{
|
||||
int owarn;
|
||||
long spc;
|
||||
Prog *sp;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
suppress++;
|
||||
owarn = warnreach;
|
||||
warnreach = 0;
|
||||
spc = pc;
|
||||
sp = lastp;
|
||||
gen(n);
|
||||
lastp = sp;
|
||||
pc = spc;
|
||||
sp->link = nil;
|
||||
suppress--;
|
||||
warnreach = owarn;
|
||||
}
|
||||
|
||||
void
|
||||
gen(Node *n)
|
||||
{
|
||||
Node *l, nod;
|
||||
Prog *sp, *spc, *spb;
|
||||
Case *cn;
|
||||
long sbc, scc;
|
||||
int snbreak, sncontin;
|
||||
int f, o, oldreach;
|
||||
|
||||
loop:
|
||||
if(n == Z)
|
||||
return;
|
||||
nearln = n->lineno;
|
||||
o = n->op;
|
||||
if(debug['G'])
|
||||
if(o != OLIST)
|
||||
print("%L %O\n", nearln, o);
|
||||
|
||||
if(!canreach) {
|
||||
switch(o) {
|
||||
case OLABEL:
|
||||
case OCASE:
|
||||
case OLIST:
|
||||
case OBREAK:
|
||||
case OFOR:
|
||||
case OWHILE:
|
||||
case ODWHILE:
|
||||
/* all handled specially - see switch body below */
|
||||
break;
|
||||
default:
|
||||
if(warnreach) {
|
||||
warn(n, "unreachable code %O", o);
|
||||
warnreach = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(o) {
|
||||
|
||||
default:
|
||||
complex(n);
|
||||
cgen(n, Z);
|
||||
break;
|
||||
|
||||
case OLIST:
|
||||
gen(n->left);
|
||||
|
||||
rloop:
|
||||
n = n->right;
|
||||
goto loop;
|
||||
|
||||
case ORETURN:
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
complex(n);
|
||||
if(n->type == T)
|
||||
break;
|
||||
l = n->left;
|
||||
if(l == Z) {
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
}
|
||||
if(typecmplx[n->type->etype]) {
|
||||
sugen(l, nodret, n->type->width);
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
}
|
||||
regret(&nod, n);
|
||||
cgen(l, &nod);
|
||||
regfree(&nod);
|
||||
if(typefd[n->type->etype])
|
||||
noretval(1);
|
||||
else
|
||||
noretval(2);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
|
||||
case OLABEL:
|
||||
canreach = 1;
|
||||
l = n->left;
|
||||
if(l) {
|
||||
l->pc = pc;
|
||||
if(l->label)
|
||||
patch(l->label, pc);
|
||||
}
|
||||
gbranch(OGOTO); /* prevent self reference in reg */
|
||||
patch(p, pc);
|
||||
goto rloop;
|
||||
|
||||
case OGOTO:
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
n = n->left;
|
||||
if(n == Z)
|
||||
return;
|
||||
if(n->complex == 0) {
|
||||
diag(Z, "label undefined: %s", n->sym->name);
|
||||
return;
|
||||
}
|
||||
if(suppress)
|
||||
return;
|
||||
gbranch(OGOTO);
|
||||
if(n->pc) {
|
||||
patch(p, n->pc);
|
||||
return;
|
||||
}
|
||||
if(n->label)
|
||||
patch(n->label, pc-1);
|
||||
n->label = p;
|
||||
return;
|
||||
|
||||
case OCASE:
|
||||
canreach = 1;
|
||||
l = n->left;
|
||||
if(cases == C)
|
||||
diag(n, "case/default outside a switch");
|
||||
if(l == Z) {
|
||||
cas();
|
||||
cases->val = 0;
|
||||
cases->def = 1;
|
||||
cases->label = pc;
|
||||
cases->isv = 0;
|
||||
goto rloop;
|
||||
}
|
||||
complex(l);
|
||||
if(l->type == T)
|
||||
goto rloop;
|
||||
if(l->op == OCONST)
|
||||
if(typeword[l->type->etype] && l->type->etype != TIND) {
|
||||
cas();
|
||||
cases->val = l->vconst;
|
||||
cases->def = 0;
|
||||
cases->label = pc;
|
||||
cases->isv = typev[l->type->etype];
|
||||
goto rloop;
|
||||
}
|
||||
diag(n, "case expression must be integer constant");
|
||||
goto rloop;
|
||||
|
||||
case OSWITCH:
|
||||
l = n->left;
|
||||
complex(l);
|
||||
if(l->type == T)
|
||||
break;
|
||||
if(!typeword[l->type->etype] || l->type->etype == TIND) {
|
||||
diag(n, "switch expression must be integer");
|
||||
break;
|
||||
}
|
||||
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
cn = cases;
|
||||
cases = C;
|
||||
cas();
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
gen(n->right); /* body */
|
||||
if(canreach){
|
||||
gbranch(OGOTO);
|
||||
patch(p, breakpc);
|
||||
nbreak++;
|
||||
}
|
||||
|
||||
patch(sp, pc);
|
||||
regalloc(&nod, l, Z);
|
||||
/* always signed */
|
||||
if(typev[l->type->etype])
|
||||
nod.type = types[TVLONG];
|
||||
else
|
||||
nod.type = types[TLONG];
|
||||
cgen(l, &nod);
|
||||
doswit(&nod);
|
||||
regfree(&nod);
|
||||
patch(spb, pc);
|
||||
|
||||
cases = cn;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
break;
|
||||
|
||||
case OWHILE:
|
||||
case ODWHILE:
|
||||
l = n->left;
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
scc = continpc;
|
||||
continpc = pc;
|
||||
gbranch(OGOTO);
|
||||
spc = p;
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
patch(spc, pc);
|
||||
if(n->op == OWHILE)
|
||||
patch(sp, pc);
|
||||
bcomplex(l, Z); /* test */
|
||||
patch(p, breakpc);
|
||||
if(l->op != OCONST || vconst(l) == 0)
|
||||
nbreak++;
|
||||
|
||||
if(n->op == ODWHILE)
|
||||
patch(sp, pc);
|
||||
gen(n->right); /* body */
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
|
||||
patch(spb, pc);
|
||||
continpc = scc;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
break;
|
||||
|
||||
case OFOR:
|
||||
l = n->left;
|
||||
if(!canreach && l->right->left && warnreach) {
|
||||
warn(n, "unreachable code FOR");
|
||||
warnreach = 0;
|
||||
}
|
||||
gen(l->right->left); /* init */
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
/*
|
||||
* if there are no incoming labels in the
|
||||
* body and the top's not reachable, warn
|
||||
*/
|
||||
if(!canreach && warnreach && deadheads(n)) {
|
||||
warn(n, "unreachable code %O", o);
|
||||
warnreach = 0;
|
||||
}
|
||||
|
||||
scc = continpc;
|
||||
continpc = pc;
|
||||
gbranch(OGOTO);
|
||||
spc = p;
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
sncontin = ncontin;
|
||||
ncontin = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
patch(spc, pc);
|
||||
gen(l->right->right); /* inc */
|
||||
patch(sp, pc);
|
||||
if(l->left != Z) { /* test */
|
||||
bcomplex(l->left, Z);
|
||||
patch(p, breakpc);
|
||||
if(l->left->op != OCONST || vconst(l->left) == 0)
|
||||
nbreak++;
|
||||
}
|
||||
canreach = 1;
|
||||
gen(n->right); /* body */
|
||||
if(canreach){
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
ncontin++;
|
||||
}
|
||||
if(!ncontin && l->right->right && warnreach) {
|
||||
warn(l->right->right, "unreachable FOR inc");
|
||||
warnreach = 0;
|
||||
}
|
||||
|
||||
patch(spb, pc);
|
||||
continpc = scc;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
ncontin = sncontin;
|
||||
break;
|
||||
|
||||
case OCONTINUE:
|
||||
if(continpc < 0) {
|
||||
diag(n, "continue not in a loop");
|
||||
break;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
ncontin++;
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
break;
|
||||
|
||||
case OBREAK:
|
||||
if(breakpc < 0) {
|
||||
diag(n, "break not in a loop");
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Don't complain about unreachable break statements.
|
||||
* There are breaks hidden in yacc's output and some people
|
||||
* write return; break; in their switch statements out of habit.
|
||||
* However, don't confuse the analysis by inserting an
|
||||
* unreachable reference to breakpc either.
|
||||
*/
|
||||
if(!canreach)
|
||||
break;
|
||||
gbranch(OGOTO);
|
||||
patch(p, breakpc);
|
||||
nbreak++;
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
break;
|
||||
|
||||
case OIF:
|
||||
l = n->left;
|
||||
if(bcomplex(l, n->right)) {
|
||||
if(typefd[l->type->etype])
|
||||
f = !l->fconst;
|
||||
else
|
||||
f = !l->vconst;
|
||||
if(debug['c'])
|
||||
print("%L const if %s\n", nearln, f ? "false" : "true");
|
||||
if(f) {
|
||||
canreach = 1;
|
||||
supgen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
gen(n->right->right);
|
||||
/*
|
||||
* treat constant ifs as regular ifs for
|
||||
* reachability warnings.
|
||||
*/
|
||||
if(!canreach && oldreach && debug['w'] < 2)
|
||||
warnreach = 0;
|
||||
}
|
||||
else {
|
||||
canreach = 1;
|
||||
gen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
supgen(n->right->right);
|
||||
/*
|
||||
* treat constant ifs as regular ifs for
|
||||
* reachability warnings.
|
||||
*/
|
||||
if(!oldreach && canreach && debug['w'] < 2)
|
||||
warnreach = 0;
|
||||
canreach = oldreach;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sp = p;
|
||||
canreach = 1;
|
||||
if(n->right->left != Z)
|
||||
gen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
if(n->right->right != Z) {
|
||||
gbranch(OGOTO);
|
||||
patch(sp, pc);
|
||||
sp = p;
|
||||
gen(n->right->right);
|
||||
}
|
||||
patch(sp, pc);
|
||||
canreach = canreach || oldreach;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSET:
|
||||
case OUSED:
|
||||
usedset(n->left, o);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usedset(Node *n, int o)
|
||||
{
|
||||
if(n->op == OLIST) {
|
||||
usedset(n->left, o);
|
||||
usedset(n->right, o);
|
||||
return;
|
||||
}
|
||||
complex(n);
|
||||
switch(n->op) {
|
||||
case OADDR: /* volatile */
|
||||
gins(ANOP, n, Z);
|
||||
break;
|
||||
case ONAME:
|
||||
if(o == OSET)
|
||||
gins(ANOP, Z, n);
|
||||
else
|
||||
gins(ANOP, n, Z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bcomplex(Node *n, Node *c)
|
||||
{
|
||||
|
||||
complex(n);
|
||||
if(n->type != T)
|
||||
if(tcompat(n, T, n->type, tnot))
|
||||
n->type = T;
|
||||
if(n->type == T) {
|
||||
gbranch(OGOTO);
|
||||
return 0;
|
||||
}
|
||||
if(c != Z && n->op == OCONST && deadheads(c))
|
||||
return 1;
|
||||
bool64(n);
|
||||
boolgen(n, 1, Z);
|
||||
return 0;
|
||||
}
|
||||
298
src/cmd/cc/pickle.c
Normal file
298
src/cmd/cc/pickle.c
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
// Inferno utils/cc/pickle.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/pickle.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
static char *kwd[] =
|
||||
{
|
||||
"$adt", "$aggr", "$append", "$complex", "$defn",
|
||||
"$delete", "$do", "$else", "$eval", "$head", "$if",
|
||||
"$local", "$loop", "$return", "$tail", "$then",
|
||||
"$union", "$whatis", "$while",
|
||||
};
|
||||
static char picklestr[] = "\tbp = pickle(bp, ep, un, ";
|
||||
|
||||
static char*
|
||||
pmap(char *s)
|
||||
{
|
||||
int i, bot, top, new;
|
||||
|
||||
bot = 0;
|
||||
top = bot + nelem(kwd) - 1;
|
||||
while(bot <= top){
|
||||
new = bot + (top - bot)/2;
|
||||
i = strcmp(kwd[new]+1, s);
|
||||
if(i == 0)
|
||||
return kwd[new];
|
||||
|
||||
if(i < 0)
|
||||
bot = new + 1;
|
||||
else
|
||||
top = new - 1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Sym*
|
||||
picklesue(Type *t)
|
||||
{
|
||||
int h;
|
||||
Sym *s;
|
||||
|
||||
if(t != T)
|
||||
for(h=0; h<nelem(hash); h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->suetag && s->suetag->link == t)
|
||||
return s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sym*
|
||||
picklefun(Type *t)
|
||||
{
|
||||
int h;
|
||||
Sym *s;
|
||||
|
||||
for(h=0; h<nelem(hash); h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->type == t)
|
||||
return s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char picklechar[NTYPE];
|
||||
Init picklecinit[] =
|
||||
{
|
||||
TCHAR, 'C', 0,
|
||||
TUCHAR, 'b', 0,
|
||||
TSHORT, 'd', 0,
|
||||
TUSHORT, 'u', 0,
|
||||
TLONG, 'D', 0,
|
||||
TULONG, 'U', 0,
|
||||
TVLONG, 'V', 0,
|
||||
TUVLONG, 'W', 0,
|
||||
TFLOAT, 'f', 0,
|
||||
TDOUBLE, 'F', 0,
|
||||
TARRAY, 'a', 0,
|
||||
TIND, 'X', 0,
|
||||
-1, 0, 0,
|
||||
};
|
||||
|
||||
static void
|
||||
pickleinit(void)
|
||||
{
|
||||
Init *p;
|
||||
|
||||
for(p=picklecinit; p->code >= 0; p++)
|
||||
picklechar[p->code] = p->value;
|
||||
|
||||
picklechar[TINT] = picklechar[TLONG];
|
||||
picklechar[TUINT] = picklechar[TULONG];
|
||||
if(types[TINT]->width != types[TLONG]->width) {
|
||||
picklechar[TINT] = picklechar[TSHORT];
|
||||
picklechar[TUINT] = picklechar[TUSHORT];
|
||||
if(types[TINT]->width != types[TSHORT]->width)
|
||||
warn(Z, "picklemember int not long or short");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
picklemember(Type *t, long off)
|
||||
{
|
||||
Sym *s, *s1;
|
||||
static int picklecharinit = 0;
|
||||
|
||||
if(picklecharinit == 0) {
|
||||
pickleinit();
|
||||
picklecharinit = 1;
|
||||
}
|
||||
s = t->sym;
|
||||
switch(t->etype) {
|
||||
default:
|
||||
Bprint(&outbuf, " T%d\n", t->etype);
|
||||
break;
|
||||
|
||||
case TIND:
|
||||
if(s == S)
|
||||
Bprint(&outbuf,
|
||||
"%s\"p\", (char*)addr+%ld+_i*%ld);\n",
|
||||
picklestr, t->offset+off, t->width);
|
||||
else
|
||||
Bprint(&outbuf,
|
||||
"%s\"p\", &addr->%s);\n",
|
||||
picklestr, pmap(s->name));
|
||||
break;
|
||||
|
||||
case TINT:
|
||||
case TUINT:
|
||||
case TCHAR:
|
||||
case TUCHAR:
|
||||
case TSHORT:
|
||||
case TUSHORT:
|
||||
case TLONG:
|
||||
case TULONG:
|
||||
case TVLONG:
|
||||
case TUVLONG:
|
||||
case TFLOAT:
|
||||
case TDOUBLE:
|
||||
if(s == S)
|
||||
Bprint(&outbuf, "%s\"%c\", (char*)addr+%ld+_i*%ld);\n",
|
||||
picklestr, picklechar[t->etype], t->offset+off, t->width);
|
||||
else
|
||||
Bprint(&outbuf, "%s\"%c\", &addr->%s);\n",
|
||||
picklestr, picklechar[t->etype], pmap(s->name));
|
||||
break;
|
||||
case TARRAY:
|
||||
Bprint(&outbuf, "\tfor(_i = 0; _i < %ld; _i++) {\n\t",
|
||||
t->width/t->link->width);
|
||||
picklemember(t->link, t->offset+off);
|
||||
Bprint(&outbuf, "\t}\n\t_i = 0;\n\tUSED(_i);\n");
|
||||
break;
|
||||
|
||||
case TSTRUCT:
|
||||
case TUNION:
|
||||
s1 = picklesue(t->link);
|
||||
if(s1 == S)
|
||||
break;
|
||||
if(s == S) {
|
||||
Bprint(&outbuf, "\tbp = pickle_%s(bp, ep, un, (%s*)((char*)addr+%ld+_i*%ld));\n",
|
||||
pmap(s1->name), pmap(s1->name), t->offset+off, t->width);
|
||||
} else {
|
||||
Bprint(&outbuf, "\tbp = pickle_%s(bp, ep, un, &addr->%s);\n",
|
||||
pmap(s1->name), pmap(s->name));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pickletype(Type *t)
|
||||
{
|
||||
Sym *s;
|
||||
Type *l;
|
||||
Io *i;
|
||||
int n;
|
||||
char *an;
|
||||
|
||||
if(!debug['P'])
|
||||
return;
|
||||
if(debug['P'] > 1) {
|
||||
n = 0;
|
||||
for(i=iostack; i; i=i->link)
|
||||
n++;
|
||||
if(n > 1)
|
||||
return;
|
||||
}
|
||||
s = picklesue(t->link);
|
||||
if(s == S)
|
||||
return;
|
||||
switch(t->etype) {
|
||||
default:
|
||||
Bprint(&outbuf, "T%d\n", t->etype);
|
||||
return;
|
||||
|
||||
case TUNION:
|
||||
case TSTRUCT:
|
||||
if(debug['s'])
|
||||
goto asmstr;
|
||||
an = pmap(s->name);
|
||||
|
||||
Bprint(&outbuf, "char *\npickle_%s(char *bp, char *ep, int un, %s *addr)\n{\n\tint _i = 0;\n\n\tUSED(_i);\n", an, an);
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
picklemember(l, 0);
|
||||
Bprint(&outbuf, "\treturn bp;\n}\n\n");
|
||||
break;
|
||||
asmstr:
|
||||
if(s == S)
|
||||
break;
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
if(l->sym != S)
|
||||
Bprint(&outbuf, "#define\t%s.%s\t%ld\n",
|
||||
s->name,
|
||||
l->sym->name,
|
||||
l->offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
picklevar(Sym *s)
|
||||
{
|
||||
int n;
|
||||
Io *i;
|
||||
Type *t;
|
||||
Sym *s1, *s2;
|
||||
|
||||
if(!debug['P'] || debug['s'])
|
||||
return;
|
||||
if(debug['P'] > 1) {
|
||||
n = 0;
|
||||
for(i=iostack; i; i=i->link)
|
||||
n++;
|
||||
if(n > 1)
|
||||
return;
|
||||
}
|
||||
t = s->type;
|
||||
while(t && t->etype == TIND)
|
||||
t = t->link;
|
||||
if(t == T)
|
||||
return;
|
||||
if(t->etype == TENUM) {
|
||||
Bprint(&outbuf, "%s = ", pmap(s->name));
|
||||
if(!typefd[t->etype])
|
||||
Bprint(&outbuf, "%lld;\n", s->vconst);
|
||||
else
|
||||
Bprint(&outbuf, "%f\n;", s->fconst);
|
||||
return;
|
||||
}
|
||||
if(!typesu[t->etype])
|
||||
return;
|
||||
s1 = picklesue(t->link);
|
||||
if(s1 == S)
|
||||
return;
|
||||
switch(s->class) {
|
||||
case CAUTO:
|
||||
case CPARAM:
|
||||
s2 = picklefun(thisfn);
|
||||
if(s2)
|
||||
Bprint(&outbuf, "complex %s %s:%s;\n",
|
||||
pmap(s1->name), pmap(s2->name), pmap(s->name));
|
||||
break;
|
||||
|
||||
case CSTATIC:
|
||||
case CEXTERN:
|
||||
case CGLOBL:
|
||||
case CLOCAL:
|
||||
Bprint(&outbuf, "complex %s %s;\n",
|
||||
pmap(s1->name), pmap(s->name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
168
src/cmd/cc/pswt.c
Normal file
168
src/cmd/cc/pswt.c
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
// Inferno utils/6c/swt.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
int
|
||||
swcmp(const void *a1, const void *a2)
|
||||
{
|
||||
C1 *p1, *p2;
|
||||
|
||||
p1 = (C1*)a1;
|
||||
p2 = (C1*)a2;
|
||||
if(p1->val < p2->val)
|
||||
return -1;
|
||||
return p1->val > p2->val;
|
||||
}
|
||||
|
||||
void
|
||||
doswit(Node *n)
|
||||
{
|
||||
Case *c;
|
||||
C1 *q, *iq;
|
||||
long def, nc, i, isv;
|
||||
|
||||
def = 0;
|
||||
nc = 0;
|
||||
isv = 0;
|
||||
for(c = cases; c->link != C; c = c->link) {
|
||||
if(c->def) {
|
||||
if(def)
|
||||
diag(n, "more than one default in switch");
|
||||
def = c->label;
|
||||
continue;
|
||||
}
|
||||
isv |= c->isv;
|
||||
nc++;
|
||||
}
|
||||
if(isv && !typev[n->type->etype])
|
||||
warn(n, "32-bit switch expression with 64-bit case constant");
|
||||
|
||||
iq = alloc(nc*sizeof(C1));
|
||||
q = iq;
|
||||
for(c = cases; c->link != C; c = c->link) {
|
||||
if(c->def)
|
||||
continue;
|
||||
q->label = c->label;
|
||||
if(isv)
|
||||
q->val = c->val;
|
||||
else
|
||||
q->val = (long)c->val; /* cast ensures correct value for 32-bit switch on 64-bit architecture */
|
||||
q++;
|
||||
}
|
||||
qsort(iq, nc, sizeof(C1), swcmp);
|
||||
if(debug['W'])
|
||||
for(i=0; i<nc; i++)
|
||||
print("case %2ld: = %.8llux\n", i, (vlong)iq[i].val);
|
||||
for(i=0; i<nc-1; i++)
|
||||
if(iq[i].val == iq[i+1].val)
|
||||
diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val);
|
||||
if(def == 0) {
|
||||
def = breakpc;
|
||||
nbreak++;
|
||||
}
|
||||
swit1(iq, nc, def, n);
|
||||
}
|
||||
|
||||
void
|
||||
cas(void)
|
||||
{
|
||||
Case *c;
|
||||
|
||||
c = alloc(sizeof(*c));
|
||||
c->link = cases;
|
||||
cases = c;
|
||||
}
|
||||
|
||||
long
|
||||
outlstring(ushort *s, long n)
|
||||
{
|
||||
char buf[2];
|
||||
int c;
|
||||
long r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
while(nstring & 1)
|
||||
outstring("", 1);
|
||||
r = nstring;
|
||||
while(n > 0) {
|
||||
c = *s++;
|
||||
if(align(0, types[TCHAR], Aarg1)) {
|
||||
buf[0] = c>>8;
|
||||
buf[1] = c;
|
||||
} else {
|
||||
buf[0] = c;
|
||||
buf[1] = c>>8;
|
||||
}
|
||||
outstring(buf, 2);
|
||||
n -= sizeof(ushort);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
nullwarn(Node *l, Node *r)
|
||||
{
|
||||
warn(Z, "result of operation not used");
|
||||
if(l != Z)
|
||||
cgen(l, Z);
|
||||
if(r != Z)
|
||||
cgen(r, Z);
|
||||
}
|
||||
|
||||
void
|
||||
ieeedtod(Ieee *ieee, double native)
|
||||
{
|
||||
double fr, ho, f;
|
||||
int exp;
|
||||
|
||||
if(native < 0) {
|
||||
ieeedtod(ieee, -native);
|
||||
ieee->h |= 0x80000000L;
|
||||
return;
|
||||
}
|
||||
if(native == 0) {
|
||||
ieee->l = 0;
|
||||
ieee->h = 0;
|
||||
return;
|
||||
}
|
||||
fr = frexp(native, &exp);
|
||||
f = 2097152L; /* shouldnt use fp constants here */
|
||||
fr = modf(fr*f, &ho);
|
||||
ieee->h = ho;
|
||||
ieee->h &= 0xfffffL;
|
||||
ieee->h |= (exp+1022L) << 20;
|
||||
f = 65536L;
|
||||
fr = modf(fr*f, &ho);
|
||||
ieee->l = ho;
|
||||
ieee->l <<= 16;
|
||||
ieee->l |= (long)(fr*f);
|
||||
}
|
||||
636
src/cmd/cc/scon.c
Normal file
636
src/cmd/cc/scon.c
Normal file
|
|
@ -0,0 +1,636 @@
|
|||
// Inferno utils/cc/scon.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/scon.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
static Node*
|
||||
acast(Type *t, Node *n)
|
||||
{
|
||||
if(n->type->etype != t->etype || n->op == OBIT) {
|
||||
n = new1(OCAST, n, Z);
|
||||
if(nocast(n->left->type, t))
|
||||
*n = *n->left;
|
||||
n->type = t;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
evconst(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
int et, isf;
|
||||
vlong v;
|
||||
double d;
|
||||
|
||||
if(n == Z || n->type == T)
|
||||
return;
|
||||
|
||||
et = n->type->etype;
|
||||
isf = typefd[et];
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
|
||||
d = 0;
|
||||
v = 0;
|
||||
|
||||
switch(n->op) {
|
||||
default:
|
||||
return;
|
||||
|
||||
case ONEG:
|
||||
if(isf)
|
||||
d = -l->fconst;
|
||||
else
|
||||
v = -l->vconst;
|
||||
break;
|
||||
|
||||
case OCOM:
|
||||
v = ~l->vconst;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
if(et == TVOID)
|
||||
return;
|
||||
et = l->type->etype;
|
||||
if(isf) {
|
||||
if(typefd[et])
|
||||
d = l->fconst;
|
||||
else
|
||||
d = l->vconst;
|
||||
} else {
|
||||
if(typefd[et])
|
||||
v = l->fconst;
|
||||
else
|
||||
v = convvtox(l->vconst, n->type->etype);
|
||||
}
|
||||
break;
|
||||
|
||||
case OCONST:
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
if(isf)
|
||||
d = l->fconst + r->fconst;
|
||||
else {
|
||||
v = l->vconst + r->vconst;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSUB:
|
||||
if(isf)
|
||||
d = l->fconst - r->fconst;
|
||||
else
|
||||
v = l->vconst - r->vconst;
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
if(isf)
|
||||
d = l->fconst * r->fconst;
|
||||
else {
|
||||
v = l->vconst * r->vconst;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLMUL:
|
||||
v = (uvlong)l->vconst * (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
|
||||
case ODIV:
|
||||
if(vconst(r) == 0) {
|
||||
warn(n, "divide by zero");
|
||||
return;
|
||||
}
|
||||
if(isf)
|
||||
d = l->fconst / r->fconst;
|
||||
else
|
||||
v = l->vconst / r->vconst;
|
||||
break;
|
||||
|
||||
case OLDIV:
|
||||
if(vconst(r) == 0) {
|
||||
warn(n, "divide by zero");
|
||||
return;
|
||||
}
|
||||
v = (uvlong)l->vconst / (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OMOD:
|
||||
if(vconst(r) == 0) {
|
||||
warn(n, "modulo by zero");
|
||||
return;
|
||||
}
|
||||
v = l->vconst % r->vconst;
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
if(vconst(r) == 0) {
|
||||
warn(n, "modulo by zero");
|
||||
return;
|
||||
}
|
||||
v = (uvlong)l->vconst % (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OAND:
|
||||
v = l->vconst & r->vconst;
|
||||
break;
|
||||
|
||||
case OOR:
|
||||
v = l->vconst | r->vconst;
|
||||
break;
|
||||
|
||||
case OXOR:
|
||||
v = l->vconst ^ r->vconst;
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
v = (uvlong)l->vconst >> r->vconst;
|
||||
break;
|
||||
|
||||
case OASHR:
|
||||
v = l->vconst >> r->vconst;
|
||||
break;
|
||||
|
||||
case OASHL:
|
||||
v = l->vconst << r->vconst;
|
||||
break;
|
||||
|
||||
case OLO:
|
||||
v = (uvlong)l->vconst < (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OLT:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst < r->fconst;
|
||||
else
|
||||
v = l->vconst < r->vconst;
|
||||
break;
|
||||
|
||||
case OHI:
|
||||
v = (uvlong)l->vconst > (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OGT:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst > r->fconst;
|
||||
else
|
||||
v = l->vconst > r->vconst;
|
||||
break;
|
||||
|
||||
case OLS:
|
||||
v = (uvlong)l->vconst <= (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OLE:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst <= r->fconst;
|
||||
else
|
||||
v = l->vconst <= r->vconst;
|
||||
break;
|
||||
|
||||
case OHS:
|
||||
v = (uvlong)l->vconst >= (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OGE:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst >= r->fconst;
|
||||
else
|
||||
v = l->vconst >= r->vconst;
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst == r->fconst;
|
||||
else
|
||||
v = l->vconst == r->vconst;
|
||||
break;
|
||||
|
||||
case ONE:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst != r->fconst;
|
||||
else
|
||||
v = l->vconst != r->vconst;
|
||||
break;
|
||||
|
||||
case ONOT:
|
||||
if(typefd[l->type->etype])
|
||||
v = !l->fconst;
|
||||
else
|
||||
v = !l->vconst;
|
||||
break;
|
||||
|
||||
case OANDAND:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst && r->fconst;
|
||||
else
|
||||
v = l->vconst && r->vconst;
|
||||
break;
|
||||
|
||||
case OOROR:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst || r->fconst;
|
||||
else
|
||||
v = l->vconst || r->vconst;
|
||||
break;
|
||||
}
|
||||
if(isf) {
|
||||
n->fconst = d;
|
||||
} else {
|
||||
n->vconst = convvtox(v, n->type->etype);
|
||||
}
|
||||
n->oldop = n->op;
|
||||
n->op = OCONST;
|
||||
}
|
||||
|
||||
void
|
||||
acom(Node *n)
|
||||
{
|
||||
Type *t;
|
||||
Node *l, *r;
|
||||
int i;
|
||||
|
||||
switch(n->op)
|
||||
{
|
||||
|
||||
case ONAME:
|
||||
case OCONST:
|
||||
case OSTRING:
|
||||
case OINDREG:
|
||||
case OREGISTER:
|
||||
return;
|
||||
|
||||
case ONEG:
|
||||
l = n->left;
|
||||
if(addo(n) && addo(l))
|
||||
break;
|
||||
acom(l);
|
||||
return;
|
||||
|
||||
case OADD:
|
||||
case OSUB:
|
||||
case OMUL:
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(addo(n)) {
|
||||
if(addo(r))
|
||||
break;
|
||||
if(addo(l))
|
||||
break;
|
||||
}
|
||||
acom(l);
|
||||
acom(r);
|
||||
return;
|
||||
|
||||
default:
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l != Z)
|
||||
acom(l);
|
||||
if(r != Z)
|
||||
acom(r);
|
||||
return;
|
||||
}
|
||||
|
||||
/* bust terms out */
|
||||
t = n->type;
|
||||
term[0].mult = 0;
|
||||
term[0].node = Z;
|
||||
nterm = 1;
|
||||
acom1(1, n);
|
||||
if(debug['m'])
|
||||
for(i=0; i<nterm; i++) {
|
||||
print("%d %3lld ", i, term[i].mult);
|
||||
prtree1(term[i].node, 1, 0);
|
||||
}
|
||||
if(nterm < NTERM)
|
||||
acom2(n, t);
|
||||
n->type = t;
|
||||
}
|
||||
|
||||
int
|
||||
acomcmp1(const void *a1, const void *a2)
|
||||
{
|
||||
vlong c1, c2;
|
||||
Term *t1, *t2;
|
||||
|
||||
t1 = (Term*)a1;
|
||||
t2 = (Term*)a2;
|
||||
c1 = t1->mult;
|
||||
if(c1 < 0)
|
||||
c1 = -c1;
|
||||
c2 = t2->mult;
|
||||
if(c2 < 0)
|
||||
c2 = -c2;
|
||||
if(c1 > c2)
|
||||
return 1;
|
||||
if(c1 < c2)
|
||||
return -1;
|
||||
c1 = 1;
|
||||
if(t1->mult < 0)
|
||||
c1 = 0;
|
||||
c2 = 1;
|
||||
if(t2->mult < 0)
|
||||
c2 = 0;
|
||||
if(c2 -= c1)
|
||||
return c2;
|
||||
if(t2 > t1)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
acomcmp2(const void *a1, const void *a2)
|
||||
{
|
||||
vlong c1, c2;
|
||||
Term *t1, *t2;
|
||||
|
||||
t1 = (Term*)a1;
|
||||
t2 = (Term*)a2;
|
||||
c1 = t1->mult;
|
||||
c2 = t2->mult;
|
||||
if(c1 > c2)
|
||||
return 1;
|
||||
if(c1 < c2)
|
||||
return -1;
|
||||
if(t2 > t1)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
acom2(Node *n, Type *t)
|
||||
{
|
||||
Node *l, *r;
|
||||
Term trm[NTERM];
|
||||
int et, nt, i, j;
|
||||
vlong c1, c2;
|
||||
|
||||
/*
|
||||
* copy into automatic
|
||||
*/
|
||||
c2 = 0;
|
||||
nt = nterm;
|
||||
for(i=0; i<nt; i++)
|
||||
trm[i] = term[i];
|
||||
/*
|
||||
* recur on subtrees
|
||||
*/
|
||||
j = 0;
|
||||
for(i=1; i<nt; i++) {
|
||||
c1 = trm[i].mult;
|
||||
if(c1 == 0)
|
||||
continue;
|
||||
l = trm[i].node;
|
||||
if(l != Z) {
|
||||
j = 1;
|
||||
acom(l);
|
||||
}
|
||||
}
|
||||
c1 = trm[0].mult;
|
||||
if(j == 0) {
|
||||
n->oldop = n->op;
|
||||
n->op = OCONST;
|
||||
n->vconst = c1;
|
||||
return;
|
||||
}
|
||||
et = t->etype;
|
||||
|
||||
/*
|
||||
* prepare constant term,
|
||||
* combine it with an addressing term
|
||||
*/
|
||||
if(c1 != 0) {
|
||||
l = new1(OCONST, Z, Z);
|
||||
l->type = t;
|
||||
l->vconst = c1;
|
||||
trm[0].mult = 1;
|
||||
for(i=1; i<nt; i++) {
|
||||
if(trm[i].mult != 1)
|
||||
continue;
|
||||
r = trm[i].node;
|
||||
if(r->op != OADDR)
|
||||
continue;
|
||||
r->type = t;
|
||||
l = new1(OADD, r, l);
|
||||
l->type = t;
|
||||
trm[i].mult = 0;
|
||||
break;
|
||||
}
|
||||
trm[0].node = l;
|
||||
}
|
||||
/*
|
||||
* look for factorable terms
|
||||
* c1*i + c1*c2*j -> c1*(i + c2*j)
|
||||
*/
|
||||
qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
|
||||
for(i=nt-1; i>=0; i--) {
|
||||
c1 = trm[i].mult;
|
||||
if(c1 < 0)
|
||||
c1 = -c1;
|
||||
if(c1 <= 1)
|
||||
continue;
|
||||
for(j=i+1; j<nt; j++) {
|
||||
c2 = trm[j].mult;
|
||||
if(c2 < 0)
|
||||
c2 = -c2;
|
||||
if(c2 <= 1)
|
||||
continue;
|
||||
if(c2 % c1)
|
||||
continue;
|
||||
r = trm[j].node;
|
||||
if(r->type->etype != et)
|
||||
r = acast(t, r);
|
||||
c2 = trm[j].mult/trm[i].mult;
|
||||
if(c2 != 1 && c2 != -1) {
|
||||
r = new1(OMUL, r, new(OCONST, Z, Z));
|
||||
r->type = t;
|
||||
r->right->type = t;
|
||||
r->right->vconst = c2;
|
||||
}
|
||||
l = trm[i].node;
|
||||
if(l->type->etype != et)
|
||||
l = acast(t, l);
|
||||
r = new1(OADD, l, r);
|
||||
r->type = t;
|
||||
if(c2 == -1)
|
||||
r->op = OSUB;
|
||||
trm[i].node = r;
|
||||
trm[j].mult = 0;
|
||||
}
|
||||
}
|
||||
if(debug['m']) {
|
||||
print("\n");
|
||||
for(i=0; i<nt; i++) {
|
||||
print("%d %3lld ", i, trm[i].mult);
|
||||
prtree1(trm[i].node, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* put it all back together
|
||||
*/
|
||||
qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
|
||||
l = Z;
|
||||
for(i=nt-1; i>=0; i--) {
|
||||
c1 = trm[i].mult;
|
||||
if(c1 == 0)
|
||||
continue;
|
||||
r = trm[i].node;
|
||||
if(r->type->etype != et || r->op == OBIT)
|
||||
r = acast(t, r);
|
||||
if(c1 != 1 && c1 != -1) {
|
||||
r = new1(OMUL, r, new(OCONST, Z, Z));
|
||||
r->type = t;
|
||||
r->right->type = t;
|
||||
if(c1 < 0) {
|
||||
r->right->vconst = -c1;
|
||||
c1 = -1;
|
||||
} else {
|
||||
r->right->vconst = c1;
|
||||
c1 = 1;
|
||||
}
|
||||
}
|
||||
if(l == Z) {
|
||||
l = r;
|
||||
c2 = c1;
|
||||
continue;
|
||||
}
|
||||
if(c1 < 0)
|
||||
if(c2 < 0)
|
||||
l = new1(OADD, l, r);
|
||||
else
|
||||
l = new1(OSUB, l, r);
|
||||
else
|
||||
if(c2 < 0) {
|
||||
l = new1(OSUB, r, l);
|
||||
c2 = 1;
|
||||
} else
|
||||
l = new1(OADD, l, r);
|
||||
l->type = t;
|
||||
}
|
||||
if(c2 < 0) {
|
||||
r = new1(OCONST, 0, 0);
|
||||
r->vconst = 0;
|
||||
r->type = t;
|
||||
l = new1(OSUB, r, l);
|
||||
l->type = t;
|
||||
}
|
||||
*n = *l;
|
||||
}
|
||||
|
||||
void
|
||||
acom1(vlong v, Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
if(v == 0 || nterm >= NTERM)
|
||||
return;
|
||||
if(!addo(n)) {
|
||||
if(n->op == OCONST)
|
||||
if(!typefd[n->type->etype]) {
|
||||
term[0].mult += v*n->vconst;
|
||||
return;
|
||||
}
|
||||
term[nterm].mult = v;
|
||||
term[nterm].node = n;
|
||||
nterm++;
|
||||
return;
|
||||
}
|
||||
switch(n->op) {
|
||||
|
||||
case OCAST:
|
||||
acom1(v, n->left);
|
||||
break;
|
||||
|
||||
case ONEG:
|
||||
acom1(-v, n->left);
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
acom1(v, n->left);
|
||||
acom1(v, n->right);
|
||||
break;
|
||||
|
||||
case OSUB:
|
||||
acom1(v, n->left);
|
||||
acom1(-v, n->right);
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l->op == OCONST)
|
||||
if(!typefd[n->type->etype]) {
|
||||
acom1(v*l->vconst, r);
|
||||
break;
|
||||
}
|
||||
if(r->op == OCONST)
|
||||
if(!typefd[n->type->etype]) {
|
||||
acom1(v*r->vconst, l);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
diag(n, "not addo");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
addo(Node *n)
|
||||
{
|
||||
|
||||
if(n != Z)
|
||||
if(!typefd[n->type->etype])
|
||||
if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
|
||||
switch(n->op) {
|
||||
|
||||
case OCAST:
|
||||
if(nilcast(n->left->type, n->type))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case ONEG:
|
||||
case OADD:
|
||||
case OSUB:
|
||||
return 1;
|
||||
|
||||
case OMUL:
|
||||
if(n->left->op == OCONST)
|
||||
return 1;
|
||||
if(n->right->op == OCONST)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
2054
src/cmd/cc/sub.c
Normal file
2054
src/cmd/cc/sub.c
Normal file
File diff suppressed because it is too large
Load diff
370
src/cmd/gc/const.c
Normal file
370
src/cmd/gc/const.c
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "go.h"
|
||||
#define TUP(x,y) (((x)<<16)|(y))
|
||||
|
||||
void
|
||||
convlit(Node *n, Type *t)
|
||||
{
|
||||
int et;
|
||||
|
||||
if(n->op != OLITERAL)
|
||||
return;
|
||||
if(t == T)
|
||||
return;
|
||||
|
||||
n->type = t;
|
||||
et = t->etype;
|
||||
|
||||
switch(whatis(n)) {
|
||||
case Wlitint:
|
||||
if(isptrto(t, TSTRING)) {
|
||||
Rune rune;
|
||||
int l;
|
||||
String *s;
|
||||
|
||||
rune = n->val.vval;
|
||||
l = runelen(rune);
|
||||
s = mal(sizeof(*s)+l);
|
||||
s->len = l;
|
||||
runetochar((char*)(s->s), &rune);
|
||||
|
||||
n->val.sval = s;
|
||||
n->val.ctype = CTSTR;
|
||||
break;
|
||||
}
|
||||
if(isint[et]) {
|
||||
if(n->val.vval < minintval[et])
|
||||
goto bad2;
|
||||
if(n->val.vval > maxintval[et])
|
||||
goto bad2;
|
||||
break;
|
||||
}
|
||||
if(isfloat[et]) {
|
||||
if(n->val.vval < minfloatval[et])
|
||||
goto bad2;
|
||||
if(n->val.vval > maxfloatval[et])
|
||||
goto bad2;
|
||||
n->val.dval = n->val.vval;
|
||||
n->val.ctype = CTFLT;
|
||||
break;
|
||||
}
|
||||
goto bad1;
|
||||
|
||||
case Wlitfloat:
|
||||
if(isint[et]) {
|
||||
if(n->val.dval < minintval[et])
|
||||
goto bad2;
|
||||
if(n->val.dval > maxintval[et])
|
||||
goto bad2;
|
||||
n->val.vval = n->val.dval;
|
||||
n->val.ctype = CTINT;
|
||||
break;
|
||||
}
|
||||
if(isfloat[et]) {
|
||||
if(n->val.dval < minfloatval[et])
|
||||
goto bad2;
|
||||
if(n->val.dval > maxfloatval[et])
|
||||
goto bad2;
|
||||
break;
|
||||
}
|
||||
goto bad1;
|
||||
}
|
||||
return;
|
||||
|
||||
bad1:
|
||||
yyerror("illegal conversion of constant to %T", t);
|
||||
return;
|
||||
|
||||
bad2:
|
||||
yyerror("overflow converting constant to %T", t);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
evconst(Node *n)
|
||||
{
|
||||
Node *nl, *nr;
|
||||
long len;
|
||||
String *str;
|
||||
int wl, wr;
|
||||
|
||||
nl = n->left;
|
||||
if(nl == N)
|
||||
return;
|
||||
|
||||
wl = whatis(nl);
|
||||
switch(wl) {
|
||||
default:
|
||||
return;
|
||||
|
||||
case Wlitint:
|
||||
case Wlitfloat:
|
||||
case Wlitbool:
|
||||
case Wlitstr:
|
||||
break;
|
||||
}
|
||||
|
||||
nr = n->right;
|
||||
if(nr == N)
|
||||
goto unary;
|
||||
|
||||
wr = whatis(nr);
|
||||
switch(wr) {
|
||||
default:
|
||||
return;
|
||||
|
||||
case Wlitint:
|
||||
case Wlitfloat:
|
||||
case Wlitbool:
|
||||
case Wlitstr:
|
||||
break;
|
||||
}
|
||||
if(wl != wr) {
|
||||
yyerror("illegal combination of literals %d %d", nl->etype, nr->etype);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(TUP(n->op, wl)) {
|
||||
default:
|
||||
yyerror("illegal combination of literals %O %d", n->op, wl);
|
||||
return;
|
||||
|
||||
case TUP(OADD, Wlitint):
|
||||
nl->val.vval += nr->val.vval;
|
||||
break;
|
||||
case TUP(OSUB, Wlitint):
|
||||
nl->val.vval -= nr->val.vval;
|
||||
break;
|
||||
case TUP(OMUL, Wlitint):
|
||||
nl->val.vval *= nr->val.vval;
|
||||
break;
|
||||
case TUP(ODIV, Wlitint):
|
||||
nl->val.vval /= nr->val.vval;
|
||||
break;
|
||||
case TUP(OMOD, Wlitint):
|
||||
nl->val.vval %= nr->val.vval;
|
||||
break;
|
||||
case TUP(OLSH, Wlitint):
|
||||
nl->val.vval <<= nr->val.vval;
|
||||
break;
|
||||
case TUP(ORSH, Wlitint):
|
||||
nl->val.vval >>= nr->val.vval;
|
||||
break;
|
||||
case TUP(OOR, Wlitint):
|
||||
nl->val.vval |= nr->val.vval;
|
||||
break;
|
||||
case TUP(OAND, Wlitint):
|
||||
nl->val.vval &= nr->val.vval;
|
||||
break;
|
||||
|
||||
case TUP(OADD, Wlitfloat):
|
||||
nl->val.dval += nr->val.dval;
|
||||
break;
|
||||
case TUP(OSUB, Wlitfloat):
|
||||
nl->val.dval -= nr->val.dval;
|
||||
break;
|
||||
case TUP(OMUL, Wlitfloat):
|
||||
nl->val.dval *= nr->val.dval;
|
||||
break;
|
||||
case TUP(ODIV, Wlitfloat):
|
||||
nl->val.dval /= nr->val.dval;
|
||||
break;
|
||||
|
||||
case TUP(OEQ, Wlitint):
|
||||
if(nl->val.vval == nr->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(ONE, Wlitint):
|
||||
if(nl->val.vval != nr->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OLT, Wlitint):
|
||||
if(nl->val.vval < nr->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OLE, Wlitint):
|
||||
if(nl->val.vval <= nr->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OGE, Wlitint):
|
||||
if(nl->val.vval >= nr->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OGT, Wlitint):
|
||||
if(nl->val.vval > nr->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
|
||||
case TUP(OEQ, Wlitfloat):
|
||||
if(nl->val.dval == nr->val.dval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(ONE, Wlitfloat):
|
||||
if(nl->val.dval != nr->val.dval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OLT, Wlitfloat):
|
||||
if(nl->val.dval < nr->val.dval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OLE, Wlitfloat):
|
||||
if(nl->val.dval <= nr->val.dval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OGE, Wlitfloat):
|
||||
if(nl->val.dval >= nr->val.dval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OGT, Wlitfloat):
|
||||
if(nl->val.dval > nr->val.dval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
|
||||
|
||||
case TUP(OEQ, Wlitstr):
|
||||
if(cmpslit(nl, nr) == 0)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(ONE, Wlitstr):
|
||||
if(cmpslit(nl, nr) != 0)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OLT, Wlitstr):
|
||||
if(cmpslit(nl, nr) < 0)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OLE, Wlitstr):
|
||||
if(cmpslit(nl, nr) <= 0)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OGE, Wlitstr):
|
||||
if(cmpslit(nl, nr) >= 0l)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OGT, Wlitstr):
|
||||
if(cmpslit(nl, nr) > 0)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OADD, Wlitstr):
|
||||
len = nl->val.sval->len + nr->val.sval->len;
|
||||
str = mal(sizeof(*str) + len);
|
||||
str->len = len;
|
||||
memcpy(str->s, nl->val.sval->s, nl->val.sval->len);
|
||||
memcpy(str->s+nl->val.sval->len, nr->val.sval->s, nr->val.sval->len);
|
||||
str->len = len;
|
||||
nl->val.sval = str;
|
||||
break;
|
||||
|
||||
case TUP(OOROR, Wlitbool):
|
||||
if(nl->val.vval || nr->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
case TUP(OANDAND, Wlitbool):
|
||||
if(nl->val.vval && nr->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
}
|
||||
*n = *nl;
|
||||
return;
|
||||
|
||||
settrue:
|
||||
*n = *booltrue;
|
||||
return;
|
||||
|
||||
setfalse:
|
||||
*n = *boolfalse;
|
||||
return;
|
||||
|
||||
unary:
|
||||
switch(TUP(n->op, wl)) {
|
||||
default:
|
||||
yyerror("illegal combination of literals %O %d", n->op, wl);
|
||||
return;
|
||||
|
||||
case TUP(OPLUS, Wlitint):
|
||||
nl->val.vval = +nl->val.vval;
|
||||
break;
|
||||
case TUP(OMINUS, Wlitint):
|
||||
nl->val.vval = -nl->val.vval;
|
||||
break;
|
||||
case TUP(OCOM, Wlitint):
|
||||
nl->val.vval = ~nl->val.vval;
|
||||
break;
|
||||
|
||||
case TUP(OPLUS, Wlitfloat):
|
||||
nl->val.dval = +nl->val.dval;
|
||||
break;
|
||||
case TUP(OMINUS, Wlitfloat):
|
||||
nl->val.dval = -nl->val.dval;
|
||||
break;
|
||||
|
||||
case TUP(ONOT, Wlitbool):
|
||||
if(nl->val.vval)
|
||||
goto settrue;
|
||||
goto setfalse;
|
||||
}
|
||||
*n = *nl;
|
||||
}
|
||||
|
||||
void
|
||||
defaultlit(Node *n)
|
||||
{
|
||||
if(n == N)
|
||||
return;
|
||||
if(n->type != T)
|
||||
return;
|
||||
if(n->op != OLITERAL)
|
||||
return;
|
||||
|
||||
switch(n->val.ctype) {
|
||||
default:
|
||||
yyerror("defaultlit: unknown literal: %N", n);
|
||||
break;
|
||||
case CTINT:
|
||||
case CTSINT:
|
||||
case CTUINT:
|
||||
n->type = types[TINT32];
|
||||
break;
|
||||
case CTFLT:
|
||||
n->type = types[TFLOAT64];
|
||||
break;
|
||||
case CTBOOL:
|
||||
n->type = types[TBOOL];
|
||||
break;
|
||||
case CTSTR:
|
||||
n->type = types[TSTRING];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cmpslit(Node *l, Node *r)
|
||||
{
|
||||
long l1, l2, i, m;
|
||||
char *s1, *s2;
|
||||
|
||||
l1 = l->val.sval->len;
|
||||
l2 = r->val.sval->len;
|
||||
s1 = l->val.sval->s;
|
||||
s2 = r->val.sval->s;
|
||||
|
||||
m = l1;
|
||||
if(l2 < m)
|
||||
m = l2;
|
||||
|
||||
for(i=0; i<m; i++) {
|
||||
if(s1[i] == s2[i])
|
||||
continue;
|
||||
if(s1[i] > s2[i])
|
||||
return +1;
|
||||
return -1;
|
||||
}
|
||||
if(l1 == l2)
|
||||
return 0;
|
||||
if(l1 > l2)
|
||||
return +1;
|
||||
return -1;
|
||||
}
|
||||
814
src/cmd/gc/dcl.c
Normal file
814
src/cmd/gc/dcl.c
Normal file
|
|
@ -0,0 +1,814 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "go.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
void
|
||||
dodclvar(Node *n, Type *t)
|
||||
{
|
||||
|
||||
loop:
|
||||
if(n == N)
|
||||
return;
|
||||
|
||||
if(n->op == OLIST) {
|
||||
dodclvar(n->left, t);
|
||||
n = n->right;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
addvar(n, t, dclcontext);
|
||||
}
|
||||
|
||||
void
|
||||
dodcltype(Type *n, Type *t)
|
||||
{
|
||||
|
||||
if(n == T)
|
||||
return;
|
||||
addtyp(n, t, dclcontext);
|
||||
}
|
||||
|
||||
void
|
||||
dodclconst(Node *n, Node *e)
|
||||
{
|
||||
Sym *s;
|
||||
Dcl *r, *d;
|
||||
|
||||
loop:
|
||||
if(n == N)
|
||||
return;
|
||||
if(n->op == OLIST) {
|
||||
dodclconst(n->left, e);
|
||||
n = n->right;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if(n->op != ONAME)
|
||||
fatal("dodclconst: not a name");
|
||||
|
||||
if(e->op != OLITERAL) {
|
||||
yyerror("expression must be a constant");
|
||||
goto loop;
|
||||
}
|
||||
s = n->sym;
|
||||
|
||||
s->oconst = e;
|
||||
s->lexical = LACONST;
|
||||
|
||||
r = autodcl;
|
||||
if(dclcontext == PEXTERN)
|
||||
r = externdcl;
|
||||
|
||||
d = dcl();
|
||||
d->dsym = s;
|
||||
d->dnode = e;
|
||||
d->op = OCONST;
|
||||
|
||||
r->back->forw = d;
|
||||
r->back = d;
|
||||
|
||||
if(debug['d'])
|
||||
print("const-dcl %S %N\n", n->sym, n->sym->oconst);
|
||||
}
|
||||
|
||||
/*
|
||||
* return nelem of list
|
||||
*/
|
||||
int
|
||||
listcount(Node *n)
|
||||
{
|
||||
int v;
|
||||
|
||||
v = 0;
|
||||
while(n != N) {
|
||||
v++;
|
||||
if(n->op != OLIST)
|
||||
break;
|
||||
n = n->right;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* turn a parsed function declaration
|
||||
* into a type
|
||||
*/
|
||||
Type*
|
||||
functype(Node *this, Node *in, Node *out)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = typ(TFUNC);
|
||||
|
||||
t->type = dostruct(this, TSTRUCT);
|
||||
t->type->down = dostruct(out, TSTRUCT);
|
||||
t->type->down->down = dostruct(in, TSTRUCT);
|
||||
|
||||
t->thistuple = listcount(this);
|
||||
t->outtuple = listcount(out);
|
||||
t->intuple = listcount(in);
|
||||
|
||||
dowidth(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void
|
||||
funcnam(Type *t, char *nam)
|
||||
{
|
||||
Node *n;
|
||||
Sym *s;
|
||||
char buf[100];
|
||||
|
||||
if(nam == nil) {
|
||||
vargen++;
|
||||
snprint(buf, sizeof(buf), "_f%.3ld", vargen);
|
||||
nam = buf;
|
||||
}
|
||||
|
||||
if(t->etype != TFUNC)
|
||||
fatal("funcnam: not func %T\n", t);
|
||||
|
||||
if(t->thistuple > 0) {
|
||||
vargen++;
|
||||
snprint(namebuf, sizeof(namebuf), "_t%.3ld", vargen);
|
||||
s = lookup(namebuf);
|
||||
addtyp(newtype(s), t->type, PEXTERN);
|
||||
n = newname(s);
|
||||
n->vargen = vargen;
|
||||
t->type->nname = n;
|
||||
}
|
||||
if(t->outtuple > 0) {
|
||||
vargen++;
|
||||
snprint(namebuf, sizeof(namebuf), "_o%.3ld", vargen);
|
||||
s = lookup(namebuf);
|
||||
addtyp(newtype(s), t->type->down, PEXTERN);
|
||||
n = newname(s);
|
||||
n->vargen = vargen;
|
||||
t->type->down->nname = n;
|
||||
}
|
||||
if(t->intuple > 0) {
|
||||
vargen++;
|
||||
snprint(namebuf, sizeof(namebuf), "_i%.3ld", vargen);
|
||||
s = lookup(namebuf);
|
||||
addtyp(newtype(s), t->type->down->down, PEXTERN);
|
||||
n = newname(s);
|
||||
n->vargen = vargen;
|
||||
t->type->down->down->nname = n;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
methcmp(Type *t1, Type *t2)
|
||||
{
|
||||
if(t1->etype != TFUNC)
|
||||
return 0;
|
||||
if(t2->etype != TFUNC)
|
||||
return 0;
|
||||
|
||||
t1 = t1->type->down; // skip this arg
|
||||
t2 = t2->type->down; // skip this arg
|
||||
for(;;) {
|
||||
if(t1 == t2)
|
||||
break;
|
||||
if(t1 == T || t2 == T)
|
||||
return 0;
|
||||
if(t1->etype != TSTRUCT || t2->etype != TSTRUCT)
|
||||
return 0;
|
||||
|
||||
if(!eqtype(t1->type, t2->type, 0))
|
||||
return 0;
|
||||
|
||||
t1 = t1->down;
|
||||
t2 = t2->down;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Node*
|
||||
methodname(Node *n, Type *t)
|
||||
{
|
||||
if(isptr[t->etype])
|
||||
t = t->type;
|
||||
if(t->etype != TSTRUCT)
|
||||
goto bad;
|
||||
if(t->sym == S)
|
||||
goto bad;
|
||||
|
||||
snprint(namebuf, sizeof(namebuf), "%s_%s", t->sym->name, n->sym->name);
|
||||
return newname(lookup(namebuf));
|
||||
|
||||
bad:
|
||||
yyerror("illegal <this> pointer");
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* add a method, declared as a function,
|
||||
* into the structure
|
||||
*/
|
||||
void
|
||||
addmethod(Node *n, Type *pa, Type *t)
|
||||
{
|
||||
Type *f, *d, *p;
|
||||
Sym *s;
|
||||
|
||||
if(n->op != ONAME)
|
||||
goto bad;
|
||||
s = n->sym;
|
||||
if(s == S)
|
||||
goto bad;
|
||||
if(pa == T)
|
||||
goto bad;
|
||||
if(!isptr[pa->etype])
|
||||
goto bad;
|
||||
p = pa->type;
|
||||
if(p == T)
|
||||
goto bad;
|
||||
if(p->etype != TSTRUCT)
|
||||
goto bad;
|
||||
if(p->sym == S)
|
||||
goto bad;
|
||||
|
||||
if(p->type == T) {
|
||||
n = nod(ODCLFIELD, newname(s), N);
|
||||
n->type = t;
|
||||
|
||||
stotype(n, &p->type);
|
||||
return;
|
||||
}
|
||||
|
||||
d = T; // last found
|
||||
for(f=p->type; f!=T; f=f->down) {
|
||||
if(f->etype != TFIELD)
|
||||
fatal("addmethod: not TFIELD: %N", f);
|
||||
|
||||
if(strcmp(s->name, f->sym->name) != 0) {
|
||||
d = f;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if a field matches a non-this function
|
||||
// then delete it and let it be redeclared
|
||||
if(methcmp(t, f->type)) {
|
||||
if(d == T) {
|
||||
p->type = f->down;
|
||||
continue;
|
||||
}
|
||||
d->down = f->down;
|
||||
continue;
|
||||
}
|
||||
if(!eqtype(t, f->type, 0))
|
||||
yyerror("field redeclared as method: %S", s);
|
||||
return;
|
||||
}
|
||||
|
||||
n = nod(ODCLFIELD, newname(s), N);
|
||||
n->type = t;
|
||||
|
||||
if(d == T)
|
||||
stotype(n, &p->type);
|
||||
else
|
||||
stotype(n, &d->down);
|
||||
return;
|
||||
|
||||
bad:
|
||||
yyerror("unknown method pointer: %T", pa);
|
||||
}
|
||||
|
||||
/*
|
||||
* declare the function proper.
|
||||
* and declare the arguments
|
||||
* called in extern-declaration context
|
||||
* returns in auto-declaration context.
|
||||
*/
|
||||
void
|
||||
funchdr(Node *n)
|
||||
{
|
||||
Node *on;
|
||||
Sym *s;
|
||||
|
||||
s = n->nname->sym;
|
||||
on = s->oname;
|
||||
|
||||
// check for same types
|
||||
if(on != N) {
|
||||
if(eqtype(n->type, on->type, 0)) {
|
||||
if(!eqargs(n->type, on->type))
|
||||
yyerror("foreward declarations not the same: %S", s);
|
||||
} else {
|
||||
yyerror("redeclare of function: %S", s);
|
||||
on = N;
|
||||
}
|
||||
}
|
||||
|
||||
// check for foreward declaration
|
||||
if(on == N) {
|
||||
// initial declaration or redeclaration
|
||||
// declare fun name, argument types and argument names
|
||||
funcnam(n->type, s->name);
|
||||
n->nname->type = n->type;
|
||||
if(n->type->thistuple == 0)
|
||||
addvar(n->nname, n->type, PEXTERN);
|
||||
else
|
||||
n->nname->class = PEXTERN;
|
||||
} else {
|
||||
// identical redeclaration
|
||||
// steal previous names
|
||||
n->nname = on;
|
||||
n->type = on->type;
|
||||
n->class = on->class;
|
||||
n->sym = s;
|
||||
if(debug['d'])
|
||||
print("forew var-dcl %S %T\n", n->sym, n->type);
|
||||
}
|
||||
|
||||
// change the declaration context from extern to auto
|
||||
autodcl = dcl();
|
||||
autodcl->back = autodcl;
|
||||
|
||||
if(dclcontext != PEXTERN)
|
||||
fatal("funchdr: dclcontext");
|
||||
|
||||
dclcontext = PAUTO;
|
||||
markdcl("func");
|
||||
funcargs(n->type);
|
||||
|
||||
if(n->type->thistuple > 0) {
|
||||
Type *t;
|
||||
t = *getthis(n->type);
|
||||
addmethod(n->nname, t->type->type, n->type);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
funcargs(Type *t)
|
||||
{
|
||||
Type *n1;
|
||||
Iter save;
|
||||
|
||||
// declare the this argument
|
||||
n1 = funcfirst(&save, t);
|
||||
while(n1 != T) {
|
||||
if(n1->nname != N)
|
||||
addvar(n1->nname, n1->type, PPARAM);
|
||||
n1 = funcnext(&save);
|
||||
}
|
||||
|
||||
// declare the outgoing arguments
|
||||
// n1 = structfirst(&save, getoutarg(t));
|
||||
// while(n1 != T) {
|
||||
// n1->left = newname(n1->sym);
|
||||
// if(n1->nname != N)
|
||||
// addvar(n1->nname, n1->type, PPARAM);
|
||||
// n1 = structnext(&save);
|
||||
// }
|
||||
}
|
||||
|
||||
/*
|
||||
* compile the function.
|
||||
* called in auto-declaration context.
|
||||
* returns in extern-declaration context.
|
||||
*/
|
||||
void
|
||||
funcbody(Node *n)
|
||||
{
|
||||
|
||||
compile(n);
|
||||
|
||||
// change the declaration context from auto to extern
|
||||
if(dclcontext != PAUTO)
|
||||
fatal("funcbody: dclcontext");
|
||||
popdcl("func");
|
||||
dclcontext = PEXTERN;
|
||||
}
|
||||
|
||||
/*
|
||||
* turn a parsed struct into a type
|
||||
*/
|
||||
Type**
|
||||
stotype(Node *n, Type **t)
|
||||
{
|
||||
Type *f;
|
||||
Iter save;
|
||||
|
||||
n = listfirst(&save, &n);
|
||||
|
||||
loop:
|
||||
if(n == N) {
|
||||
*t = T;
|
||||
return t;
|
||||
}
|
||||
|
||||
if(n->op == OLIST) {
|
||||
// recursive because it can be lists of lists
|
||||
t = stotype(n, t);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if(n->op != ODCLFIELD || n->type == T)
|
||||
fatal("stotype: oops %N\n", n);
|
||||
|
||||
if(n->type->etype == TDARRAY)
|
||||
yyerror("type of a structure field cannot be an open array");
|
||||
|
||||
f = typ(TFIELD);
|
||||
f->type = n->type;
|
||||
|
||||
if(n->left != N && n->left->op == ONAME) {
|
||||
f->nname = n->left;
|
||||
} else {
|
||||
vargen++;
|
||||
snprint(namebuf, sizeof(namebuf), "_e%.3ld", vargen);
|
||||
f->nname = newname(lookup(namebuf));
|
||||
}
|
||||
f->sym = f->nname->sym;
|
||||
|
||||
*t = f;
|
||||
t = &f->down;
|
||||
|
||||
next:
|
||||
n = listnext(&save);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
Type*
|
||||
dostruct(Node *n, int et)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
/*
|
||||
* convert a parsed id/type list into
|
||||
* a type for struct/interface/arglist
|
||||
*/
|
||||
|
||||
t = typ(et);
|
||||
stotype(n, &t->type);
|
||||
dowidth(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Type*
|
||||
sortinter(Type *t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
void
|
||||
dcopy(Sym *a, Sym *b)
|
||||
{
|
||||
a->name = b->name;
|
||||
a->oname = b->oname;
|
||||
a->otype = b->otype;
|
||||
a->oconst = b->oconst;
|
||||
a->package = b->package;
|
||||
a->opackage = b->opackage;
|
||||
a->forwtype = b->forwtype;
|
||||
a->lexical = b->lexical;
|
||||
a->undef = b->undef;
|
||||
a->vargen = b->vargen;
|
||||
}
|
||||
|
||||
Sym*
|
||||
push(void)
|
||||
{
|
||||
Sym *d;
|
||||
|
||||
d = mal(sizeof(*d));
|
||||
d->link = dclstack;
|
||||
dclstack = d;
|
||||
return d;
|
||||
}
|
||||
|
||||
Sym*
|
||||
pushdcl(Sym *s)
|
||||
{
|
||||
Sym *d;
|
||||
|
||||
d = push();
|
||||
dcopy(d, s);
|
||||
return d;
|
||||
}
|
||||
|
||||
void
|
||||
popdcl(char *why)
|
||||
{
|
||||
Sym *d, *s;
|
||||
|
||||
// if(debug['d'])
|
||||
// print("revert\n");
|
||||
for(d=dclstack; d!=S; d=d->link) {
|
||||
if(d->name == nil)
|
||||
break;
|
||||
s = pkglookup(d->name, d->package);
|
||||
dcopy(s, d);
|
||||
if(debug['d'])
|
||||
print("\t%ld pop %S\n", curio.lineno, s);
|
||||
}
|
||||
if(d == S)
|
||||
fatal("popdcl: no mark");
|
||||
if(strcmp(why, d->package) != 0)
|
||||
fatal("popdcl: pushed as %s poped as %s", d->package, why);
|
||||
dclstack = d->link;
|
||||
}
|
||||
|
||||
void
|
||||
poptodcl(void)
|
||||
{
|
||||
Sym *d, *s;
|
||||
|
||||
for(d=dclstack; d!=S; d=d->link) {
|
||||
if(d->name == nil)
|
||||
break;
|
||||
s = pkglookup(d->name, d->package);
|
||||
dcopy(s, d);
|
||||
if(debug['d'])
|
||||
print("\t%ld pop %S\n", curio.lineno, s);
|
||||
}
|
||||
if(d == S)
|
||||
fatal("poptodcl: no mark");
|
||||
}
|
||||
|
||||
void
|
||||
markdcl(char *why)
|
||||
{
|
||||
Sym *d;
|
||||
|
||||
d = push();
|
||||
d->name = nil; // used as a mark in fifo
|
||||
d->package = why; // diagnostic for unmatched
|
||||
// if(debug['d'])
|
||||
// print("markdcl\n");
|
||||
}
|
||||
|
||||
void
|
||||
markdclstack(void)
|
||||
{
|
||||
Sym *d, *s;
|
||||
|
||||
markdcl("fnlit");
|
||||
|
||||
// copy the entire pop of the stack
|
||||
// all the way back to block0.
|
||||
// after this the symbol table is at
|
||||
// block0 and popdcl will restore it.
|
||||
for(d=dclstack; d!=S; d=d->link) {
|
||||
if(d == b0stack)
|
||||
break;
|
||||
if(d->name != nil) {
|
||||
s = pkglookup(d->name, d->package);
|
||||
pushdcl(s);
|
||||
dcopy(s, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testdclstack(void)
|
||||
{
|
||||
Sym *d;
|
||||
|
||||
for(d=dclstack; d!=S; d=d->link) {
|
||||
if(d->name == nil) {
|
||||
yyerror("mark left on the stack");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
addvar(Node *n, Type *t, int ctxt)
|
||||
{
|
||||
Dcl *r, *d;
|
||||
Sym *s;
|
||||
Type *ot;
|
||||
Node *on;
|
||||
int gen;
|
||||
|
||||
if(n==N || n->sym == S || n->op != ONAME || t == T)
|
||||
fatal("addvar: n=%N t=%T nil", n, t);
|
||||
|
||||
ot = t;
|
||||
if(isptr[ot->etype])
|
||||
ot = ot->type;
|
||||
|
||||
if(ot->etype == TSTRUCT && ot->vargen == 0) {
|
||||
vargen++;
|
||||
snprint(namebuf, sizeof(namebuf), "_s%.3ld", vargen);
|
||||
s = lookup(namebuf);
|
||||
addtyp(newtype(s), ot, PEXTERN);
|
||||
}
|
||||
|
||||
s = n->sym;
|
||||
vargen++;
|
||||
gen = vargen;
|
||||
|
||||
r = autodcl;
|
||||
if(ctxt == PEXTERN) {
|
||||
on = s->oname;
|
||||
if(on != N) {
|
||||
if(eqtype(t, on->type, 0)) {
|
||||
warn("%S redeclared", s);
|
||||
return;
|
||||
}
|
||||
yyerror("%S redeclared (%T %T)", s,
|
||||
on->type, t);
|
||||
}
|
||||
r = externdcl;
|
||||
gen = 0;
|
||||
}
|
||||
|
||||
if(ctxt != PEXTERN)
|
||||
pushdcl(s);
|
||||
|
||||
s->vargen = gen;
|
||||
s->oname = n;
|
||||
s->offset = 0;
|
||||
|
||||
n->type = t;
|
||||
n->vargen = gen;
|
||||
n->class = ctxt;
|
||||
|
||||
d = dcl();
|
||||
d->dsym = s;
|
||||
d->dnode = n;
|
||||
d->op = ONAME;
|
||||
|
||||
r->back->forw = d;
|
||||
r->back = d;
|
||||
|
||||
if(debug['d']) {
|
||||
if(ctxt == PEXTERN)
|
||||
print("extern var-dcl %S G%ld %T\n", s, s->vargen, t);
|
||||
else
|
||||
print("auto var-dcl %S G%ld %T\n", s, s->vargen, t);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
addtyp(Type *n, Type *t, int ctxt)
|
||||
{
|
||||
Dcl *r, *d;
|
||||
Sym *s;
|
||||
Type *f, *ot;
|
||||
|
||||
if(n==T || n->sym == S || t == T)
|
||||
fatal("addtyp: n=%T t=%T nil", n, t);
|
||||
|
||||
s = n->sym;
|
||||
|
||||
r = autodcl;
|
||||
if(ctxt == PEXTERN) {
|
||||
ot = s->otype;
|
||||
if(ot != T) {
|
||||
// allow nil interface to be
|
||||
// redeclared as an interface
|
||||
if(ot->etype == TINTER && ot->type == T && t->etype == TINTER) {
|
||||
if(debug['d'])
|
||||
print("forew typ-dcl %S G%ld %T\n", s, s->vargen, t);
|
||||
s->otype = t;
|
||||
return;
|
||||
}
|
||||
if(eqtype(t, ot, 0)) {
|
||||
warn("%S redeclared", s);
|
||||
return;
|
||||
}
|
||||
yyerror("%S redeclared (%T %T)", s,
|
||||
ot, t);
|
||||
}
|
||||
r = externdcl;
|
||||
}
|
||||
|
||||
if(ctxt != PEXTERN)
|
||||
pushdcl(s);
|
||||
|
||||
if(t->sym != S)
|
||||
warn("addtyp: renaming %S/%lT to %S/%lT", t->sym, t->sym->otype, s, n);
|
||||
|
||||
vargen++;
|
||||
s->vargen = vargen;
|
||||
s->otype = t;
|
||||
s->lexical = LATYPE;
|
||||
|
||||
t->sym = s;
|
||||
t->vargen = vargen;
|
||||
|
||||
for(f=s->forwtype; f!=T; f=f->nforw) {
|
||||
if(!isptr[f->etype])
|
||||
fatal("addtyp: foreward");
|
||||
f->type = t;
|
||||
}
|
||||
s->forwtype = T;
|
||||
|
||||
d = dcl();
|
||||
d->dsym = s;
|
||||
d->dtype = t;
|
||||
d->op = OTYPE;
|
||||
|
||||
r->back->forw = d;
|
||||
r->back = d;
|
||||
|
||||
if(debug['d']) {
|
||||
if(ctxt == PEXTERN)
|
||||
print("extern typ-dcl %S G%ld %T\n", s, s->vargen, t);
|
||||
else
|
||||
print("auto typ-dcl %S G%ld %T\n", s, s->vargen, t);
|
||||
}
|
||||
}
|
||||
|
||||
Node*
|
||||
fakethis(void)
|
||||
{
|
||||
Node *n;
|
||||
Type *t;
|
||||
|
||||
n = nod(ODCLFIELD, N, N);
|
||||
t = dostruct(N, TSTRUCT);
|
||||
t = ptrto(t);
|
||||
n->type = t;
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* this generates a new name that is
|
||||
* pushed down on the declaration list.
|
||||
* no diagnostics are produced as this
|
||||
* name will soon be declared.
|
||||
*/
|
||||
Node*
|
||||
newname(Sym *s)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = nod(ONAME, N, N);
|
||||
n->sym = s;
|
||||
n->type = T;
|
||||
n->addable = 1;
|
||||
n->ullman = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* this will return an old name
|
||||
* that has already been pushed on the
|
||||
* declaration list. a diagnostic is
|
||||
* generated if no name has been defined.
|
||||
*/
|
||||
Node*
|
||||
oldname(Sym *s)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = s->oname;
|
||||
if(n == N) {
|
||||
yyerror("%S undefined", s);
|
||||
n = newname(s);
|
||||
dodclvar(n, types[TINT32]);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* same for types
|
||||
*/
|
||||
Type*
|
||||
newtype(Sym *s)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = typ(TFORW);
|
||||
t->sym = s;
|
||||
t->type = T;
|
||||
return t;
|
||||
}
|
||||
|
||||
Type*
|
||||
oldtype(Sym *s)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = s->otype;
|
||||
if(t == T)
|
||||
fatal("%S not a type", s); // cant happen
|
||||
return t;
|
||||
}
|
||||
|
||||
Type*
|
||||
forwdcl(Sym *s)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
// this type has no meaning and
|
||||
// will cause an error if referenced.
|
||||
// it will be patched when/if the
|
||||
// type is ever assigned.
|
||||
|
||||
t = typ(TFORW);
|
||||
t = ptrto(t);
|
||||
|
||||
t->nforw = s->forwtype;
|
||||
s->forwtype = t;
|
||||
return t;
|
||||
}
|
||||
578
src/cmd/gc/export.c
Normal file
578
src/cmd/gc/export.c
Normal file
|
|
@ -0,0 +1,578 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "go.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
void
|
||||
markexport(Node *n)
|
||||
{
|
||||
Sym *s;
|
||||
Dcl *d, *r;
|
||||
|
||||
loop:
|
||||
if(n == N)
|
||||
return;
|
||||
if(n->op == OLIST) {
|
||||
markexport(n->left);
|
||||
n = n->right;
|
||||
goto loop;
|
||||
}
|
||||
if(n->op != OEXPORT)
|
||||
fatal("markexport: op no OEXPORT: %O", n->op);
|
||||
|
||||
s = n->sym;
|
||||
if(n->psym != S)
|
||||
s = pkglookup(n->sym->name, n->psym->name);
|
||||
|
||||
if(s->export != 0)
|
||||
return;
|
||||
s->export = 1;
|
||||
|
||||
d = mal(sizeof(*d));
|
||||
d->dsym = s;
|
||||
d->dnode = N;
|
||||
d->lineno = curio.lineno;
|
||||
|
||||
r = exportlist;
|
||||
d->back = r->back;
|
||||
r->back->forw = d;
|
||||
r->back = d;
|
||||
}
|
||||
|
||||
void
|
||||
reexport(Type *t)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
if(t == T)
|
||||
fatal("reexport: type nil\n");
|
||||
|
||||
s = t->sym;
|
||||
if(s == S/* || s->name[0] == '_'*/) {
|
||||
exportgen++;
|
||||
snprint(namebuf, sizeof(namebuf), "_e%.3ld", exportgen);
|
||||
s = lookup(namebuf);
|
||||
s->lexical = LATYPE;
|
||||
s->otype = t;
|
||||
t->sym = s;
|
||||
}
|
||||
dumpexporttype(s);
|
||||
}
|
||||
|
||||
void
|
||||
dumpexportconst(Sym *s)
|
||||
{
|
||||
Node *n;
|
||||
Type *t;
|
||||
|
||||
if(s->exported != 0)
|
||||
return;
|
||||
s->exported = 1;
|
||||
|
||||
n = s->oconst;
|
||||
if(n == N || n->op != OLITERAL)
|
||||
fatal("dumpexportconst: oconst nil: %S\n", s);
|
||||
|
||||
t = n->type; // may or may not be specified
|
||||
if(t != T)
|
||||
reexport(t);
|
||||
|
||||
Bprint(bout, "\tconst ");
|
||||
if(s->export != 0)
|
||||
Bprint(bout, "!");
|
||||
Bprint(bout, "%lS ", s);
|
||||
if(t != T)
|
||||
Bprint(bout, "%lS ", t->sym);
|
||||
|
||||
switch(n->val.ctype) {
|
||||
default:
|
||||
fatal("dumpexportconst: unknown ctype: %S\n", s);
|
||||
case CTINT:
|
||||
case CTSINT:
|
||||
case CTUINT:
|
||||
case CTBOOL:
|
||||
Bprint(bout, "0x%llux\n", n->val.vval);
|
||||
break;
|
||||
case CTFLT:
|
||||
Bprint(bout, "%.17e\n", n->val.dval);
|
||||
break;
|
||||
case CTSTR:
|
||||
Bprint(bout, "\"%Z\"\n", n->val.sval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dumpexportvar(Sym *s)
|
||||
{
|
||||
Node *n;
|
||||
Type *t;
|
||||
|
||||
if(s->exported != 0)
|
||||
return;
|
||||
s->exported = 1;
|
||||
|
||||
n = s->oname;
|
||||
if(n == N || n->type == T)
|
||||
fatal("dumpexportvar: oname nil: %S\n", s);
|
||||
|
||||
t = n->type;
|
||||
reexport(t);
|
||||
|
||||
Bprint(bout, "\tvar ");
|
||||
if(s->export != 0)
|
||||
Bprint(bout, "!");
|
||||
Bprint(bout, "%lS %lS\n", s, t->sym);
|
||||
}
|
||||
|
||||
void
|
||||
dumpexporttype(Sym *s)
|
||||
{
|
||||
Type *t, *f;
|
||||
Sym *ts;
|
||||
int et;
|
||||
|
||||
if(s->exported != 0)
|
||||
return;
|
||||
s->exported = 1;
|
||||
|
||||
t = s->otype;
|
||||
if(t == T)
|
||||
fatal("dumpexporttype: otype nil: %S\n", s);
|
||||
if(t->sym != s)
|
||||
fatal("dumpexporttype: cross reference: %S\n", s);
|
||||
|
||||
et = t->etype;
|
||||
switch(et) {
|
||||
default:
|
||||
if(et < 0 || et >= nelem(types) || types[et] == T)
|
||||
fatal("dumpexporttype: basic type: %S %E\n", s, et);
|
||||
/* type 5 */
|
||||
Bprint(bout, "\ttype %lS %d\n", s, et);
|
||||
break;
|
||||
|
||||
case TARRAY:
|
||||
reexport(t->type);
|
||||
|
||||
/* type 2 */
|
||||
Bprint(bout, "\ttype ");
|
||||
if(s->export != 0)
|
||||
Bprint(bout, "!");
|
||||
Bprint(bout, "%lS [%lud] %lS\n", s, t->bound, t->type->sym);
|
||||
break;
|
||||
|
||||
case TPTR32:
|
||||
case TPTR64:
|
||||
reexport(t->type);
|
||||
|
||||
/* type 6 */
|
||||
Bprint(bout, "\ttype ");
|
||||
if(s->export != 0)
|
||||
Bprint(bout, "!");
|
||||
Bprint(bout, "%lS *%lS\n", s, t->type->sym);
|
||||
break;
|
||||
|
||||
case TFUNC:
|
||||
for(f=t->type; f!=T; f=f->down) {
|
||||
if(f->etype != TSTRUCT)
|
||||
fatal("dumpexporttype: funct not field: %T\n", f);
|
||||
reexport(f);
|
||||
}
|
||||
|
||||
/* type 3 */
|
||||
Bprint(bout, "\ttype ");
|
||||
if(s->export != 0)
|
||||
Bprint(bout, "!");
|
||||
Bprint(bout, "%lS (", s);
|
||||
for(f=t->type; f!=T; f=f->down) {
|
||||
if(f != t->type)
|
||||
Bprint(bout, " ");
|
||||
Bprint(bout, "%lS", f->sym);
|
||||
}
|
||||
Bprint(bout, ")\n");
|
||||
break;
|
||||
|
||||
case TSTRUCT:
|
||||
case TINTER:
|
||||
for(f=t->type; f!=T; f=f->down) {
|
||||
if(f->etype != TFIELD)
|
||||
fatal("dumpexporttype: funct not field: %lT\n", f);
|
||||
reexport(f->type);
|
||||
}
|
||||
|
||||
/* type 4 */
|
||||
Bprint(bout, "\ttype ");
|
||||
if(s->export)
|
||||
Bprint(bout, "!");
|
||||
Bprint(bout, "%lS %c", s, (et==TSTRUCT)? '{': '<');
|
||||
for(f=t->type; f!=T; f=f->down) {
|
||||
ts = f->type->sym;
|
||||
if(f != t->type)
|
||||
Bprint(bout, " ");
|
||||
Bprint(bout, "%s %lS", f->sym->name, ts);
|
||||
}
|
||||
Bprint(bout, "%c\n", (et==TSTRUCT)? '}': '>');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dumpe(Sym *s)
|
||||
{
|
||||
switch(s->lexical) {
|
||||
default:
|
||||
yyerror("unknown export symbol: %S\n", s, s->lexical);
|
||||
break;
|
||||
case LPACK:
|
||||
yyerror("package export symbol: %S\n", s);
|
||||
break;
|
||||
case LATYPE:
|
||||
case LBASETYPE:
|
||||
dumpexporttype(s);
|
||||
break;
|
||||
case LNAME:
|
||||
dumpexportvar(s);
|
||||
break;
|
||||
case LACONST:
|
||||
dumpexportconst(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dumpexport(void)
|
||||
{
|
||||
Dcl *d;
|
||||
long lno;
|
||||
|
||||
lno = dynlineno;
|
||||
|
||||
Bprint(bout, " import\n");
|
||||
Bprint(bout, " ((\n");
|
||||
|
||||
// print it depth first
|
||||
for(d=exportlist->forw; d!=D; d=d->forw) {
|
||||
dynlineno = d->lineno;
|
||||
dumpe(d->dsym);
|
||||
}
|
||||
|
||||
Bprint(bout, " ))\n");
|
||||
|
||||
dynlineno = lno;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******* import *******
|
||||
*/
|
||||
Type*
|
||||
importlooktype(Node *n)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
if(n->op != OIMPORT)
|
||||
fatal("importlooktype: oops1 %N\n", n);
|
||||
|
||||
s = pkglookup(n->sym->name, n->psym->name);
|
||||
if(s->otype == T)
|
||||
fatal("importlooktype: oops2 %S\n", s);
|
||||
|
||||
return s->otype;
|
||||
}
|
||||
|
||||
Type**
|
||||
importstotype(Node *fl, Type **t, Type *uber)
|
||||
{
|
||||
Type *f;
|
||||
Iter save;
|
||||
Node *n;
|
||||
|
||||
n = listfirst(&save, &fl);
|
||||
|
||||
loop:
|
||||
if(n == N) {
|
||||
*t = T;
|
||||
return t;
|
||||
}
|
||||
f = typ(TFIELD);
|
||||
f->type = importlooktype(n);
|
||||
|
||||
if(n->fsym != S) {
|
||||
f->nname = newname(n->fsym);
|
||||
} else {
|
||||
vargen++;
|
||||
snprint(namebuf, sizeof(namebuf), "_m%.3ld", vargen);
|
||||
f->nname = newname(lookup(namebuf));
|
||||
}
|
||||
f->sym = f->nname->sym;
|
||||
|
||||
*t = f;
|
||||
t = &f->down;
|
||||
|
||||
n = listnext(&save);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
importcount(Type *t)
|
||||
{
|
||||
int i;
|
||||
Type *f;
|
||||
|
||||
if(t == T || t->etype != TSTRUCT)
|
||||
fatal("importcount: not a struct: %N", t);
|
||||
|
||||
i = 0;
|
||||
for(f=t->type; f!=T; f=f->down)
|
||||
i = i+1;
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
importfuncnam(Type *t)
|
||||
{
|
||||
Node *n;
|
||||
Type *t1;
|
||||
|
||||
if(t->etype != TFUNC)
|
||||
fatal("importfuncnam: not func %T\n", t);
|
||||
|
||||
if(t->thistuple > 0) {
|
||||
t1 = t->type;
|
||||
if(t1->sym == S)
|
||||
fatal("importfuncnam: no this");
|
||||
n = newname(t1->sym);
|
||||
vargen++;
|
||||
n->vargen = vargen;
|
||||
t1->nname = n;
|
||||
}
|
||||
if(t->outtuple > 0) {
|
||||
t1 = t->type->down;
|
||||
if(t1->sym == S)
|
||||
fatal("importfuncnam: no output");
|
||||
n = newname(t1->sym);
|
||||
vargen++;
|
||||
n->vargen = vargen;
|
||||
t1->nname = n;
|
||||
}
|
||||
if(t->intuple > 0) {
|
||||
t1 = t->type->down->down;
|
||||
if(t1->sym == S)
|
||||
fatal("importfuncnam: no input");
|
||||
n = newname(t1->sym);
|
||||
vargen++;
|
||||
n->vargen = vargen;
|
||||
t1->nname = n;
|
||||
}
|
||||
}
|
||||
|
||||
Sym*
|
||||
getimportsym(Node *ss)
|
||||
{
|
||||
char *pkg;
|
||||
Sym *s;
|
||||
|
||||
pkg = ss->psym->name;
|
||||
if(pkgmyname != S)
|
||||
pkg = pkgmyname->name;
|
||||
|
||||
s = pkglookup(ss->sym->name, pkg);
|
||||
/* botch - need some diagnostic checking for the following assignment */
|
||||
s->opackage = ss->osym->name;
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
importaddtyp(Node *ss, Type *t)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
s = getimportsym(ss);
|
||||
if(s->otype == T || !eqtype(t, s->otype, 0)) {
|
||||
addtyp(newtype(s), t, PEXTERN);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LCONST importsym LITERAL
|
||||
* untyped constant
|
||||
*/
|
||||
void
|
||||
doimportc1(Node *ss, Val *v)
|
||||
{
|
||||
Node *n;
|
||||
Sym *s;
|
||||
|
||||
n = nod(OLITERAL, N, N);
|
||||
n->val = *v;
|
||||
|
||||
s = getimportsym(ss);
|
||||
if(s->oconst == N) {
|
||||
// botch sould ask if already declared the same
|
||||
dodclconst(newname(s), n);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LCONST importsym importsym LITERAL
|
||||
* typed constant
|
||||
*/
|
||||
void
|
||||
doimportc2(Node *ss, Node *st, Val *v)
|
||||
{
|
||||
Node *n;
|
||||
Type *t;
|
||||
Sym *s;
|
||||
|
||||
n = nod(OLITERAL, N, N);
|
||||
n->val = *v;
|
||||
|
||||
t = importlooktype(st);
|
||||
n->type = t;
|
||||
|
||||
s = getimportsym(ss);
|
||||
if(s->oconst == N) {
|
||||
// botch sould ask if already declared the same
|
||||
dodclconst(newname(s), n);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LVAR importsym importsym
|
||||
* variable
|
||||
*/
|
||||
void
|
||||
doimportv1(Node *ss, Node *st)
|
||||
{
|
||||
Type *t;
|
||||
Sym *s;
|
||||
|
||||
t = importlooktype(st);
|
||||
s = getimportsym(ss);
|
||||
if(s->oname == N || !eqtype(t, s->oname->type, 0)) {
|
||||
addvar(newname(s), t, dclcontext);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LTYPE importsym [ importsym ] importsym
|
||||
* array type
|
||||
*/
|
||||
void
|
||||
doimport1(Node *ss, Node *ss1, Node *s)
|
||||
{
|
||||
fatal("doimport1");
|
||||
}
|
||||
|
||||
/*
|
||||
* LTYPE importsym [ LLITERAL ] importsym
|
||||
* array type
|
||||
*/
|
||||
void
|
||||
doimport2(Node *ss, Val *b, Node *st)
|
||||
{
|
||||
Type *t;
|
||||
Sym *s;
|
||||
|
||||
t = typ(TARRAY);
|
||||
t->bound = b->vval;
|
||||
s = pkglookup(st->sym->name, st->psym->name);
|
||||
t->type = s->otype;
|
||||
|
||||
importaddtyp(ss, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* LTYPE importsym '(' importsym_list ')'
|
||||
* function/method type
|
||||
*/
|
||||
void
|
||||
doimport3(Node *ss, Node *n)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = typ(TFUNC);
|
||||
|
||||
t->type = importlooktype(n->left);
|
||||
t->type->down = importlooktype(n->right->left);
|
||||
t->type->down->down = importlooktype(n->right->right);
|
||||
|
||||
t->thistuple = importcount(t->type);
|
||||
t->outtuple = importcount(t->type->down);
|
||||
t->intuple = importcount(t->type->down->down);
|
||||
|
||||
importfuncnam(t);
|
||||
|
||||
importaddtyp(ss, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* LTYPE importsym '{' importsym_list '}'
|
||||
* structure type
|
||||
*/
|
||||
void
|
||||
doimport4(Node *ss, Node *n)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = typ(TSTRUCT);
|
||||
importstotype(n, &t->type, t);
|
||||
|
||||
importaddtyp(ss, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* LTYPE importsym LLITERAL
|
||||
* basic type
|
||||
*/
|
||||
void
|
||||
doimport5(Node *ss, Val *v)
|
||||
{
|
||||
int et;
|
||||
Type *t;
|
||||
|
||||
et = v->vval;
|
||||
if(et <= 0 || et >= nelem(types) || types[et] == T)
|
||||
fatal("doimport5: bad type index: %E\n", et);
|
||||
|
||||
t = typ(et);
|
||||
t->sym = S;
|
||||
|
||||
importaddtyp(ss, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* LTYPE importsym * importsym
|
||||
* pointer type
|
||||
*/
|
||||
void
|
||||
doimport6(Node *ss, Node *st)
|
||||
{
|
||||
Type *t;
|
||||
Sym *s;
|
||||
|
||||
s = pkglookup(st->sym->name, st->psym->name);
|
||||
t = s->otype;
|
||||
if(t == T)
|
||||
t = forwdcl(s);
|
||||
else
|
||||
t = ptrto(t);
|
||||
|
||||
importaddtyp(ss, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* LTYPE importsym '<' importsym '>'
|
||||
* interface type
|
||||
*/
|
||||
void
|
||||
doimport7(Node *ss, Node *n)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = typ(TINTER);
|
||||
importstotype(n, &t->type, t);
|
||||
|
||||
importaddtyp(ss, t);
|
||||
}
|
||||
553
src/cmd/gc/go.h
Normal file
553
src/cmd/gc/go.h
Normal file
|
|
@ -0,0 +1,553 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
todo:
|
||||
1. dyn arrays
|
||||
2. multi
|
||||
3. block 0
|
||||
tothinkabout:
|
||||
2. argument in import
|
||||
*/
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
enum
|
||||
{
|
||||
NHUNK = 50000,
|
||||
BUFSIZ = 8192,
|
||||
NSYMB = 500,
|
||||
NHASH = 1024,
|
||||
STRINGSZ = 200,
|
||||
YYMAXDEPTH = 500,
|
||||
MAXALIGN = 7,
|
||||
UINF = 100,
|
||||
|
||||
PRIME1 = 3,
|
||||
PRIME2 = 10007,
|
||||
PRIME3 = 10009,
|
||||
PRIME4 = 10037,
|
||||
PRIME5 = 10039,
|
||||
PRIME6 = 10061,
|
||||
PRIME7 = 10067,
|
||||
PRIME8 = 10079,
|
||||
PRIME9 = 10091,
|
||||
};
|
||||
|
||||
/*
|
||||
* note this is the representation
|
||||
* of the compilers string literals,
|
||||
* it happens to also be the runtime
|
||||
* representation, ignoring sizes and
|
||||
* alignment, but that may change.
|
||||
*/
|
||||
typedef struct String String;
|
||||
struct String
|
||||
{
|
||||
long len;
|
||||
char s[3]; // variable
|
||||
};
|
||||
|
||||
typedef struct Val Val;
|
||||
struct Val
|
||||
{
|
||||
int ctype;
|
||||
double dval;
|
||||
vlong vval;
|
||||
String* sval;
|
||||
};
|
||||
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Node Node;
|
||||
typedef struct Type Type;
|
||||
|
||||
struct Type
|
||||
{
|
||||
int etype;
|
||||
int chan;
|
||||
uchar recur; // to detect loops
|
||||
uchar trecur; // to detect loops
|
||||
Sym* sym;
|
||||
long vargen; // unique name for OTYPE/ONAME
|
||||
|
||||
// most nodes
|
||||
Type* type;
|
||||
vlong width; // offset in TFIELD, width in all others
|
||||
|
||||
// TFIELD
|
||||
Type* down; // also used in TMAP
|
||||
|
||||
// TPTR
|
||||
Type* nforw;
|
||||
|
||||
// TFUNCT
|
||||
Type* this;
|
||||
Type* argout;
|
||||
Type* argin;
|
||||
Node* nname;
|
||||
|
||||
uchar thistuple;
|
||||
uchar outtuple;
|
||||
uchar intuple;
|
||||
|
||||
// TARRAY
|
||||
long bound;
|
||||
};
|
||||
#define T ((Type*)0)
|
||||
|
||||
struct Node
|
||||
{
|
||||
int op;
|
||||
|
||||
// most nodes
|
||||
Node* left;
|
||||
Node* right;
|
||||
Type* type;
|
||||
|
||||
// for-body
|
||||
Node* ninit;
|
||||
Node* ntest;
|
||||
Node* nincr;
|
||||
Node* nbody;
|
||||
|
||||
// if-body
|
||||
Node* nelse;
|
||||
|
||||
// cases
|
||||
Node* ncase;
|
||||
|
||||
// func
|
||||
Node* nname;
|
||||
|
||||
// OLITERAL
|
||||
Val val;
|
||||
|
||||
Sym* osym; // import
|
||||
Sym* fsym; // import
|
||||
Sym* psym; // import
|
||||
Sym* sym; // various
|
||||
uchar ullman; // sethi/ullman number
|
||||
uchar addable; // type of addressability - 0 is not addressable
|
||||
uchar trecur; // to detect loops
|
||||
uchar etype; // op for OASOP, etype for OTYPE, exclam for export
|
||||
uchar class; // PPARAM, PAUTO, PEXTERN, PSTATIC
|
||||
long vargen; // unique name for OTYPE/ONAME
|
||||
ulong lineno;
|
||||
vlong xoffset;
|
||||
};
|
||||
#define N ((Node*)0)
|
||||
|
||||
struct Sym
|
||||
{
|
||||
char* opackage; // original package name
|
||||
char* package; // package name
|
||||
char* name; // variable name
|
||||
Node* oname; // ONAME node if a var
|
||||
Type* otype; // TYPE node if a type
|
||||
Node* oconst; // OLITERAL node if a const
|
||||
Type* forwtype; // TPTR iff foreward declared
|
||||
void* label; // pointer to Prog* of label
|
||||
vlong offset; // stack location if automatic
|
||||
long lexical;
|
||||
long vargen; // unique variable number
|
||||
uchar undef; // a diagnostic has been generated
|
||||
uchar export; // marked as export
|
||||
uchar exported; // has been exported
|
||||
uchar sym; // huffman encoding in object file
|
||||
Sym* link;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
|
||||
typedef struct Dcl Dcl;
|
||||
struct Dcl
|
||||
{
|
||||
int op;
|
||||
Sym* dsym; // for printing only
|
||||
Node* dnode; // oname
|
||||
Type* dtype; // otype
|
||||
long lineno;
|
||||
|
||||
Dcl* forw;
|
||||
Dcl* back; // sentinel has pointer to last
|
||||
};
|
||||
#define D ((Dcl*)0)
|
||||
|
||||
typedef struct Iter Iter;
|
||||
struct Iter
|
||||
{
|
||||
int done;
|
||||
Type* tfunc;
|
||||
Type* t;
|
||||
Node** an;
|
||||
Node* n;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
OXXX,
|
||||
|
||||
OTYPE, OCONST, OVAR, OEXPORT, OIMPORT,
|
||||
|
||||
ONAME,
|
||||
ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
|
||||
ODCLFUNC, ODCLFIELD, ODCLARG,
|
||||
OLIST, OCMP,
|
||||
OPTR, OARRAY,
|
||||
ORETURN, OFOR, OIF, OSWITCH, OI2S, OS2I, OI2I,
|
||||
OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL,
|
||||
OGOTO, OPROC, ONEW, OPANIC, OPRINT, OEMPTY,
|
||||
|
||||
OOROR,
|
||||
OANDAND,
|
||||
OEQ, ONE, OLT, OLE, OGE, OGT,
|
||||
OADD, OSUB, OOR, OXOR,
|
||||
OMUL, ODIV, OMOD, OLSH, ORSH, OAND,
|
||||
ODEC, OINC,
|
||||
OLEN,
|
||||
OFUNC,
|
||||
OLABEL,
|
||||
OBREAK,
|
||||
OCONTINUE,
|
||||
OADDR,
|
||||
OIND,
|
||||
OCALL, OCALLMETH, OCALLINTER,
|
||||
OINDEX, OINDEXPTR, OSLICE,
|
||||
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
|
||||
OLITERAL, OREGISTER, OINDREG,
|
||||
OCONV,
|
||||
OBAD,
|
||||
|
||||
OEND,
|
||||
};
|
||||
enum
|
||||
{
|
||||
Txxx, // 0
|
||||
|
||||
TINT8, TUINT8, // 1
|
||||
TINT16, TUINT16,
|
||||
TINT32, TUINT32,
|
||||
TINT64, TUINT64,
|
||||
|
||||
TFLOAT32, // 9
|
||||
TFLOAT64,
|
||||
TFLOAT80,
|
||||
|
||||
TBOOL, // 12
|
||||
|
||||
TPTR32, TPTR64, // 13
|
||||
|
||||
TFUNC,
|
||||
TARRAY,
|
||||
TDARRAY,
|
||||
TSTRUCT,
|
||||
TCHAN,
|
||||
TMAP,
|
||||
TINTER,
|
||||
TFORW,
|
||||
TFIELD,
|
||||
TANY,
|
||||
TSTRING,
|
||||
|
||||
NTYPE, // 26
|
||||
};
|
||||
enum
|
||||
{
|
||||
CTxxx,
|
||||
|
||||
CTINT,
|
||||
CTSINT,
|
||||
CTUINT,
|
||||
CTFLT,
|
||||
|
||||
CTSTR,
|
||||
CTBOOL,
|
||||
CTNIL,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* indications for whatis() */
|
||||
Wnil = 0,
|
||||
Wtnil,
|
||||
|
||||
Wtfloat,
|
||||
Wtint,
|
||||
Wtbool,
|
||||
Wtstr,
|
||||
|
||||
Wlitfloat,
|
||||
Wlitint,
|
||||
Wlitbool,
|
||||
Wlitstr,
|
||||
|
||||
Wtunkn,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* types of channel */
|
||||
Cxxx,
|
||||
Cboth,
|
||||
Crecv,
|
||||
Csend,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Pxxx,
|
||||
|
||||
PEXTERN, // declaration context
|
||||
PAUTO,
|
||||
PPARAM,
|
||||
PSTATIC,
|
||||
};
|
||||
|
||||
typedef struct Io Io;
|
||||
struct Io
|
||||
{
|
||||
char* infile;
|
||||
Biobuf* bin;
|
||||
long lineno;
|
||||
int peekc;
|
||||
char* cp; // used for content when bin==nil
|
||||
};
|
||||
|
||||
EXTERN Io curio;
|
||||
EXTERN Io pushedio;
|
||||
|
||||
EXTERN char* outfile;
|
||||
EXTERN char* package;
|
||||
EXTERN Biobuf* bout;
|
||||
EXTERN int nerrors;
|
||||
EXTERN char namebuf[NSYMB];
|
||||
EXTERN char debug[256];
|
||||
EXTERN long dynlineno;
|
||||
EXTERN Sym* hash[NHASH];
|
||||
EXTERN Sym* dclstack;
|
||||
EXTERN Sym* b0stack;
|
||||
EXTERN Sym* pkgmyname; // my name for package
|
||||
EXTERN int tptr; // either TPTR32 or TPTR64
|
||||
extern char* sysimport;
|
||||
|
||||
EXTERN Type* types[NTYPE];
|
||||
EXTERN uchar isptr[NTYPE];
|
||||
EXTERN uchar isint[NTYPE];
|
||||
EXTERN uchar isfloat[NTYPE];
|
||||
EXTERN uchar issigned[NTYPE];
|
||||
EXTERN uchar okforeq[NTYPE];
|
||||
EXTERN uchar okforadd[NTYPE];
|
||||
EXTERN uchar okforand[NTYPE];
|
||||
EXTERN double minfloatval[NTYPE];
|
||||
EXTERN double maxfloatval[NTYPE];
|
||||
EXTERN vlong minintval[NTYPE];
|
||||
EXTERN vlong maxintval[NTYPE];
|
||||
|
||||
EXTERN Dcl* autodcl;
|
||||
EXTERN Dcl* externdcl;
|
||||
EXTERN Dcl* exportlist;
|
||||
EXTERN int dclcontext; // PEXTERN/PAUTO
|
||||
EXTERN int importflag;
|
||||
|
||||
EXTERN Node* booltrue;
|
||||
EXTERN Node* boolfalse;
|
||||
EXTERN ulong iota;
|
||||
EXTERN long vargen;
|
||||
EXTERN long exportgen;
|
||||
|
||||
EXTERN Node* retnil;
|
||||
EXTERN Node* fskel;
|
||||
|
||||
EXTERN char* context;
|
||||
EXTERN int thechar;
|
||||
EXTERN char* thestring;
|
||||
EXTERN char* hunk;
|
||||
EXTERN long nhunk;
|
||||
EXTERN long thunk;
|
||||
|
||||
/*
|
||||
* y.tab.c
|
||||
*/
|
||||
int yyparse(void);
|
||||
|
||||
/*
|
||||
* lex.c
|
||||
*/
|
||||
int main(int, char*[]);
|
||||
void importfile(Val*);
|
||||
void cannedimports(void);
|
||||
void unimportfile();
|
||||
long yylex(void);
|
||||
void lexinit(void);
|
||||
char* lexname(int);
|
||||
long getr(void);
|
||||
int getnsc(void);
|
||||
long escchar(long, int*);
|
||||
int getc(void);
|
||||
void ungetc(int);
|
||||
void mkpackage(char*);
|
||||
|
||||
/*
|
||||
* mpatof.c
|
||||
*/
|
||||
int mpatof(char*, double*);
|
||||
int mpatov(char*, vlong*);
|
||||
|
||||
/*
|
||||
* subr.c
|
||||
*/
|
||||
void myexit(int);
|
||||
void* mal(long);
|
||||
void* remal(void*, long, long);
|
||||
void errorexit(void);
|
||||
ulong stringhash(char*);
|
||||
Sym* lookup(char*);
|
||||
Sym* pkglookup(char*, char*);
|
||||
void yyerror(char*, ...);
|
||||
void warn(char*, ...);
|
||||
void fatal(char*, ...);
|
||||
Node* nod(int, Node*, Node*);
|
||||
Type* typ(int);
|
||||
Dcl* dcl(void);
|
||||
Node* rev(Node*);
|
||||
Node* unrev(Node*);
|
||||
void dodump(Node*, int);
|
||||
void dump(char*, Node*);
|
||||
Type* aindex(Node*, Type*);
|
||||
int isnil(Node*);
|
||||
int isptrto(Type*, int);
|
||||
int isinter(Type*);
|
||||
int isbytearray(Type*);
|
||||
int eqtype(Type*, Type*, int);
|
||||
int eqargs(Type*, Type*);
|
||||
ulong typehash(Type*, int);
|
||||
void frame(int);
|
||||
Node* literal(long);
|
||||
Node* dobad(void);
|
||||
Node* nodintconst(long);
|
||||
void ullmancalc(Node*);
|
||||
void badtype(int, Type*, Type*);
|
||||
Type* ptrto(Type*);
|
||||
Node* cleanidlist(Node*);
|
||||
|
||||
Type** getthis(Type*);
|
||||
Type** getoutarg(Type*);
|
||||
Type** getinarg(Type*);
|
||||
|
||||
Type* getthisx(Type*);
|
||||
Type* getoutargx(Type*);
|
||||
Type* getinargx(Type*);
|
||||
|
||||
Node* listfirst(Iter*, Node**);
|
||||
Node* listnext(Iter*);
|
||||
Type* structfirst(Iter*, Type**);
|
||||
Type* structnext(Iter*);
|
||||
Type* funcfirst(Iter*, Type*);
|
||||
Type* funcnext(Iter*);
|
||||
|
||||
int Econv(Fmt*);
|
||||
int Jconv(Fmt*);
|
||||
int Oconv(Fmt*);
|
||||
int Sconv(Fmt*);
|
||||
int Tconv(Fmt*);
|
||||
int Nconv(Fmt*);
|
||||
int Zconv(Fmt*);
|
||||
|
||||
/*
|
||||
* dcl.c
|
||||
*/
|
||||
void dodclvar(Node*, Type*);
|
||||
void dodcltype(Type*, Type*);
|
||||
void dodclconst(Node*, Node*);
|
||||
void defaultlit(Node*);
|
||||
int listcount(Node*);
|
||||
Node* methodname(Node*, Type*);
|
||||
Type* functype(Node*, Node*, Node*);
|
||||
char* thistypenam(Node*);
|
||||
void funcnam(Type*, char*);
|
||||
void funchdr(Node*);
|
||||
void funcargs(Type*);
|
||||
void funcbody(Node*);
|
||||
Type* dostruct(Node*, int);
|
||||
Type** stotype(Node*, Type**);
|
||||
Type* sortinter(Type*);
|
||||
void markdcl(char*);
|
||||
void popdcl(char*);
|
||||
void poptodcl(void);
|
||||
void markdclstack(void);
|
||||
void testdclstack(void);
|
||||
Sym* pushdcl(Sym*);
|
||||
void addvar(Node*, Type*, int);
|
||||
void addtyp(Type*, Type*, int);
|
||||
Node* fakethis(void);
|
||||
Node* newname(Sym*);
|
||||
Node* oldname(Sym*);
|
||||
Type* newtype(Sym*);
|
||||
Type* oldtype(Sym*);
|
||||
Type* forwdcl(Sym*);
|
||||
|
||||
/*
|
||||
* export.c
|
||||
*/
|
||||
void markexport(Node*);
|
||||
void dumpe(Sym*);
|
||||
void dumpexport(void);
|
||||
void dumpexporttype(Sym*);
|
||||
void dumpexportvar(Sym*);
|
||||
void dumpexportconst(Sym*);
|
||||
void doimportv1(Node*, Node*);
|
||||
void doimportc1(Node*, Val*);
|
||||
void doimportc2(Node*, Node*, Val*);
|
||||
void doimport1(Node*, Node*, Node*);
|
||||
void doimport2(Node*, Val*, Node*);
|
||||
void doimport3(Node*, Node*);
|
||||
void doimport4(Node*, Node*);
|
||||
void doimport5(Node*, Val*);
|
||||
void doimport6(Node*, Node*);
|
||||
void doimport7(Node*, Node*);
|
||||
|
||||
/*
|
||||
* walk.c
|
||||
*/
|
||||
void walk(Node*);
|
||||
void walktype(Node*, int);
|
||||
Type* walkswitch(Node*, Node*, Type*(*)(Node*, Type*));
|
||||
int casebody(Node*);
|
||||
int whatis(Node*);
|
||||
void walkdot(Node*);
|
||||
Node* ascompatee(int, Node**, Node**);
|
||||
Node* ascompatet(int, Node**, Type**, int);
|
||||
Node* ascompatte(int, Type**, Node**, int);
|
||||
int ascompat(Type*, Type*);
|
||||
Node* prcompat(Node*);
|
||||
Node* nodpanic(long);
|
||||
Node* newcompat(Node*);
|
||||
Node* stringop(Node*);
|
||||
Node* convas(Node*);
|
||||
Node* reorder(Node*);
|
||||
|
||||
/*
|
||||
* const.c
|
||||
*/
|
||||
void convlit(Node*, Type*);
|
||||
void evconst(Node*);
|
||||
int cmpslit(Node *l, Node *r);
|
||||
|
||||
/*
|
||||
* gen.c/gsubr.c/obj.c
|
||||
*/
|
||||
void belexinit(int);
|
||||
void besetptr(void);
|
||||
vlong convvtox(vlong, int);
|
||||
void compile(Node*);
|
||||
void proglist(void);
|
||||
int optopop(int);
|
||||
void dumpobj(void);
|
||||
void dowidth(Type*);
|
||||
void argspace(long);
|
||||
Node* nodarg(Type*, int);
|
||||
1292
src/cmd/gc/go.y
Normal file
1292
src/cmd/gc/go.y
Normal file
File diff suppressed because it is too large
Load diff
1088
src/cmd/gc/lex.c
Normal file
1088
src/cmd/gc/lex.c
Normal file
File diff suppressed because it is too large
Load diff
19
src/cmd/gc/mksys.bash
Normal file
19
src/cmd/gc/mksys.bash
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
6g sys.go
|
||||
echo '1,/((/d
|
||||
/))/+1,$d
|
||||
1,$s/foop/sys/g
|
||||
1,$s/^[ ]*/ "/g
|
||||
1,$s/$/\\n"/g
|
||||
1i
|
||||
char* sysimport =
|
||||
.
|
||||
$a
|
||||
;
|
||||
|
||||
.
|
||||
w sysimport.c
|
||||
q' | ed foop.6
|
||||
342
src/cmd/gc/mpatof.c
Normal file
342
src/cmd/gc/mpatof.c
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
int mpatof(char*, double*);
|
||||
int mpatov(char *s, vlong *v);
|
||||
|
||||
enum
|
||||
{
|
||||
Mpscale = 29, /* safely smaller than bits in a long */
|
||||
Mpprec = 36, /* Mpscale*Mpprec sb > largest fp exp */
|
||||
Mpbase = 1L<<Mpscale,
|
||||
};
|
||||
|
||||
typedef
|
||||
struct
|
||||
{
|
||||
long a[Mpprec];
|
||||
char ovf;
|
||||
} Mp;
|
||||
|
||||
static void mpint(Mp*, int);
|
||||
static void mppow(Mp*, int, int);
|
||||
static void mpmul(Mp*, int);
|
||||
static void mpadd(Mp*, Mp*);
|
||||
static int mptof(Mp*, double*);
|
||||
|
||||
/*
|
||||
* convert a string, s, to floating in *d
|
||||
* return conversion overflow.
|
||||
* required syntax is [+-]d*[.]d*[e[+-]d*]
|
||||
*/
|
||||
int
|
||||
mpatof(char *s, double *d)
|
||||
{
|
||||
Mp a, b;
|
||||
int dp, c, f, ef, ex, zer;
|
||||
double d1, d2;
|
||||
|
||||
dp = 0; /* digits after decimal point */
|
||||
f = 0; /* sign */
|
||||
ex = 0; /* exponent */
|
||||
zer = 1; /* zero */
|
||||
memset(&a, 0, sizeof(a));
|
||||
for(;;) {
|
||||
switch(c = *s++) {
|
||||
default:
|
||||
goto bad;
|
||||
case '-':
|
||||
f = 1;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '+':
|
||||
continue;
|
||||
case '.':
|
||||
dp = 1;
|
||||
continue;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
zer = 0;
|
||||
case '0':
|
||||
mpint(&b, c-'0');
|
||||
mpmul(&a, 10);
|
||||
mpadd(&a, &b);
|
||||
if(dp)
|
||||
dp++;
|
||||
continue;
|
||||
case 'E':
|
||||
case 'e':
|
||||
ex = 0;
|
||||
ef = 0;
|
||||
for(;;) {
|
||||
c = *s++;
|
||||
if(c == '+' || c == ' ' || c == '\t')
|
||||
continue;
|
||||
if(c == '-') {
|
||||
ef = 1;
|
||||
continue;
|
||||
}
|
||||
if(c >= '0' && c <= '9') {
|
||||
ex = ex*10 + (c-'0');
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(ef)
|
||||
ex = -ex;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(a.ovf)
|
||||
goto bad;
|
||||
if(zer) {
|
||||
*d = 0;
|
||||
return 0;
|
||||
}
|
||||
if(dp)
|
||||
dp--;
|
||||
dp -= ex;
|
||||
if(dp > 0) {
|
||||
/*
|
||||
* must divide by 10**dp
|
||||
*/
|
||||
if(mptof(&a, &d1))
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* trial exponent of 8**dp
|
||||
* 8 (being between 5 and 10)
|
||||
* should pick up all underflows
|
||||
* in the division of 5**dp.
|
||||
*/
|
||||
d2 = frexp(d1, &ex);
|
||||
d2 = ldexp(d2, ex-3*dp);
|
||||
if(d2 == 0)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* decompose each 10 into 5*2.
|
||||
* create 5**dp in fixed point
|
||||
* and then play with the exponent
|
||||
* for the remaining 2**dp.
|
||||
* note that 5**dp will overflow
|
||||
* with as few as 134 input digits.
|
||||
*/
|
||||
mpint(&a, 1);
|
||||
mppow(&a, 5, dp);
|
||||
if(mptof(&a, &d2))
|
||||
goto bad;
|
||||
d1 = frexp(d1/d2, &ex);
|
||||
d1 = ldexp(d1, ex-dp);
|
||||
if(d1 == 0)
|
||||
goto bad;
|
||||
} else {
|
||||
/*
|
||||
* must multiply by 10**|dp| --
|
||||
* just do it in fixed point.
|
||||
*/
|
||||
mppow(&a, 10, -dp);
|
||||
if(mptof(&a, &d1))
|
||||
goto bad;
|
||||
}
|
||||
if(f)
|
||||
d1 = -d1;
|
||||
*d = d1;
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert a to floating in *d
|
||||
* return conversion overflow
|
||||
*/
|
||||
static int
|
||||
mptof(Mp *a, double *d)
|
||||
{
|
||||
double f, g;
|
||||
long x, *a1;
|
||||
int i;
|
||||
|
||||
if(a->ovf)
|
||||
return 1;
|
||||
a1 = a->a;
|
||||
f = ldexp(*a1++, 0);
|
||||
for(i=Mpscale; i<Mpprec*Mpscale; i+=Mpscale)
|
||||
if(x = *a1++) {
|
||||
g = ldexp(x, i);
|
||||
/*
|
||||
* NOTE: the test (g==0) is plan9
|
||||
* specific. ansi compliant overflow
|
||||
* is signaled by HUGE and errno==ERANGE.
|
||||
* change this for your particular ldexp.
|
||||
*/
|
||||
if(g == 0)
|
||||
return 1;
|
||||
f += g; /* this could bomb! */
|
||||
}
|
||||
*d = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a += b
|
||||
*/
|
||||
static void
|
||||
mpadd(Mp *a, Mp *b)
|
||||
{
|
||||
int i, c;
|
||||
long x, *a1, *b1;
|
||||
|
||||
if(b->ovf)
|
||||
a->ovf = 1;
|
||||
if(a->ovf)
|
||||
return;
|
||||
c = 0;
|
||||
a1 = a->a;
|
||||
b1 = b->a;
|
||||
for(i=0; i<Mpprec; i++) {
|
||||
x = *a1 + *b1++ + c;
|
||||
c = 0;
|
||||
if(x >= Mpbase) {
|
||||
x -= Mpbase;
|
||||
c = 1;
|
||||
}
|
||||
*a1++ = x;
|
||||
}
|
||||
a->ovf = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a = c
|
||||
*/
|
||||
static void
|
||||
mpint(Mp *a, int c)
|
||||
{
|
||||
|
||||
memset(a, 0, sizeof(*a));
|
||||
a->a[0] = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a *= c
|
||||
*/
|
||||
static void
|
||||
mpmul(Mp *a, int c)
|
||||
{
|
||||
Mp p;
|
||||
int b;
|
||||
memmove(&p, a, sizeof(p));
|
||||
if(!(c & 1))
|
||||
memset(a, 0, sizeof(*a));
|
||||
c &= ~1;
|
||||
for(b=2; c; b<<=1) {
|
||||
mpadd(&p, &p);
|
||||
if(c & b) {
|
||||
mpadd(a, &p);
|
||||
c &= ~b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* return a *= b**e
|
||||
*/
|
||||
static void
|
||||
mppow(Mp *a, int b, int e)
|
||||
{
|
||||
int b1;
|
||||
|
||||
b1 = b*b;
|
||||
b1 = b1*b1;
|
||||
while(e >= 4) {
|
||||
mpmul(a, b1);
|
||||
e -= 4;
|
||||
if(a->ovf)
|
||||
return;
|
||||
}
|
||||
while(e > 0) {
|
||||
mpmul(a, b);
|
||||
e--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* convert a string, s, to vlong in *v
|
||||
* return conversion overflow.
|
||||
* required syntax is [0[x]]d*
|
||||
*/
|
||||
int
|
||||
mpatov(char *s, vlong *v)
|
||||
{
|
||||
vlong n, nn;
|
||||
int c;
|
||||
n = 0;
|
||||
c = *s;
|
||||
if(c == '0')
|
||||
goto oct;
|
||||
while(c = *s++) {
|
||||
if(c >= '0' && c <= '9')
|
||||
nn = n*10 + c-'0';
|
||||
else
|
||||
goto bad;
|
||||
if(n < 0 && nn >= 0)
|
||||
goto bad;
|
||||
n = nn;
|
||||
}
|
||||
goto out;
|
||||
oct:
|
||||
s++;
|
||||
c = *s;
|
||||
if(c == 'x' || c == 'X')
|
||||
goto hex;
|
||||
while(c = *s++) {
|
||||
if(c >= '0' || c <= '7')
|
||||
nn = n*8 + c-'0';
|
||||
else
|
||||
goto bad;
|
||||
if(n < 0 && nn >= 0)
|
||||
goto bad;
|
||||
n = nn;
|
||||
}
|
||||
goto out;
|
||||
hex:
|
||||
s++;
|
||||
while(c = *s++) {
|
||||
if(c >= '0' && c <= '9')
|
||||
c += 0-'0';
|
||||
else
|
||||
if(c >= 'a' && c <= 'f')
|
||||
c += 10-'a';
|
||||
else
|
||||
if(c >= 'A' && c <= 'F')
|
||||
c += 10-'A';
|
||||
else
|
||||
goto bad;
|
||||
nn = n*16 + c;
|
||||
if(n < 0 && nn >= 0)
|
||||
goto bad;
|
||||
n = nn;
|
||||
}
|
||||
out:
|
||||
*v = n;
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
*v = ~0;
|
||||
return 1;
|
||||
}
|
||||
1591
src/cmd/gc/subr.c
Normal file
1591
src/cmd/gc/subr.c
Normal file
File diff suppressed because it is too large
Load diff
44
src/cmd/gc/sys.go
Normal file
44
src/cmd/gc/sys.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
||||
package foop // rename to avoid redeclaration
|
||||
|
||||
func mal(uint32) *byte;
|
||||
func breakpoint();
|
||||
func panicl(int32);
|
||||
|
||||
func printbool(bool);
|
||||
func printfloat(double);
|
||||
func printint(int64);
|
||||
func printstring(string);
|
||||
func printpointer(*byte);
|
||||
|
||||
func catstring(string, string) string;
|
||||
func cmpstring(string, string) int32;
|
||||
func slicestring(string, int32, int32) string;
|
||||
func indexstring(string, int32) byte;
|
||||
func intstring(int64) string;
|
||||
func byteastring(*byte, int32) string;
|
||||
func mkiface(*byte, *byte, *struct{}) interface{};
|
||||
|
||||
export
|
||||
mal
|
||||
breakpoint
|
||||
panicl
|
||||
|
||||
printbool
|
||||
printfloat
|
||||
printint
|
||||
printstring
|
||||
printpointer
|
||||
|
||||
catstring
|
||||
cmpstring
|
||||
slicestring
|
||||
indexstring
|
||||
intstring
|
||||
byteastring
|
||||
mkiface
|
||||
;
|
||||
2
src/cmd/gc/sysimport.c
Normal file
2
src/cmd/gc/sysimport.c
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
;
|
||||
|
||||
1278
src/cmd/gc/walk.c
Normal file
1278
src/cmd/gc/walk.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue