diff options
Diffstat (limited to 'src/cmd')
46 files changed, 709 insertions, 463 deletions
| diff --git a/src/cmd/5a/lex.c b/src/cmd/5a/lex.c index b36094a78..e762f5646 100644 --- a/src/cmd/5a/lex.c +++ b/src/cmd/5a/lex.c @@ -187,7 +187,7 @@ assemble(char *file)  	pass = 1;  	pinit(file); -	Bprint(&obuf, "%s\n", thestring); +	Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());  	for(i=0; i<nDlist; i++)  		dodefine(Dlist[i]); diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c index 43eb73c94..d45aabc5e 100644 --- a/src/cmd/5c/swt.c +++ b/src/cmd/5c/swt.c @@ -373,7 +373,7 @@ outcode(void)  		}  	} -	Bprint(&outbuf, "%s\n", thestring); +	Bprint(&outbuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());  	if(ndynimp > 0 || ndynexp > 0) {  		int i; diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c index 78f2f4aeb..4da8db2ae 100644 --- a/src/cmd/5g/cgen64.c +++ b/src/cmd/5g/cgen64.c @@ -64,17 +64,21 @@ cgen64(Node *n, Node *res)  		return;  	case OCOM: +		regalloc(&t1, lo1.type, N); +		gmove(ncon(-1), &t1); +  		split64(res, &lo2, &hi2);  		regalloc(&n1, lo1.type, N);  		gins(AMOVW, &lo1, &n1); -		gins(AMVN, &n1, &n1); +		gins(AEOR, &t1, &n1);  		gins(AMOVW, &n1, &lo2);  		gins(AMOVW, &hi1, &n1); -		gins(AMVN, &n1, &n1); +		gins(AEOR, &t1, &n1);  		gins(AMOVW, &n1, &hi2); +		regfree(&t1);  		regfree(&n1);  		splitclean();  		splitclean(); @@ -204,14 +208,17 @@ cgen64(Node *n, Node *res)  				// here and below (verify it optimizes to EOR)  				gins(AEOR, &al, &al);  				gins(AEOR, &ah, &ah); -			} else if(v > 32) { +			} else +			if(v > 32) {  				gins(AEOR, &al, &al);  				//	MOVW	bl<<(v-32), ah  				gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah); -			} else if(v == 32) { +			} else +			if(v == 32) {  				gins(AEOR, &al, &al);  				gins(AMOVW, &bl, &ah); -			} else if(v > 0) { +			} else +			if(v > 0) {  				//	MOVW	bl<<v, al  				gshift(AMOVW, &bl, SHIFT_LL, v, &al); @@ -341,7 +348,8 @@ olsh_break:  					gins(AEOR, &al, &al);  					gins(AEOR, &ah, &ah);  				} -			} else if(v > 32) { +			} else +			if(v > 32) {  				if(bh.type->etype == TINT32) {  					//	MOVW	bh->(v-32), al  					gshift(AMOVW, &bh, SHIFT_AR, v-32, &al); @@ -353,7 +361,8 @@ olsh_break:  					gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);  					gins(AEOR, &ah, &ah);  				} -			} else if(v == 32) { +			} else +			if(v == 32) {  				gins(AMOVW, &bh, &al);  				if(bh.type->etype == TINT32) {  					//	MOVW	bh->31, ah @@ -361,7 +370,8 @@ olsh_break:  				} else {  					gins(AEOR, &ah, &ah);  				} -			} else if( v > 0) { +			} else +			if( v > 0) {  				//	MOVW	bl>>v, al  				gshift(AMOVW, &bl, SHIFT_LR, v, &al); @@ -384,11 +394,16 @@ olsh_break:  		regalloc(&s, types[TUINT32], N);  		regalloc(&creg, types[TUINT32], N); -		if (is64(r->type)) { +		if(is64(r->type)) {  			// shift is >= 1<<32  			split64(r, &cl, &ch);  			gmove(&ch, &s); -			p1 = gins(ATST, &s, N); +			gins(ATST, &s, N); +			if(bh.type->etype == TINT32) +				p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); +			else +				p1 = gins(AEOR, &ah, &ah); +			p1->scond = C_SCOND_NE;  			p6 = gbranch(ABNE, T);  			gmove(&cl, &s);  			splitclean(); @@ -441,7 +456,6 @@ olsh_break:  			p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);  		else  			p1 = gins(AEOR, &ah, &ah); -		p1->scond = C_SCOND_EQ;  		p4 = gbranch(ABEQ, T);  		// check if shift is < 64 @@ -461,33 +475,23 @@ olsh_break:  			//	MOVW	bh->(s-32), al  			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);  			p1->scond = C_SCOND_LO; - -			//	MOVW	bh->31, ah -			p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); -			p1->scond = C_SCOND_LO;  		} else {  			//	MOVW	bh>>(v-32), al  			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);  			p1->scond = C_SCOND_LO; - -			p1 = gins(AEOR, &ah, &ah); -			p1->scond = C_SCOND_LO;  		}  		//	BLO	end  		p5 = gbranch(ABLO, T);  		// s >= 64 -		if (p6 != P) patch(p6, pc); +		if(p6 != P) +			patch(p6, pc);  		if(bh.type->etype == TINT32) {  			//	MOVW	bh->31, al  			gshift(AMOVW, &bh, SHIFT_AR, 31, &al); - -			//	MOVW	bh->31, ah -			gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);  		} else {  			gins(AEOR, &al, &al); -			gins(AEOR, &ah, &ah);  		}  		patch(p2, pc); diff --git a/src/cmd/5g/list.c b/src/cmd/5g/list.c index ce74d6478..0c6dbbf71 100644 --- a/src/cmd/5g/list.c +++ b/src/cmd/5g/list.c @@ -87,6 +87,10 @@ Dconv(Fmt *fp)  	int32 v;  	a = va_arg(fp->args, Addr*); +	if(a == A) { +		sprint(str, "<nil>"); +		goto conv; +	}  	i = a->type;  	switch(i) { @@ -183,7 +187,7 @@ Dconv(Fmt *fp)  //		a->type = D_ADDR;  //		goto conv;  	} -//conv: +conv:  	return fmtstrcpy(fp, str);  } diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c index f619a6206..ca12d70f2 100644 --- a/src/cmd/5g/peep.c +++ b/src/cmd/5g/peep.c @@ -48,7 +48,6 @@ peep(void)  /*   * complete R structure   */ -	t = 0;  	for(r=firstr; r!=R; r=r1) {  		r1 = r->link;  		if(r1 == R) @@ -68,7 +67,6 @@ peep(void)  			r1->p1 = r2;  			r = r2; -			t++;  		case ADATA:  		case AGLOBL: @@ -77,8 +75,10 @@ peep(void)  			p = p->link;  		}  	} +//dumpit("begin", firstr);  loop1: +  	t = 0;  	for(r=firstr; r!=R; r=r->link) {  		p = r->prog; @@ -99,71 +99,75 @@ loop1:  		case AMOVW:  		case AMOVF:  		case AMOVD: -			if(!regtyp(&p->to)) -				break; -//			if(isdconst(&p->from)) { -//				constprop(&p->from, &p->to, r->s1); -//				break; -//			} -			if(!regtyp(&p->from)) -				break; -			if(p->from.type != p->to.type) -				break; -			if(copyprop(r)) { -				excise(r); -				t++; -				break; +			if(regtyp(&p->from)) +			if(p->from.type == p->to.type) +			if(p->scond == C_SCOND_NONE) { +				if(copyprop(r)) { +					excise(r); +					t++; +					break; +				} +				if(subprop(r) && copyprop(r)) { +					excise(r); +					t++; +					break; +				}  			} -			if(subprop(r) && copyprop(r)) { -				excise(r); -				t++; -				break; +			break; + +			if(p->scond == C_SCOND_NONE) +			if(regtyp(&p->to)) +			if(isdconst(&p->from)) { +				constprop(&p->from, &p->to, r->s1);  			} +			break;  		}  	}  	if(t)  		goto loop1; -	/* -	 * look for MOVB x,R; MOVB R,R -	 */ + +return; +  	for(r=firstr; r!=R; r=r->link) {  		p = r->prog;  		switch(p->as) { -		default: -			continue; -		case AEOR: -			/* -			 * EOR -1,x,y => MVN x,y -			 */ -			if(isdconst(&p->from) && p->from.offset == -1) { -				p->as = AMVN; -				p->from.type = D_REG; -				if(p->reg != NREG) -					p->from.reg = p->reg; -				else -					p->from.reg = p->to.reg; -				p->reg = NREG; -			} -			continue; +//		case AEOR: +//			/* +//			 * EOR -1,x,y => MVN x,y +//			 */ +//			if(isdconst(&p->from) && p->from.offset == -1) { +//				p->as = AMVN; +//				p->from.type = D_REG; +//				if(p->reg != NREG) +//					p->from.reg = p->reg; +//				else +//					p->from.reg = p->to.reg; +//				p->reg = NREG; +//			} +//			break; +  		case AMOVH:  		case AMOVHU:  		case AMOVB:  		case AMOVBU: +			/* +			 * look for MOVB x,R; MOVB R,R +			 */  			if(p->to.type != D_REG) -				continue; +				break; +			if(r1 == R) +				break; +			p1 = r1->prog; +			if(p1->as != p->as) +				break; +			if(p1->from.type != D_REG || p1->from.reg != p->to.reg) +				break; +			if(p1->to.type != D_REG || p1->to.reg != p->to.reg) +				break; +			excise(r1);  			break;  		}  		r1 = r->link; -		if(r1 == R) -			continue; -		p1 = r1->prog; -		if(p1->as != p->as) -			continue; -		if(p1->from.type != D_REG || p1->from.reg != p->to.reg) -			continue; -		if(p1->to.type != D_REG || p1->to.reg != p->to.reg) -			continue; -		excise(r1);  	}  //	for(r=firstr; r!=R; r=r->link) { @@ -335,6 +339,8 @@ subprop(Reg *r0)  		case AMULLU:  		case AMULA: +		case AMVN: +			return 0;  		case ACMN:  		case AADD: @@ -347,7 +353,6 @@ subprop(Reg *r0)  		case AORR:  		case AAND:  		case AEOR: -		case AMVN:  		case AMUL:  		case AMULU:  		case ADIV: @@ -364,7 +369,8 @@ subprop(Reg *r0)  		case ADIVD:  		case ADIVF:  			if(p->to.type == v1->type) -			if(p->to.reg == v1->reg) { +			if(p->to.reg == v1->reg) +			if(p->scond == C_SCOND_NONE) {  				if(p->reg == NREG)  					p->reg = p->to.reg;  				goto gotit; @@ -376,6 +382,7 @@ subprop(Reg *r0)  		case AMOVW:  			if(p->to.type == v1->type)  			if(p->to.reg == v1->reg) +			if(p->scond == C_SCOND_NONE)  				goto gotit;  			break; @@ -662,7 +669,7 @@ shiftprop(Reg *r)  			FAIL("can't swap");  		if(p1->reg == NREG && p1->to.reg == n)  			FAIL("shift result used twice"); -	case AMVN: +//	case AMVN:  		if(p1->from.type == D_SHIFT)  			FAIL("shift result used in shift");  		if(p1->from.type != D_REG || p1->from.reg != n) @@ -971,7 +978,7 @@ copyu(Prog *p, Adr *v, Adr *s)  		}  		return 0; -	case ANOP:	/* read, write */ +	case ANOP:	/* read,, write */  	case AMOVW:  	case AMOVF:  	case AMOVD: @@ -979,6 +986,8 @@ copyu(Prog *p, Adr *v, Adr *s)  	case AMOVHU:  	case AMOVB:  	case AMOVBU: +	case AMOVFW: +	case AMOVWF:  	case AMOVDW:  	case AMOVWD:  	case AMOVFD: @@ -1014,6 +1023,7 @@ copyu(Prog *p, Adr *v, Adr *s)  	case AMULLU:	/* read, read, write, write */  	case AMULA: +	case AMVN:  		return 2;  	case AADD:	/* read, read, write */ @@ -1027,7 +1037,6 @@ copyu(Prog *p, Adr *v, Adr *s)  	case AORR:  	case AAND:  	case AEOR: -	case AMVN:  	case AMUL:  	case AMULU:  	case ADIV: @@ -1043,12 +1052,12 @@ copyu(Prog *p, Adr *v, Adr *s)  	case ADIVF:  	case ADIVD: -	case ACMPF: +	case ACMPF:	/* read, read, */  	case ACMPD: -	case ATST:  	case ACMP:  	case ACMN:  	case ACASE: +	case ATST:	/* read,, */  		if(s != A) {  			if(copysub(&p->from, v, s, 1))  				return 1; @@ -1150,53 +1159,6 @@ copyu(Prog *p, Adr *v, Adr *s)  	return 0;  } -int -a2type(Prog *p) -{ - -	switch(p->as) { - -	case ATST: -	case ACMP: -	case ACMN: - -	case AMULLU: -	case AMULA: - -	case AADD: -	case ASUB: -	case ARSB: -	case ASLL: -	case ASRL: -	case ASRA: -	case AORR: -	case AAND: -	case AEOR: -	case AMVN: -	case AMUL: -	case AMULU: -	case ADIV: -	case ADIVU: -	case AMOD: -	case AMODU: -		return D_REG; - -	case ACMPF: -	case ACMPD: - -	case AADDF: -	case AADDD: -	case ASUBF: -	case ASUBD: -	case AMULF: -	case AMULD: -	case ADIVF: -	case ADIVD: -		return D_FREG; -	} -	return D_NONE; -} -  /*   * direct reference,   * could be set/use depending on @@ -1233,15 +1195,15 @@ copyau(Adr *a, Adr *v)  		return 1;  	if(v->type == D_REG) {  		if(a->type == D_CONST && a->reg != NREG) { -			if(v->reg == a->reg) +			if(a->reg == v->reg)  				return 1;  		} else  		if(a->type == D_OREG) { -			if(v->reg == a->reg) +			if(a->reg == v->reg)  				return 1;  		} else  		if(a->type == D_REGREG) { -			if(v->reg == a->reg) +			if(a->reg == v->reg)  				return 1;  			if(a->offset == v->reg)  				return 1; @@ -1256,17 +1218,33 @@ copyau(Adr *a, Adr *v)  	return 0;  } +/* + * compare v to the center + * register in p (p->reg) + * the trick is that this + * register might be D_REG + * D_FREG. there are basically + * two cases, + *	ADD r,r,r + *	CMP r,r, + */  int  copyau1(Prog *p, Adr *v)  { -	if(regtyp(v)) { -		if(a2type(p) == v->type) -		if(p->reg == v->reg) { -			if(a2type(p) != v->type) -				print("botch a2type %P\n", p); -			return 1; +	if(regtyp(v)) +	if(p->reg == v->reg) { +		if(p->to.type != D_NONE) { +			if(v->type == p->to.type) +				return 1; +			return 0; +		} +		if(p->from.type != D_NONE) { +			if(v->type == p->from.type) +				return 1; +			return 0;  		} +		print("copyau1: cant tell %P\n", p);  	}  	return 0;  } @@ -1479,24 +1457,24 @@ applypred(Reg *rstart, Joininfo *j, int cond, int branch)  		pred = predinfo[rstart->prog->as - ABEQ].notscond;  	for(r = j->start;; r = successor(r)) { -		if (r->prog->as == AB) { -			if (r != j->last || branch == Delbranch) +		if(r->prog->as == AB) { +			if(r != j->last || branch == Delbranch)  				excise(r);  			else { -				if (cond == Truecond) +				if(cond == Truecond)  					r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;  				else  					r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;  			}  		}  		else -		if (predicable(r->prog)) +		if(predicable(r->prog))  			r->prog->scond = (r->prog->scond&~C_SCOND)|pred; -		if (r->s1 != r->link) { +		if(r->s1 != r->link) {  			r->s1 = r->link;  			r->link->p1 = r;  		} -		if (r == j->last) +		if(r == j->last)  			break;  	}  } diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index eaf02b237..f31f70535 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -140,8 +140,8 @@ regopt(Prog *firstp)  	if(first == 0) {  		fmtinstall('Q', Qconv);  	} -	first++; +	first++;  	if(debug['K']) {  		if(first != 13)  			return; @@ -491,7 +491,7 @@ brk:  	 * peep-hole on basic block  	 */  	if(!debug['R'] || debug['P']) { -//		peep(); +		peep();  	}  	/* @@ -1375,3 +1375,71 @@ noreturn(Prog *p)  			return 1;  	return 0;  } + +void +dumpone(Reg *r) +{ +	int z; +	Bits bit; + +	print("%d:%P", r->loop, r->prog); +	for(z=0; z<BITS; z++) +		bit.b[z] = +			r->set.b[z] | +			r->use1.b[z] | +			r->use2.b[z] | +			r->refbehind.b[z] | +			r->refahead.b[z] | +			r->calbehind.b[z] | +			r->calahead.b[z] | +			r->regdiff.b[z] | +			r->act.b[z] | +				0; +//	if(bany(&bit)) { +//		print("\t"); +//		if(bany(&r->set)) +//			print(" s:%Q", r->set); +//		if(bany(&r->use1)) +//			print(" u1:%Q", r->use1); +//		if(bany(&r->use2)) +//			print(" u2:%Q", r->use2); +//		if(bany(&r->refbehind)) +//			print(" rb:%Q ", r->refbehind); +//		if(bany(&r->refahead)) +//			print(" ra:%Q ", r->refahead); +//		if(bany(&r->calbehind)) +//			print("cb:%Q ", r->calbehind); +//		if(bany(&r->calahead)) +//			print(" ca:%Q ", r->calahead); +//		if(bany(&r->regdiff)) +//			print(" d:%Q ", r->regdiff); +//		if(bany(&r->act)) +//			print(" a:%Q ", r->act); +//	} +	print("\n"); +} + +void +dumpit(char *str, Reg *r0) +{ +	Reg *r, *r1; + +	print("\n%s\n", str); +	for(r = r0; r != R; r = r->link) { +		dumpone(r); +		r1 = r->p2; +		if(r1 != R) { +			print("	pred:"); +			for(; r1 != R; r1 = r1->p2link) +				print(" %.4ud", r1->prog->loc); +			print("\n"); +		} +//		r1 = r->s1; +//		if(r1 != R) { +//			print("	succ:"); +//			for(; r1 != R; r1 = r1->s1) +//				print(" %.4ud", r1->prog->loc); +//			print("\n"); +//		} +	} +} diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index 34565629f..7163997c0 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -637,13 +637,6 @@ wput(int32 l)  		cflush();  } -void -wputl(ushort w) -{ -	cput(w); -	cput(w>>8); -} -  void  hput(int32 l) @@ -672,20 +665,6 @@ lput(int32 l)  }  void -lputl(int32 l) -{ - -	cbp[3] = l>>24; -	cbp[2] = l>>16; -	cbp[1] = l>>8; -	cbp[0] = l; -	cbp += 4; -	cbc -= 4; -	if(cbc <= 0) -		cflush(); -} - -void  cflush(void)  {  	int n; @@ -1491,15 +1470,24 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na  		o1 |= (p->scond & C_SCOND) << 28;  		break;  	case 80:	/* fmov zfcon,freg */ -		if((p->scond & C_SCOND) != C_SCOND_NONE) -			diag("floating point cannot be conditional");	// cant happen -		o1 = 0xf3000110;	// EOR 64 - -		// always clears the double float register +		if(p->as == AMOVD) { +			o1 = 0xeeb00b00;	// VMOV imm 64 +			o2 = oprrr(ASUBD, p->scond); +		} else { +			o1 = 0x0eb00a00;	// VMOV imm 32 +			o2 = oprrr(ASUBF, p->scond); +		} +		v = 0x70;	// 1.0  		r = p->to.reg; -		o1 |= r << 0; + +		// movf $1.0, r +		o1 |= (p->scond & C_SCOND) << 28;  		o1 |= r << 12; -		o1 |= r << 16; +		o1 |= (v&0xf) << 0; +		o1 |= (v&0xf0) << 12; + +		// subf r,r,r +		o2 |= r | (r<<16) | (r<<12);  		break;  	case 81:	/* fmov sfcon,freg */  		o1 = 0x0eb00a00;		// VMOV imm 32 diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h index c31028416..e42be4e98 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -410,6 +410,7 @@ Sym*	lookup(char*, int);  void	cput(int);  void	hput(int32);  void	lput(int32); +void	lputb(int32);  void	lputl(int32);  void*	mysbrk(uint32);  void	names(void); diff --git a/src/cmd/5l/optab.c b/src/cmd/5l/optab.c index 9ad0193ac..8b3135e06 100644 --- a/src/cmd/5l/optab.c +++ b/src/cmd/5l/optab.c @@ -236,7 +236,7 @@ Optab	optab[] =  	{ ALDREX,	C_SOREG,C_NONE,	C_REG,		77, 4, 0 },  	{ ASTREX,	C_SOREG,C_REG,	C_REG,		78, 4, 0 }, -	{ AMOVF,	C_ZFCON,C_NONE,	C_FREG,		80, 4, 0 }, +	{ AMOVF,	C_ZFCON,C_NONE,	C_FREG,		80, 8, 0 },  	{ AMOVF,	C_SFCON,C_NONE,	C_FREG,		81, 4, 0 },  	{ ACMPF,	C_FREG,	C_REG,	C_NONE,		82, 8, 0 }, diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c index 1b8bb6344..37144c888 100644 --- a/src/cmd/6a/lex.c +++ b/src/cmd/6a/lex.c @@ -189,7 +189,7 @@ assemble(char *file)  	pass = 1;  	pinit(file); -	Bprint(&obuf, "%s\n", thestring); +	Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());  	for(i=0; i<nDlist; i++)  		dodefine(Dlist[i]); diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c index 47975a0c8..6d886f459 100644 --- a/src/cmd/6c/swt.c +++ b/src/cmd/6c/swt.c @@ -231,7 +231,7 @@ outcode(void)  	}  	Binit(&b, f, OWRITE); -	Bprint(&b, "%s\n", thestring); +	Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion());  	if(ndynimp > 0 || ndynexp > 0) {  		int i; diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index d6ffa4ff9..d179e77b1 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -63,52 +63,6 @@ entryvalue(void)  	return s->value;  } -void -wputl(uint16 w) -{ -	cput(w); -	cput(w>>8); -} - -void -wputb(uint16 w) -{ -	cput(w>>8); -	cput(w); -} - -void -lputb(int32 l) -{ -	cput(l>>24); -	cput(l>>16); -	cput(l>>8); -	cput(l); -} - -void -vputb(uint64 v) -{ -	lputb(v>>32); -	lputb(v); -} - -void -lputl(int32 l) -{ -	cput(l); -	cput(l>>8); -	cput(l>>16); -	cput(l>>24); -} - -void -vputl(uint64 v) -{ -	lputl(v); -	lputl(v>>32); -} -  vlong  datoff(vlong addr)  { diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index 7f22493e0..70473ecd2 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -429,6 +429,7 @@ vlong	rnd(vlong, vlong);  void	span(void);  void	undef(void);  vlong	symaddr(Sym*); +void	vputb(uint64);  void	vputl(uint64);  void	wputb(uint16);  void	wputl(uint16); diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c index bf298b266..d5fa959aa 100644 --- a/src/cmd/8a/lex.c +++ b/src/cmd/8a/lex.c @@ -189,7 +189,7 @@ assemble(char *file)  	pass = 1;  	pinit(file); -	Bprint(&obuf, "%s\n", thestring); +	Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());  	for(i=0; i<nDlist; i++)  		dodefine(Dlist[i]); diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c index be48885f8..d07a5439c 100644 --- a/src/cmd/8c/swt.c +++ b/src/cmd/8c/swt.c @@ -230,7 +230,7 @@ outcode(void)  	}  	Binit(&b, f, OWRITE); -	Bprint(&b, "%s\n", thestring); +	Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion());  	if(ndynimp > 0 || ndynexp > 0) {  		int i; diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index 6e83d8dea..d90eab7e7 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -59,45 +59,6 @@ entryvalue(void)  	return s->value;  } -void -wputl(ushort w) -{ -	cput(w); -	cput(w>>8); -} - -void -wput(ushort w) -{ -	cput(w>>8); -	cput(w); -} - -void -lput(int32 l) -{ -	cput(l>>24); -	cput(l>>16); -	cput(l>>8); -	cput(l); -} - -void -lputl(int32 l) -{ -	cput(l); -	cput(l>>8); -	cput(l>>16); -	cput(l>>24); -} - -void -vputl(uvlong l) -{ -	lputl(l >> 32); -	lputl(l); -} -  vlong  datoff(vlong addr)  { @@ -688,6 +649,8 @@ asmb(void)  	ElfPhdr *ph, *pph;  	ElfShdr *sh;  	Section *sect; +	Sym *sym; +	int i;  	if(debug['v'])  		Bprint(&bso, "%5.2f asmb\n", cputime()); @@ -741,7 +704,7 @@ asmb(void)  			seek(cout, rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen, 0);  			break;  		case 2: -			seek(cout, HEADR+segtext.filelen+segdata.filelen, 0); +			symo = HEADR+segtext.filelen+segdata.filelen;  			break;  		case 3:  		case 4: @@ -761,11 +724,27 @@ asmb(void)  			symo = rnd(symo, PEFILEALIGN);  			break;  		} -		if(HEADTYPE != 10 && !debug['s']) { +		if(!debug['s']) {  			seek(cout, symo, 0); -			if(debug['v']) -				Bprint(&bso, "%5.2f dwarf\n", cputime()); -			dwarfemitdebugsections(); +			 +			if(HEADTYPE == 2) { +				asmplan9sym(); +				cflush(); +				 +				sym = lookup("pclntab", 0); +				if(sym != nil) { +					lcsize = sym->np; +					for(i=0; i < lcsize; i++) +						cput(sym->p[i]); +					 +					cflush(); +				} +				 +			} else if(HEADTYPE != 10) { +				if(debug['v']) +					Bprint(&bso, "%5.2f dwarf\n", cputime()); +				dwarfemitdebugsections(); +			}  		}  	}  	if(debug['v']) @@ -777,25 +756,25 @@ asmb(void)  		if(iself)  			goto Elfput;  	case 0:	/* garbage */ -		lput(0x160L<<16);		/* magic and sections */ -		lput(0L);			/* time and date */ -		lput(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen); -		lput(symsize);			/* nsyms */ -		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */ -		lput((0413<<16)|0437L);		/* magic and version */ -		lput(rnd(HEADR+segtext.filelen, 4096));	/* sizes */ -		lput(segdata.filelen); -		lput(segdata.len - segdata.filelen); -		lput(entryvalue());		/* va of entry */ -		lput(INITTEXT-HEADR);		/* va of base of text */ -		lput(segdata.vaddr);			/* va of base of data */ -		lput(segdata.vaddr+segdata.filelen);		/* va of base of bss */ -		lput(~0L);			/* gp reg mask */ -		lput(0L); -		lput(0L); -		lput(0L); -		lput(0L); -		lput(~0L);			/* gp value ?? */ +		lputb(0x160L<<16);		/* magic and sections */ +		lputb(0L);			/* time and date */ +		lputb(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen); +		lputb(symsize);			/* nsyms */ +		lputb((0x38L<<16)|7L);		/* size of optional hdr and flags */ +		lputb((0413<<16)|0437L);		/* magic and version */ +		lputb(rnd(HEADR+segtext.filelen, 4096));	/* sizes */ +		lputb(segdata.filelen); +		lputb(segdata.len - segdata.filelen); +		lputb(entryvalue());		/* va of entry */ +		lputb(INITTEXT-HEADR);		/* va of base of text */ +		lputb(segdata.vaddr);			/* va of base of data */ +		lputb(segdata.vaddr+segdata.filelen);		/* va of base of bss */ +		lputb(~0L);			/* gp reg mask */ +		lputb(0L); +		lputb(0L); +		lputb(0L); +		lputb(0L); +		lputb(~0L);			/* gp value ?? */  		break;  		lputl(0);			/* x */  	case 1:	/* unix coff */ @@ -814,7 +793,7 @@ asmb(void)  		lputl(rnd(segtext.filelen, INITRND));	/* text sizes */  		lputl(segdata.filelen);			/* data sizes */  		lputl(segdata.len - segdata.filelen);			/* bss sizes */ -		lput(entryvalue());		/* va of entry */ +		lputb(entryvalue());		/* va of entry */  		lputl(INITTEXT);		/* text start */  		lputl(segdata.vaddr);			/* data start */  		/* @@ -868,14 +847,14 @@ asmb(void)  		break;  	case 2:	/* plan9 */  		magic = 4*11*11+7; -		lput(magic);		/* magic */ -		lput(segtext.filelen);			/* sizes */ -		lput(segdata.filelen); -		lput(segdata.len - segdata.filelen); -		lput(symsize);			/* nsyms */ -		lput(entryvalue());		/* va of entry */ -		lput(spsize);			/* sp offsets */ -		lput(lcsize);			/* line offsets */ +		lputb(magic);		/* magic */ +		lputb(segtext.filelen);			/* sizes */ +		lputb(segdata.filelen); +		lputb(segdata.len - segdata.filelen); +		lputb(symsize);			/* nsyms */ +		lputb(entryvalue());		/* va of entry */ +		lputb(spsize);			/* sp offsets */ +		lputb(lcsize);			/* line offsets */  		break;  	case 3:  		/* MS-DOS .COM */ diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index e0746fc75..f2546cf20 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -363,9 +363,9 @@ void	follow(void);  void	instinit(void);  void	listinit(void);  Sym*	lookup(char*, int); -void	lput(int32); +void	lputb(int32);  void	lputl(int32); -void	vputl(uvlong); +void	vputl(uint64);  void	strnput(char*, int);  void	main(int, char*[]);  void*	mal(uint32); diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index fefb6d8b0..9c687f2fc 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -188,6 +188,7 @@ main(int argc, char *argv[])  			INITRND = 0;  		break;  	case 2:	/* plan 9 */ +		tlsoffset = -8;  		HEADR = 32L;  		if(INITTEXT == -1)  			INITTEXT = 4096+32; diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c index 878a73dac..67acfa167 100644 --- a/src/cmd/8l/pass.c +++ b/src/cmd/8l/pass.c @@ -250,6 +250,7 @@ patch(void)  	Prog *p, *q;  	Sym *s;  	int32 vexit; +	Sym *plan9_tos;  	if(debug['v'])  		Bprint(&bso, "%5.2f mkfwd\n", cputime()); @@ -260,6 +261,10 @@ patch(void)  	Bflush(&bso);  	s = lookup("exit", 0);  	vexit = s->value; +	 +	if(HEADTYPE == 2) +		plan9_tos = lookup("_tos", 0); +	  	for(cursym = textp; cursym != nil; cursym = cursym->next) {  		for(p = cursym->text; p != P; p = p->link) {  			if(HEADTYPE == 10) {	// Windows @@ -303,9 +308,15 @@ patch(void)  			if(HEADTYPE == 2) {	// Plan 9  				if(p->from.type == D_INDIR+D_GS  				&& p->to.type >= D_AX && p->to.type <= D_DI) { +					q = appendp(p); +					q->from = p->from; +					q->from.type = D_INDIR + p->to.type; +					q->to = p->to; +					q->as = p->as;  					p->as = AMOVL; -					p->from.type = D_ADDR+D_STATIC; -					p->from.offset += 0xdfffefc0; +					p->from.type = D_EXTERN; +					p->from.sym = plan9_tos; +					p->from.offset = 0;  				}  			}  			if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) { @@ -389,6 +400,7 @@ dostkoff(void)  	int a;  	Prog *pmorestack;  	Sym *symmorestack; +	Sym *plan9_tos;  	pmorestack = P;  	symmorestack = lookup("runtime.morestack", 0); @@ -399,6 +411,9 @@ dostkoff(void)  		pmorestack = symmorestack->text;  		symmorestack->text->from.scale |= NOSPLIT;  	} +	 +	if(HEADTYPE == 2)	 +		plan9_tos = lookup("_tos", 0);  	for(cursym = textp; cursym != nil; cursym = cursym->next) {  		if(cursym->text == nil || cursym->text->link == nil) @@ -443,9 +458,15 @@ dostkoff(void)  			case 2:	// Plan 9  				p->as = AMOVL; -				p->from.type = D_ADDR+D_STATIC; -				p->from.offset = 0xdfffefc0; +				p->from.type = D_EXTERN; +				p->from.sym = plan9_tos;  				p->to.type = D_CX; +				 +				p = appendp(p); +				p->as = AMOVL; +				p->from.type = D_INDIR+D_CX; +				p->from.offset = tlsoffset + 0; +				p->to.type = D_CX;				  				break;  			default: diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index c4868345c..b3aa9aded 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -25,9 +25,12 @@ the package.  For example:  CFLAGS and LDFLAGS may be defined with pseudo #cgo directives  within these comments to tweak the behavior of gcc.  Values defined -in multiple directives are concatenated together.  For example: +in multiple directives are concatenated together.  Options prefixed +by $GOOS, $GOARCH, or $GOOS/$GOARCH are only defined in matching +systems.  For example:  	// #cgo CFLAGS: -DPNG_DEBUG=1 +	// #cgo linux CFLAGS: -DLINUX=1  	// #cgo LDFLAGS: -lpng  	// #include <png.h>  	import "C" diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index cadc6fae9..e6ce21ed3 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -19,6 +19,7 @@ import (  	"go/parser"  	"go/token"  	"os" +	"runtime"  	"strconv"  	"strings"  	"unicode" @@ -66,6 +67,8 @@ func cname(s string) string {  func (p *Package) ParseFlags(f *File, srcfile string) {  	linesIn := strings.Split(f.Preamble, "\n", -1)  	linesOut := make([]string, 0, len(linesIn)) + +NextLine:  	for _, line := range linesIn {  		l := strings.TrimSpace(line)  		if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(int(l[4])) { @@ -79,11 +82,29 @@ func (p *Package) ParseFlags(f *File, srcfile string) {  			fatal("%s: bad #cgo line: %s", srcfile, line)  		} -		k := fields[0] -		v := strings.TrimSpace(fields[1]) +		var k string +		kf := strings.Fields(fields[0]) +		switch len(kf) { +		case 1: +			k = kf[0] +		case 2: +			k = kf[1] +			switch kf[0] { +			case runtime.GOOS: +			case runtime.GOARCH: +			case runtime.GOOS + "/" + runtime.GOARCH: +			default: +				continue NextLine +			} +		default: +			fatal("%s: bad #cgo option: %s", srcfile, fields[0]) +		} +  		if k != "CFLAGS" && k != "LDFLAGS" {  			fatal("%s: unsupported #cgo option %s", srcfile, k)  		} + +		v := strings.TrimSpace(fields[1])  		args, err := splitQuoted(v)  		if err != nil {  			fatal("%s: bad #cgo option %s: %s", srcfile, k, err.String()) @@ -288,7 +309,7 @@ func (p *Package) guessKinds(f *File) []*Name {  	var b bytes.Buffer  	b.WriteString(builtinProlog)  	b.WriteString(f.Preamble) -	b.WriteString("void f(void) {\n") +	b.WriteString("void __cgo__f__(void) {\n")  	b.WriteString("#line 0 \"cgo-test\"\n")  	for i, n := range toSniff {  		fmt.Fprintf(&b, "%s; enum { _cgo_enum_%d = %s }; /* cgo-test:%d */\n", n.C, i, n.C, i) @@ -753,6 +774,8 @@ var dwarfToName = map[string]string{  	"double complex":         "complexdouble",  } +const signedDelta = 64 +  // Type returns a *Type with the same memory layout as  // dtype when used as the type of a variable or a struct field.  func (c *typeConv) Type(dtype dwarf.Type) *Type { @@ -818,7 +841,19 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {  		t.Align = 1  	case *dwarf.EnumType: -		switch t.Size { +		if t.Align = t.Size; t.Align >= c.ptrSize { +			t.Align = c.ptrSize +		} +		t.C = "enum " + dt.EnumName +		signed := 0 +		t.EnumValues = make(map[string]int64) +		for _, ev := range dt.Val { +			t.EnumValues[ev.Name] = ev.Val +			if ev.Val < 0 { +				signed = signedDelta +			} +		} +		switch t.Size + int64(signed) {  		default:  			fatal("unexpected: %d-byte enum type - %s", t.Size, dtype)  		case 1: @@ -829,14 +864,14 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {  			t.Go = c.uint32  		case 8:  			t.Go = c.uint64 -		} -		if t.Align = t.Size; t.Align >= c.ptrSize { -			t.Align = c.ptrSize -		} -		t.C = "enum " + dt.EnumName -		t.EnumValues = make(map[string]int64) -		for _, ev := range dt.Val { -			t.EnumValues[ev.Name] = ev.Val +		case 1 + signedDelta: +			t.Go = c.int8 +		case 2 + signedDelta: +			t.Go = c.int16 +		case 4 + signedDelta: +			t.Go = c.int32 +		case 8 + signedDelta: +			t.Go = c.int64  		}  	case *dwarf.FloatType: diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go index a6f509dc4..59529a6d2 100644 --- a/src/cmd/cgo/util.go +++ b/src/cmd/cgo/util.go @@ -32,10 +32,11 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {  	if err != nil {  		fatal("%s", err)  	} -	pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2}) +	p, err := os.StartProcess(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2})  	if err != nil {  		fatal("%s", err)  	} +	defer p.Release()  	r0.Close()  	w1.Close()  	w2.Close() @@ -55,7 +56,7 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {  	<-c  	<-c -	w, err := os.Wait(pid, 0) +	w, err := p.Wait(0)  	if err != nil {  		fatal("%s", err)  	} diff --git a/src/cmd/clean.bash b/src/cmd/clean.bash index 6349919a8..92d8cc5c9 100644 --- a/src/cmd/clean.bash +++ b/src/cmd/clean.bash @@ -3,9 +3,14 @@  # Use of this source code is governed by a BSD-style  # license that can be found in the LICENSE file. +gomake=gomake +if [ "$1" == "--gomake" -a "$2" != "" ]; then +	gomake=$2 +fi +  for i in cc 6l 6a 6c 8l 8a 8c 8g 5l 5a 5c 5g gc 6g gopack nm cgo cov ebnflint godefs godoc gofmt goinstall gotest goyacc hgpatch prof  do  	cd $i -	gomake clean +	$gomake clean  	cd ..  done diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c index ed20e7e8b..833eba19a 100644 --- a/src/cmd/gc/align.c +++ b/src/cmd/gc/align.c @@ -54,7 +54,8 @@ widstruct(Type *t, uint32 o, int flag)  		if(f->type->width < 0)  			fatal("invalid width %lld", f->type->width);  		w = f->type->width; -		o = rnd(o, f->type->align); +		if(f->type->align > 0) +			o = rnd(o, f->type->align);  		f->width = o;	// really offset for TFIELD  		if(f->nname != N) {  			// this same stackparam logic is in addrescapes diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 994840ee8..86e3cae33 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -242,14 +242,6 @@ import_package:  		if(safemode && !curio.importsafe)  			yyerror("cannot import unsafe package %Z", importpkg->path); - -		// NOTE(rsc): This is no longer a technical restriction: -		// the 6g tool chain would work just fine without giving -		// special meaning to a package being named main. -		// Other implementations might need the restriction -		// (gccgo does), so it stays in the language and the compiler. -		if(strcmp($2->name, "main") == 0) -			yyerror("cannot import package main");  	}  import_safety: diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index 45b1257fa..e79d3b0f8 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -405,7 +405,7 @@ void  importfile(Val *f, int line)  {  	Biobuf *imp; -	char *file; +	char *file, *p, *q;  	int32 c;  	int len;  	Strlit *path; @@ -423,6 +423,15 @@ importfile(Val *f, int line)  		errorexit();  	} +	// The package name main is no longer reserved, +	// but we reserve the import path "main" to identify +	// the main package, just as we reserve the import  +	// path "math" to identify the standard math package. +	if(strcmp(f->u.sval->s, "main") == 0) { +		yyerror("cannot import \"main\""); +		errorexit(); +	} +  	if(strcmp(f->u.sval->s, "unsafe") == 0) {  		if(safemode) {  			yyerror("cannot import package unsafe"); @@ -432,7 +441,7 @@ importfile(Val *f, int line)  		cannedimports("unsafe.6", unsafeimport);  		return;  	} - +	  	path = f->u.sval;  	if(islocalname(path)) {  		cleanbuf = mal(strlen(pathname) + strlen(path->s) + 2); @@ -459,9 +468,24 @@ importfile(Val *f, int line)  	len = strlen(namebuf);  	if(len > 2 && namebuf[len-2] == '.' && namebuf[len-1] == 'a') {  		if(!skiptopkgdef(imp)) { -			yyerror("import not package file: %s", namebuf); +			yyerror("import %s: not a package file", file); +			errorexit(); +		} +	} +	 +	// check object header +	p = Brdstr(imp, '\n', 1); +	if(strcmp(p, "empty archive") != 0) { +		if(strncmp(p, "go object ", 10) != 0) { +			yyerror("import %s: not a go object file", file);  			errorexit();  		} +		q = smprint("%s %s %s", getgoos(), thestring, getgoversion()); +		if(strcmp(p+10, q) != 0) { +			yyerror("import %s: object is [%s] expected [%s]", file, p+10, q); +			errorexit(); +		} +		free(q);  	}  	// assume files move (get installed) @@ -479,6 +503,7 @@ importfile(Val *f, int line)  	curio.infile = file;  	curio.nlsemi = 0;  	typecheckok = 1; +  	for(;;) {  		c = getc();  		if(c == EOF) diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c index 7b7e66668..b11a4f5f1 100644 --- a/src/cmd/gc/mparith3.c +++ b/src/cmd/gc/mparith3.c @@ -179,7 +179,7 @@ mpdivfltflt(Mpflt *a, Mpflt *b)  double  mpgetflt(Mpflt *a)  { -	int s, i; +	int s, i, e;  	uvlong v, vm;  	double f; @@ -200,12 +200,12 @@ mpgetflt(Mpflt *a)  		a->exp -= 1;  	} -	// the magic numbers (64, 63, 53, 10) are +	// the magic numbers (64, 63, 53, 10, -1074) are  	// IEEE specific. this should be done machine  	// independently or in the 6g half of the compiler -	// pick up the mantissa in a uvlong -	s = 53; +	// pick up the mantissa and a rounding bit in a uvlong +	s = 53+1;  	v = 0;  	for(i=Mpnorm-1; s>=Mpscale; i--) {  		v = (v<<Mpscale) | a->val.a[i]; @@ -224,13 +224,26 @@ mpgetflt(Mpflt *a)  	if(s > 0)  		v = (v<<s) | (a->val.a[i]>>(Mpscale-s)); +	// gradual underflow +	e = Mpnorm*Mpscale + a->exp - 53; +	if(e < -1074) { +		s = -e - 1074; +		if(s > 54) +			s = 54; +		v |= vm & ((1ULL<<s) - 1); +		vm >>= s; +		e = -1074; +	} +  //print("vm=%.16llux v=%.16llux\n", vm, v);  	// round toward even -	if(v != (1ULL<<63) || (vm&1ULL) != 0) -		vm += v>>63; +	if(v != 0 || (vm&2ULL) != 0) +		vm = (vm>>1) + (vm&1ULL); +	else +		vm >>= 1;  	f = (double)(vm); -	f = ldexp(f, Mpnorm*Mpscale + a->exp - 53); +	f = ldexp(f, e);  	if(a->val.neg)  		f = -f; diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c index 0d0d70ac9..fbabe0d43 100644 --- a/src/cmd/gc/obj.c +++ b/src/cmd/gc/obj.c @@ -21,7 +21,7 @@ dumpobj(void)  		errorexit();  	} -	Bprint(bout, "%s\n", thestring); +	Bprint(bout, "go object %s %s %s\n", getgoos(), thestring, getgoversion());  	Bprint(bout, "  exports automatically generated from\n");  	Bprint(bout, "  %s in package \"%s\"\n", curio.infile, localpkg->name);  	dumpexport(); diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c index 5686e9599..58a147745 100644 --- a/src/cmd/gc/select.c +++ b/src/cmd/gc/select.c @@ -157,7 +157,7 @@ walkselect(Node *sel)  			if(n->left == N || isblank(n->left))  				n->left = nodnil();  			else if(n->left->op == ONAME && -					(!n->colas || (n->class&PHEAP) == 0) && +					(!n->colas || (n->left->class&PHEAP) == 0) &&  					convertop(ch->type->type, n->left->type, nil) == OCONVNOP) {  				n->left = nod(OADDR, n->left, N);  				n->left->etype = 1;  // pointer does not escape @@ -170,9 +170,9 @@ walkselect(Node *sel)  				typecheck(&a, Erv);  				r = nod(OAS, n->left, tmp);  				typecheck(&r, Etop); +				cas->nbody = concat(list1(r), cas->nbody);  				cas->nbody = concat(n->ninit, cas->nbody);  				n->ninit = nil; -				cas->nbody = concat(list1(r), cas->nbody);  				n->left = a;  			}  		} diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index cb5e2a831..0755ca3cd 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -203,6 +203,7 @@ fatal(char *fmt, ...)  	flusherrors(); +*(int*)0=0;  	print("%L: internal compiler error: ", lineno);  	va_start(arg, fmt);  	vfprint(1, fmt, arg); @@ -213,7 +214,7 @@ fatal(char *fmt, ...)  	if(strncmp(getgoversion(), "release", 7) == 0) {  		print("\n");  		print("Please file a bug report including a short program that triggers the error.\n"); -		print("http://code.google.com/p/go/issues/entry?template=compilerbug"); +		print("http://code.google.com/p/go/issues/entry?template=compilerbug\n");  	}  	hcrash();  	errorexit(); diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index 931d0327a..5edca964a 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -96,7 +96,7 @@ typecheck(Node **np, int top)  	Node *n, *l, *r;  	NodeList *args;  	int lno, ok, ntop; -	Type *t, *missing, *have; +	Type *t, *tp, *missing, *have;  	Sym *sym;  	Val v;  	char *why; @@ -552,6 +552,7 @@ reswitch:  			ok = Erv;  			goto ret;  		} +		tp = t;  		if(isptr[t->etype] && t->type->etype != TINTER) {  			t = t->type;  			if(t == T) @@ -563,7 +564,7 @@ reswitch:  			if(lookdot(n, t, 1))  				yyerror("%#N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);  			else -				yyerror("%#N undefined (type %T has no field or method %S)", n, t, n->right->sym); +				yyerror("%#N undefined (type %T has no field or method %S)", n, tp, n->right->sym);  			goto error;  		}  		switch(n->op) { diff --git a/src/cmd/godoc/format.go b/src/cmd/godoc/format.go index 66b01aa64..da1466b21 100644 --- a/src/cmd/godoc/format.go +++ b/src/cmd/godoc/format.go @@ -11,7 +11,6 @@  package main  import ( -	"bytes"  	"fmt"  	"go/scanner"  	"go/token" @@ -335,12 +334,12 @@ func selectionTag(w io.Writer, text []byte, selections int) {  } -// FormatText HTML-escapes text and returns it wrapped in <pre> tags. -// Conscutive text segments are wrapped in HTML spans (with tags as +// FormatText HTML-escapes text and writes it to w. +// Consecutive text segments are wrapped in HTML spans (with tags as  // defined by startTags and endTag) as follows:  // -//	- if line >= 0, line numbers are printed before each line, starting -//	  with the value of line +//	- if line >= 0, line number (ln) spans are inserted before each line, +//	  starting with the value of line  //	- if the text is Go source, comments get the "comment" span class  //	- each occurrence of the regular expression pattern gets the "highlight"  //	  span class @@ -349,10 +348,7 @@ func selectionTag(w io.Writer, text []byte, selections int) {  // Comments, highlights, and selections may overlap arbitrarily; the respective  // HTML span classes are specified in the startTags variable.  // -func FormatText(text []byte, line int, goSource bool, pattern string, selection Selection) []byte { -	var buf bytes.Buffer -	buf.WriteString("<pre>\n") - +func FormatText(w io.Writer, text []byte, line int, goSource bool, pattern string, selection Selection) {  	var comments, highlights Selection  	if goSource {  		comments = commentSelection(text) @@ -370,11 +366,8 @@ func FormatText(text []byte, line int, goSource bool, pattern string, selection  				}  			}  		} -		FormatSelections(&buf, text, lineTag, lineSelection(text), selectionTag, comments, highlights, selection) +		FormatSelections(w, text, lineTag, lineSelection(text), selectionTag, comments, highlights, selection)  	} else { -		template.HTMLEscape(&buf, text) +		template.HTMLEscape(w, text)  	} - -	buf.WriteString("</pre>\n") -	return buf.Bytes()  } diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 6a00a3e70..c91dc33db 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -274,7 +274,7 @@ func relativePath(path string) string {  // ----------------------------------------------------------------------------  // Tab conversion -var spaces = []byte("                ") // 16 spaces seems like a good number +var spaces = []byte("                                ") // 32 spaces seems like a good number  const (  	indenting = iota @@ -291,25 +291,31 @@ type tconv struct {  func (p *tconv) writeIndent() (err os.Error) {  	i := p.indent -	for i > len(spaces) { +	for i >= len(spaces) {  		i -= len(spaces)  		if _, err = p.output.Write(spaces); err != nil {  			return  		}  	} -	_, err = p.output.Write(spaces[0:i]) +	// i < len(spaces) +	if i > 0 { +		_, err = p.output.Write(spaces[0:i]) +	}  	return  }  func (p *tconv) Write(data []byte) (n int, err os.Error) { +	if len(data) == 0 { +		return +	}  	pos := 0 // valid if p.state == collecting  	var b byte  	for n, b = range data {  		switch p.state {  		case indenting:  			switch b { -			case '\t', '\v': +			case '\t':  				p.indent += *tabwidth  			case '\n':  				p.indent = 0 @@ -336,7 +342,7 @@ func (p *tconv) Write(data []byte) (n int, err os.Error) {  		}  	}  	n = len(data) -	if p.state == collecting { +	if pos < n && p.state == collecting {  		_, err = p.output.Write(data[pos:])  	}  	return @@ -346,47 +352,51 @@ func (p *tconv) Write(data []byte) (n int, err os.Error) {  // ----------------------------------------------------------------------------  // Templates -// Write an AST-node to w; optionally html-escaped. -func writeNode(w io.Writer, fset *token.FileSet, node interface{}, html bool) { -	mode := printer.TabIndent | printer.UseSpaces -	if html { -		mode |= printer.GenHTML -	} +// Write an AST node to w. +func writeNode(w io.Writer, fset *token.FileSet, x interface{}) {  	// convert trailing tabs into spaces using a tconv filter  	// to ensure a good outcome in most browsers (there may still  	// be tabs in comments and strings, but converting those into  	// the right number of spaces is much harder) -	(&printer.Config{mode, *tabwidth, nil}).Fprint(&tconv{output: w}, fset, node) +	// +	// TODO(gri) rethink printer flags - perhaps tconv can be eliminated +	//           with an another printer mode (which is more efficiently +	//           implemented in the printer than here with another layer) +	mode := printer.TabIndent | printer.UseSpaces +	(&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x)  } -// Write text to w; optionally html-escaped. -func writeText(w io.Writer, text []byte, html bool) { -	if html { -		template.HTMLEscape(w, text) -		return +// Write anything to w. +func writeAny(w io.Writer, fset *token.FileSet, x interface{}) { +	switch v := x.(type) { +	case []byte: +		w.Write(v) +	case string: +		w.Write([]byte(v)) +	case ast.Decl, ast.Expr, ast.Stmt, *ast.File: +		writeNode(w, fset, x) +	default: +		fmt.Fprint(w, x)  	} -	w.Write(text)  } -// Write anything to w; optionally html-escaped. -func writeAny(w io.Writer, fset *token.FileSet, html bool, x interface{}) { +// Write anything html-escaped to w. +func writeAnyHTML(w io.Writer, fset *token.FileSet, x interface{}) {  	switch v := x.(type) {  	case []byte: -		writeText(w, v, html) +		template.HTMLEscape(w, v)  	case string: -		writeText(w, []byte(v), html) +		template.HTMLEscape(w, []byte(v))  	case ast.Decl, ast.Expr, ast.Stmt, *ast.File: -		writeNode(w, fset, x, html) +		var buf bytes.Buffer +		writeNode(&buf, fset, x) +		FormatText(w, buf.Bytes(), -1, true, "", nil)  	default: -		if html { -			var buf bytes.Buffer -			fmt.Fprint(&buf, x) -			writeText(w, buf.Bytes(), true) -		} else { -			fmt.Fprint(w, x) -		} +		var buf bytes.Buffer +		fmt.Fprint(&buf, x) +		template.HTMLEscape(w, buf.Bytes())  	}  } @@ -401,24 +411,16 @@ func fileset(x []interface{}) *token.FileSet {  } -// Template formatter for "html" format. -func htmlFmt(w io.Writer, format string, x ...interface{}) { -	writeAny(w, fileset(x), true, x[0]) -} - -  // Template formatter for "html-esc" format.  func htmlEscFmt(w io.Writer, format string, x ...interface{}) { -	var buf bytes.Buffer -	writeAny(&buf, fileset(x), false, x[0]) -	template.HTMLEscape(w, buf.Bytes()) +	writeAnyHTML(w, fileset(x), x[0])  }  // Template formatter for "html-comment" format.  func htmlCommentFmt(w io.Writer, format string, x ...interface{}) {  	var buf bytes.Buffer -	writeAny(&buf, fileset(x), false, x[0]) +	writeAny(&buf, fileset(x), x[0])  	// TODO(gri) Provide list of words (e.g. function parameters)  	//           to be emphasized by ToHTML.  	doc.ToHTML(w, buf.Bytes(), nil) // does html-escaping @@ -427,14 +429,14 @@ func htmlCommentFmt(w io.Writer, format string, x ...interface{}) {  // Template formatter for "" (default) format.  func textFmt(w io.Writer, format string, x ...interface{}) { -	writeAny(w, fileset(x), false, x[0]) +	writeAny(w, fileset(x), x[0])  }  // Template formatter for "urlquery-esc" format.  func urlQueryEscFmt(w io.Writer, format string, x ...interface{}) {  	var buf bytes.Buffer -	writeAny(&buf, fileset(x), false, x[0]) +	writeAny(&buf, fileset(x), x[0])  	template.HTMLEscape(w, []byte(http.URLEscape(string(buf.Bytes()))))  } @@ -603,7 +605,6 @@ func numlinesFmt(w io.Writer, format string, x ...interface{}) {  var fmap = template.FormatterMap{  	"":             textFmt, -	"html":         htmlFmt,  	"html-esc":     htmlEscFmt,  	"html-comment": htmlCommentFmt,  	"urlquery-esc": urlQueryEscFmt, @@ -683,7 +684,7 @@ func servePage(w http.ResponseWriter, title, subtitle, query string, content []b  		content,  	} -	if err := godocHTML.Execute(&d, w); err != nil { +	if err := godocHTML.Execute(w, &d); err != nil {  		log.Printf("godocHTML.Execute: %s", err)  	}  } @@ -751,7 +752,7 @@ func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath strin  func applyTemplate(t *template.Template, name string, data interface{}) []byte {  	var buf bytes.Buffer -	if err := t.Execute(data, &buf); err != nil { +	if err := t.Execute(&buf, data); err != nil {  		log.Printf("%s.Execute: %s", name, err)  	}  	return buf.Bytes() @@ -775,8 +776,12 @@ func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, tit  		return  	} -	contents := FormatText(src, 1, pathutil.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s"))) -	servePage(w, title+" "+relpath, "", "", contents) +	var buf bytes.Buffer +	buf.WriteString("<pre>") +	FormatText(&buf, src, 1, pathutil.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s"))) +	buf.WriteString("</pre>") + +	servePage(w, title+" "+relpath, "", "", buf.Bytes())  } @@ -891,6 +896,11 @@ type PageInfo struct {  } +func (info *PageInfo) IsEmpty() bool { +	return info.Err != nil || info.PAst == nil && info.PDoc == nil && info.Dirs == nil +} + +  type httpHandler struct {  	pattern string // url pattern; e.g. "/pkg/"  	fsRoot  string // file system root to which the pattern is mapped diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go index 581409cde..56f31f5cf 100644 --- a/src/cmd/godoc/index.go +++ b/src/cmd/godoc/index.go @@ -430,7 +430,6 @@ func (a *AltWords) filter(s string) *AltWords {  // Indexer  // Adjust these flags as seems best. -const includeNonGoFiles = true  const includeMainPackages = true  const includeTestFiles = true @@ -728,7 +727,7 @@ func isWhitelisted(filename string) bool {  } -func (x *Indexer) visitFile(dirname string, f *os.FileInfo) { +func (x *Indexer) visitFile(dirname string, f *os.FileInfo, fulltextIndex bool) {  	if !f.IsRegular() {  		return  	} @@ -746,7 +745,7 @@ func (x *Indexer) visitFile(dirname string, f *os.FileInfo) {  		}  		goFile = true -	case !includeNonGoFiles || !isWhitelisted(f.Name): +	case !fulltextIndex || !isWhitelisted(f.Name):  		return  	} @@ -811,7 +810,7 @@ func NewIndex(dirnames <-chan string, fulltextIndex bool) *Index {  		}  		for _, f := range list {  			if !f.IsDirectory() { -				x.visitFile(dirname, f) +				x.visitFile(dirname, f, fulltextIndex)  			}  		}  	} diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go index f1b11a760..ea1e3c42e 100644 --- a/src/cmd/godoc/main.go +++ b/src/cmd/godoc/main.go @@ -83,20 +83,21 @@ func exec(rw http.ResponseWriter, args []string) (status int) {  	if *verbose {  		log.Printf("executing %v", args)  	} -	pid, err := os.ForkExec(bin, args, os.Environ(), *goroot, fds) +	p, err := os.StartProcess(bin, args, os.Environ(), *goroot, fds)  	defer r.Close()  	w.Close()  	if err != nil { -		log.Printf("os.ForkExec(%q): %v", bin, err) +		log.Printf("os.StartProcess(%q): %v", bin, err)  		return 2  	} +	defer p.Release()  	var buf bytes.Buffer  	io.Copy(&buf, r) -	wait, err := os.Wait(pid, 0) +	wait, err := p.Wait(0)  	if err != nil {  		os.Stderr.Write(buf.Bytes()) -		log.Printf("os.Wait(%d, 0): %v", pid, err) +		log.Printf("os.Wait(%d, 0): %v", p.Pid, err)  		return 2  	}  	status = wait.ExitStatus() @@ -317,7 +318,7 @@ func main() {  	}  	relpath := path  	abspath := path -	if len(path) > 0 && path[0] != '/' { +	if !pathutil.IsAbs(path) {  		abspath = absolutePath(path, pkgHandler.fsRoot)  	} else {  		relpath = relativePath(path) @@ -336,12 +337,17 @@ func main() {  	//            if there are multiple packages in a directory.  	info := pkgHandler.getPageInfo(abspath, relpath, "", mode) -	if info.Err != nil || info.PAst == nil && info.PDoc == nil && info.Dirs == nil { +	if info.IsEmpty() {  		// try again, this time assume it's a command -		if len(path) > 0 && path[0] != '/' { +		if !pathutil.IsAbs(path) {  			abspath = absolutePath(path, cmdHandler.fsRoot)  		} -		info = cmdHandler.getPageInfo(abspath, relpath, "", mode) +		cmdInfo := cmdHandler.getPageInfo(abspath, relpath, "", mode) +		// only use the cmdInfo if it actually contains a result +		// (don't hide errors reported from looking up a package) +		if !cmdInfo.IsEmpty() { +			info = cmdInfo +		}  	}  	if info.Err != nil {  		log.Fatalf("%v", info.Err) @@ -366,7 +372,11 @@ func main() {  				if i > 0 {  					fmt.Println()  				} -				writeAny(os.Stdout, info.FSet, *html, d) +				if *html { +					writeAnyHTML(os.Stdout, info.FSet, d) +				} else { +					writeAny(os.Stdout, info.FSet, d) +				}  				fmt.Println()  			}  			return @@ -376,7 +386,7 @@ func main() {  		}  	} -	if err := packageText.Execute(info, os.Stdout); err != nil { +	if err := packageText.Execute(os.Stdout, info); err != nil {  		log.Printf("packageText.Execute: %s", err)  	}  } diff --git a/src/cmd/godoc/snippet.go b/src/cmd/godoc/snippet.go index c2838ed5a..c5f4c1edf 100755 --- a/src/cmd/godoc/snippet.go +++ b/src/cmd/godoc/snippet.go @@ -25,9 +25,14 @@ type Snippet struct {  func newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {  	// TODO instead of pretty-printing the node, should use the original source instead -	var buf bytes.Buffer -	writeNode(&buf, fset, decl, false) -	return &Snippet{fset.Position(id.Pos()).Line, FormatText(buf.Bytes(), -1, true, id.Name, nil)} +	var buf1 bytes.Buffer +	writeNode(&buf1, fset, decl) +	// wrap text with <pre> tag +	var buf2 bytes.Buffer +	buf2.WriteString("<pre>") +	FormatText(&buf2, buf1.Bytes(), -1, true, id.Name, nil) +	buf2.WriteString("</pre>") +	return &Snippet{fset.Position(id.Pos()).Line, buf2.Bytes()}  } diff --git a/src/cmd/godoc/utils.go b/src/cmd/godoc/utils.go index a032bd331..cc028cc4d 100644 --- a/src/cmd/godoc/utils.go +++ b/src/cmd/godoc/utils.go @@ -60,10 +60,10 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string {  			continue // ignore empty paths (don't assume ".")  		}  		// len(path) > 0: normalize path -		if path[0] != '/' { -			path = pathutil.Join(cwd, path) -		} else { +		if pathutil.IsAbs(path) {  			path = pathutil.Clean(path) +		} else { +			path = pathutil.Join(cwd, path)  		}  		// we have a non-empty absolute path  		if filter != nil && !filter(path) { diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index d7b70c461..41c12b88d 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -113,19 +113,20 @@ func processFile(f *os.File) os.Error {  		simplify(file)  	} -	var res bytes.Buffer -	_, err = (&printer.Config{printerMode, *tabWidth, nil}).Fprint(&res, fset, file) +	var buf bytes.Buffer +	_, err = (&printer.Config{printerMode, *tabWidth}).Fprint(&buf, fset, file)  	if err != nil {  		return err  	} +	res := buf.Bytes() -	if bytes.Compare(src, res.Bytes()) != 0 { +	if !bytes.Equal(src, res) {  		// formatting has changed  		if *list {  			fmt.Fprintln(os.Stdout, f.Name())  		}  		if *write { -			err = ioutil.WriteFile(f.Name(), res.Bytes(), 0) +			err = ioutil.WriteFile(f.Name(), res, 0)  			if err != nil {  				return err  			} @@ -133,7 +134,7 @@ func processFile(f *os.File) os.Error {  	}  	if !*list && !*write { -		_, err = os.Stdout.Write(res.Bytes()) +		_, err = os.Stdout.Write(res)  	}  	return err diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh index b5f4de1e2..2f60a3e7b 100755 --- a/src/cmd/gofmt/test.sh +++ b/src/cmd/gofmt/test.sh @@ -42,7 +42,7 @@ apply1() {  	bug163.go | bug166.go | bug169.go | bug217.go | bug222.go | \  	bug226.go | bug228.go | bug248.go | bug274.go | bug280.go | \  	bug282.go | bug287.go | bug298.go | bug299.go | bug300.go | \ -	bug302.go | bug306.go ) return ;; +	bug302.go | bug306.go | bug322.go ) return ;;  	esac  	# the following directories are skipped because they contain test  	# cases for syntax errors and thus won't parse in the first place: diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go index 93a648b2b..8d4d6c5d2 100644 --- a/src/cmd/goinstall/make.go +++ b/src/cmd/goinstall/make.go @@ -75,7 +75,7 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {  	var buf bytes.Buffer  	md := makedata{pkg, goFiles, cgoFiles, oFiles} -	if err := makefileTemplate.Execute(&md, &buf); err != nil { +	if err := makefileTemplate.Execute(&buf, &md); err != nil {  		return nil, err  	}  	return buf.Bytes(), nil diff --git a/src/cmd/gopack/ar.c b/src/cmd/gopack/ar.c index a16e98cfe..702f104a6 100644 --- a/src/cmd/gopack/ar.c +++ b/src/cmd/gopack/ar.c @@ -131,6 +131,7 @@ Arfile *astart, *amiddle, *aend;	/* Temp file control block pointers */  int	allobj = 1;			/* set when all members are object files of the same type */  int	symdefsize;			/* size of symdef file */  char	*pkgstmt;		/* string "package foo" */ +char	*objhdr;		/* string "go object darwin 386 release.2010-01-01 2345+" */  int	dupfound;			/* flag for duplicate symbol */  Hashchain	*hash[NHASH];		/* hash table of text symbols */ @@ -246,6 +247,8 @@ main(int argc, char *argv[])  	argc -= 3;  	argv += 3;  	(*comfun)(cp, argc, argv);	/* do the command */ +	if(errors && cflag) +		remove(cp);  	cp = 0;  	while (argc--) {  		if (*argv) { @@ -590,10 +593,11 @@ void  scanobj(Biobuf *b, Arfile *ap, long size)  {  	int obj; -	vlong offset; +	vlong offset, offset1;  	Dir *d;  	static int lastobj = -1;  	uchar buf[4]; +	char *p;  	if (!allobj)			/* non-object file encountered */  		return; @@ -628,14 +632,32 @@ scanobj(Biobuf *b, Arfile *ap, long size)  		Bseek(b, offset, 0);  		return;  	} -	if (lastobj >= 0 && obj != lastobj) { + +	offset1 = Boffset(b); +	Bseek(b, offset, 0); +	p = Brdstr(b, '\n', 1); +	Bseek(b, offset1, 0); +	if(p == nil || strncmp(p, "go object ", 10) != 0) { +		fprint(2, "gopack: malformed object file %s\n", file); +		errors++; +		Bseek(b, offset, 0); +		free(p); +		return; +	} +	 +	if ((lastobj >= 0 && obj != lastobj) || (objhdr != nil && strcmp(p, objhdr) != 0)) {  		fprint(2, "gopack: inconsistent object file %s\n", file);  		errors++;  		allobj = 0; -		Bseek(b, offset, 0); +		free(p);  		return;  	}  	lastobj = obj; +	if(objhdr == nil) +		objhdr = p; +	else +		free(p); +		  	if (!readar(b, obj, offset+size, 0)) {  		fprint(2, "gopack: invalid symbol reference in file %s\n", file);  		errors++; @@ -677,7 +699,7 @@ char*	importblock;  void  getpkgdef(char **datap, int *lenp)  { -	char *tag; +	char *tag, *hdr;  	if(pkgname == nil) {  		pkgname = "__emptyarchive__"; @@ -688,7 +710,11 @@ getpkgdef(char **datap, int *lenp)  	if(safe || Sflag)  		tag = "safe"; -	*datap = smprint("import\n$$\npackage %s %s\n%s\n$$\n", pkgname, tag, importblock); +	hdr = "empty archive"; +	if(objhdr != nil) +		hdr = objhdr; + +	*datap = smprint("%s\nimport\n$$\npackage %s %s\n%s\n$$\n", hdr, pkgname, tag, importblock);  	*lenp = strlen(*datap);  } diff --git a/src/cmd/gotest/gotest b/src/cmd/gotest/gotest index 87c680089..69eaae730 100755 --- a/src/cmd/gotest/gotest +++ b/src/cmd/gotest/gotest @@ -119,6 +119,12 @@ nmgrep() {  	done  } +localname() { +	# The package main has been renamed to __main__ when imported. +	# Adjust its uses. +	echo $1 | sed 's/^main\./__main__./' +} +  importpath=$(gomake -s importpath)  {  	# test functions are named TestFoo @@ -139,9 +145,20 @@ importpath=$(gomake -s importpath)  	echo  	# imports  	if echo "$tests" | egrep -v '_test\.' >/dev/null; then -		if [ "$importpath" != "testing" ]; then +		case "$importpath" in +		testing) +			;; +		main) +			# Import path main is reserved, so import with +			# explicit reference to ./_test/main instead. +			# Also, the file we are writing defines a function named main, +			# so rename this import to __main__ to avoid name conflict. +			echo 'import __main__ "./_test/main"' +			;; +		*)  			echo 'import "'$importpath'"' -		fi +			;; +		esac  	fi  	if $havex; then  		echo 'import "./_xtest_"' @@ -153,23 +170,20 @@ importpath=$(gomake -s importpath)  	echo 'var tests = []testing.InternalTest{'  	for i in $tests  	do -		echo '	{"'$i'", '$i'},' +		j=$(localname $i) +		echo '	{"'$i'", '$j'},'  	done  	echo '}'  	# benchmark array -	if [ "$benchmarks" = "" ] -	then -		# keep the empty array gofmt-safe. -		# (not an issue for the test array, which is never empty.) -		echo 'var benchmarks = []testing.InternalBenchmark{}' -	else -		echo 'var benchmarks = []testing.InternalBenchmark{' -		for i in $benchmarks -		do -			echo '	{"'$i'", '$i'},' -		done -		echo '}' -	fi +	# The comment makes the multiline declaration +	# gofmt-safe even when there are no benchmarks. +	echo 'var benchmarks = []testing.InternalBenchmark{ //' +	for i in $benchmarks +	do +		j=$(localname $i) +		echo '	{"'$i'", '$j'},' +	done +	echo '}'  	# body  	echo  	echo 'func main() {' diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c index 8966b2a1f..2c6a6d084 100644 --- a/src/cmd/ld/go.c +++ b/src/cmd/ld/go.c @@ -148,8 +148,6 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)  		}  		if(strcmp(pkg, "main") == 0 && strcmp(name, "main") != 0)  			fprint(2, "%s: %s: not package main (package %s)\n", argv0, filename, name); -		else if(strcmp(pkg, "main") != 0 && strcmp(name, "main") == 0) -			fprint(2, "%s: %s: importing %s, found package main", argv0, filename, pkg);  		loadpkgdata(filename, pkg, p0, p1 - p0);  	} diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index b1a62f25e..c144d4295 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -378,10 +378,9 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)  	int n, c1, c2, c3, c4;  	uint32 magic;  	vlong import0, import1, eof; -	char src[1024]; +	char *t;  	eof = Boffset(f) + len; -	src[0] = '\0';  	pn = strdup(pn); @@ -415,22 +414,34 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)  	line = Brdline(f, '\n');  	if(line == nil) {  		if(Blinelen(f) > 0) { -			diag("%s: malformed object file", pn); +			diag("%s: not an object file", pn);  			return;  		}  		goto eof;  	}  	n = Blinelen(f) - 1; -	if(n != strlen(thestring) || strncmp(line, thestring, n) != 0) { -		if(line) -			line[n] = '\0'; +	line[n] = '\0'; +	if(strncmp(line, "go object ", 10) != 0) {  		if(strlen(pn) > 3 && strcmp(pn+strlen(pn)-3, ".go") == 0) {  			print("%cl: input %s is not .%c file (use %cg to compile .go files)\n", thechar, pn, thechar, thechar);  			errorexit();  		} -		diag("file not %s [%s]\n", thestring, line); +		if(strcmp(line, thestring) == 0) { +			// old header format: just $GOOS +			diag("%s: stale object file", pn); +			return; +		} +		diag("%s: not an object file", pn); +		return; +	} +	t = smprint("%s %s %s", getgoos(), thestring, getgoversion()); +	if(strcmp(line+10, t) != 0) { +		diag("%s: object is [%s] expected [%s]", pn, line+10, t); +		free(t);  		return;  	} +	free(t); +	line[n] = '\n';  	/* skip over exports and other info -- ends with \n!\n */  	import0 = Boffset(f); diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 4ac5d37f9..16dfb0dc3 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -156,6 +156,7 @@ vlong	adduint8(Sym*, uint8);  vlong	adduint16(Sym*, uint16);  void	asmsym(void);  void	asmelfsym64(void); +void	asmplan9sym(void);  void	strnput(char*, int);  void	dodata(void);  void	address(void); diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c index 26e4def64..22777b6b5 100644 --- a/src/cmd/ld/symtab.c +++ b/src/cmd/ld/symtab.c @@ -136,6 +136,62 @@ asmelfsym32(void)  	genasmsym(putelfsym32);  } +void +putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) +{ +	int i; +		 +	switch(t) { +	case 'T': +	case 't': +	case 'L': +	case 'l': +	case 'D': +	case 'd': +	case 'B': +	case 'b': +	case 'a': +	case 'p': +	 +	case 'f': +	case 'z': +	case 'Z': +		 +	case 'm': +		lputb(addr); +		cput(t+0x80); /* 0x80 is variable length */ +		 +		if(t == 'z' || t == 'Z') { +			cput(0); +			for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { +				cput(s[i]); +				cput(s[i+1]); +			} +			cput(0); +			cput(0); +			i++; +		} else { +			/* skip the '<' in filenames */ +			if(t=='f') +				s++; +			 +			for(i=0; s[i]; i++) +				cput(s[i]); +			cput(0); +		} +		 +		symsize += 4 + 1 + i + 1; +		break; +	default: +		return; +	};	 +} + +void +asmplan9sym(void) +{ +	genasmsym(putplan9sym); +}  static Sym *symt; @@ -165,6 +221,52 @@ slputb(int32 v)  }  void +wputl(ushort w) +{ +	cput(w); +	cput(w>>8); +} + +void +wputb(ushort w) +{ +	cput(w>>8); +	cput(w); +} + +void +lputb(int32 l) +{ +	cput(l>>24); +	cput(l>>16); +	cput(l>>8); +	cput(l); +} + +void +lputl(int32 l) +{ +	cput(l); +	cput(l>>8); +	cput(l>>16); +	cput(l>>24); +} + +void +vputb(uint64 v) +{ +	lputb(v>>32); +	lputb(v); +} + +void +vputl(uint64 v) +{ +	lputl(v); +	lputl(v >> 32); +} + +void  putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)  {  	int i, f, l; | 
