More denoops

This commit is contained in:
Mid 2025-09-19 19:05:18 +03:00
parent e80f6643dc
commit fb6fd76d0b

View File

@ -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) { 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` // 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; *nptr = n->exprUnOp.operand->exprUnOp.operand;
*success = true; *success = true;
@ -635,6 +638,15 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST
*nptr = n->exprBinOp.operands[0]; *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; *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) { } 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)` // 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) { } 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 // 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; *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; *success = true;
} else if(n->nodeKind == AST_EXPR_EXT_SIZEOF) { } else if(n->nodeKind == AST_EXPR_EXT_SIZEOF) {
ASTExprPrimitive *prim = calloc(1, sizeof(*prim)); 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 convention correctness pass converts all function calls & function sources to the form
* the architecture most closely. For example, arguments (and return values) in cdecl are always * hat matches the architecture most closely. For example, arguments (and return values) in
* passed as 32-bit integers, even if they are defined as 8-bit or 16-bit in the source. * 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. * 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; AST *n = *nptr;
if(n->nodeKind == AST_STMT_DECL && n->stmtDecl.thing->kind == SCOPEITEM_SYMBOL && n->stmtDecl.thing->type->type == TYPE_TYPE_FUNCTION) { if(n->nodeKind == AST_EXPR_CALL) {
Type *type = n->stmtDecl.thing->type; Type *type = n->exprCall.what->expression.type;
assert(n->stmtDecl.expression->exprFunc.chunk->chunk.functionType == type); assert(type->type == TYPE_TYPE_POINTER);
assert(type->function.ret->type == TYPE_TYPE_PRIMITIVE || type->function.ret->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++) { 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); if(type->function.args[i]->type == TYPE_TYPE_PRIMITIVE) {
type->function.args[i] = type_prim_cast(type->function.args[i], 8 * x86_max_gpr_size()); n->exprCall.args[i] = ast_cast_expr(n->exprCall.args[i], type_prim_cast(type->function.args[i], 8 * x86_max_gpr_size()));
}
} }
} }
} }