SNODE *casestmt(SNODE *lst) /* * cases are returned as seperate statements. for normal * cases label is the case value and s2 is zero. for the * default case s2 is nonzero. */ { SNODE *snp; SNODE *head=0, *tail; snp = xalloc(sizeof(SNODE)); snp->next = 0; if( lastst == kw_case ) { getsym(); snp->s2 = 0; snp->stype = st_case; snp->label = (SNODE *)intexpr(0); } else if( lastst == kw_default) { goodcode |= GF_DEF; getsym(); snp->stype = st_case; snp->s2 = (SNODE *)1; } else { generror(ERR_NOCASE,0,0); return 0; } needpunc(colon,0); head = 0; if (lst) { head = tail = lst; lst->next = 0; } while( lastst != end && lastst != eof && lastst != kw_case && lastst != kw_default ) { if (goodcode & (GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO)) { if (lastst == id) { while( isspace(lastch) ) getch(); if (lastch != ':') generror(ERR_UNREACHABLE,0,0); } else generror(ERR_UNREACHABLE,0,0); } goodcode &= ~(GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO); if( head == 0 ) head = tail = statement(); else { tail->next = statement(); } while( tail->next != 0 ) tail = tail->next; } if (goodcode & GF_BREAK) goodcode &= ~GF_UNREACH; snp->s1 = head; return snp; }
SNODE *_genwordstmt(void) /* * Insert data in the code stream */ { SNODE *snp; snp = xalloc(sizeof(SNODE)); snp->next = 0; snp->stype = st__genword; snp->exp = 0; getsym(); if (lastst != openpa) { generror(ERR_PUNCT,openpa,skm_semi); getsym(); snp = 0; } else { getsym(); snp->exp = (ENODE *) intexpr(0); if (lastst != closepa) { generror(ERR_PUNCT,closepa,skm_semi); snp = 0; } getsym(); } if (lastst != eof) needpunc(semicolon,0); return(snp); }
static void symtab_enter(const char *key, void *data) { ENTRY symtab_entry; symtab_entry.key = (char *)key; symtab_entry.data = data; if (hsearch(symtab_entry, FIND) != NULL) generror("rd %s", symtab_entry.key); if (hsearch(symtab_entry, ENTER) == NULL) generror(">s"); }
/* scan an expression and determine if there are any pias */ TYP *doassign(ENODE **exp, int canerror, int *skm) { TYP *tp; if( (tp =expression(exp)) == 0 ) { if (canerror) generror(ERR_EXPREXPECT,0,skm); *exp = 0; } else { if (scanassign(*exp)) generror(ERR_BADEQUATE,0,0); } return tp; }
LLVMValueRef gen_name(struct node *ast) { LLVMValueRef func, ptr, val; LLVMTypeRef type; ptr = lvalue(ast); type = LLVMTypeOf(ptr); if (LLVMGetTypeKind(type) == LLVMLabelTypeKind) { func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); return LLVMBuildPtrToInt(builder, LLVMBlockAddress(func, (LLVMBasicBlockRef)ptr), TYPE_INT, ""); } type = LLVMGetElementType(LLVMTypeOf(ptr)); switch (LLVMGetTypeKind(type)) { case LLVMIntegerTypeKind: val = LLVMBuildLoad(builder, ptr, ast->val); if (LLVMIsAGlobalValue(ptr)) val = LLVMBuildLShr(builder, val, CONST(WORDPOW), ""); return val; default: generror("unexpected type '%s'", LLVMPrintTypeToString(type)); return NULL; } }
void need_begin(void) { if (lastst != begin && lastst != kw_begin) generror(ERR_BEGIN_EXPECTED, 0); getsym(); need_eol(); }
int checkcases(SNODE *head) /* * checkcases will check to see if any duplicate cases * exist in the case list pointed to by head. */ { SNODE *top, *cur; top = head; while( top != 0 ) { cur = top->next; while( cur != 0 ) { if( (!(cur->s1 || cur->s2) && cur->label == top->label) || (cur->s2 && top->s2) ) { generror(ERR_DUPCASE,(int)cur->label,0); return 1; } cur = cur->next; } top = top->next; } return 0; }
LLVMValueRef gen_case(struct node *ast) { LLVMValueRef func; LLVMBasicBlockRef this_block, next_block; this_block = LLVMGetInsertBlock(builder); func = LLVMGetBasicBlockParent(this_block); next_block = LLVMAppendBasicBlock(func, ""); LLVMMoveBasicBlockAfter(next_block, this_block); case_blocks[case_count] = next_block; case_vals[case_count] = codegen(ast->one); LLVMBuildBr(builder, next_block); LLVMPositionBuilderAtEnd(builder, next_block); case_count++; if (case_count >= MAX_CASES) generror(">c"); codegen(ast->two); return NULL; }
void doautoinit(SYM *sym) /* * This is here rather than in init because autoinit is a type of * statement */ { if (lastst == assign) { SNODE *snp = snp_line(); if (snp) if (cbautoinithead == 0) cbautoinithead = cbautoinittail = snp; else { cbautoinittail->next = snp; cbautoinittail= snp; } getsym(); snp = xalloc(sizeof(SNODE)); snp->next = 0; snp->stype = st_expr; if (autoasnop(&(snp->exp), sym) == 0) { generror(ERR_EXPREXPECT,0,0); getsym(); } else { if (cbautoinithead == 0) cbautoinithead = cbautoinittail = snp; else { cbautoinittail->next = snp; cbautoinittail= snp; } } } }
void need_end(void) { if (lastst != end && lastst != kw_end) generror(ERR_END_EXPECTED, 0); getsym(); need_eol(); }
static void predeclare_labels(struct node *ast) { LLVMBasicBlockRef label_block; LLVMValueRef func; char *name; if (ast->one) predeclare_labels(ast->one); if (ast->two) predeclare_labels(ast->two); if (ast->three) predeclare_labels(ast->three); if (ast->codegen == gen_label) { name = ast->one->val; func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); label_block = LLVMAppendBasicBlock(func, name); symtab_enter(name, label_block); if (label_count >= MAX_LABELS) generror(">i"); label_blocks[label_count++] = label_block; } }
/* * getexp - get exponent part of floating number. * * this algorithm is primative but usefull. Floating * exponents are limited to +/-255 but most hardware * won't support more anyway. */ void getexp(char **ptr) { long double expo, exmul; expo = 1.0; if (lastst != rconst) rval = ival; if (**ptr == '-') { exmul = 0.1; (*ptr)++; } else { exmul = 10.0; if (**ptr == '+') (*ptr)++; } getbase(10, ptr); if (ival > 255) generror(ERR_FPCON, 0); else while (ival--) expo *= exmul; rval *= expo; lastst = rconst; }
SNODE *exprstmt(void) /* * exprstmt is called whenever a statement does not begin * with a keyword. the statement should be an expression. */ { SNODE *snp; snp = xalloc(sizeof(SNODE)); snp->next = 0; snp->stype = st_expr; goodcode &= ~(GF_ASSIGN); if( expression(&snp->exp) == 0 ) { generror(ERR_EXPREXPECT,0,skm_semi); snp->exp = 0; } if (!(goodcode & GF_ASSIGN)) generror(ERR_CODENONE,0,0); if( lastst != eof) needpunc( semicolon,0 ); return snp; }
static LLVMValueRef lvalue_name(struct node *ast) { LLVMValueRef lvalue; lvalue = symtab_find(ast->val); if (lvalue == NULL) generror("un %s", ast->val); return lvalue; }
SNODE *retstmt(void) /* * Handle return */ { SNODE *snp; TYP *tp; snp = xalloc(sizeof(SNODE)); snp->next = 0; snp->stype = st_return; snp->exp = 0; getsym(); if (lastst == end || lastst == semicolon) { if (currentfunc->tp->btp->type != bt_void) generror(ERR_RETMISMATCH,0,0); needpunc(semicolon,0); } else { int ogc = goodcode; goodcode |= GF_SUPERAND; tp = expression(&(snp->exp)); goodcode = ogc; if( lastst != eof) needpunc( semicolon, 0 ); if (tp->type == bt_void) { generror(ERR_NOVOIDRET,0,0); } else /* if (tp->type == bt_pointer && tp->val_flag) generror(ERR_NOFUNCARRAY,0,0); else */ if (!checktype(tp,currentfunc->tp->btp)) if (isscalar(tp) && isscalar(currentfunc->tp->btp)) promote_type(currentfunc->tp->btp, &(snp->exp)); else if (currentfunc->tp->btp->type != bt_pointer || floatrecurse(snp->exp)) generror(ERR_RETMISMATCH,0,0); } return snp; }
SNODE *compound(void) /* * Process the body of a compound block. Declarations are already * handled by now. * */ { SNODE *head, *tail; head = cbautoinithead; tail = cbautoinittail; goodcode &= ~(GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO); while( lastst != end && lastst != eof) { if (goodcode & (GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO)) if (lastst == id) { while( isspace(lastch) ) getch(); if (lastch != ':') generror(ERR_UNREACHABLE,0,0); } else generror(ERR_UNREACHABLE,0,0); goodcode &= ~(GF_RETURN | GF_BREAK| GF_CONTINUE | GF_GOTO); if( head == 0 ) head = tail = statement(); else { tail->next = statement(); } while( tail->next != 0 ) tail = tail->next; } if (head) tail->next = snp_line(); if (lastst == eof) generror(ERR_PUNCT,end,0); else getsym(); return head; }
void compile(struct node *ast, const char *outfile) { /* TODO: Free module, define "dbc" as constant */ if ((module = LLVMModuleCreateWithName("dbc")) == NULL) generror("Failed to create LLVM module"); if ((builder = LLVMCreateBuilder()) == NULL) generror("Failed to create LLVM instruction builder"); if (ast) codegen(ast); if (LLVMVerifyModule(module, LLVMPrintMessageAction, NULL) != 0) { fprintf(stderr, "\nCongratulations, you've found a bug!\n" "Please submit your program to " "<https://github.com/dobyrch/dbc/issues>\n"); exit(EXIT_FAILURE); } if (LLVMWriteBitcodeToFile(module, outfile) != 0) generror("Failed to write bitcode"); }
static LLVMValueRef lvalue(struct node *ast) { if (ast->codegen == gen_name) return lvalue_name(ast); else if (ast->codegen == gen_indir) return lvalue_indir(ast); else if (ast->codegen == gen_index) return lvalue_index(ast); else generror("lv"); return NULL; }
static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { if (snac->subtype == 0x0001) return generror(sess, mod, rx, snac, bs); else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) { aim_rxcallback_t userfunc; if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) return userfunc(sess, rx); } return 0; }
SNODE *contstmt(void) /* * handle continue */ { SNODE *snp; snp = xalloc(sizeof(SNODE)); snp->next = 0; snp->stype = st_continue; if (!(goodcode & GF_CONTINUABLE)) generror(ERR_NOCONTINUE,0,0); getsym(); if( lastst != eof) needpunc( semicolon,0 ); return snp; }
void dodefaultinit(SYM *sp) /* * Evalueate a C++ default clause */ { TYP *tp; if (lastst == assign) { getsym(); if ((tp =autoasnop(&(sp->defalt), sp)) == 0) { generror(ERR_EXPREXPECT,0,0); getsym(); } else sp->defalt = sp->defalt->v.p[1]; } }
LLVMValueRef gen_ivals(struct node *ast) { LLVMValueRef *ival_list; int size, i; size = count_chain(ast); ival_list = calloc(sizeof(LLVMValueRef), size); if (size > 0 && ival_list == NULL) generror("out of memory"); for (i = 0; i < size; i++, ast = ast->two) ival_list[i] = codegen(ast->one); /* TODO: Figure out how to initialize int with vector without error */ /*return LLVMConstArray(TYPE_INT, ival_list, size);*/ return size ? ival_list[0] : CONST(0); }
LLVMValueRef gen_vecdef(struct node *ast) { LLVMValueRef global, array, init, *ival_list; struct node *n; int size, initsize, i; initsize = count_chain(ast->three); if (ast->two) size = LLVMConstIntGetZExtValue(codegen(ast->two)); else size = 0; if (initsize > size) size = initsize; ival_list = calloc(sizeof(LLVMValueRef), size); if (size > 0 && ival_list == NULL) generror("out of memory"); for (i = 0, n = ast->three; i < initsize; i++, n = n->two) /* TODO: handle NAMES (convert global pointer to int) */ ival_list[initsize - i - 1] = codegen(n->one); for (i = initsize; i < size; i++) ival_list[i] = CONST(0); global = find_or_add_global(ast->one->val); array = LLVMAddGlobal(module, TYPE_ARRAY(size), ".gvec"); LLVMSetLinkage(array, LLVMPrivateLinkage); if (initsize) init = LLVMConstArray(TYPE_INT, ival_list, size); else init = LLVMConstNull(TYPE_ARRAY(size)); LLVMSetInitializer(array, init); LLVMSetInitializer(global, LLVMBuildPtrToInt(builder, array, TYPE_INT, "")); return NULL; }
LLVMValueRef gen_call(struct node *ast) { LLVMValueRef func, *arg_list = NULL; struct node *n; int arg_count, i; func = LLVMBuildBitCast(builder, rvalue_to_lvalue(codegen(ast->one)), LLVMPointerType(TYPE_FUNC, 0), ""); arg_count = count_chain(ast->two); arg_list = calloc(sizeof(LLVMValueRef), arg_count); if (arg_count > 0 && arg_list == NULL) generror("out of memory"); for (i = 0, n = ast->two; i < arg_count; i++, n = n->two) arg_list[arg_count - i - 1] = codegen(n->one); return LLVMBuildCall(builder, func, arg_list, arg_count, ""); }
/* * getbase - get an integer in any base. */ void getbase(int b, char **ptr) { register long i, j; int errd = 0; i = 0; while (isalnum(**ptr)) { if ((j = radix36(*(*ptr)++)) < b) { if (i > (ULONG_MAX - j) / b) if (!errd) { generror(ERR_CONSTTOOLARGE, 0); errd++; } i = i * b + j; } else break; } ival = i; lastst = iconst; }
/* * getid - get an identifier. * * identifiers are any isidch conglomerate * that doesn't start with a numeric character. * this set INCLUDES keywords. */ void getid() { register int i; i = 0; /* Mangling */ if (lastch == 'L') { lastid[i++] = 'L'; getch(); if (lastch == '\"') { getch(); i = 0; while (lastch != '\"' && lastch) { *(((short*)(laststr)) + i++) = lastch; getch(); } if ((lastch &0x7f) != '\"') generror(ERR_NEEDCHAR, '\"'); else getch(); *(((short*)(laststr)) + i) = 0; laststrlen = i; lastst = lsconst; return ; } } while (issymchar(lastch)) { if (i < sizeof(lastid)/sizeof(lastid[0])) lastid[i++] = lastch; getch(); } lastid[i] = '\0'; lastst = ident; }
SNODE *gotostmt(void) /* * gotostmt processes the goto statement and puts undefined * labels into the symbol table. */ { SNODE *snp; SYM *sp; getsym(); if( lastst != id ) { generror(ERR_IDEXPECT,0,0); return 0; } snp = xalloc(sizeof(SNODE)); snp->next = 0; if( (sp = search(lastid,&lsyms)) == 0 ) { sp = xalloc(sizeof(SYM)); sp->name = litlate(lastid); sp->value.i = nextlabel++; sp->storage_class = sc_ulabel; sp->tp = xalloc(sizeof(TYP)); sp->tp->type = bt_unsigned; insert(sp,&lsyms); } sp->tp->uflags = UF_USED; getsym(); /* get past label name */ if( lastst != eof) needpunc( semicolon,0 ); if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel) gensymerror( ERR_LABEL,sp->name); else { snp->stype = st_goto; snp->label = (SNODE *)sp->value.i; snp->next = 0; return snp; } return 0; }
int getsym2(void) /* * translate character sequences to appropriate token names */ { register int i, j, k; int size; //swlp: switch (lastch) { case '+': getch(); if (lastch == '+') { getch(); lastst = autoinc; } else if (lastch == '=') { getch(); lastst = asplus; } else lastst = plus; break; case '-': getch(); if (lastch == '-') { getch(); lastst = autodec; } else if (lastch == '=') { getch(); lastst = asminus; } else if (lastch == '>') { getch(); lastst = pointsto; } else lastst = minus; break; case '*': getch(); if (lastch == '=') { getch(); lastst = astimes; } else lastst = star; break; case '/': getch(); if (lastch == '=') { getch(); lastst = asdivide; } else lastst = divide; break; case '^': getch(); if (lastch == '=') { getch(); lastst = asxor; } else lastst = uparrow; break; case ';': getch(); lastst = semicolon; break; case ':': getch(); lastst = colon; break; case '=': getch(); if (lastch == '=') { getch(); lastst = eq; } else lastst = assign; break; case '>': getch(); if (lastch == '=') { getch(); lastst = geq; } else if (lastch == '>') { getch(); if (lastch == '=') { getch(); lastst = asrshift; } else lastst = rshift; } else lastst = gt; break; case '<': getch(); if (incconst) { incconst = FALSE; for (i = 0; i < MAX_STRLEN; ++i) { if (lastch == '>') break; if ((j = getsch()) == - 1) break; else laststr[i] = j; } laststr[i] = 0; lastst = sconst; laststrlen = i; if (lastch != '>') generror(ERR_NEEDCHAR, '>'); else getch(); } else if (lastch == '=') { getch(); lastst = leq; } else if (lastch == '<') { getch(); if (lastch == '=') { getch(); lastst = aslshift; } else lastst = lshift; } else lastst = lt; break; case '\\': getch(); lastst = backslash; break; case '\'': getch(); j = 0; k = 0; ival = 0; for (i = 0, j = 0, k = 0; i < 4; i++, k += 8) { if (lastch == '\'') break; j = getsch(); /* get a string char */ ival += j << k; } if (i == 0) { generror(ERR_CHAR4CHAR, 0); getch(); } else if (lastch != '\'') { while (*lptr && *lptr != '\'') lptr++; if (*lptr) lptr++; generror(ERR_CHAR4CHAR, 0); } else getch(); lastst = cconst; break; case '\"': size = 0; while (lastch == '\"') { getch(); for (i = size; i < MAX_STRLEN; ++i) { if (lastch == '\"') break; if ((j = getsch()) == - 1) break; else laststr[i] = j; } laststr[i] = 0; laststrlen = size = i; lastst = sconst; if (lastch != '\"') generror(ERR_NEEDCHAR, '\"'); else { getch(); while (iswhitespacechar(lastch) && lastch >= 32) getch(); } } break; case '!': getch(); if (lastch == '=') { getch(); lastst = neq; } else lastst = not; break; case '%': getch(); if (lastch == '=') { getch(); lastst = asmodop; } else lastst = modop; break; case '~': getch(); lastst = compl; break; case '.': if (isdigit(*lptr)) getnum(); else { getch(); if (lastch == '.') { getch(); if (lastch == '.') { getch(); lastst = ellipse; break; } else { generror(ERR_ILLCHAR, lastch); } } else lastst = dot; } break; case ',': getch(); lastst = comma; break; case '&': getch(); if (lastch == '&') { lastst = land; getch(); } else if (lastch == '=') { lastst = asand; getch(); } else lastst = and; break; case '|': getch(); if (lastch == '|') { lastst = lor; getch(); } else if (lastch == '=') { lastst = asor; getch(); } else lastst = or; break; case '(': getch(); lastst = openpa; break; case ')': getch(); lastst = closepa; break; case '[': getch(); lastst = openbr; break; case ']': getch(); lastst = closebr; break; case '{': getch(); lastst = begin; break; case '}': getch(); lastst = end; break; case '?': getch(); lastst = hook; break; default: generror(ERR_ILLCHAR, lastch); getch(); return 1; } return 0; }
/* * getsch - get a character in a quoted string. * * this routine handles all of the escape mechanisms * for characters in strings and character constants. */ int getsch(void) /* return an in-quote character */ { register int i, j; if (lastch == '\n') return - 1; if (incconst || lastch != '\\') { i = lastch; getch(); return i; } getch(); /* get an escaped character */ if (isdigit(lastch)) { for (i = 0, j = 0; j < 3; ++j) { if (lastch <= '7' && lastch >= '0') i = (i << 3) + lastch - '0'; else break; getch(); } return i; } i = lastch; getch(); switch (i) { case '\n': getch(); return getsch(); case 'a': return '\a'; case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case '\'': return '\''; case '\"': return '\"'; case '\\': return '\\'; case 'x': { int n = 0, count = 0; while (isxdigit(lastch)) { count++; lastch -= 0x30; if (lastch > 10) lastch -= 7; if (lastch > 15) lastch -= 32; n *= 16; n += lastch; getch(); } if (count > 2) generror(ERR_CONSTTOOLARGE, 0); return n; } default: if (isdigit(i) && i < '8') { int n = 0; while (isdigit(i) && i < '8') { n = n * 8+(lastch - '0'); getch(); } return n; } return i; } }
int getline(int listflag) /* * Read in a line, preprocess it, and dump it to the list and preproc files * Also strip comments and alter trigraphs */ { int rv, rvc, prepping, temp; static int inpreprocess; char ibuf[4096], xbuf[4096], *xptr; char *ptr = ibuf; if (cantnewline) { return (0); } repeatit: do { rv = FALSE; prepping = FALSE; rvc = 0; // add: while (rvc + 131 < 4096 && !rv) { ++lineno; ++errlineno; rv = getstring(ibuf + rvc, 4096 - rvc, inputFile); if (rv) { break; } rvc = strlen(ibuf); if (ibuf[rvc - 1] != '\n') { ibuf[rvc++] = '\n'; ibuf[rvc] = 0; } rvc -= 2; while (ibuf[rvc] == ' ') rvc--; // if (ibuf[rvc] != '\\') break; } if (rvc) rv = FALSE; if (rv) { if (ifs) generror(ERR_PREPROCMATCH, 0); if (commentlevel) generror(ERR_COMMENTMATCH, 0); if (incldepth > 0) { if (inSymFile && !strcmp(infile, rcIdFile)) inSymFile = FALSE; fclose(inputFile); inputFile = inclfile[--incldepth]; lineno = inclline[incldepth]; inhfile = inclhfile[incldepth]; infile = inclfname[incldepth]; free(inputBuffer); inputBuffer = inclInputBuffer[incldepth]; inputLen = inclInputLen[incldepth]; ibufPtr = inclibufPtr[incldepth]; errlineno = lineno; errfile = infile; ifs = ifshold[incldepth]; commentlevel = 0; popif(); goto repeatit; } } if (rv) return 1; lptr = inputline; ptr = ibuf; xptr = xbuf; while ((temp = *ptr++) != 0) { *lptr++ = (unsigned char)temp; *xptr++ = (unsigned char)temp; } *lptr = 0; *xptr = 0; stripcomment(inputline); lptr = inputline; while (iswhitespacechar(*lptr)) lptr++; CacheLine((WCHAR *)lptr, xbuf); if (lptr[0] == '#') { inpreprocess++; listflag = preprocess(); inpreprocess--; prepping = TRUE; lastst = eol; } if (incldepth) lastst = eol; } while (ifskip || prepping || (inhfile && !inpreprocess)) ; rvc = strlen(ibuf); /* if (defcheck(inputline) == - 10 && rvc + 131 < 4096) { if (ibuf[rvc - 1] == '\n') ibuf[rvc - 1] = ' '; goto add; } */ return 0; }