Skip to content

Commit 3d05c80

Browse files
committed
Resizes variable when assigning
1 parent c13d260 commit 3d05c80

File tree

10 files changed

+150
-83
lines changed

10 files changed

+150
-83
lines changed

src/arm-codegen.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
126126
elf_offset += 4;
127127
return;
128128
default:
129-
printf("Unknown opcode\n");
130-
abort();
129+
error_no_loc("Unknown opcode");
131130
}
132131
}
133132

@@ -428,24 +427,24 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
428427
emit(__mov_i(__EQ, rd, 1));
429428
return;
430429
case OP_trunc:
431-
if (rm == 1) {
430+
if (rm == 1)
432431
rm = 0xFF;
433-
} else if (rm == 4) {
432+
else if (rm == 2)
433+
rm = 0xFFFF;
434+
else if (rm == 4)
434435
rm = 0xFFFFFFFF;
435-
} else {
436-
printf("Unsupported truncation operation with target size %d\n",
437-
rm);
438-
abort();
439-
}
436+
else
437+
error_no_loc(
438+
"Unsupported truncation operation with invalid target size");
440439

441440
emit(__and_i(__AL, rd, rn, rm));
442441
return;
443442
case OP_sign_ext:
443+
/* TODO: Allow to sign extends to other types */
444444
emit(__sxtb(__AL, rd, rn, 0));
445445
return;
446446
default:
447-
printf("Unknown opcode\n");
448-
abort();
447+
error_no_loc("Unknown opcode");
449448
}
450449
}
451450

src/arm.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,8 @@ int __teq(arm_reg rd)
357357

358358
int __sxtb(arm_cond_t cond, arm_reg rd, arm_reg rm, int rotation)
359359
{
360-
if (rotation != 0 && rotation != 8 && rotation != 16 && rotation != 24) {
361-
printf("SXTB rotation must be 0, 8, 16, or 24\n");
362-
abort();
363-
}
360+
if (rotation != 0 && rotation != 8 && rotation != 16 && rotation != 24)
361+
error_no_loc("SXTB rotation must be 0, 8, 16, or 24");
364362

365363
return arm_encode(cond, 106, 0xF, rd,
366364
rm | ((rotation >> 3) << 10) | (0x7 << 4));

src/defs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,6 @@ typedef struct var_list {
290290
} var_list_t;
291291

292292
struct var {
293-
char type_name[MAX_TYPE_LEN];
294293
type_t *type;
295294
char var_name[MAX_VAR_LEN];
296295
int is_ptr;

src/elf.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
/* ELF file manipulation */
99

10+
#include "../config"
11+
#include "defs.h"
12+
#include "globals.c"
13+
1014
int elf_symbol_index;
1115

1216
void elf_write_str(strbuf_t *elf_array, char *vals)

src/globals.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#pragma once
9+
#include <stdarg.h>
910
#include <stdbool.h>
1011
#include <stdio.h>
1112
#include <stdlib.h>
@@ -691,9 +692,7 @@ int size_var(var_t *var)
691692
if (var->is_ptr > 0 || var->is_func) {
692693
size = 4;
693694
} else {
694-
type_t *type = find_type(var->type_name, 0);
695-
if (!type)
696-
error("Incomplete type");
695+
type_t *type = var->type;
697696
if (type->size == 0)
698697
size = type->base_struct->size;
699698
else
@@ -1018,6 +1017,14 @@ void global_release()
10181017
strbuf_free(elf_section);
10191018
}
10201019

1020+
/* Reports an error without specifying a position */
1021+
void error_no_loc(char *msg)
1022+
{
1023+
printf("[Error]: %s\n", msg);
1024+
abort();
1025+
}
1026+
1027+
/* Reports an error and specifying a position */
10211028
void error(char *msg)
10221029
{
10231030
/* Construct error source diagnostics, enabling precise identification of
@@ -1081,7 +1088,7 @@ void dump_bb_insn(func_t *func, basic_block_t *bb, bool *at_func_start)
10811088
continue;
10821089
case OP_allocat:
10831090
print_indent(1);
1084-
printf("allocat %s", rd->type_name);
1091+
printf("allocat %s", rd->type->type_name);
10851092

10861093
for (int i = 0; i < rd->is_ptr; i++)
10871094
printf("*");
@@ -1287,7 +1294,7 @@ void dump_insn()
12871294
for (func_t *func = FUNC_LIST.head; func; func = func->next) {
12881295
bool at_func_start = true;
12891296

1290-
printf("def %s", func->return_def.type_name);
1297+
printf("def %s", func->return_def.type->type_name);
12911298

12921299
for (int i = 0; i < func->return_def.is_ptr; i++)
12931300
printf("*");
@@ -1296,11 +1303,11 @@ void dump_insn()
12961303
for (int i = 0; i < func->num_params; i++) {
12971304
if (i != 0)
12981305
printf(", ");
1299-
printf("%s", func->param_defs[i].type_name);
1306+
printf("%s", func->param_defs[i].type->type_name);
13001307

13011308
for (int k = 0; k < func->param_defs[i].is_ptr; k++)
13021309
printf("*");
1303-
printf(" %%%s", func->param_defs[i].var_name);
1310+
printf(" %%%s", func->param_defs[i].type->type_name);
13041311
}
13051312
printf(") {\n");
13061313

@@ -1312,7 +1319,7 @@ void dump_insn()
13121319
if (!bb)
13131320
continue;
13141321

1315-
if (strcmp(func->return_def.type_name, "void"))
1322+
if (func->return_def.type != TY_void)
13161323
continue;
13171324

13181325
if (bb->insn_list.tail)

src/parser.c

Lines changed: 79 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ int write_symbol(char *data)
122122
return start_len;
123123
}
124124

125-
int get_size(var_t *var, type_t *type)
125+
int get_size(var_t *var)
126126
{
127127
if (var->is_ptr || var->is_func)
128128
return PTR_SIZE;
129-
return type->size;
129+
return var->type->size;
130130
}
131131

132132
int get_operator_prio(opcode_t op)
@@ -222,24 +222,74 @@ opcode_t get_operator()
222222
return op;
223223
}
224224

225-
var_t *promote(block_t *block, basic_block_t **bb, var_t *var)
225+
/**
226+
*
227+
*/
228+
var_t *promote_unchecked(block_t *block,
229+
basic_block_t **bb,
230+
var_t *var,
231+
type_t *target_type,
232+
int target_ptr)
233+
{
234+
var_t *rd = require_typed_ptr_var(block, target_type, target_ptr);
235+
gen_name_to(rd->var_name);
236+
add_insn(block, *bb, OP_sign_ext, rd, var, NULL, target_type->size, NULL);
237+
return rd;
238+
}
239+
240+
var_t *promote(block_t *block,
241+
basic_block_t **bb,
242+
var_t *var,
243+
type_t *target_type,
244+
int target_ptr)
226245
{
227246
/* Effectively checking whether var has size of int */
228-
if (var->type->size == 4 || var->is_ptr || var->array_size != 0)
247+
if (var->type->size == target_type->size || var->is_ptr || var->array_size)
229248
return var;
230249

231-
if (var->type->size > 4 && !var->is_ptr) {
250+
if (var->type->size > TY_int->size && !var->is_ptr) {
232251
printf("Warning: Suspicious type promotion %s\n", var->type->type_name);
233252
return var;
234253
}
235254

236-
var_t *rd = require_var(block);
237-
gen_name_to(rd->var_name);
238-
add_insn(block, *bb, OP_sign_ext, rd, var, NULL, 4, NULL);
255+
return promote_unchecked(block, bb, var, target_type, target_ptr);
256+
}
239257

258+
var_t *truncate_unchecked(block_t *block,
259+
basic_block_t **bb,
260+
var_t *var,
261+
type_t *target_type,
262+
int target_ptr)
263+
{
264+
var_t *rd = require_typed_ptr_var(block, target_type, target_ptr);
265+
gen_name_to(rd->var_name);
266+
add_insn(block, *bb, OP_trunc, rd, var, NULL, target_type->size, NULL);
240267
return rd;
241268
}
242269

270+
var_t *resize_var(block_t *block, basic_block_t **bb, var_t *from, var_t *to)
271+
{
272+
bool is_from_ptr = from->is_ptr || from->array_size,
273+
is_to_ptr = to->is_ptr || to->array_size;
274+
275+
if (is_from_ptr && is_to_ptr)
276+
return from;
277+
278+
int from_size = get_size(from), to_size = get_size(to);
279+
280+
if (from_size > to_size) {
281+
/* Truncation */
282+
return truncate_unchecked(block, bb, from, to->type, to->is_ptr);
283+
}
284+
285+
if (from_size < to_size) {
286+
/* Sign extend */
287+
return promote_unchecked(block, bb, from, to->type, to->is_ptr);
288+
}
289+
290+
return from;
291+
}
292+
243293
int read_numeric_constant(char buffer[])
244294
{
245295
int i = 0;
@@ -655,8 +705,7 @@ void read_full_var_decl(var_t *vd, int anon, int is_param)
655705
{
656706
char type_name[MAX_TYPE_LEN];
657707
int find_type_flag = lex_accept(T_struct) ? 2 : 1;
658-
lex_ident(T_identifier, vd->type_name);
659-
strcpy(type_name, vd->type_name);
708+
lex_ident(T_identifier, type_name);
660709
type_t *type = find_type(type_name, find_type_flag);
661710

662711
if (!type) {
@@ -672,7 +721,6 @@ void read_full_var_decl(var_t *vd, int anon, int is_param)
672721
/* starting next_token, need to check the type */
673722
void read_partial_var_decl(var_t *vd, var_t *template)
674723
{
675-
strcpy(vd->type_name, template->type_name);
676724
read_inner_var_decl(vd, 0, 0);
677725
}
678726

@@ -790,8 +838,13 @@ void read_func_parameters(func_t *func, block_t *parent, basic_block_t **bb)
790838

791839
param = opstack_pop();
792840

793-
if (func && param_num >= func->num_params && func->va_args) {
794-
param = promote(parent, bb, param);
841+
if (func) {
842+
if (param_num >= func->num_params && func->va_args) {
843+
param = promote(parent, bb, param, TY_int, 0);
844+
} else {
845+
param =
846+
resize_var(parent, bb, param, &func->param_defs[param_num]);
847+
}
795848
}
796849

797850
params[param_num++] = param;
@@ -1269,8 +1322,8 @@ void read_lvalue(lvalue_t *lvalue,
12691322
/* already peeked and have the variable */
12701323
lex_expect(T_identifier);
12711324

1272-
lvalue->type = find_type(var->type_name, 0);
1273-
lvalue->size = get_size(var, lvalue->type);
1325+
lvalue->type = var->type;
1326+
lvalue->size = get_size(var);
12741327
lvalue->is_ptr = var->is_ptr;
12751328
lvalue->is_func = var->is_func;
12761329
lvalue->is_reference = false;
@@ -1368,10 +1421,10 @@ void read_lvalue(lvalue_t *lvalue,
13681421

13691422
/* change type currently pointed to */
13701423
var = find_member(token, lvalue->type);
1371-
lvalue->type = find_type(var->type_name, 0);
1424+
lvalue->type = var->type;
13721425
lvalue->is_ptr = var->is_ptr;
13731426
lvalue->is_func = var->is_func;
1374-
lvalue->size = get_size(var, lvalue->type);
1427+
lvalue->size = get_size(var);
13751428

13761429
/* if it is an array, get the address of first element instead of
13771430
* its value.
@@ -1829,6 +1882,7 @@ bool read_body_assignment(char *token,
18291882
if (lvalue.is_reference) {
18301883
add_insn(parent, *bb, OP_write, NULL, t, vd, size, NULL);
18311884
} else {
1885+
vd = resize_var(parent, bb, vd, t);
18321886
add_insn(parent, *bb, OP_assign, t, vd, NULL, 0, NULL);
18331887
}
18341888
} else {
@@ -1868,14 +1922,7 @@ bool read_body_assignment(char *token,
18681922
add_insn(parent, *bb, OP_write, NULL, t, vd, lvalue.size,
18691923
NULL);
18701924
} else {
1871-
if (lvalue.type->size < vd->type->size) {
1872-
rs1 = require_typed_var(parent, TY_char);
1873-
gen_name_to(rs1->var_name);
1874-
add_insn(parent, *bb, OP_trunc, rs1, vd, NULL,
1875-
lvalue.size, NULL);
1876-
vd = rs1;
1877-
}
1878-
1925+
vd = resize_var(parent, bb, vd, t);
18791926
add_insn(parent, *bb, OP_assign, t, vd, NULL, 0, NULL);
18801927
}
18811928
}
@@ -1894,6 +1941,7 @@ bool read_body_assignment(char *token,
18941941
} else {
18951942
rs1 = opstack_pop();
18961943
vd = opstack_pop();
1944+
rs1 = resize_var(parent, bb, rs1, vd);
18971945
add_insn(parent, *bb, OP_assign, vd, rs1, NULL, 0, NULL);
18981946
}
18991947
}
@@ -2447,15 +2495,15 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
24472495
int find_type_flag = lex_accept(T_struct) ? 2 : 1;
24482496
type = find_type(token, find_type_flag);
24492497
if (type) {
2450-
var = require_var(blk);
2498+
var = require_typed_var(blk, type);
24512499
read_full_var_decl(var, 0, 0);
24522500
add_insn(blk, setup, OP_allocat, var, NULL, NULL, 0, NULL);
24532501
add_symbol(setup, var);
24542502
if (lex_accept(T_assign)) {
24552503
read_expr(blk, &setup);
24562504
read_ternary_operation(blk, &setup);
24572505

2458-
rs1 = opstack_pop();
2506+
rs1 = resize_var(parent, &bb, opstack_pop(), var);
24592507
add_insn(blk, setup, OP_assign, var, rs1, NULL, 0, NULL);
24602508
}
24612509
while (lex_accept(T_comma)) {
@@ -2465,14 +2513,14 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
24652513
perform_side_effect(blk, setup);
24662514

24672515
/* multiple (partial) declarations */
2468-
nv = require_var(blk);
2516+
nv = require_typed_var(blk, type);
24692517
read_partial_var_decl(nv, var); /* partial */
24702518
add_insn(blk, setup, OP_allocat, nv, NULL, NULL, 0, NULL);
24712519
add_symbol(setup, nv);
24722520
if (lex_accept(T_assign)) {
24732521
read_expr(blk, &setup);
24742522

2475-
rs1 = opstack_pop();
2523+
rs1 = resize_var(parent, &bb, opstack_pop(), nv);
24762524
add_insn(blk, setup, OP_assign, nv, rs1, NULL, 0, NULL);
24772525
}
24782526
}
@@ -2604,7 +2652,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
26042652
read_expr(parent, &bb);
26052653
read_ternary_operation(parent, &bb);
26062654

2607-
rs1 = opstack_pop();
2655+
rs1 = resize_var(parent, &bb, opstack_pop(), var);
26082656
add_insn(parent, bb, OP_assign, var, rs1, NULL, 0, NULL);
26092657
}
26102658
while (lex_accept(T_comma)) {
@@ -2621,7 +2669,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
26212669
if (lex_accept(T_assign)) {
26222670
read_expr(parent, &bb);
26232671

2624-
rs1 = opstack_pop();
2672+
rs1 = resize_var(parent, &bb, opstack_pop(), nv);
26252673
add_insn(parent, bb, OP_assign, nv, rs1, NULL, 0, NULL);
26262674
}
26272675
}

0 commit comments

Comments
 (0)