diff --git a/src/x86/dumberdowner.c b/src/x86/dumberdowner.c index 5006d89..071e623 100644 --- a/src/x86/dumberdowner.c +++ b/src/x86/dumberdowner.c @@ -611,6 +611,9 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_REF && n->exprUnOp.operand->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operand->exprUnOp.operator == UNOP_DEREF) { // Turn `&*a` into `a` + // Artificially change type of casted expression to keep types valid for subsequent passes + n->exprUnOp.operand->exprUnOp.operand->expression.type = n->expression.type; + *nptr = n->exprUnOp.operand->exprUnOp.operand; *success = true; @@ -635,6 +638,15 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *nptr = n->exprBinOp.operands[0]; + *success = true; + } else if(n->nodeKind == AST_EXPR_BINARY_OP && n->exprBinOp.operator == BINOP_ADD && n->exprBinOp.operands[1]->nodeKind == AST_EXPR_PRIMITIVE && n->exprBinOp.operands[1]->exprPrim.val == 0) { + // Turn `x + 0` into `x` + + // Artificially change type of casted expression to keep types valid for subsequent passes + n->exprBinOp.operands[0]->expression.type = n->expression.type; + + *nptr = n->exprBinOp.operands[0]; + *success = true; } else if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_NOT && n->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && binop_comp_opposite(n->exprUnOp.operand->exprBinOp.operator) != BINOP_WTF) { // Turn `!(a op b)` to `(a !op b)` @@ -653,8 +665,31 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST } else if(n->nodeKind == AST_EXPR_CAST && n->exprCast.what->expression.type->type == TYPE_TYPE_POINTER && n->exprCast.to->type == TYPE_TYPE_POINTER) { // Turn (x as A*) into x, since all pointer types are identical in Nectar's AST + // Artificially change type of casted expression to keep types valid for subsequent passes + n->exprCast.what->expression.type = n->exprCast.to; + *nptr = n->exprCast.what; + *success = true; + } else if(n->nodeKind == AST_EXPR_BINARY_OP && n->exprBinOp.operator == BINOP_ADD && n->exprBinOp.operands[0]->nodeKind == AST_EXPR_PRIMITIVE && n->exprBinOp.operands[1]->nodeKind == AST_EXPR_PRIMITIVE) { + // Constant propagation of + operator + + AST *prim = n->exprBinOp.operands[0]; + prim->expression.type = n->exprBinOp.type; + prim->exprPrim.val = n->exprBinOp.operands[0]->exprPrim.val + n->exprBinOp.operands[1]->exprPrim.val; + + *nptr = prim; + + *success = true; + } else if(n->nodeKind == AST_EXPR_BINARY_OP && n->exprBinOp.operator == BINOP_SUB && n->exprBinOp.operands[0]->nodeKind == AST_EXPR_PRIMITIVE && n->exprBinOp.operands[1]->nodeKind == AST_EXPR_PRIMITIVE) { + // Constant propagation of - operator + + AST *prim = n->exprBinOp.operands[0]; + prim->expression.type = n->exprBinOp.type; + prim->exprPrim.val = n->exprBinOp.operands[0]->exprPrim.val - n->exprBinOp.operands[1]->exprPrim.val; + + *nptr = prim; + *success = true; } else if(n->nodeKind == AST_EXPR_EXT_SIZEOF) { ASTExprPrimitive *prim = calloc(1, sizeof(*prim)); @@ -709,9 +744,10 @@ void ast_denoop(AST *tlc, AST **node) { } /* - * The convention correctness pass converts all function calls & definitions to the form that matches - * the architecture most closely. For example, arguments (and return values) in cdecl are always - * passed as 32-bit integers, even if they are defined as 8-bit or 16-bit in the source. + * The convention correctness pass converts all function calls & function sources to the form + * hat matches the architecture most closely. For example, arguments (and return values) in + * cdecl are always passed as 32-bit integers, even if they are defined as 8-bit or 16-bit in + * the source. * * TODO: convert records to proper form also. */ @@ -722,17 +758,19 @@ static void convention_correctness_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *n = *nptr; - if(n->nodeKind == AST_STMT_DECL && n->stmtDecl.thing->kind == SCOPEITEM_SYMBOL && n->stmtDecl.thing->type->type == TYPE_TYPE_FUNCTION) { - Type *type = n->stmtDecl.thing->type; + if(n->nodeKind == AST_EXPR_CALL) { + Type *type = n->exprCall.what->expression.type; - assert(n->stmtDecl.expression->exprFunc.chunk->chunk.functionType == type); - assert(type->function.ret->type == TYPE_TYPE_PRIMITIVE || type->function.ret->type == TYPE_TYPE_POINTER); + assert(type->type == TYPE_TYPE_POINTER); - type->function.ret = type_prim_cast(type->function.ret, 8 * x86_max_gpr_size()); + type = type->pointer.of; + + assert(type->type == TYPE_TYPE_FUNCTION); for(size_t i = 0; i < type->function.argCount; i++) { - assert(type->function.args[i]->type == TYPE_TYPE_PRIMITIVE || type->function.args[i]->type == TYPE_TYPE_POINTER); - type->function.args[i] = type_prim_cast(type->function.args[i], 8 * x86_max_gpr_size()); + if(type->function.args[i]->type == TYPE_TYPE_PRIMITIVE) { + n->exprCall.args[i] = ast_cast_expr(n->exprCall.args[i], type_prim_cast(type->function.args[i], 8 * x86_max_gpr_size())); + } } } }