Browse Source

Plan 9 from Bell Labs 2012-03-08

David du Colombier 12 years ago
parent
commit
c315ecf8a5

+ 0 - 7
sys/man/1/2c

@@ -488,13 +488,6 @@ are implemented.
 No new features of C11, the 2011 ANSI C standard,
 are implemented.
 .PP
-.B switch
-expressions may not be either signedness of
-.B vlong
-on 32-bit architectures
-.RI ( 8c
-at least).
-.PP
 The implementation of
 .B vlong
 assignment can use a static location

+ 1 - 0
sys/src/cmd/6c/txt.c

@@ -23,6 +23,7 @@ ginit(void)
 	tfield = types[TINT];
 
 	typeword = typechlvp;
+	typeswitch = typechlv;
 	typecmplx = typesu;
 
 	/* TO DO */

+ 2 - 2
sys/src/cmd/8c/gc.h

@@ -61,7 +61,7 @@ struct	Prog
 struct	Case
 {
 	Case*	link;
-	long	val;
+	vlong	val;
 	long	label;
 	char	def;
 	char isv;
@@ -70,7 +70,7 @@ struct	Case
 
 struct	C1
 {
-	long	val;
+	vlong	val;
 	long	label;
 };
 

+ 3 - 3
sys/src/cmd/8c/swt.c

@@ -10,7 +10,7 @@ swit1(C1 *q, int nc, long def, Node *n)
 	if(nc < 5) {
 		for(i=0; i<nc; i++) {
 			if(debug['W'])
-				print("case = %.8lux\n", q->val);
+				print("case = %.8llux\n", q->val);
 			gopcode(OEQ, n->type, n, nodconst(q->val));
 			patch(p, q->label);
 			q++;
@@ -22,7 +22,7 @@ swit1(C1 *q, int nc, long def, Node *n)
 	i = nc / 2;
 	r = q+i;
 	if(debug['W'])
-		print("case > %.8lux\n", r->val);
+		print("case > %.8llux\n", r->val);
 	gopcode(OGT, n->type, n, nodconst(r->val));
 	sp = p;
 	gbranch(OGOTO);
@@ -31,7 +31,7 @@ swit1(C1 *q, int nc, long def, Node *n)
 	swit1(q, i, def, n);
 
 	if(debug['W'])
-		print("case < %.8lux\n", r->val);
+		print("case < %.8llux\n", r->val);
 	patch(sp, pc);
 	swit1(r+1, nc-i-1, def, n);
 }

+ 34 - 12
sys/src/cmd/8c/txt.c

@@ -22,6 +22,8 @@ ginit(void)
 	lastp = P;
 	tfield = types[TLONG];
 
+	typeswitch = typechlv;
+
 	zprog.link = P;
 	zprog.as = AGOK;
 	zprog.from.type = D_NONE;
@@ -314,9 +316,29 @@ abort();
 
 	case TFLOAT:
 	case TDOUBLE:
-	case TVLONG:
 		i = D_F0;
 		goto out;
+
+	case TVLONG:
+	case TUVLONG:
+		n->op = OREGPAIR;
+		n->complex = 0; /* already in registers */
+		n->addable = 11;
+		n->type = tn->type;
+		n->lineno = nearln;
+		n->left = alloc(sizeof(Node));
+		n->right = alloc(sizeof(Node));
+		if(o != Z && o->op == OREGPAIR) {
+			regalloc(n->left, &regnode, o->left);
+			regalloc(n->right, &regnode, o->right);
+		} else {
+			regalloc(n->left, &regnode, Z);
+			regalloc(n->right, &regnode, Z);
+		}
+		n->right->type = types[TULONG];
+		if(tn->type->etype == TUVLONG)
+			n->left->type = types[TULONG];
+		return;
 	}
 	diag(tn, "unknown type in regalloc: %T", tn->type);
 err:
@@ -343,6 +365,12 @@ regfree(Node *n)
 {
 	int i;
 
+	if(n->op == OREGPAIR) {
+		regfree(n->left);
+		regfree(n->right);
+		return;
+	}
+
 	i = 0;
 	if(n->op != OREGISTER && n->op != OINDREG)
 		goto err;
@@ -618,9 +646,6 @@ gmove(Node *f, Node *t)
 	case TDOUBLE:
 		gins(AFMOVD, f, t);
 		return;
-	case TVLONG:
-		gins(AFMOVV, f, t);
-		return;
 	}
 
 /*
@@ -659,9 +684,6 @@ gmove(Node *f, Node *t)
 	case TDOUBLE:
 		gins(AFMOVDP, f, t);
 		return;
-	case TVLONG:
-		gins(AFMOVVP, f, t);
-		return;
 	}
 
 /*
@@ -989,7 +1011,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
 		if(et == TFLOAT)
 			a = AFADDF;
 		else
-		if(et == TDOUBLE || et == TVLONG) {
+		if(et == TDOUBLE) {
 			a = AFADDD;
 			if(pop)
 				a = AFADDDP;
@@ -1003,7 +1025,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
 			if(rev)
 				a = AFSUBRF;
 		} else
-		if(et == TDOUBLE || et == TVLONG) {
+		if(et == TDOUBLE) {
 			a = AFSUBD;
 			if(pop)
 				a = AFSUBDP;
@@ -1020,7 +1042,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
 		if(et == TFLOAT)
 			a = AFMULF;
 		else
-		if(et == TDOUBLE || et == TVLONG) {
+		if(et == TDOUBLE) {
 			a = AFMULD;
 			if(pop)
 				a = AFMULDP;
@@ -1036,7 +1058,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
 			if(rev)
 				a = AFDIVRF;
 		} else
-		if(et == TDOUBLE || et == TVLONG) {
+		if(et == TDOUBLE) {
 			a = AFDIVD;
 			if(pop)
 				a = AFDIVDP;
@@ -1063,7 +1085,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
 					a = AGOK;
 			}
 		} else
-		if(et == TDOUBLE || et == TVLONG) {
+		if(et == TDOUBLE) {
 			a = AFCOMF;
 			if(pop) {
 				a = AFCOMDP;

+ 1 - 0
sys/src/cmd/cc/cc.h

@@ -509,6 +509,7 @@ extern	char	typechlvp[];
 extern	char	typechlp[];
 extern	char	typechlpfd[];
 
+EXTERN	char*	typeswitch;
 EXTERN	char*	typeword;
 EXTERN	char*	typecmplx;
 

+ 14 - 11
sys/src/cmd/cc/pgen.c

@@ -70,8 +70,12 @@ codgen(Node *n, Node *nn)
 	canreach = 1;
 	warnreach = 1;
 	gen(n);
-	if(canreach && thisfn->link->etype != TVOID)
-		warn(Z, "no return at end of function: %s", n1->sym->name);
+	if(canreach && thisfn->link->etype != TVOID){
+		if(debug['B'])
+			warn(Z, "no return at end of function: %s", n1->sym->name);
+		else
+			diag(Z, "no return at end of function: %s", n1->sym->name);
+	}
 	noretval(3);
 	gbranch(ORETURN);
 
@@ -267,16 +271,15 @@ loop:
 		complex(l);
 		if(l->type == T)
 			goto rloop;
-		if(l->op == OCONST)
-		if(typeword[l->type->etype] && l->type->etype != TIND) {
-			casf();
-			cases->val = l->vconst;
-			cases->def = 0;
-			cases->label = pc;
-			cases->isv = typev[l->type->etype];
+		if(l->op != OCONST || !typeswitch[l->type->etype]) {
+			diag(n, "case expression must be integer constant");
 			goto rloop;
 		}
-		diag(n, "case expression must be integer constant");
+		casf();
+		cases->val = l->vconst;
+		cases->def = 0;
+		cases->label = pc;
+		cases->isv = typev[l->type->etype];
 		goto rloop;
 
 	case OSWITCH:
@@ -284,7 +287,7 @@ loop:
 		complex(l);
 		if(l->type == T)
 			break;
-		if(!typeword[l->type->etype] || l->type->etype == TIND) {
+		if(!typeswitch[l->type->etype]) {
 			diag(n, "switch expression must be integer");
 			break;
 		}

+ 58 - 4
sys/src/cmd/cc/pswt.c

@@ -16,8 +16,10 @@ void
 doswit(Node *n)
 {
 	Case *c;
-	C1 *q, *iq;
-	long def, nc, i, isv;
+	C1 *q, *iq, *iqh, *iql;
+	long def, nc, i, j, isv, nh;
+	Prog *hsb;
+	Node *vr[2];
 	int dup;
 
 	def = 0;
@@ -33,14 +35,20 @@ doswit(Node *n)
 		isv |= c->isv;
 		nc++;
 	}
-	if(isv && !typev[n->type->etype])
+	if(typev[n->type->etype])
+		isv = 1;
+	else if(isv){
 		warn(n, "32-bit switch expression with 64-bit case constant");
+		isv = 0;
+	}
 
 	iq = alloc(nc*sizeof(C1));
 	q = iq;
 	for(c = cases; c->link != C; c = c->link) {
 		if(c->def)
 			continue;
+		if(c->isv && !isv)
+			continue;	/* can never match */
 		q->label = c->label;
 		if(isv)
 			q->val = c->val;
@@ -64,7 +72,53 @@ doswit(Node *n)
 		def = breakpc;
 		nbreak++;
 	}
-	swit1(iq, nc, def, n);
+	if(!isv || ewidth[TIND] > ewidth[TLONG] || n->op == OREGISTER) {
+		swit1(iq, nc, def, n);
+		return;
+	}
+
+	/*
+	 * 64-bit case on 32-bit machine:
+	 * switch on high-order words, and
+	 * in each of those, switch on low-order words
+	 */
+	if(n->op != OREGPAIR)
+		fatal(n, "internal: expected register pair");
+	if(thechar == '8'){	/* TO DO: need an enquiry function */
+		vr[0] = n->left;	/* low */
+		vr[1] = n->right;	/* high */
+	}else{
+		vr[0] = n->right;
+		vr[1] = n->left;
+	}
+	vr[0]->type = types[TLONG];
+	vr[1]->type = types[TLONG];
+	gbranch(OGOTO);
+	hsb = p;
+	iqh = alloc(nc*sizeof(C1));
+	iql = alloc(nc*sizeof(C1));
+	nh = 0;
+	for(i=0; i<nc;){
+		iqh[nh].val = iq[i].val >> 32;
+		q = iql;
+		/* iq is sorted, so equal top halves are adjacent */
+		for(j = i; j < nc; j++){
+			if((iq[j].val>>32) != iqh[nh].val)
+				break;
+			q->val = (long)iq[j].val;
+			q->label = iq[j].label;
+			q++;
+		}
+		qsort(iql,  q-iql, sizeof(C1), swcmp);
+if(0){for(int k=0; k<(q-iql); k++)print("nh=%ld k=%d h=%#llux l=%#llux lab=%ld\n", nh, k, (vlong)iqh[nh].val,  (vlong)iql[k].val, iql[k].label);}
+		iqh[nh].label = pc;
+		nh++;
+		swit1(iql, q-iql, def, vr[0]);
+		i = j;
+	}
+	patch(hsb, pc);
+if(0){for(int k=0; k<nh; k++)print("k*=%d h=%#llux lab=%ld\n", k, (vlong)iqh[k].val,  iqh[k].label);}
+	swit1(iqh, nh, def, vr[1]);
 }
 
 void

+ 1 - 0
sys/src/cmd/cc/sub.c

@@ -1952,6 +1952,7 @@ tinit(void)
 	
 	/* 32-bit defaults */
 	typeword = typechlp;
+	typeswitch = typechl;
 	typecmplx = typesuv;
 }
 

+ 2 - 2
sys/src/cmd/qc/gc.h

@@ -57,7 +57,7 @@ struct	Prog
 struct	Case
 {
 	Case*	link;
-	long	val;
+	vlong	val;
 	long	label;
 	char	def;
 	char isv;
@@ -66,7 +66,7 @@ struct	Case
 
 struct	C1
 {
-	long	val;
+	vlong	val;
 	long	label;
 };
 

+ 3 - 0
sys/src/cmd/qc/txt.c

@@ -15,6 +15,7 @@ ginit(void)
 	thestring = "power";
 	exregoffset = REGEXT;
 	exfregoffset = FREGEXT;
+	newvlongcode = 1;
 	listinit();
 	nstring = 0;
 	mnstring = 0;
@@ -27,6 +28,8 @@ ginit(void)
 	lastp = P;
 	tfield = types[TLONG];
 
+	typeswitch = typechlv;
+
 	zprog.link = P;
 	zprog.as = AGOK;
 	zprog.reg = NREG;