// CHECK-LABEL: @test1 int test1(int *a, int i) { // CHECK: store i32* %a, i32** [[A_ADDR:%.+]], align // CHECK: [[A:%.+]] = load i32*, i32** [[A_ADDR]] // CHECK: [[CMP:%.+]] = icmp ne i32* [[A]], null // CHECK: call void @llvm.assume(i1 [[CMP]]) // CHECK: [[CALL:%.+]] = call i32 @isconst() // CHECK: [[BOOL:%.+]] = icmp ne i32 [[CALL]], 0 // CHECK: call void @llvm.assume(i1 [[BOOL]]) // CHECK: [[CALLPURE:%.+]] = call i32 @ispure() // CHECK: [[BOOLPURE:%.+]] = icmp ne i32 [[CALLPURE]], 0 // CHECK: call void @llvm.assume(i1 [[BOOLPURE]]) #ifdef _MSC_VER __assume(a != 0) __assume(isconst()); __assume(ispure()); #else __builtin_assume(a != 0); __builtin_assume(isconst()); __builtin_assume(ispure()); #endif // Nothing is generated for an assume with side effects... // CHECK-NOT: load i32*, i32** %i.addr // CHECK-NOT: call void @llvm.assume // CHECK-NOT: call i32 @nonconst() #ifdef _MSC_VER __assume(++i != 0) __assume(nonconst()); #else __builtin_assume(++i != 0); __builtin_assume(nonconst()); #endif return a[0]; }
Tree asgntree(int op, Tree l, Tree r) { Type aty, ty; r = pointer(r); ty = assign(l->type, r); if (ty) r = cast(r, ty); else { typeerror(ASGN, l, r); if (r->type == voidtype) r = retype(r, inttype); ty = r->type; } if (l->op != FIELD) l = lvalue(l); aty = l->type; if (isptr(aty)) aty = unqual(aty)->type; if ( isconst(aty) || isstruct(aty) && unqual(aty)->u.sym->u.s.cfields) if (isaddrop(l->op) && !l->u.sym->computed && !l->u.sym->generated) error("assignment to const identifier `%s'\n", l->u.sym->name); else error("assignment to const location\n"); if (l->op == FIELD) { long n = 8*l->u.field->type->size - fieldsize(l->u.field); if (n > 0 && isunsigned(l->u.field->type)) r = bittree(BAND, r, cnsttree(r->type, (unsigned long)fieldmask(l->u.field))); else if (n > 0) { if (r->op == CNST+I) { n = r->u.v.i; if (n&(1<<(fieldsize(l->u.field)-1))) n |= ~0UL<<fieldsize(l->u.field); r = cnsttree(r->type, n); } else r = shtree(RSH, shtree(LSH, r, cnsttree(inttype, n)), cnsttree(inttype, n)); } } if (isstruct(ty) && isaddrop(l->op) && iscallb(r)) return tree(RIGHT, ty, tree(CALL+B, ty, r->kids[0]->kids[0], l), idtree(l->u.sym)); return tree(mkop(op,ty), ty, l, r); }
static TYPE *enumConst(char *buf, TYPE *tp) { while (isconst(tp) || isvolatile(tp) || isrestrict(tp)) { switch(tp->type) { case bt_const: strcat(buf, tn_const); break; case bt_volatile: strcat(buf, tn_volatile); break; case bt_restrict: /* strcat(buf, tn_restrict); */ break; } tp = tp->btp; } return tp; }
ExtArray ExtArray::deriv(value_t dt) const { if (isconst()) return const_array(0.0); if (data_size_ == 1) { const value_t dx = (last_ - data_.get()[0]) / (2 * dt); value_t* x = new value_t[2]; x[0] = dx; /* left and right finite differences */ x[1] = dx; return ExtArray(shared_owner(x), 0.0, 2); } else { const value_t dt2 = 2 * dt; value_t* x = new value_t[data_size_ + 1]; /* left/right finite difference for edges, otherwise central diff */ x[0] = (data_.get()[1] - data_.get()[0]) / dt; for (size_t i = 1; i < data_size_-1; ++i) x[i] = (data_.get()[i + 1] - data_.get()[i - 1]) / dt2; if (data_size_ >= 3) x[data_size_ - 1] = (last_ - data_.get()[data_size_ - 2]) / dt2; x[data_size_] = (last_ - data_.get()[data_size_-1]) / dt; return ExtArray(shared_owner(x), 0.0, data_size_ + 1); } }
void EiC_showvalue(AR_t * arg) { int t; if(!EiC_interActive || !arg->type) return ; fputc('\t', stdout); t = EiC_gettype(arg->type); if(isconst(arg->type) && t != t_pointer) { outputval(t, &arg->v); fputc('\n', stdout); return; } switch ((t = EiC_gettype(arg->type))) { case t_union: fputs("(Union)",stdout); break; case t_struct: showstruct(arg); break; case t_char: case t_uchar: case t_short: case t_ushort: outputval(t_int, &arg->v.ival); break; case t_float: outputval(t_double, &arg->v.ival); break; case t_array: case t_pointer: if (EiC_gettype(nextType(arg->type)) == t_char) t = STR; else t = t_pointer; default: outputval(t, &arg->v); break; } fputc('\n', stdout); }
Type assign(Type xty, Tree e) { Type yty = unqual(e->type); xty = unqual(xty); if (isenum(xty)) xty = xty->type; if (xty->size == 0 || yty->size == 0) return NULL; if ( isarith(xty) && isarith(yty) || isstruct(xty) && xty == yty) return xty; if (isptr(xty) && isnullptr(e)) return xty; if ((isvoidptr(xty) && isptr(yty) || isptr(xty) && isvoidptr(yty)) && ( (isconst(xty->type) || !isconst(yty->type)) && (isvolatile(xty->type) || !isvolatile(yty->type)))) return xty; if ((isptr(xty) && isptr(yty) && eqtype(unqual(xty->type), unqual(yty->type), 1)) && ( (isconst(xty->type) || !isconst(yty->type)) && (isvolatile(xty->type) || !isvolatile(yty->type)))) return xty; if (isptr(xty) && isptr(yty) && ( (isconst(xty->type) || !isconst(yty->type)) && (isvolatile(xty->type) || !isvolatile(yty->type)))) { Type lty = unqual(xty->type), rty = unqual(yty->type); if (isenum(lty) && rty == inttype || isenum(rty) && lty == inttype) { if (Aflag >= 1) warning("assignment between `%t' and `%t' is compiler-dependent\n", xty, yty); return xty; } } return NULL; }
/* * normal (expression) switch. * rebulid case statements into if .. goto */ static void exprswitch(Node *sw) { Node *def; NodeList *cas; Node *a; Case *c0, *c, *c1; Type *t; int arg, ncase; casebody(sw, N); arg = Snorm; if(isconst(sw->ntest, CTBOOL)) { arg = Strue; if(sw->ntest->val.u.bval == 0) arg = Sfalse; } walkexpr(&sw->ntest, &sw->ninit); t = sw->type; if(t == T) return; /* * convert the switch into OIF statements */ exprname = N; cas = nil; if(arg != Strue && arg != Sfalse) { exprname = temp(sw->ntest->type); cas = list1(nod(OAS, exprname, sw->ntest)); typechecklist(cas, Etop); } else { exprname = nodbool(arg == Strue); } c0 = mkcaselist(sw, arg); if(c0 != C && c0->type == Tdefault) { def = c0->node->right; c0 = c0->link; } else { def = nod(OBREAK, N, N); } loop: if(c0 == C) { cas = list(cas, def); sw->nbody = concat(cas, sw->nbody); sw->list = nil; walkstmtlist(sw->nbody); return; } // deal with the variables one-at-a-time if(!okforcmp[t->etype] || c0->type != Texprconst) { a = exprbsw(c0, 1, arg); cas = list(cas, a); c0 = c0->link; goto loop; } // do binary search on run of constants ncase = 1; for(c=c0; c->link!=C; c=c->link) { if(c->link->type != Texprconst) break; ncase++; } // break the chain at the count c1 = c->link; c->link = C; // sort and compile constants c0 = csort(c0, exprcmp); a = exprbsw(c0, ncase, arg); cas = list(cas, a); c0 = c1; goto loop; }
BOOL comparetypes(TYPE *typ1, TYPE *typ2, int exact) { if (typ1->type == bt_any || typ2->type == bt_any) return TRUE; if (typ1->type == bt_typedef) typ1 = basetype(typ1); if (typ2->type == bt_typedef) typ2 = basetype(typ2); if (isref(typ1)) typ1 = basetype(typ1)->btp; if (isref(typ2)) typ2 = basetype(typ2)->btp; if (ispointer(typ1) && ispointer(typ2)) if (exact) { int arr = FALSE; int first = TRUE; while (ispointer(typ1) && ispointer(typ2)) { if (!first && (exact == 1)) if (isconst(typ2) && !isconst(typ1) || isvolatile(typ2) && !isvolatile(typ1)) return FALSE; first = FALSE; typ1 = basetype(typ1); typ2 = basetype(typ2); if (typ1->type != typ2->type) return FALSE; if (arr && typ1->array != typ2->array) return FALSE; if (arr && typ1->size != typ2->size) return FALSE; arr |= typ1->array | typ2->array; typ1 = typ1->btp; typ2 = typ2->btp; } if ((exact == 1) && (isconst(typ2) && !isconst(typ1) || isvolatile(typ2) && !isvolatile(typ1))) return FALSE; return comparetypes(typ1, typ2, TRUE); } else return TRUE; typ1 = basetype(typ1); typ2 = basetype(typ2); if (exact && (isfunction(typ1) || isfuncptr(typ1)) && (isfunction(typ2) || isfuncptr(typ2))) { HASHREC *hr1; HASHREC *hr2; typ1 = basetype(typ1); typ2 = basetype(typ2); if (ispointer(typ1)) typ1 = basetype(typ1->btp); if (ispointer(typ2)) typ2 = basetype(typ2->btp); if (!comparetypes(typ1->btp, typ2->btp, exact)) return FALSE; hr1 = typ1->syms->table[0]; hr2 = typ2->syms->table[0]; while (hr1 && hr2) { SYMBOL *sp1 = (SYMBOL *)hr1->p; SYMBOL *sp2 = (SYMBOL *)hr2->p; if (!comparetypes(sp1->tp, sp2->tp, exact)) return FALSE; hr1 = hr1->next; hr2 = hr2->next; } if (hr1 || hr2) return FALSE; return TRUE; } if (cparams.prm_cplusplus) { if (typ1->scoped != typ2->scoped) return FALSE; if (typ1->type == bt_enum) { if (typ2->type == bt_enum) return typ1->sp == typ2->sp; else return isint(typ2); } else if (typ2->type == bt_enum) { return isint(typ1); } if (typ1->type == typ2->type && typ1->type == bt_memberptr) { if (typ1->sp != typ2->sp) { if (classRefCount(typ2->sp, typ1->sp) != 1) return FALSE; } return comparetypes(typ1->btp, typ2->btp, exact); } } if (typ1->type == typ2->type && (isstructured(typ1) || exact && typ1->type == bt_enum)) return typ1->sp == typ2->sp; if (typ1->type == typ2->type || !exact && isarithmetic(typ2) && isarithmetic(typ1)) return TRUE; if (isfunction(typ1) && isfunction(typ2) && typ1->sp->linkage == typ2->sp->linkage) return TRUE; else if (!exact && (ispointer(typ1) && (isfuncptr(typ2) || isfunction(typ2) || isint(typ2)) || ispointer(typ2) && (isfuncptr(typ1) || isfunction(typ1) || isint(typ1)))) return (TRUE); else if (typ1->type == bt_enum && isint(typ2)) { return TRUE; } else if (typ2->type == bt_enum && isint(typ1)) { return TRUE; } return FALSE; }
/* List a variable */ void list_var(SYMBOL *sp, int i) { int j; long val; if (!cparams.prm_listfile) return ; if (sp->dontlist) return; if (sp->tp->type == bt_aggregate) { HASHREC *hr = sp->tp->syms->table[0]; while (hr) { sp = (SYMBOL *)hr->p; list_var(sp, 0); hr = hr->next; } return ; } for (j = i; j; --j) fprintf(listFile, " "); if (sp->storage_class == sc_auto && !sp->regmode) val = (long)getautoval(sp->offset); else val = sp->value.u; fprintf(listFile,"Identifier: %s\n ", unmangledname(sp->name)); for (j = i; j; --j) fprintf(listFile, " "); if (sp->regmode == 1) { fprintf(listFile,"Register: %-3s& ",lookupRegName((-sp->offset) & 255)); } else if (sp->regmode == 2) { fprintf(listFile,"Register: %-3s ",lookupRegName((-sp->offset) & 255)); } else fprintf(listFile,"Offset: %08lX ", val); fprintf(listFile,"Storage: "); if (sp->tp->type == bt_ifunc) if (sp->isInline && !sp->noinline) fprintf(listFile,"%-7s","inline"); else fprintf(listFile,"%-7s","code"); else if (sp->storage_class == sc_auto) if (sp->regmode) fprintf(listFile,"%-7s","reg"); else fprintf(listFile,"%-7s","stack"); else if (sp->storage_class == sc_global || sp->storage_class == sc_static || sp->storage_class == sc_localstatic) if (isconst(sp->tp)) fprintf(listFile,"%-7s","const"); else if (sp->init) fprintf(listFile,"%-7s","data"); else fprintf(listFile,"%-7s","bss"); else if (sp->storage_class == sc_constant || sp->storage_class == sc_enumconstant) fprintf(listFile,"%-7s","constant"); else fprintf(listFile,"%-7s","none"); put_sc(sp->storage_class); put_ty(sp->tp); fprintf(listFile, "\n"); if (sp->tp == 0) return ; if (isstructured(sp->tp) && sp->storage_class == sc_type) list_table(sp->tp->syms, i + 1); }
/* * emittype - emit ty's type number, emitting its definition if necessary. * Returns the output column number after emission; col is the approximate * output column before emission and is used to emit continuation lines for long * struct, union, and enum types. Continuations are not emitted for other types, * even if the definition is long. lev is the depth of calls to emittype. */ static int emittype(Type ty, int lev, int col) { int tc = ty->x.typeno; if (isconst(ty) || isvolatile(ty)) { col = emittype(ty->type, lev, col); ty->x.typeno = ty->type->x.typeno; ty->x.printed = 1; return col; } if (tc == 0) { ty->x.typeno = tc = ++ntypes; /* fprint(2,"`%t'=%d\n", ty, tc); */ } print("%d", tc), col += 3; if (ty->x.printed) return col; ty->x.printed = 1; switch (ty->op) { case VOID: /* void is defined as itself */ print("=%d", tc), col += 1+3; break; case INT: if (ty == chartype) /* plain char is a subrange of itself */ print("=r%d;%d;%d;", tc, ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i), col += 2+3+2*2.408*ty->size+2; else /* other signed ints are subranges of int */ print("=r1;%D;%D;", ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i), col += 4+2*2.408*ty->size+2; break; case UNSIGNED: if (ty == chartype) /* plain char is a subrange of itself */ print("=r%d;0;%u;", tc, ty->u.sym->u.limits.max.i), col += 2+3+2+2.408*ty->size+1; else /* other signed ints are subranges of int */ print("=r1;0;%U;", ty->u.sym->u.limits.max.i), col += 4+2.408*ty->size+1; break; case FLOAT: /* float, double, long double get sizes, not ranges */ print("=r1;%d;0;", ty->size), col += 4+1+3; break; case POINTER: print("=*"), col += 2; col = emittype(ty->type, lev + 1, col); break; case FUNCTION: print("=f"), col += 2; col = emittype(ty->type, lev + 1, col); break; case ARRAY: /* array includes subscript as an int range */ if (ty->size && ty->type->size) print("=ar1;0;%d;", ty->size/ty->type->size - 1), col += 7+3+1; else print("=ar1;0;-1;"), col += 10; col = emittype(ty->type, lev + 1, col); break; case STRUCT: case UNION: { Field p; if (!ty->u.sym->defined) { print("=x%c%s:", ty->op == STRUCT ? 's' : 'u', ty->u.sym->name); col += 2+1+strlen(ty->u.sym->name)+1; break; } if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) { ty->x.printed = 0; break; } print("=%c%d", ty->op == STRUCT ? 's' : 'u', ty->size), col += 1+1+3; for (p = fieldlist(ty); p; p = p->link) { if (p->name) print("%s:", p->name), col += strlen(p->name)+1; else print(":"), col += 1; col = emittype(p->type, lev + 1, col); if (p->lsb) print(",%d,%d;", 8*p->offset + (IR->little_endian ? fieldright(p) : fieldleft(p)), fieldsize(p)); else print(",%d,%d;", 8*p->offset, 8*p->type->size); col += 1+3+1+3+1; /* accounts for ,%d,%d; */ if (col >= 80 && p->link) { print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM); col = 8; } } print(";"), col += 1; break; } case ENUM: { Symbol *p; if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) { ty->x.printed = 0; break; } print("=e"), col += 2; for (p = ty->u.sym->u.idlist; *p; p++) { print("%s:%d,", (*p)->name, (*p)->u.value), col += strlen((*p)->name)+3; if (col >= 80 && p[1]) { print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM); col = 8; } } print(";"), col += 1; break; } default: assert(0); } return col; }
static void EiC_showdectype(type_expr * t, int expand, FILE *fp) { struct_t *S; int i; static int level = 0; while (t) { if(isconst(t) || isconstp(t)) fputs("const ",fp); switch (EiC_gettype(t)) { case t_var: fputs("...", fp); break; case t_enum: fputs("enum ", fp); break; case t_char: fputs("char ", fp); break; case t_uchar: fputs("unsigned char ", fp); break; case t_short: fputs("short ", fp); break; case t_ushort:fputs("unsigned short ", fp); break; case t_int: fputs("int ", fp); break; case t_uint: fputs("unsigned ", fp); break; case t_long: fputs("long int ", fp); break; case t_ulong: fputs("unsigned long int ", fp); break; case t_llong: fputs("long long ",fp); break; case t_float: fputs("float ", fp); break; case t_double:fputs("double ", fp); break; case t_pointer: if(isunsafe(t)) fputs("unsafe ", fp); /*else if(issafe(t)) fputs("safe ", fp);*/ fputs("* ", fp); break; case t_void: fputs("void ", fp); break; case t_hidden: fputs("hidden ",fp); break; case t_funcdec: fputs("dec_", fp); showFunc(&t,fp); break; case t_func: showFunc(&t,fp); break; case t_builtin: fputs("Builtin ",fp); showFunc(&t,fp); break; case t_array: fprintf(fp,"ARY[%d]",(int) EiC_getInf(t)); break; case t_union: case t_struct: S = EiC_getInf(t); if(!S) { fputs("Incomplete", fp); break; } if (EiC_gettype(t) == t_struct) fprintf(fp,"struct: size %u bytes",S->tsize); else fprintf(fp,"union: size %u bytes",S->tsize); if (expand) { level++; fputc('\n', fp); if (level <= 2) { int j; for (i = 0; i < S->n; i++) { for (j = 0; j < level; j++) fputc('\t', fp); fputs(S->id[i], fp); fputs(" -> ", fp); EiC_showdectype(S->type[i], expand,fp); fputc('\n', fp); } } level--; } break; case t_ref: fputs("Reference ",fp);break; case ID: fputs("Identifier ", fp); break; default: fputs("Uknown identifier", fp); return; } t = nextType(t); } }
char *mangleType (char *in, TYPE *tp, BOOLEAN first) { char nm[4096]; int i; HASHREC *hr ; if(!tp) { sprintf(in, "%d%s", strlen("initializer-list"), "initializer-list"); in += strlen(in); } else if (tp->type == bt_typedef) { in = mangleType(in, tp->btp, FALSE); } else if (isstructured(tp) && basetype(tp)->sp->templateLevel) { { if (isconst(tp)) *in++ = 'x'; if (isvolatile(tp)) *in++ = 'y'; if (islrqual(tp)) *in++ = 'r'; if (isrrqual(tp)) *in++ = 'R'; } in = mangleTemplate(in, basetype(tp)->sp, basetype(tp)->sp->templateParams); } else { // if (ispointer(tp) || isref(tp)) // { // if (basetype(tp)->btp) // { // if (isconst(basetype(tp)->btp)) // *in++ = 'x'; // if (isvolatile(basetype(tp)->btp)) // *in++ = 'y'; // } // } // if (isfunction(tp)) { if (isconst(tp)) *in++ = 'x'; if (isvolatile(tp)) *in++ = 'y'; if (islrqual(tp)) *in++ = 'r'; if (isrrqual(tp)) *in++ = 'R'; } tp = basetype(tp); switch (tp->type) { /* case bt_templateplaceholder: tplPlaceholder(nm, tp->lst.head->name, tp->lst.tail); sprintf(buf, "%d%s", strlen(nm), nm); buf += strlen(buf); break; */ case bt_func: case bt_ifunc: if (basetype(tp)->sp && basetype(tp)->sp->parentClass && !first) { *in++ = 'M'; in = getName(in, tp->sp->parentClass); in += strlen(in); } *in++ = 'q'; hr = tp->syms->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; if (!sp->thisPtr) in = mangleType(in, sp->tp, TRUE); hr = hr->next ; } *in++ = '$'; // return value in = mangleType(in, tp->btp, TRUE); break; case bt_memberptr: *in++ = 'M'; in = getName(in, tp->sp); if (isfunction(tp->btp)) { *in++ = 'q'; hr = basetype(tp->btp)->syms->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; if (!sp->thisPtr) in = mangleType(in, sp->tp, TRUE); hr = hr->next ; } *in++ = '$'; in = mangleType (in, tp->btp->btp, TRUE); } else { *in++ = '$'; in = mangleType (in, basetype(tp)->btp, TRUE); } break; case bt_enum: case bt_struct: case bt_union: case bt_class: in = getName(in, tp->sp); break; case bt_bool: in = lookupName(in, "bool"); in += strlen(in); break; case bt_unsigned_short: *in++ = 'u'; case bt_short: *in++ = 's'; break; case bt_unsigned: *in++ = 'u'; case bt_int: *in++ = 'i'; break; case bt_char16_t: *in++ = 'h'; break; case bt_char32_t: *in++ = 'H'; break; case bt_unsigned_long: *in++ = 'u'; case bt_long: *in++ = 'l'; break; case bt_unsigned_long_long: *in++ = 'u'; case bt_long_long: *in++ = 'L'; break; case bt_unsigned_char: *in++ = 'u'; case bt_char: *in++ = 'c'; break; case bt_signed_char: *in++ = 'S'; *in++ = 'c'; break; case bt_wchar_t: *in++ = 'C'; break; case bt_float_complex: *in++ = 'F'; break; case bt_double_complex: *in++ = 'D'; break; case bt_long_double_complex: *in++ = 'G'; break; case bt_float: *in++ = 'f'; break; case bt_double: *in++ = 'd'; break; case bt_long_double: *in++ = 'g'; break; case bt_pointer: if (tp->nullptrType) { in = lookupName(in, "nullptr_t"); in += strlen(in); } else { if (first|| !tp->array) { *in++ = 'p'; } else { sprintf(in,"A%ld",tp->btp->size ? tp->size / tp->btp->size : 0); in += strlen(in); } in = mangleType(in, tp->btp, FALSE); } break; case bt_far: *in++ = 'P'; in = mangleType(in, tp->btp, FALSE); break; case bt_lref: *in++ = 'r'; in = mangleType(in, tp->btp, FALSE); break; case bt_rref: *in++ = 'R'; in = mangleType(in, tp->btp, FALSE); break; case bt_ellipse: *in++ = 'e'; break; case bt_void: case bt_any: *in++ = 'v'; break; case bt_templateparam: in = getName(in, tp->templateParam->p->sym); break; case bt_templateselector: { TEMPLATESELECTOR *s = tp->sp->templateSelector; char *p; s = s->next; if (s->isTemplate) p = mangleTemplate(nm, s->sym, s->templateParams); else p = getName(nm, s->sym); p[0] =0; if (strlen(nm) > sizeof(nm)) p = mangleTemplate(nm, s->sym, s->templateParams); s = s->next ; while (s) { strcat(nm , "@"); strcat(nm , s->name); s= s->next; } p = nm; while (isdigit(*p)) p++; sprintf(in, "%d%s", strlen(p), p); in += strlen(in); } break; case bt_templatedecltype: // the index is being used to make names unique so two decltypes won't collide when storing them // in a symbol table... declTypeIndex = (declTypeIndex + 1) %1000; *in++ = 'E'; sprintf(in, "%03d", declTypeIndex); in += 3; break; case bt_aggregate: in = getName(in, tp->sp); break; default: diag("mangleType: unknown type"); break; } } *in= 0; return in; }
/* * generate: * res = &n; */ void agen(Node *n, Node *res) { Node *nl, *nr; Node n1, n2, n3, tmp, n4; Prog *p1; uint32 w; uint64 v; Type *t; if(debug['g']) { dump("\nagen-res", res); dump("agen-r", n); } if(n == N || n->type == T) return; if(!isptr[res->type->etype]) fatal("agen: not tptr: %T", res->type); while(n->op == OCONVNOP) n = n->left; if(n->addable) { regalloc(&n1, types[tptr], res); gins(ALEAQ, n, &n1); gmove(&n1, res); regfree(&n1); goto ret; } nl = n->left; nr = n->right; switch(n->op) { default: fatal("agen: unknown op %N", n); break; case OCALLMETH: cgen_callmeth(n, 0); cgen_aret(n, res); break; case OCALLINTER: cgen_callinter(n, res, 0); cgen_aret(n, res); break; case OCALLFUNC: cgen_call(n, 0); cgen_aret(n, res); break; case OINDEX: w = n->type->width; if(nr->addable) goto irad; if(nl->addable) { if(!isconst(nr, CTINT)) { regalloc(&n1, nr->type, N); cgen(nr, &n1); } regalloc(&n3, types[tptr], res); agen(nl, &n3); goto index; } tempname(&tmp, nr->type); cgen(nr, &tmp); nr = &tmp; irad: regalloc(&n3, types[tptr], res); agen(nl, &n3); if(!isconst(nr, CTINT)) { regalloc(&n1, nr->type, N); cgen(nr, &n1); } goto index; index: // &a is in &n3 (allocated in res) // i is in &n1 (if not constant) // w is width // explicit check for nil if array is large enough // that we might derive too big a pointer. if(!isslice(nl->type) && nl->type->width >= unmappedzero) { regalloc(&n4, types[tptr], &n3); gmove(&n3, &n4); n4.op = OINDREG; n4.type = types[TUINT8]; n4.xoffset = 0; gins(ATESTB, nodintconst(0), &n4); regfree(&n4); } if(w == 0) fatal("index is zero width"); // constant index if(isconst(nr, CTINT)) { v = mpgetfix(nr->val.u.xval); if(isslice(nl->type)) { if(!debug['B'] && !n->etype) { n1 = n3; n1.op = OINDREG; n1.type = types[tptr]; n1.xoffset = Array_nel; nodconst(&n2, types[TUINT64], v); gins(optoas(OCMP, types[TUINT32]), &n1, &n2); p1 = gbranch(optoas(OGT, types[TUINT32]), T); ginscall(throwindex, 0); patch(p1, pc); } n1 = n3; n1.op = OINDREG; n1.type = types[tptr]; n1.xoffset = Array_array; gmove(&n1, &n3); } else if(!debug['B'] && !n->etype) { if(v < 0) yyerror("out of bounds on array"); else if(v >= nl->type->bound) yyerror("out of bounds on array"); } nodconst(&n2, types[tptr], v*w); gins(optoas(OADD, types[tptr]), &n2, &n3); gmove(&n3, res); regfree(&n3); break; } // type of the index t = types[TUINT64]; if(issigned[n1.type->etype]) t = types[TINT64]; regalloc(&n2, t, &n1); // i gmove(&n1, &n2); regfree(&n1); if(!debug['B'] && !n->etype) { // check bounds if(isslice(nl->type)) { n1 = n3; n1.op = OINDREG; n1.type = types[tptr]; n1.xoffset = Array_nel; } else nodconst(&n1, types[TUINT64], nl->type->bound); gins(optoas(OCMP, types[TUINT32]), &n2, &n1); p1 = gbranch(optoas(OLT, types[TUINT32]), T); ginscall(throwindex, 0); patch(p1, pc); } if(isslice(nl->type)) { n1 = n3; n1.op = OINDREG; n1.type = types[tptr]; n1.xoffset = Array_array; gmove(&n1, &n3); } if(w == 1 || w == 2 || w == 4 || w == 8) { p1 = gins(ALEAQ, &n2, &n3); p1->from.scale = w; p1->from.index = p1->from.type; p1->from.type = p1->to.type + D_INDIR; } else { nodconst(&n1, t, w); gins(optoas(OMUL, t), &n1, &n2); gins(optoas(OADD, types[tptr]), &n2, &n3); gmove(&n3, res); } gmove(&n3, res); regfree(&n2); regfree(&n3); break; case ONAME: // should only get here with names in this func. if(n->funcdepth > 0 && n->funcdepth != funcdepth) { dump("bad agen", n); fatal("agen: bad ONAME funcdepth %d != %d", n->funcdepth, funcdepth); } // should only get here for heap vars or paramref if(!(n->class & PHEAP) && n->class != PPARAMREF) { dump("bad agen", n); fatal("agen: bad ONAME class %#x", n->class); } cgen(n->heapaddr, res); if(n->xoffset != 0) { nodconst(&n1, types[TINT64], n->xoffset); gins(optoas(OADD, types[tptr]), &n1, res); } break; case OIND: cgen(nl, res); break; case ODOT: agen(nl, res); if(n->xoffset != 0) { nodconst(&n1, types[TINT64], n->xoffset); gins(optoas(OADD, types[tptr]), &n1, res); } break; case ODOTPTR: cgen(nl, res); if(n->xoffset != 0) { // explicit check for nil if struct is large enough // that we might derive too big a pointer. if(nl->type->type->width >= unmappedzero) { regalloc(&n1, types[tptr], res); gmove(res, &n1); n1.op = OINDREG; n1.type = types[TUINT8]; n1.xoffset = 0; gins(ATESTB, nodintconst(0), &n1); regfree(&n1); } nodconst(&n1, types[TINT64], n->xoffset); gins(optoas(OADD, types[tptr]), &n1, res); } break; } ret: ; }
/* * type check switch statement */ void typecheckswitch(Node *n) { int top, lno, ptr; char *nilonly; Type *t, *badtype, *missing, *have; NodeList *l, *ll; Node *ncase, *nvar; Node *def; lno = lineno; typechecklist(n->ninit, Etop); nilonly = nil; if(n->ntest != N && n->ntest->op == OTYPESW) { // type switch top = Etype; typecheck(&n->ntest->right, Erv); t = n->ntest->right->type; if(t != T && t->etype != TINTER) yyerror("cannot type switch on non-interface value %lN", n->ntest->right); } else { // value switch top = Erv; if(n->ntest) { typecheck(&n->ntest, Erv); defaultlit(&n->ntest, T); t = n->ntest->type; } else t = types[TBOOL]; if(t) { if(!okforeq[t->etype]) yyerror("cannot switch on %lN", n->ntest); else if(t->etype == TARRAY && !isfixedarray(t)) nilonly = "slice"; else if(t->etype == TARRAY && isfixedarray(t) && algtype1(t, nil) == ANOEQ) yyerror("cannot switch on %lN", n->ntest); else if(t->etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ) yyerror("cannot switch on %lN (struct containing %T cannot be compared)", n->ntest, badtype); else if(t->etype == TFUNC) nilonly = "func"; else if(t->etype == TMAP) nilonly = "map"; } } n->type = t; def = N; for(l=n->list; l; l=l->next) { ncase = l->n; setlineno(n); if(ncase->list == nil) { // default if(def != N) yyerror("multiple defaults in switch (first at %L)", def->lineno); else def = ncase; } else { for(ll=ncase->list; ll; ll=ll->next) { setlineno(ll->n); typecheck(&ll->n, Erv | Etype); if(ll->n->type == T || t == T) continue; setlineno(ncase); switch(top) { case Erv: // expression switch defaultlit(&ll->n, t); if(ll->n->op == OTYPE) yyerror("type %T is not an expression", ll->n->type); else if(ll->n->type != T && !assignop(ll->n->type, t, nil) && !assignop(t, ll->n->type, nil)) { if(n->ntest) yyerror("invalid case %N in switch on %N (mismatched types %T and %T)", ll->n, n->ntest, ll->n->type, t); else yyerror("invalid case %N in switch (mismatched types %T and bool)", ll->n, ll->n->type); } else if(nilonly && !isconst(ll->n, CTNIL)) { yyerror("invalid case %N in switch (can only compare %s %N to nil)", ll->n, nilonly, n->ntest); } break; case Etype: // type switch if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) { ; } else if(ll->n->op != OTYPE && ll->n->type != T) { // should this be ||? yyerror("%lN is not a type", ll->n); // reset to original type ll->n = n->ntest->right; } else if(ll->n->type->etype != TINTER && t->etype == TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) { if(have && !missing->broke && !have->broke) yyerror("impossible type switch case: %lN cannot have dynamic type %T" " (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT", n->ntest->right, ll->n->type, missing->sym, have->sym, have->type, missing->sym, missing->type); else if(!missing->broke) yyerror("impossible type switch case: %lN cannot have dynamic type %T" " (missing %S method)", n->ntest->right, ll->n->type, missing->sym); } break; } } } if(top == Etype && n->type != T) { ll = ncase->list; nvar = ncase->nname; if(nvar != N) { if(ll && ll->next == nil && ll->n->type != T && !istype(ll->n->type, TNIL)) { // single entry type switch nvar->ntype = typenod(ll->n->type); } else { // multiple entry type switch or default nvar->ntype = typenod(n->type); } } } typechecklist(ncase->nbody, Etop); } lineno = lno; }
static void *uid2type(int uid) { assert(uid >= 0 && uid < nuids); if (itemmap[uid] == NULL) { Type ty; rcc_type_ty type = (void *)items[uid]; assert(items[uid]); assert(items[uid]->uid == uid); assert(items[uid]->kind == rcc_Type_enum); type = items[uid]->v.rcc_Type.type; assert(type); switch (type->kind) { case rcc_INT_enum: ty = btot(INT, type->size); assert(ty->align == type->align); break; case rcc_UNSIGNED_enum: ty = btot(UNSIGNED, type->size); assert(ty->align == type->align); break; case rcc_FLOAT_enum: ty = btot(FLOAT, type->size); assert(ty->align == type->align); break; case rcc_VOID_enum: ty = voidtype; break; case rcc_POINTER_enum: ty = ptr(uid2type(type->v.rcc_POINTER.type)); break; case rcc_ARRAY_enum: ty = uid2type(type->v.rcc_ARRAY.type); assert(ty->size > 0); ty = array(ty, type->size/ty->size, 0); break; case rcc_CONST_enum: ty = qual(CONST, uid2type(type->v.rcc_CONST.type)); break; case rcc_VOLATILE_enum: ty = qual(VOLATILE, uid2type(type->v.rcc_VOLATILE.type)); break; case rcc_ENUM_enum: { int i, n = Seq_length(type->v.rcc_ENUM.ids); ty = newstruct(ENUM, string(type->v.rcc_ENUM.tag)); ty->type = inttype; ty->size = ty->type->size; ty->align = ty->type->align; ty->u.sym->u.idlist = newarray(n + 1, sizeof *ty->u.sym->u.idlist, PERM); for (i = 0; i < n; i++) { rcc_enum__ty e = Seq_remlo(type->v.rcc_ENUM.ids); Symbol p = install(e->id, &identifiers, GLOBAL, PERM); p->type = ty; p->sclass = ENUM; p->u.value = e->value; ty->u.sym->u.idlist[i] = p; free(e); } ty->u.sym->u.idlist[i] = NULL; Seq_free(&type->v.rcc_ENUM.ids); break; } case rcc_STRUCT_enum: case rcc_UNION_enum: { int i, n; Field *tail; list_ty fields; if (type->kind == rcc_STRUCT_enum) { ty = newstruct(STRUCT, string(type->v.rcc_STRUCT.tag)); fields = type->v.rcc_STRUCT.fields; } else { ty = newstruct(UNION, string(type->v.rcc_UNION.tag)); fields = type->v.rcc_UNION.fields; } itemmap[uid] = ty; /* recursive types */ ty->size = type->size; ty->align = type->align; tail = &ty->u.sym->u.s.flist; n = Seq_length(fields); for (i = 0; i < n; i++) { rcc_field_ty field = Seq_remlo(fields); NEW0(*tail, PERM); (*tail)->name = (char *)field->id; (*tail)->type = uid2type(field->type); (*tail)->offset = field->offset; (*tail)->bitsize = field->bitsize; (*tail)->lsb = field->lsb; if (isconst((*tail)->type)) ty->u.sym->u.s.cfields = 1; if (isvolatile((*tail)->type)) ty->u.sym->u.s.vfields = 1; tail = &(*tail)->link; free(field); } Seq_free(&fields); break; } case rcc_FUNCTION_enum: { int n = Seq_length(type->v.rcc_FUNCTION.formals); if (n > 0) { int i; Type *proto = newarray(n + 1, sizeof *proto, PERM); for (i = 0; i < n; i++) { int *formal = Seq_remlo(type->v.rcc_FUNCTION.formals); proto[i] = uid2type(*formal); free(formal); } proto[i] = NULL; ty = func(uid2type(type->v.rcc_FUNCTION.type), proto, 0); } else ty = func(uid2type(type->v.rcc_FUNCTION.type), NULL, 1); Seq_free(&type->v.rcc_FUNCTION.formals); break; } default: assert(0); } if (itemmap[uid] == NULL) { itemmap[uid] = ty; free(type); free(items[uid]); items[uid] = NULL; } else assert(itemmap[uid] == ty); } return itemmap[uid]; }
int argcnt(const char c) //count of arguments {if (isconst(c)) return 0; if (isfn(c) && c!=fpow && c!=f_op_pow && c!=f_op_root && c!=froot && c!=flogn || c=='!' || c=='_') return 1; return 2; }
BOOLEAN comparetypes(TYPE *typ1, TYPE *typ2, int exact) { if (typ1->type == bt_any || typ2->type == bt_any) return TRUE; while (typ1->type == bt_typedef) typ1 = basetype(typ1); while (typ2->type == bt_typedef) typ2 = basetype(typ2); typ1 = replaceTemplateSelector(typ1); typ2 = replaceTemplateSelector(typ2); if (isDerivedFromTemplate(typ1)) typ1 = typ1->btp; if (isDerivedFromTemplate(typ2)) typ2 = typ2->btp; while (isref(typ1)) typ1 = basetype(typ1)->btp; while (isref(typ2)) typ2 = basetype(typ2)->btp; while (typ1->type == bt_typedef) typ1 = basetype(typ1); while (typ2->type == bt_typedef) typ2 = basetype(typ2); if (typ1->type == bt_templateselector && typ2->type == bt_templateselector) return templateselectorcompare(typ1->sp->templateSelector, typ2->sp->templateSelector); if (typ1->type == bt_templatedecltype && typ2->type == bt_templatedecltype) return templatecompareexpressions(typ1->templateDeclType, typ2->templateDeclType); if (ispointer(typ1) && ispointer(typ2)) { if (exact) { int arr = FALSE; int first = TRUE; while (ispointer(typ1) && ispointer(typ2)) { if (!first && (exact == 1)) if ((isconst(typ2) && !isconst(typ1)) || (isvolatile(typ2) && !isvolatile(typ1))) return FALSE; first = FALSE; typ1 = basetype(typ1); typ2 = basetype(typ2); if (typ1->type != typ2->type) return FALSE; if (arr && typ1->array != typ2->array) return FALSE; if (arr && typ1->size != typ2->size) return FALSE; arr |= typ1->array | typ2->array; typ1 = typ1->btp; typ2 = typ2->btp; } if (exact == 1 && ((isconst(typ2) && !isconst(typ1)) || (isvolatile(typ2) && !isvolatile(typ1)))) return FALSE; return comparetypes(typ1, typ2, TRUE); } else return TRUE; } typ1 = basetype(typ1); typ2 = basetype(typ2); if (exact && (isfunction(typ1) || isfuncptr(typ1)) && (isfunction(typ2) || isfuncptr(typ2))) { HASHREC *hr1; HASHREC *hr2; typ1 = basetype(typ1); typ2 = basetype(typ2); if (ispointer(typ1)) typ1 = basetype(typ1)->btp; if (ispointer(typ2)) typ2 = basetype(typ2)->btp; if (!comparetypes(typ1->btp, typ2->btp, exact)) return FALSE; if (!matchOverload(typ1, typ2, TRUE)) return FALSE; return TRUE; } if (cparams.prm_cplusplus) { if (typ1->scoped != typ2->scoped) return FALSE; if (typ1->type == bt_enum) { if (typ2->type == bt_enum) return typ1->sp == typ2->sp; else return isint(typ2); } else if (typ2->type == bt_enum) { return isint(typ1); } if (typ1->type == typ2->type && typ1->type == bt_memberptr) { if (typ1->sp != typ2->sp) { if (classRefCount(typ1->sp, typ2->sp) != 1) return FALSE; } return comparetypes(typ1->btp, typ2->btp, exact); } } if (typ1->type == typ2->type && (isstructured(typ1) || (exact && typ1->type == bt_enum))) return typ1->sp == typ2->sp; if (typ1->type == typ2->type || (!exact && isarithmetic(typ2) && isarithmetic(typ1))) return TRUE; if (isfunction(typ1) && isfunction(typ2) && typ1->sp->linkage == typ2->sp->linkage) return TRUE; else if (!exact && ((ispointer(typ1) && (isfuncptr(typ2) || isfunction(typ2) || isint(typ2))) || (ispointer(typ2) && (isfuncptr(typ1) || isfunction(typ1) || isint(typ1))))) return (TRUE); else if (typ1->type == bt_enum && isint(typ2)) { return TRUE; } else if (typ2->type == bt_enum && isint(typ1)) { return TRUE; } return FALSE; }
char* TSolver::convtopol() //converts symbol-function string to polish record {if (S==NULL || !strlen(S)) seterr(E_VOID); char* r; if (Err!=E_NO) {ERROR: if (r!=NULL) free(r); free(S); return S=NULL; } int i,j=0; int p; int SL=strlen(S); r=(char*)calloc(SL*2+2,sizeof(char)); r[0]='\0'; cst_clear; for (i=0;S[i]!='\0';i++) {if (isnumc(S[i]) || isconst(S[i]) || (S[i]=='-' && (minusE || minusN))) {r[j++]=S[i]; continue; } if (S[i]=='!') {addspc(); r[j++]=S[i]; addspc(); continue; } p=prior(S[i]); {if (S[i]==')') {addspc(); while ((!cst_free) && cst_end!='(') {r[j++]=cpop(); r[j++]=' '; } cpop(); if ((!cst_free) && isfn(cst_end)) {r[j++]=cpop(); r[j++]=' '; } continue; } if (S[i]==']') {addspc(); while ((!cst_free) && cst_end!='[') {r[j++]=cpop(); r[j++]=' '; } cpop(); r[j++]=f_abs; r[j++]=' '; continue; } if ((((!cst_free) && (p>=prior(cst_end)) && (prior(cst_end)>0)&&cst_end!='_'&&S[i]!='_') || S[i]==',')) {addspc(); while ((!cst_free) && p>=prior(cst_end) && prior(cst_end)>0) {r[j++]=cpop(); r[j++]=' '; } if (S[i]==',') continue; } cpush(S[i]); if (j>0) addspc(); } } if (Err!=E_NO) goto ERROR; if (r[j-1]!=' ') r[j++]=' '; while (!cst_free) {r[j++]=cpop(); r[j++]=' '; } if (r[j-1]!=' ') r[j++]=' '; r[j]='\0'; free(S); S=strdbl(r); free(r); #ifdef debug printf("%s\n",S); #endif poled=1; return S; }