├── README ├── c-grammar.lex ├── c-grammar.y ├── command.c ├── command.h ├── hash.c ├── hash.h ├── makefile ├── node.h ├── parser.c ├── test ├── test.c ├── test2.c ├── test3.c └── test4.c └── var.h /README: -------------------------------------------------------------------------------- 1 | make lex 2 | make yacc 3 | make 4 | 5 | ./parser < test.c > test.asm 6 | 7 | nasm -f elf test.asm 8 | ld -s -o test test.o 9 | -------------------------------------------------------------------------------- /c-grammar.lex: -------------------------------------------------------------------------------- 1 | D [0-9] 2 | L [a-zA-Z_] 3 | H [a-fA-F0-9] 4 | E [Ee][+-]?{D}+ 5 | P [Pp][+-]?{D}+ 6 | FS (f|F|l|L) 7 | IS ((u|U)|(u|U)?(l|L|ll|LL)|(l|L|ll|LL)(u|U)) 8 | 9 | %{ 10 | #include 11 | #include 12 | #include "node.h" 13 | #include "y.tab.h" 14 | #include "hash.h" 15 | 16 | void count(void); 17 | %} 18 | 19 | %% 20 | "/*" { comment(); } 21 | "//"[^\n]* { /* consume //-comment */ } 22 | 23 | 24 | "auto" { count(); return(AUTO); } 25 | "_Bool" { count(); return(BOOL); } 26 | "break" { count(); return(BREAK); } 27 | "case" { count(); return(CASE); } 28 | "char" { count(); return(CHAR); } 29 | "_Complex" { count(); return(COMPLEX); } 30 | "const" { count(); return(CONST); } 31 | "continue" { count(); return(CONTINUE); } 32 | "default" { count(); return(DEFAULT); } 33 | "do" { count(); return(DO); } 34 | "double" { count(); return(DOUBLE); } 35 | "else" { count(); return(ELSE); } 36 | "enum" { count(); return(ENUM); } 37 | "extern" { count(); return(EXTERN); } 38 | "float" { count(); return(FLOAT); } 39 | "for" { count(); return(FOR); } 40 | "goto" { count(); return(GOTO); } 41 | "if" { count(); return(IF); } 42 | "_Imaginary" { count(); return(IMAGINARY); } 43 | "inline" { count(); return(INLINE); } 44 | "int" { count(); return(INT); } 45 | "long" { count(); return(LONG); } 46 | "register" { count(); return(REGISTER); } 47 | "restrict" { count(); return(RESTRICT); } 48 | "return" { count(); return(RETURN); } 49 | "short" { count(); return(SHORT); } 50 | "signed" { count(); return(SIGNED); } 51 | "sizeof" { count(); return(SIZEOF); } 52 | "static" { count(); return(STATIC); } 53 | "struct" { count(); return(STRUCT); } 54 | "switch" { count(); return(SWITCH); } 55 | "typedef" { count(); return(TYPEDEF); } 56 | "union" { count(); return(UNION); } 57 | "unsigned" { count(); return(UNSIGNED); } 58 | "void" { count(); return(VOID); } 59 | "volatile" { count(); return(VOLATILE); } 60 | "while" { count(); return(WHILE); } 61 | 62 | {L}({L}|{D})* { count(); return(check_type()); } 63 | 64 | 0[xX]{H}+{IS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 65 | 0{D}+{IS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 66 | {D}+{IS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 67 | L?'(\\.|[^\\'\n])+' { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 68 | 69 | {D}+{E}{FS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 70 | {D}*"."{D}+({E})?{FS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 71 | {D}+"."{D}*({E})?{FS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 72 | 0[xX]{H}+{P}{FS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 73 | 0[xX]{H}*"."{H}+({P})?{FS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 74 | 0[xX]{H}+"."{H}*({P})?{FS}? { count(); yylval.iValue = atoi(yytext); return(CONSTANT); } 75 | 76 | 77 | L?\"(\\.|[^\\"\n])*\" { count(); return(STRING_LITERAL); } 78 | 79 | "..." { count(); return(ELLIPSIS); } 80 | ">>=" { count(); return(RIGHT_ASSIGN); } 81 | "<<=" { count(); return(LEFT_ASSIGN); } 82 | "+=" { count(); return(ADD_ASSIGN); } 83 | "-=" { count(); return(SUB_ASSIGN); } 84 | "*=" { count(); return(MUL_ASSIGN); } 85 | "/=" { count(); return(DIV_ASSIGN); } 86 | "%=" { count(); return(MOD_ASSIGN); } 87 | "&=" { count(); return(AND_ASSIGN); } 88 | "^=" { count(); return(XOR_ASSIGN); } 89 | "|=" { count(); return(OR_ASSIGN); } 90 | ">>" { count(); return(RIGHT_OP); } 91 | "<<" { count(); return(LEFT_OP); } 92 | "++" { count(); return(INC_OP); } 93 | "--" { count(); return(DEC_OP); } 94 | "->" { count(); return(PTR_OP); } 95 | "&&" { count(); return(AND_OP); } 96 | "||" { count(); return(OR_OP); } 97 | "<=" { count(); return(LE_OP); } 98 | ">=" { count(); return(GE_OP); } 99 | "==" { count(); return(EQ_OP); } 100 | "!=" { count(); return(NE_OP); } 101 | ";" { count(); return(';'); } 102 | ("{"|"<%") { count(); return('{'); } 103 | ("}"|"%>") { count(); return('}'); } 104 | "," { count(); return(','); } 105 | ":" { count(); return(':'); } 106 | "=" { count(); return('='); } 107 | "(" { count(); return('('); } 108 | ")" { count(); return(')'); } 109 | ("["|"<:") { count(); return('['); } 110 | ("]"|":>") { count(); return(']'); } 111 | "." { count(); return('.'); } 112 | "&" { count(); return('&'); } 113 | "!" { count(); return('!'); } 114 | "~" { count(); return('~'); } 115 | "-" { count(); return('-'); } 116 | "+" { count(); return('+'); } 117 | "*" { count(); return('*'); } 118 | "/" { count(); return('/'); } 119 | "%" { count(); return('%'); } 120 | "<" { count(); return('<'); } 121 | ">" { count(); return('>'); } 122 | "^" { count(); return('^'); } 123 | "|" { count(); return('|'); } 124 | "?" { count(); return('?'); } 125 | 126 | [ \t\v\n\f] { count(); } 127 | . { /* Add code to complain about unmatched characters */ } 128 | 129 | %% 130 | 131 | int yywrap(void) 132 | { 133 | return 1; 134 | } 135 | 136 | 137 | void comment(void) 138 | { 139 | char c, prev = 0; 140 | 141 | while ((c = input()) != 0) /* (EOF maps to 0) */ 142 | { 143 | if (c == '/' && prev == '*') 144 | return; 145 | prev = c; 146 | } 147 | error("unterminated comment"); 148 | } 149 | 150 | 151 | int column = 0; 152 | 153 | void count(void) 154 | { 155 | int i; 156 | 157 | for (i = 0; yytext[i] != '\0'; i++) 158 | if (yytext[i] == '\n') 159 | column = 0; 160 | else if (yytext[i] == '\t') 161 | column += 8 - (column % 8); 162 | else 163 | column++; 164 | 165 | /*ECHO; */ 166 | } 167 | 168 | 169 | int check_type(void) 170 | { 171 | /* 172 | * pseudo code --- this is what it should check 173 | * 174 | * if (yytext == type_name) 175 | * return TYPE_NAME; 176 | * 177 | * return IDENTIFIER; 178 | */ 179 | 180 | /* 181 | * it actually will only return IDENTIFIER 182 | */ 183 | yylval.sIndex = ELFHash(yytext, strlen(yytext)); 184 | 185 | return IDENTIFIER; 186 | } 187 | -------------------------------------------------------------------------------- /c-grammar.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #include "node.h" 6 | #include "hash.h" 7 | #include "var.h" 8 | #include "command.h" 9 | 10 | Node *tmp; 11 | 12 | /* 属性操作类型 */ 13 | Node *opr(int name, int num, ...); 14 | Node *set_index(int value); 15 | Node *set_content(int value); 16 | void freeNode(Node *p); 17 | int exeNode(Node *p, int signal); 18 | 19 | int yylexeNode(void); 20 | void yyerror(char *s); 21 | 22 | /*int var[26]; [> 变量数组 <]*/ 23 | 24 | %} 25 | 26 | %union { 27 | int iValue; 28 | int sIndex; 29 | Node *nPtr; 30 | }; 31 | 32 | %token CONSTANT INT VOID 33 | %token IDENTIFIER 34 | %token STRING_LITERAL SIZEOF 35 | %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP 36 | %token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN 37 | %token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN 38 | %token XOR_ASSIGN OR_ASSIGN TYPE_NAME 39 | 40 | %token TYPEDEF EXTERN STATIC AUTO REGISTER INLINE RESTRICT 41 | %token CHAR SHORT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE 42 | %token BOOL COMPLEX IMAGINARY 43 | %token STRUCT UNION ENUM ELLIPSIS 44 | 45 | %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN 46 | 47 | %token PARAM FUNC VAR CALL GLOBAL_VAR 48 | 49 | %nonassoc LOWER_THAN_ELSE 50 | %nonassoc ELSE 51 | 52 | %type term var factor var_declaration local_declarations 53 | %type additive_expression simple_expression expression 54 | %type return_stmt iteration_stmt expression_stmt selection_stmt compound_stmt 55 | %type statement statement_list 56 | %type param params_list params type_specifier 57 | %type fun_declaration declaration declaration_list 58 | %type call args arg_list 59 | %type relop mulop addop 60 | 61 | %start program 62 | %% 63 | 64 | program 65 | : declaration_list { exeNode($1, 0); freeNode($1); } 66 | ; 67 | 68 | declaration_list 69 | : declaration_list declaration { $$ = opr(';', 2, $1, $2); } 70 | | declaration { $$ = $1; } 71 | ; 72 | 73 | declaration 74 | : var_declaration 75 | { 76 | $$ = opr(GLOBAL_VAR, 1, $1); 77 | } 78 | | fun_declaration { $$ = $1; } 79 | ; 80 | 81 | var_declaration 82 | : type_specifier IDENTIFIER ';' 83 | { 84 | Node *tmp1; 85 | /* here to insert new var declaration */ 86 | tmp1 = set_index($2); 87 | $$ = opr(VAR, 2, $1, tmp1); 88 | } 89 | | type_specifier IDENTIFIER '[' CONSTANT ']' ';' 90 | { 91 | Node *tmp1, *tmp2; 92 | tmp1 = set_index($2); 93 | tmp2 = set_content($4); 94 | $$ = opr(VAR, 3, $1, tmp1, tmp2); 95 | } 96 | ; 97 | 98 | type_specifier 99 | : INT { $$ = set_content(INT); } 100 | | VOID { $$ = set_content(VOID); } 101 | ; 102 | 103 | fun_declaration 104 | : type_specifier IDENTIFIER '(' params ')' 105 | { 106 | Node *tmp1; 107 | tmp1 = set_index($2); 108 | $$ = opr(FUNC, 3, $1, tmp1, $4); 109 | } 110 | 111 | | compound_stmt 112 | { $$ = opr(FUNC, 1, $1); } 113 | ; 114 | 115 | params 116 | : params_list { $$ = $1; } 117 | | VOID { $$ = NULL; } 118 | ; 119 | 120 | params_list 121 | : params_list ',' param { $$ = opr(',', 2, $1, $3); } 122 | | param { $$ = $1; } 123 | ; 124 | 125 | param 126 | : type_specifier IDENTIFIER 127 | { 128 | Node *tmp1; 129 | /* here to insert new var declaration */ 130 | tmp1 = set_index($2); 131 | $$ = opr(PARAM, 2, $1, tmp1); 132 | } 133 | | type_specifier IDENTIFIER '[' ']' 134 | { 135 | Node *tmp1; 136 | /* here to insert new var declaration */ 137 | tmp1 = set_index($2); 138 | $$ = opr(PARAM, 3, $1, tmp1, NULL); 139 | } 140 | ; 141 | 142 | compound_stmt 143 | : '{' local_declarations statement_list '}' 144 | { $$ = opr('{', 2, $2, $3); } 145 | ; 146 | 147 | local_declarations 148 | : local_declarations var_declaration { $$ = opr(';', 2, $1, $2); } 149 | | /* empty */ { $$ = NULL; } 150 | ; 151 | 152 | statement_list 153 | : statement_list statement { $$ = opr(';', 2, $1, $2); } 154 | | /* empty */ { $$ = NULL; } 155 | ; 156 | 157 | statement 158 | : expression_stmt { $$ = $1; } 159 | | compound_stmt { $$ = $1; } 160 | | selection_stmt { $$ = $1; } 161 | | iteration_stmt { $$ = $1; } 162 | | return_stmt { $$ = $1; } 163 | ; 164 | 165 | expression_stmt 166 | : expression ';' { $$ = $1; } 167 | | ';' { $$ = NULL; } 168 | ; 169 | 170 | selection_stmt 171 | : IF '(' expression ')' statement { $$ = opr(IF, 2, $3, $5); } 172 | | IF '(' expression ')' statement ELSE statement 173 | { $$ = opr(IF, 3, $3, $5, $7); } 174 | ; 175 | 176 | iteration_stmt 177 | : WHILE '(' expression ')' statement { $$ = opr(WHILE, 2, $3, $5); } 178 | ; 179 | 180 | return_stmt 181 | : RETURN ';' { $$ = opr(RETURN, 0); } 182 | | RETURN expression ';' { $$ = opr(RETURN, 1, $2); } 183 | ; 184 | 185 | expression 186 | : var '=' expression 187 | { 188 | $$ = opr('=', 2, $1, $3); 189 | } 190 | | simple_expression { $$ = $1; } 191 | ; 192 | 193 | var 194 | : IDENTIFIER { $$ = set_index($1); } 195 | | IDENTIFIER '[' expression ']' 196 | { 197 | Node *tmp1; 198 | tmp1 = set_index($1); 199 | $$ = opr('[', 2, tmp1, $3); 200 | } 201 | ; 202 | 203 | simple_expression 204 | : additive_expression relop additive_expression 205 | { 206 | $$ = opr($2, 2, $1, $3); 207 | } 208 | | additive_expression { $$ = $1; } 209 | ; 210 | 211 | relop 212 | : LE_OP { $$ = LE_OP; } 213 | | '<' { $$ = '<'; } 214 | | '>' { $$ = '>'; } 215 | | GE_OP { $$ = GE_OP; } 216 | | EQ_OP { $$ = EQ_OP; } 217 | | NE_OP { $$ = NE_OP; } 218 | ; 219 | 220 | additive_expression 221 | : additive_expression addop term 222 | { 223 | $$ = opr($2, 2, $1, $3); 224 | } 225 | | term 226 | { 227 | $$ = $1; 228 | } 229 | ; 230 | 231 | addop 232 | : '+' { $$ = '+'; } 233 | | '-' { $$ = '-'; } 234 | ; 235 | 236 | term 237 | : term mulop factor 238 | { 239 | $$ = opr($2, 2, $1, $3); 240 | } 241 | | factor { $$ = $1; } 242 | ; 243 | 244 | mulop 245 | : '*' { $$ = '*'; } 246 | | '/' { $$ = '/'; } 247 | ; 248 | 249 | factor 250 | : '(' expression ')' { $$ = $2; } 251 | | var { $$ = $1; } 252 | | call { $$ = $1; } 253 | | CONSTANT { $$ = set_content($1); } 254 | ; 255 | 256 | call 257 | : IDENTIFIER '(' args ')' 258 | { 259 | Node *tmp1; 260 | tmp1 = set_index($1); 261 | $$ = opr(CALL, 2, tmp1, $3); 262 | } 263 | ; 264 | 265 | args 266 | : arg_list { $$ = $1; } 267 | | /* empty */ { $$ = NULL; } 268 | ; 269 | 270 | arg_list 271 | : arg_list ',' expression { $$ = opr(',', 2, $1, $3); } 272 | | expression { $$ = $1; } 273 | ; 274 | 275 | %% 276 | #define SIZE_OF_NODE ((char *)&p->content - (char *)p) 277 | 278 | Node *set_content(int value) 279 | { 280 | Node *p; 281 | size_t sizeNode; 282 | /* 分配结点空间 */ 283 | sizeNode = SIZE_OF_NODE + sizeof(int); 284 | 285 | if ((p = malloc(sizeNode)) == NULL) 286 | yyerror("out of memory"); 287 | 288 | /* 复制内容 */ 289 | p->type = TYPE_CONTENT; 290 | p->content = value; 291 | 292 | return p; 293 | } 294 | 295 | Node *set_index(int value) 296 | { 297 | Node *p; 298 | size_t sizeNode; 299 | /* 分配结点空间 */ 300 | sizeNode = SIZE_OF_NODE + sizeof(int); 301 | if ((p = malloc(sizeNode)) == NULL) 302 | yyerror("out of memory"); 303 | 304 | /* 复制内容 */ 305 | p->type = TYPE_INDEX; 306 | p->index = value; 307 | return p; 308 | } 309 | 310 | Node *opr(int name, int num, ...) 311 | { 312 | va_list valist; 313 | Node *p; 314 | size_t sizeNode; 315 | int i; 316 | /* 分配结点空间 */ 317 | sizeNode = SIZE_OF_NODE + sizeof(OpNode) + (num - 1) * sizeof(Node*); 318 | 319 | if ((p = malloc(sizeNode)) == NULL) 320 | yyerror("out of memory"); 321 | 322 | /* 复制内容 */ 323 | p->type = TYPE_OP; 324 | p->op.name = name; 325 | p->op.num = num; 326 | va_start(valist, num); 327 | 328 | for (i = 0; i < num; i++) 329 | p->op.node[i] = va_arg(valist, Node*); 330 | 331 | va_end(valist); 332 | return p; 333 | } 334 | 335 | void freeNode(Node *p) 336 | { 337 | int i; 338 | if (!p) return; 339 | if (p->type == TYPE_OP) { 340 | for (i = 0; i < p->op.num; i++) 341 | freeNode(p->op.node[i]); 342 | } 343 | free (p); 344 | } 345 | 346 | void yyerror(char *s) 347 | { 348 | printf("%s\n", s); 349 | } 350 | 351 | int main() 352 | { 353 | 354 | hash_init(var_local, HASHSIZE); 355 | hash_init(var_local_SorA, HASHSIZE); 356 | hash_init(var_local_GorP, HASHSIZE); 357 | 358 | yyparse(); 359 | 360 | return 0; 361 | } 362 | -------------------------------------------------------------------------------- /command.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "command.h" 5 | #include "hash.h" 6 | 7 | void output(const char *str) 8 | { 9 | printf("%s\n", str); 10 | } 11 | 12 | static int func_is_main(int funcname) 13 | { 14 | if (funcname == ELFHash("main", 4)) 15 | return 1; 16 | 17 | return 0; 18 | } 19 | 20 | static void getvarstr(char *varstr, int offset) 21 | { 22 | if (offset >= 0) 23 | sprintf(varstr, "[%s+%d]", EBP, offset); 24 | else 25 | sprintf(varstr, "[%s%d]", EBP, offset); 26 | } 27 | 28 | static int getregstr(char *regstr, int reg) 29 | { 30 | switch (reg) { 31 | case 1: 32 | strcpy(regstr, EAX); 33 | return 0; 34 | case 2: 35 | strcpy(regstr, EBX); 36 | return 0; 37 | case 3: 38 | strcpy(regstr, ECX); 39 | return 0; 40 | case 4: 41 | strcpy(regstr, EDX); 42 | return 0; 43 | } 44 | 45 | return -1; 46 | } 47 | 48 | int creat_label() 49 | { 50 | static int labelno = 0; 51 | return ++labelno; 52 | } 53 | 54 | void code_label(int labelno) 55 | { 56 | sprintf(strbucket, "%s%d:", LABEL, labelno); 57 | output(strbucket); 58 | } 59 | 60 | void code_jmp(int labelno) 61 | { 62 | sprintf(strbucket, "%s\t%s%d", JMP, LABEL, labelno); 63 | output(strbucket); 64 | } 65 | 66 | void code_pop(int reg) 67 | { 68 | char regstr[REGSTR_LENGTH]; 69 | getregstr(regstr, reg); 70 | 71 | sprintf(strbucket, "%s\t%s", POP, regstr); 72 | output(strbucket); 73 | } 74 | 75 | void code_lea_global(int target, int addr, int offset) 76 | { 77 | int array; 78 | 79 | char offreg[REGSTR_LENGTH]; 80 | char tarreg[REGSTR_LENGTH]; 81 | array = getregstr(offreg, offset); 82 | getregstr(tarreg, target); 83 | 84 | if (array == -1) { /* not array */ 85 | sprintf(strbucket, "%s\t%s, [%s%d]", LEA, tarreg, GDATA_PRE, 86 | addr); 87 | } else { /* array with offset */ 88 | sprintf(strbucket, "%s\t%s, [%s%d+%s]", LEA, tarreg, GDATA_PRE, 89 | addr, offreg); 90 | } 91 | output(strbucket); 92 | } 93 | 94 | void code_lea_local(int target, int var) 95 | { 96 | char t_reg[REGSTR_LENGTH]; 97 | char s_var[VARSTR_LENGTH]; 98 | 99 | getregstr(t_reg, target); 100 | getvarstr(s_var, var); 101 | 102 | sprintf(strbucket, "%s\t%s, %s", LEA, t_reg, s_var); 103 | output(strbucket); 104 | } 105 | 106 | void code_move_reg(int target, int source) 107 | { 108 | char t_reg[REGSTR_LENGTH]; 109 | char s_reg[REGSTR_LENGTH]; 110 | 111 | if (target == source) 112 | return; 113 | 114 | getregstr(t_reg, target); 115 | getregstr(s_reg, source); 116 | 117 | sprintf(strbucket, "%s\t%s, %s", MOV, t_reg, s_reg); 118 | output(strbucket); 119 | } 120 | 121 | void code_push_mem(int addr, int offset) 122 | { 123 | char regstr[REGSTR_LENGTH]; 124 | getregstr(regstr, offset); 125 | 126 | sprintf(strbucket, "%s\t%s [%s%d+%s]", PUSH, VARSIZE, 127 | GDATA_PRE, addr, regstr); 128 | output(strbucket); 129 | } 130 | 131 | void code_push_reg(int reg, int mem) 132 | { 133 | char regstr[REGSTR_LENGTH]; 134 | getregstr(regstr, reg); 135 | 136 | if (mem) { 137 | sprintf(strbucket, "%s\t%s [%s]", PUSH, VARSIZE, regstr); 138 | } else { 139 | sprintf(strbucket, "%s\t%s %s", PUSH, VARSIZE, regstr); 140 | } 141 | output(strbucket); 142 | } 143 | 144 | void code_push_ind(int idx) 145 | { 146 | char varstr[VARSTR_LENGTH]; 147 | getvarstr(varstr, idx); 148 | sprintf(strbucket, "%s\t%s %s", PUSH, VARSIZE, varstr); 149 | output(strbucket); 150 | } 151 | 152 | void code_push_cons(int constant) 153 | { 154 | sprintf(strbucket, "%s\t%s %d", PUSH, VARSIZE, constant); 155 | output(strbucket); 156 | } 157 | 158 | void code_push_global_var(int var, int offset) 159 | { 160 | if (offset >= 0) { 161 | sprintf(strbucket, "%s\t%s [%s%d+%d]", PUSH, VARSIZE, GDATA_PRE, 162 | var, offset); 163 | } else { 164 | sprintf(strbucket, "%s\t%s [%s%d%d]", PUSH, VARSIZE, GDATA_PRE, 165 | var, offset); 166 | } 167 | output(strbucket); 168 | } 169 | 170 | void code_push_global_array(int var) 171 | { 172 | sprintf(strbucket, "%s\t%s %s%d", PUSH, VARSIZE, GDATA_PRE, var); 173 | output(strbucket); 174 | } 175 | 176 | void code_call_func(int funcname) 177 | { 178 | sprintf(strbucket, "%s\t%s%d", CALLF, FUNC_PRE, funcname); 179 | output(strbucket); 180 | } 181 | 182 | void code_start_bss() 183 | { 184 | static int bss_mark = 0; 185 | 186 | if (!bss_mark) { 187 | strcpy(strbucket, "section .bss"); 188 | output(strbucket); 189 | ++bss_mark; 190 | } 191 | } 192 | 193 | void code_start_text() 194 | { 195 | static int text_mark = 0; 196 | 197 | if (!text_mark) { 198 | strcpy(strbucket, "section .text"); 199 | output(strbucket); 200 | ++text_mark; 201 | } 202 | } 203 | 204 | void code_declare_global_var(int varname, int size) 205 | { 206 | sprintf(strbucket, "%s%d:\t%s %d", GDATA_PRE, varname, 207 | GLOBAL_VAR_DEFINE, GLOBAL_VAR_LENGTH * size); 208 | output(strbucket); 209 | } 210 | 211 | void code_start_func(int funcname) 212 | { 213 | if (func_is_main(funcname)) { 214 | strcpy(strbucket, "global _start\n_start:"); 215 | } else { 216 | sprintf(strbucket, "global %s%d\n%s%d:", FUNC_PRE, funcname, 217 | FUNC_PRE, funcname); 218 | } 219 | output(strbucket); 220 | sprintf(strbucket, "%s\t%s", PUSH, EBP); 221 | output(strbucket); 222 | sprintf(strbucket, "%s\t%s, %s", MOV, EBP, ESP); 223 | output(strbucket); 224 | } 225 | 226 | void code_clean_stack(int height) 227 | { 228 | sprintf(strbucket, "%s\t%s, %d", ADD, ESP, height); 229 | output(strbucket); 230 | } 231 | 232 | void code_end_func(int funcname) 233 | { 234 | sprintf(strbucket, "%s", LEAVE); 235 | output(LEAVE); 236 | 237 | if (!func_is_main(funcname)) { 238 | output(RET); 239 | } else { 240 | code_end_main(); 241 | } 242 | } 243 | 244 | void code_sub_esp(int size) 245 | { 246 | sprintf(strbucket, "%s\t%s, %d", SUB, ESP, size); 247 | output(strbucket); 248 | } 249 | 250 | void code_test_condition(int reg, int test, int labelno) 251 | { 252 | char regstr[REGSTR_LENGTH]; 253 | getregstr(regstr, reg); 254 | 255 | sprintf(strbucket, "%s\t%s, %d", CMP, regstr, test); 256 | output(strbucket); 257 | sprintf(strbucket, "%s\t%s%d", JE, LABEL, labelno); 258 | output(strbucket); 259 | } 260 | 261 | void code_op_assign(int target, int source) 262 | { 263 | char t_reg[VARSTR_LENGTH]; 264 | char s_reg[REGSTR_LENGTH]; 265 | 266 | getregstr(s_reg, source); 267 | getregstr(t_reg, target); 268 | 269 | sprintf(strbucket, "%s\t%s [%s], %s", MOV, VARSIZE, t_reg, s_reg); 270 | output(strbucket); 271 | } 272 | 273 | int code_get_array_offset(int baseoff, int idxreg, int varlength, int global) 274 | { 275 | char regstr[REGSTR_LENGTH]; 276 | getregstr(regstr, idxreg); 277 | 278 | if (global == 0) { /* general local var */ 279 | sprintf(strbucket, "%s\t%s, %s", MOV, EBX, EBP); 280 | output(strbucket); 281 | } else if (global == -1) { /* parameter */ 282 | /* the array position in memory */ 283 | sprintf(strbucket, "%s\t%s, [%s+%d]", MOV, EBX, EBP, baseoff); 284 | output(strbucket); 285 | } else { /* global var, just calculate the array index offset */ 286 | sprintf(strbucket, "%s\t%s, 0", MOV, EBX); 287 | output(strbucket); 288 | } 289 | 290 | /* get the array index offset */ 291 | sprintf(strbucket, "%s\t%s, %d", IMUL, regstr, varlength); 292 | output(strbucket); 293 | 294 | sprintf(strbucket, "%s\t%s, %s", ADD, EBX, EAX); 295 | output(strbucket); 296 | 297 | if (global == 0) { 298 | sprintf(strbucket, "%s\t%s, %d", SUB, EBX, abs(baseoff)); 299 | output(strbucket); 300 | } 301 | 302 | return 2; /* store in ebx */ 303 | } 304 | 305 | /* put the result in eax */ 306 | int code_op_binary(int v1, int v2, char *op) 307 | { 308 | char regstr1[REGSTR_LENGTH]; 309 | char regstr2[REGSTR_LENGTH]; 310 | 311 | getregstr(regstr1, v1); 312 | getregstr(regstr2, v2); 313 | 314 | int sar = 31; 315 | 316 | if (strcmp(op, "+") == 0) { 317 | sprintf(strbucket, "%s\t%s, [%s+%s]", LEA, EAX, regstr1, 318 | regstr2); 319 | 320 | } else if (strcmp(op, "-") == 0) { 321 | sprintf(strbucket, "%s\t%s, %s", SUB, regstr1, regstr2); 322 | 323 | } else if (strcmp(op, "*") == 0) { 324 | sprintf(strbucket, "%s\t%s, %s", IMUL, regstr1, regstr2); 325 | 326 | } else if (strcmp(op, "/") == 0) { 327 | sprintf(strbucket, "%s\t%s, %s", MOV, EDX, regstr1); 328 | output(strbucket); 329 | sprintf(strbucket, "%s\t%s, %d", SAR, EDX, sar); 330 | output(strbucket); 331 | sprintf(strbucket, "%s\t%s", IDIV, regstr2); 332 | 333 | } else { /* relop */ 334 | sprintf(strbucket, "%s\t%s, %s", CMP, regstr1, regstr2); 335 | output(strbucket); 336 | 337 | if (strcmp(op, "==") == 0) { 338 | sprintf(strbucket, "%s\t%s", SETE, AL); 339 | 340 | } else if (strcmp(op, "!=") == 0) { 341 | sprintf(strbucket, "%s\t%s", SETNE, AL); 342 | 343 | } else if (strcmp(op, ">") == 0) { 344 | sprintf(strbucket, "%s\t%s", SETG, AL); 345 | 346 | } else if (strcmp(op, "<") == 0) { 347 | sprintf(strbucket, "%s\t%s", SETL, AL); 348 | 349 | } else if (strcmp(op, ">=") == 0) { 350 | sprintf(strbucket, "%s\t%s", SETGE, AL); 351 | 352 | } else if (strcmp(op, "<=") == 0) { 353 | sprintf(strbucket, "%s\t%s", SETLE, AL); 354 | } 355 | 356 | output(strbucket); 357 | sprintf(strbucket, "%s\t%s, %s", MOVZX, EAX, AL); 358 | } 359 | 360 | output(strbucket); 361 | 362 | return 1; /* return which reg it stores the result */ 363 | } 364 | 365 | int code_data_section() 366 | { 367 | static int data_mark = 0; 368 | 369 | if (!data_mark) { 370 | strcpy(strbucket, "section .data"); 371 | output(strbucket); 372 | strcpy(strbucket, "numbers db \"0123456789\", 0xA"); 373 | output(strbucket); 374 | strcpy(strbucket, "inputchar db 0"); 375 | output(strbucket); 376 | 377 | ++data_mark; 378 | return 0; 379 | } 380 | 381 | return data_mark; 382 | } 383 | 384 | /* output function */ 385 | void code_func_output() 386 | { 387 | /*code_start_func(); */ 388 | strcpy(strbucket, 389 | "sub esp, 4\nmov dword [ebp-4], 0\njmp G2\nG1:\nadd dword [ebp-4], 1\npush edx"); 390 | output(strbucket); 391 | strcpy(strbucket, 392 | "G2:\nmov edx, 0\nmov eax, [ebp+8]\nmov ebx, 10\ndiv ebx\nmov [ebp+8], eax"); 393 | output(strbucket); 394 | strcpy(strbucket, 395 | "cmp eax, 0\njnz G1\npush edx\nadd dword [ebp-4], 1\njmp G3"); 396 | output(strbucket); 397 | strcpy(strbucket, 398 | "G4:\nsub dword [ebp-4], 1\npop edx\nmov eax, 4\nmov ebx, 1\nmov ecx, numbers"); 399 | output(strbucket); 400 | strcpy(strbucket, "add ecx, edx\nmov edx, 1\nint 80h"); 401 | output(strbucket); 402 | strcpy(strbucket, 403 | "G3:\ncmp dword [ebp-4], 0\njnz G4\nmov eax, 4\nmov ebx, 1\nlea ecx, [numbers+10]"); 404 | output(strbucket); 405 | strcpy(strbucket, "mov edx, 1\nint 80h"); 406 | output(strbucket); 407 | } 408 | 409 | /* input function */ 410 | void code_func_input() 411 | { 412 | strcpy(strbucket, 413 | "sub esp, 4\nmov dword [ebp-4], 0\nmov byte [inputchar], 0\njmp G6"); 414 | output(strbucket); 415 | strcpy(strbucket, 416 | "G5:\nmov dword eax, [ebp-4]\nmov ebx, 10\nmul ebx\nxor ecx, ecx"); 417 | output(strbucket); 418 | strcpy(strbucket, 419 | "mov byte cl, [inputchar]\nsub ecx, 48\nadd eax, ecx\nmov dword [ebp-4], eax"); 420 | output(strbucket); 421 | strcpy(strbucket, 422 | "G6:\nmov eax, 03h\nmov ebx, 00h\nmov ecx, inputchar\nmov edx, 01h"); 423 | output(strbucket); 424 | strcpy(strbucket, 425 | "int 80h\ncmp byte [inputchar], 0ah\njne G5\nmov dword eax, [ebp-4]"); 426 | output(strbucket); 427 | } 428 | 429 | static void code_end_main() 430 | { 431 | sprintf(strbucket, "mov ebx, eax\nmov eax,1\nint 80h"); 432 | output(strbucket); 433 | } 434 | -------------------------------------------------------------------------------- /command.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMAND_H 2 | #define COMMAND_H 3 | 4 | #define LABEL "L" 5 | #define CMP "cmp" 6 | #define JNE "jne" 7 | #define JE "je" 8 | #define MOV "mov" 9 | #define JMP "jmp" 10 | #define PUSH "push" 11 | #define POP "pop" 12 | #define ADD "add" 13 | #define SUB "sub" 14 | #define IMUL "imul" 15 | #define IDIV "idiv" 16 | #define LEA "lea" 17 | #define LEAVE "leave" 18 | #define RET "ret" 19 | #define SAR "sar" 20 | #define CMP "cmp" 21 | #define SETE "sete" 22 | #define SETNE "setne" 23 | #define SETG "setg" 24 | #define SETL "setl" 25 | #define SETGE "setge" 26 | #define SETLE "setle" 27 | #define MOVZX "movzx" 28 | #define CALLF "call" 29 | 30 | #define EAX "eax" 31 | #define EBX "ebx" 32 | #define ECX "ecx" 33 | #define EDX "edx" 34 | #define EBP "ebp" 35 | #define ESP "esp" 36 | #define AL "al" 37 | 38 | #define VARSIZE "dword" 39 | #define GLOBAL_VAR_LENGTH 2 40 | #define GLOBAL_VAR_DEFINE "resw" 41 | #define VARSTR_LENGTH 20 /* for [ebp-4] ... */ 42 | #define REGSTR_LENGTH 4 43 | 44 | #define MAX_STR_LENGTH 300 45 | 46 | #define FUNC_PRE "F_" 47 | #define GDATA_PRE "D_" 48 | 49 | char strbucket[MAX_STR_LENGTH]; 50 | 51 | void output(const char *str); 52 | static int func_is_main(int funcname); 53 | static void getvarstr(char *varstr, int offset); 54 | static int getregstr(char *regstr, int reg); 55 | int creat_label(); 56 | void code_label(int labelno); 57 | void code_jmp(int labelno); 58 | void code_pop(int reg); 59 | void code_lea_global(int target, int addr, int offset); 60 | void code_lea_local(int target, int var); 61 | void code_move_reg(int target, int source); 62 | void code_push_mem(int addr, int offset); 63 | void code_push_reg(int reg, int mem); 64 | void code_push_ind(int idx); 65 | void code_push_cons(int constant); 66 | void code_push_global_var(int var, int offset); 67 | void code_push_global_array(int var); 68 | void code_call_func(int funcname); 69 | void code_start_bss(); 70 | void code_start_text(); 71 | void code_declare_global_var(int varname, int size); 72 | void code_start_func(int funcname); 73 | void code_clean_stack(int height); 74 | void code_end_func(int funcname); 75 | void code_sub_esp(int size); 76 | void code_test_condition(int reg, int test, int labelno); 77 | void code_op_assign(int target, int source); 78 | int code_get_array_offset(int baseoff, int idxreg, int varlength, int global); 79 | int code_op_binary(int v1, int v2, char *op); 80 | 81 | int code_data_section(); 82 | void code_func_output(); 83 | void code_func_input(); 84 | static void code_end_main(); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /hash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hash.h" 5 | 6 | #define HASHSIZE 19 7 | 8 | #define TRUE 1 9 | #define FALSE 0 10 | 11 | unsigned int ELFHash(const char *str, unsigned int len) 12 | { 13 | unsigned int hash = 0; 14 | unsigned int x = 0; 15 | unsigned int i = 0; 16 | for (i = 0; i < len; str++, i++) { 17 | hash = (hash << 4) + (*str); 18 | if ((x = hash & 0xF0000000L) != 0) { 19 | hash ^= (x >> 24); 20 | } 21 | hash &= ~x; 22 | } 23 | return hash; 24 | } 25 | 26 | static void hash_freenode(HashNode * node) 27 | { 28 | if (node == NULL) 29 | return; 30 | 31 | if (node->next != NULL) 32 | hash_freenode(node->next); 33 | 34 | free(node); 35 | } 36 | 37 | void hash_init(HashNode * table[], int size) 38 | { 39 | int i; 40 | for (i = 0; i < size; ++i) 41 | table[i] = NULL; 42 | } 43 | 44 | void hash_freetable(HashNode * table[], int size) 45 | { 46 | int i; 47 | for (i = 0; i < size; ++i) { 48 | hash_freenode(table[i]); 49 | table[i] = NULL; 50 | } 51 | } 52 | 53 | HashNode *hash_insert(HashNode * table[], int size, int hashvalue, int data) 54 | { 55 | int index; 56 | HashNode *tmp; 57 | 58 | if ((tmp = hash_lookup(table, size, hashvalue)) != NULL) 59 | return tmp; 60 | 61 | index = hashvalue % size; 62 | tmp = table[index]; 63 | 64 | if (tmp == NULL) { 65 | table[index] = malloc(sizeof(HashNode)); 66 | table[index]->hash = hashvalue; 67 | table[index]->data = data; 68 | table[index]->next = NULL; 69 | 70 | return table[index]; 71 | } 72 | 73 | while (tmp->next != NULL) 74 | tmp = tmp->next; 75 | 76 | if ((tmp->next = malloc(sizeof(HashNode))) == NULL) 77 | return NULL; 78 | tmp->next->hash = hashvalue; 79 | tmp->next->data = data; 80 | tmp->next->next = NULL; 81 | 82 | return tmp->next; 83 | } 84 | 85 | HashNode *hash_lookup(HashNode * table[], int size, int hashvalue) 86 | { 87 | int index; 88 | HashNode *tmp; 89 | 90 | index = hashvalue % size; 91 | tmp = table[index]; 92 | 93 | if (tmp == NULL) { 94 | return NULL; 95 | } 96 | 97 | if (tmp->hash == hashvalue) 98 | return tmp; 99 | 100 | while (tmp->next != NULL) { 101 | tmp = tmp->next; 102 | if (tmp->hash == hashvalue) 103 | return tmp; 104 | } 105 | 106 | return NULL; /* not found */ 107 | } 108 | -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | #ifndef HASH_H 2 | #define HASH_H 3 | 4 | #define DATASIZE 3 5 | 6 | typedef struct HashNodeTag { 7 | int hash; 8 | int data; 9 | struct HashNodeTag *next; 10 | } HashNode; 11 | 12 | unsigned int ELFHash(const char *str, unsigned int len); 13 | void hash_freetable(HashNode * table[], int size); 14 | HashNode *hash_insert(HashNode * table[], int size, int hashvalue, int data); 15 | HashNode *hash_lookup(HashNode * table[], int size, int hashvalue); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | parser: lex.yy.c y.tab.c y.tab.h parser.c hash.h hash.c var.h command.h command.c 2 | gcc -o parser lex.yy.c y.tab.c parser.c hash.c command.c -ll 3 | 4 | lex: 5 | lex c-grammar.lex 6 | 7 | yacc: 8 | yacc -d c-grammar.y 9 | -------------------------------------------------------------------------------- /node.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_H 2 | #define NODE_H 3 | 4 | /* 定义树结点的权举类型 */ 5 | typedef enum { TYPE_CONTENT, TYPE_INDEX, TYPE_OP } NodeEnum; 6 | 7 | /* 操作符 */ 8 | typedef struct { 9 | int name; /* 操作符名称 */ 10 | int num; /* 操作元个数 */ 11 | struct NodeTag *node[1]; /* 操作元地址 可扩展 */ 12 | } OpNode; 13 | typedef struct NodeTag { 14 | NodeEnum type; /* 树结点类型 */ 15 | 16 | /* Union 必须是最后一个成员 */ 17 | union { 18 | int content; /* 内容 */ 19 | int index; /* 索引 */ 20 | OpNode op; /* 操作符对象 */ 21 | }; 22 | } Node; 23 | 24 | #endif /* */ 25 | -------------------------------------------------------------------------------- /parser.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "node.h" 4 | #include "y.tab.h" 5 | #include "hash.h" 6 | #include "var.h" 7 | int offset_local; 8 | int offset_param; 9 | int current_func; 10 | int in_func_declaration; 11 | int exeNode(Node * p, int signal) 12 | { 13 | HashNode * node, *s_or_a, *g_or_p; 14 | char binary_op_str[3]; 15 | int label[2]; 16 | int retvalue; 17 | int count; 18 | if (!p) 19 | return 0; 20 | switch (p->type) { 21 | case TYPE_CONTENT: 22 | if (signal) { 23 | code_push_cons(p->content); 24 | } 25 | return 1; 26 | case TYPE_INDEX: 27 | node = hash_lookup(var_local, HASHSIZE, p->index); 28 | if (node == NULL) { 29 | /* it should be the global var */ 30 | if (signal) { /* as right operand */ 31 | s_or_a = 32 | hash_lookup(var_global_SorA, HASHSIZE, 33 | p->index); 34 | if (s_or_a->data == SCALAR) { 35 | code_push_global_var(p->index, 0); 36 | } else { /* array */ 37 | code_push_global_array(p->index); 38 | } 39 | } else { /* as left operand */ 40 | code_lea_global(2, p->index, 0); 41 | } 42 | } else { /* local */ 43 | if (signal) { /* as right operand */ 44 | code_push_ind(node->data); 45 | } else { /* as left operand */ 46 | code_lea_local(2, node->data); 47 | } 48 | } 49 | return 1; 50 | case TYPE_OP: 51 | switch (p->op.name) { 52 | case GLOBAL_VAR: 53 | code_start_bss(); 54 | count = exeNode(p->op.node[0], 1); 55 | return count; 56 | case VAR: 57 | if (signal) { /* global var declaration */ 58 | if (p->op.num == 2) { /* not array */ 59 | code_declare_global_var(p->op.node[1]-> 60 | index, 1); 61 | s_or_a = 62 | hash_insert(var_global_SorA, 63 | HASHSIZE, 64 | p->op.node[1]->index, 65 | SCALAR); 66 | } else if (p->op.num == 3) { /* array */ 67 | code_declare_global_var(p->op.node[1]-> 68 | index, 69 | p->op. 70 | node[2]-> 71 | content); 72 | s_or_a = 73 | hash_insert(var_global_SorA, 74 | HASHSIZE, 75 | p->op.node[1]->index, 76 | ARRAY); 77 | } 78 | } else { 79 | if (p->op.num == 2) { /* not array */ 80 | 81 | /* FIXME:var_count thing, esp */ 82 | offset_local -= VAR_LENGTH; 83 | code_sub_esp(VAR_LENGTH); 84 | node = 85 | hash_insert(var_local, HASHSIZE, 86 | p->op.node[1]->index, 87 | offset_local); 88 | s_or_a = 89 | hash_insert(var_local_SorA, 90 | HASHSIZE, 91 | p->op.node[1]->index, 92 | SCALAR); 93 | g_or_p = 94 | hash_insert(var_local_GorP, 95 | HASHSIZE, 96 | p->op.node[1]->index, 97 | GENERAL); 98 | } else if (p->op.num == 3) { 99 | 100 | /* FIXME:var_count thing, esp */ 101 | offset_local -= 102 | VAR_LENGTH * p->op.node[2]->content; 103 | code_sub_esp(VAR_LENGTH * 104 | p->op.node[2]->content); 105 | node = 106 | hash_insert(var_local, HASHSIZE, 107 | p->op.node[1]->index, 108 | offset_local); 109 | s_or_a = 110 | hash_insert(var_local_SorA, 111 | HASHSIZE, 112 | p->op.node[1]->index, 113 | ARRAY); 114 | g_or_p = 115 | hash_insert(var_local_GorP, 116 | HASHSIZE, 117 | p->op.node[1]->index, 118 | GENERAL); 119 | } 120 | } 121 | return 0; 122 | case FUNC: 123 | retvalue = code_data_section(); 124 | if (!retvalue) { /* start text section */ 125 | code_start_text(); 126 | 127 | /* output function */ 128 | current_func = 129 | ELFHash(FUNC_OUTPUT_NAME, 130 | strlen(FUNC_OUTPUT_NAME)); 131 | code_start_func(current_func); 132 | code_func_output(); 133 | code_end_func(current_func); 134 | 135 | /* input function */ 136 | current_func = 137 | ELFHash(FUNC_INPUT_NAME, 138 | strlen(FUNC_INPUT_NAME)); 139 | code_start_func(current_func); 140 | code_func_input(); 141 | code_end_func(current_func); 142 | } 143 | if (p->op.num == 1) { /* compound */ 144 | in_func_declaration = 0; 145 | count = exeNode(p->op.node[0], 0); 146 | code_end_func(current_func); 147 | } else { /* declaration */ 148 | hash_freetable(var_local, HASHSIZE); 149 | hash_freetable(var_local_SorA, HASHSIZE); 150 | hash_freetable(var_local_GorP, HASHSIZE); 151 | offset_local = 0; 152 | in_func_declaration = 1; 153 | 154 | /* in callee, [ebp] is the old ebp, [ebp+4] is the caller's addr 155 | * so the param start at [ebp+8] */ 156 | offset_param = VAR_LENGTH; 157 | 158 | /*param_count = 0; */ 159 | current_func = p->op.node[1]->index; 160 | code_start_func(p->op.node[1]->index); 161 | 162 | /* the local variables */ 163 | count = exeNode(p->op.node[2], 0); 164 | } 165 | return 1; 166 | case PARAM: 167 | 168 | /*++param_count; */ 169 | offset_param += VAR_LENGTH; 170 | node = 171 | hash_insert(var_local, HASHSIZE, 172 | p->op.node[1]->index, offset_param); 173 | g_or_p = 174 | hash_insert(var_local_GorP, HASHSIZE, 175 | p->op.node[1]->index, PARAMETER); 176 | if (p->op.num == 2) { /* no [ ] */ 177 | s_or_a = 178 | hash_insert(var_local_SorA, HASHSIZE, 179 | p->op.node[1]->index, SCALAR); 180 | } else { /* [ ] pointer */ 181 | s_or_a = 182 | hash_insert(var_local_SorA, HASHSIZE, 183 | p->op.node[1]->index, ARRAY); 184 | } 185 | return 0; 186 | case '=': 187 | 188 | /* 1 means need push when means need push */ 189 | count = exeNode(p->op.node[1], 1); 190 | count += exeNode(p->op.node[0], 0); 191 | code_pop(1); 192 | code_op_assign(2, 1); 193 | if (signal) { /* as right operand */ 194 | code_push_ind(p->op.node[0]->index); 195 | } 196 | return 1; 197 | case '<': 198 | strcpy(binary_op_str, "<"); 199 | goto op_binary; 200 | case '>': 201 | strcpy(binary_op_str, ">"); 202 | goto op_binary; 203 | case LE_OP: 204 | strcpy(binary_op_str, "<="); 205 | goto op_binary; 206 | case GE_OP: 207 | strcpy(binary_op_str, ">="); 208 | goto op_binary; 209 | case EQ_OP: 210 | strcpy(binary_op_str, "=="); 211 | goto op_binary; 212 | case NE_OP: 213 | strcpy(binary_op_str, "!="); 214 | goto op_binary; 215 | case '+': 216 | strcpy(binary_op_str, "+"); 217 | goto op_binary; 218 | case '-': 219 | strcpy(binary_op_str, "-"); 220 | goto op_binary; 221 | case '*': 222 | strcpy(binary_op_str, "*"); 223 | goto op_binary; 224 | case '/': 225 | strcpy(binary_op_str, "/"); 226 | op_binary:count = 227 | exeNode(p->op.node[0], 1); 228 | count += exeNode(p->op.node[1], 1); 229 | code_pop(2); 230 | code_pop(1); 231 | retvalue = code_op_binary(1, 2, binary_op_str); 232 | if (signal) 233 | code_push_reg(retvalue, 0); 234 | return 1; 235 | case '[': /* array */ 236 | count = exeNode(p->op.node[1], 1); 237 | 238 | /* pop the idx into eax */ 239 | code_pop(1); 240 | 241 | /* get the array base offset */ 242 | node = 243 | hash_lookup(var_local, HASHSIZE, 244 | p->op.node[0]->index); 245 | if (node == NULL) { 246 | 247 | /* global */ 248 | retvalue = 249 | code_get_array_offset(0, 1, VAR_LENGTH, 1); 250 | if (signal) { /* use as right operand */ 251 | code_push_mem(p->op.node[0]->index, 252 | retvalue); 253 | } else { /* use as left oprand */ 254 | 255 | /* put the addr into ebx */ 256 | code_lea_global(2, 257 | p->op.node[0]-> 258 | index, retvalue); 259 | } 260 | } else { 261 | g_or_p = 262 | hash_lookup(var_local_GorP, HASHSIZE, 263 | p->op.node[0]->index); 264 | if (g_or_p->data == GENERAL) { 265 | retvalue = 266 | code_get_array_offset(node->data, 1, 267 | VAR_LENGTH, 268 | 0); 269 | } else if (g_or_p->data == PARAMETER) { 270 | retvalue = 271 | code_get_array_offset(node->data, 1, 272 | VAR_LENGTH, 273 | -1); 274 | } 275 | if (signal) { /* use as left oprand */ 276 | code_push_reg(retvalue, 1); 277 | } else { /* use as right oprand */ 278 | code_move_reg(2, retvalue); 279 | } 280 | } 281 | return count; 282 | case CALL: 283 | 284 | /*printf("call params:\n"); */ 285 | count = exeNode(p->op.node[1], 1); 286 | 287 | code_call_func(p->op.node[0]->index); 288 | code_clean_stack(count * VAR_LENGTH); 289 | if (signal) 290 | code_push_reg(1, 0); /* function save the ret in eax */ 291 | return count; 292 | case '{': 293 | case ';': 294 | count = exeNode(p->op.node[0], 0); 295 | return (exeNode(p->op.node[1], 0) + count); 296 | case ',': 297 | if (in_func_declaration) { 298 | 299 | /* from right to left */ 300 | count = exeNode(p->op.node[1], signal); 301 | return (exeNode(p->op.node[0], signal) + 302 | count); 303 | } else { 304 | /* from left to right */ 305 | count = exeNode(p->op.node[0], signal); 306 | return (exeNode(p->op.node[1], signal) + 307 | count); 308 | } 309 | case WHILE: 310 | label[0] = creat_label(); 311 | label[1] = creat_label(); 312 | 313 | /* the main proc */ 314 | code_jmp(label[0]); 315 | code_label(label[1]); 316 | count = exeNode(p->op.node[1], 0); 317 | 318 | /* condition */ 319 | code_label(label[0]); 320 | count += exeNode(p->op.node[0], 1); 321 | code_pop(1); 322 | code_test_condition(1, 1, label[1]); 323 | return 0; 324 | case IF: 325 | label[0] = creat_label(); 326 | 327 | /* condition */ 328 | exeNode(p->op.node[0], 1); 329 | code_pop(1); 330 | code_test_condition(1, 0, label[0]); 331 | 332 | /* the main proc */ 333 | count += exeNode(p->op.node[1], 0); 334 | if (p->op.num > 2) { /* else label */ 335 | label[1] = creat_label(); 336 | code_jmp(label[1]); 337 | } 338 | code_label(label[0]); 339 | 340 | /* else proc */ 341 | if (p->op.num > 2) { 342 | count += exeNode(p->op.node[2], 0); 343 | code_label(label[1]); 344 | } 345 | return 0; 346 | case RETURN: 347 | if (p->op.num > 0) 348 | count = exeNode(p->op.node[0], 1); 349 | code_pop(1); /* ret value */ 350 | 351 | /* FIXME: there may be two "leave & ret" 352 | * since it is also called when function ends */ 353 | code_end_func(current_func); 354 | return 0; 355 | } 356 | } 357 | return 0; 358 | } 359 | -------------------------------------------------------------------------------- /test/test.c: -------------------------------------------------------------------------------- 1 | int gcd(int u, int v) 2 | { 3 | if (v == 0) 4 | return u; 5 | else 6 | return gcd(v, u - u / v * v); 7 | } 8 | 9 | int main(void) 10 | { 11 | int x; 12 | int y; 13 | x = input(); 14 | y = input(); 15 | output(gcd(x, y)); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /test/test2.c: -------------------------------------------------------------------------------- 1 | int x[10]; 2 | 3 | int minloc(int a[], int low, int high) 4 | { 5 | int i; 6 | int x; 7 | int k; 8 | k = low; 9 | x = a[low]; 10 | i = low + 1; 11 | while (i < high) { 12 | if (a[i] < x) { 13 | x = a[i]; 14 | k = i; 15 | } 16 | i = i + 1; 17 | } 18 | 19 | return k; 20 | } 21 | 22 | void sort(int a[], int low, int high) 23 | { 24 | int i; 25 | int k; 26 | int t; 27 | i = low; 28 | while (i < high - 1) { 29 | k = minloc(a, i, high); 30 | t = a[k]; 31 | a[k] = a[i]; 32 | a[i] = t; 33 | i = i + 1; 34 | } 35 | } 36 | 37 | int main(void) 38 | { 39 | int i; 40 | i = 0; 41 | while (i < 10) { 42 | x[i] = input(); 43 | i = i + 1; 44 | } 45 | sort(x, 0, 10); 46 | i = 0; 47 | while (i < 10) { 48 | output(x[i]); 49 | i = i + 1; 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /test/test3.c: -------------------------------------------------------------------------------- 1 | int main(void) 2 | { 3 | int i; int sum; 4 | i = 1; sum = 0; 5 | while (i <= 100) { 6 | sum = sum + i; 7 | i = i + 1; 8 | } 9 | output(sum); 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /test/test4.c: -------------------------------------------------------------------------------- 1 | int fib(int n) 2 | { 3 | int result; 4 | if (n < 2) 5 | return n; 6 | 7 | result = fib(n-1) + fib(n-2); 8 | return result; 9 | } 10 | 11 | int main(void) 12 | { 13 | int n; int i; 14 | i = 0; 15 | n = input(); 16 | while (i <= n) { 17 | output(fib(i)); 18 | i = i + 1; 19 | } 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /var.h: -------------------------------------------------------------------------------- 1 | #ifndef VAR_H 2 | #define VAR_H 3 | 4 | #define VAR_LENGTH 4 5 | #define HASHSIZE 19 6 | 7 | #define SCALAR 1 8 | #define ARRAY 2 9 | #define GENERAL 1 10 | #define PARAMETER 2 11 | 12 | #define FUNC_OUTPUT_NAME "output" 13 | #define FUNC_INPUT_NAME "input" 14 | 15 | HashNode *var_local[HASHSIZE]; 16 | HashNode *var_local_SorA[HASHSIZE]; /* whether it is scalar or array */ 17 | HashNode *var_local_GorP[HASHSIZE]; /* general local or param */ 18 | HashNode *var_global_SorA[HASHSIZE]; /* general local or param */ 19 | 20 | #endif 21 | --------------------------------------------------------------------------------