From patchwork Sun Sep 17 07:56:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Van Oostenryck X-Patchwork-Id: 9954623 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F3ECA6028A for ; Sun, 17 Sep 2017 07:56:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D749928BB3 for ; Sun, 17 Sep 2017 07:56:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CBF4128BF4; Sun, 17 Sep 2017 07:56:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E5A7828BBB for ; Sun, 17 Sep 2017 07:56:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750793AbdIQH4v (ORCPT ); Sun, 17 Sep 2017 03:56:51 -0400 Received: from mail-wr0-f193.google.com ([209.85.128.193]:37640 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750761AbdIQH4v (ORCPT ); Sun, 17 Sep 2017 03:56:51 -0400 Received: by mail-wr0-f193.google.com with SMTP id u48so3401381wrf.4 for ; Sun, 17 Sep 2017 00:56:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=wnrxcaNzSVbCgWnFQ3+J+4j9rL1cg4pYeHot3Fg/3mM=; b=eQGO/nc2qd6uhiaa8LuRLPBpibtvYOzOYGP9JCCr0PeZYT0Ix/nEhcSBS77YEd4hQC JMpx9K8QNuln+/vgByGwn8R6XTaUFqCuEEwqeM7t66xFq6t9po9NvKXsZ0r/r/XtxndJ MihZRNg1/L+AuSls43HRDbyPm27pw9WL467Q+VjNR0HCTz9qRxoVs8oJh1l7muCXMFBZ 7XdBcJjCC99hTgM09SdfWqvC4iYeDd99Llq1i6vfQjd9qhankwnGgh0dIfeqCB0TKDwQ n8UUlpstJKLFyvsbfgZfG85oKtKJZ8YGgrDpZdYkN+0jQXap182IgLQf76I6EwFSO1W7 BRuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=wnrxcaNzSVbCgWnFQ3+J+4j9rL1cg4pYeHot3Fg/3mM=; b=jwR1Tp95fbe8jbHFSkspzWqzSBU2Ty0SOF6pM+OjubK9HIfh/4omJrlDb6WylUnQvH iVd7lyar+m9AD0H0XhsOwZmi5+RyXwToAQH5llY0cfH7nOlVX3NwFLJ1xvH24HZxz6Tk mOLez5h1weADqrPMbSEb0Z4KD3FVTetzfQ/hLDT0pLdtOBIesGnNMFZE+hLE+2DCUlpE WG1aEbR8tLt9sGufu2HMgh6n8A+SLVbtFOOUTzBFpCzTBzHuG4rXXagZhGfQjheEQBSy POSs8dJ6UZixChvD9RUrAWuic7Pt85AsXhL6A40PlnzdFYo81fTXdNoE6egvYtkag+AR iAFQ== X-Gm-Message-State: AHPjjUgvL8l3/PehpQO+uovNT6jDlp8RDbmhNk9xBntL1ETuO4qgX/5C LyuLXCYkjwu8tJwL604= X-Google-Smtp-Source: ADKCNb6PlmuhqtkmyI3zS663+rf/O9SCqsYYdCQ+Bmgybj3n34SOOFsrRs/hidgUIhKaUuLdFQ76sQ== X-Received: by 10.223.198.202 with SMTP id c10mr24932654wrh.230.1505635009261; Sun, 17 Sep 2017 00:56:49 -0700 (PDT) Received: from localhost.localdomain ([2a02:a03f:40aa:8400:4de8:62e4:1aab:1e0a]) by smtp.gmail.com with ESMTPSA id t37sm4026300wrc.28.2017.09.17.00.56.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 17 Sep 2017 00:56:48 -0700 (PDT) From: Luc Van Oostenryck To: linux-sparse@vger.kernel.org Cc: Christopher Li , Luc Van Oostenryck Subject: [PATCH] use a specific struct for asm operands Date: Sun, 17 Sep 2017 09:56:44 +0200 Message-Id: <20170917075644.63069-1-luc.vanoostenryck@gmail.com> X-Mailer: git-send-email 2.14.0 Sender: linux-sparse-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sparse@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP ASM operands have the following syntax: [] "" '(' ')' For some reasons, during parsing this is stored as a sequence of 3 expressions. This has some serious disadvantages though: - has not the type of an expression - it complicates processing when compared to having a specific struct for it (need to loop & maintain some state). - is optional and stored as a null pointer when not present which is annoying, for example, if null pointers are used internally in ptr-lists to mark removed pointers. Fix this by using a specific structure to store the 3 elements of ASM operands. Signed-off-by: Luc Van Oostenryck --- This patch is also available for review & testing in the git repository at: git://github.com/lucvoo/sparse.git struct-asm-ops evaluate.c | 82 +++++++++++++++++++++++++----------------------------------- expand.c | 3 +++ expression.h | 7 ++++++ inline.c | 19 ++++++-------- linearize.c | 42 +++---------------------------- parse.c | 14 ++++------- show-parse.c | 3 +++ 7 files changed, 63 insertions(+), 107 deletions(-) diff --git a/evaluate.c b/evaluate.c index 649e132b8..2ae5432f6 100644 --- a/evaluate.c +++ b/evaluate.c @@ -3160,6 +3160,9 @@ struct symbol *evaluate_expression(struct expression *expr) case EXPR_SLICE: expression_error(expr, "internal front-end error: SLICE re-evaluated"); return NULL; + case EXPR_ASM_OPERAND: + expression_error(expr, "internal front-end error: ASM_OPERAND evaluated"); + return NULL; } return NULL; } @@ -3322,8 +3325,8 @@ static void verify_input_constraint(struct expression *expr, const char *constra static void evaluate_asm_statement(struct statement *stmt) { struct expression *expr; + struct expression *op; struct symbol *sym; - int state; expr = stmt->asm_string; if (!expr || expr->type != EXPR_STRING) { @@ -3331,58 +3334,41 @@ static void evaluate_asm_statement(struct statement *stmt) return; } - state = 0; - FOR_EACH_PTR(stmt->asm_outputs, expr) { - switch (state) { - case 0: /* Identifier */ - state = 1; - continue; + FOR_EACH_PTR(stmt->asm_outputs, op) { + /* Identifier */ - case 1: /* Constraint */ - state = 2; - if (!expr || expr->type != EXPR_STRING) { - sparse_error(expr ? expr->pos : stmt->pos, "asm output constraint is not a string"); - *THIS_ADDRESS(expr) = NULL; - continue; - } + /* Constraint */ + expr = op->constraint; + if (!expr || expr->type != EXPR_STRING) { + sparse_error(expr ? expr->pos : stmt->pos, "asm output constraint is not a string"); + op->constraint = NULL; + } else verify_output_constraint(expr, expr->string->data); - continue; - case 2: /* Expression */ - state = 0; - if (!evaluate_expression(expr)) - return; - if (!lvalue_expression(expr)) - warning(expr->pos, "asm output is not an lvalue"); - evaluate_assign_to(expr, expr->ctype); - continue; - } - } END_FOR_EACH_PTR(expr); - - state = 0; - FOR_EACH_PTR(stmt->asm_inputs, expr) { - switch (state) { - case 0: /* Identifier */ - state = 1; - continue; - - case 1: /* Constraint */ - state = 2; - if (!expr || expr->type != EXPR_STRING) { - sparse_error(expr ? expr->pos : stmt->pos, "asm input constraint is not a string"); - *THIS_ADDRESS(expr) = NULL; - continue; - } + /* Expression */ + expr = op->expr; + if (!evaluate_expression(expr)) + return; + if (!lvalue_expression(expr)) + warning(expr->pos, "asm output is not an lvalue"); + evaluate_assign_to(expr, expr->ctype); + } END_FOR_EACH_PTR(op); + + FOR_EACH_PTR(stmt->asm_inputs, op) { + /* Identifier */ + + /* Constraint */ + expr = op->constraint; + if (!expr || expr->type != EXPR_STRING) { + sparse_error(expr ? expr->pos : stmt->pos, "asm input constraint is not a string"); + op->constraint = NULL; + } else verify_input_constraint(expr, expr->string->data); - continue; - case 2: /* Expression */ - state = 0; - if (!evaluate_expression(expr)) - return; - continue; - } - } END_FOR_EACH_PTR(expr); + /* Expression */ + if (!evaluate_expression(op->expr)) + return; + } END_FOR_EACH_PTR(op); FOR_EACH_PTR(stmt->asm_clobbers, expr) { if (!expr) { diff --git a/expand.c b/expand.c index f436b5b50..3c6726aa2 100644 --- a/expand.c +++ b/expand.c @@ -1048,6 +1048,9 @@ static int expand_expression(struct expression *expr) case EXPR_OFFSETOF: expression_error(expr, "internal front-end error: sizeof in expansion?"); return UNSAFE; + case EXPR_ASM_OPERAND: + expression_error(expr, "internal front-end error: ASM_OPERAND in expansion?"); + return UNSAFE; } return SIDE_EFFECTS; } diff --git a/expression.h b/expression.h index d0f3ac925..b7095640e 100644 --- a/expression.h +++ b/expression.h @@ -64,6 +64,7 @@ enum expression_type { EXPR_FVALUE, EXPR_SLICE, EXPR_OFFSETOF, + EXPR_ASM_OPERAND, }; enum { @@ -173,6 +174,12 @@ struct expression { struct expression *index; }; }; + // EXPR_ASM_OPERAND + struct { + struct ident *name; + struct expression *constraint; + struct expression *expr; + }; }; }; diff --git a/inline.c b/inline.c index a3002c6bd..012fb379a 100644 --- a/inline.c +++ b/inline.c @@ -271,6 +271,12 @@ static struct expression * copy_expression(struct expression *expr) } break; } + case EXPR_ASM_OPERAND: { + expr = dup_expression(expr); + expr->constraint = copy_expression(expr->constraint); + expr->expr = copy_expression(expr->expr); + break; + } default: warning(expr->pos, "trying to copy expression type %d", expr->type); } @@ -281,20 +287,9 @@ static struct expression_list *copy_asm_constraints(struct expression_list *in) { struct expression_list *out = NULL; struct expression *expr; - int state = 0; FOR_EACH_PTR(in, expr) { - switch (state) { - case 0: /* identifier */ - case 1: /* constraint */ - state++; - add_expression(&out, expr); - continue; - case 2: /* expression */ - state = 0; - add_expression(&out, copy_expression(expr)); - continue; - } + add_expression(&out, copy_expression(expr)); } END_FOR_EACH_PTR(expr); return out; } diff --git a/linearize.c b/linearize.c index ba76397ea..905b473e7 100644 --- a/linearize.c +++ b/linearize.c @@ -1805,12 +1805,10 @@ static void add_asm_output(struct entrypoint *ep, struct instruction *insn, stru static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement *stmt) { - int state; struct expression *expr; struct instruction *insn; struct asm_rules *rules; const char *constraint; - struct ident *ident; insn = alloc_instruction(OP_ASM, 0); expr = stmt->asm_string; @@ -1824,49 +1822,17 @@ static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement insn->asm_rules = rules; /* Gather the inputs.. */ - state = 0; - ident = NULL; - constraint = NULL; FOR_EACH_PTR(stmt->asm_inputs, expr) { - switch (state) { - case 0: /* Identifier */ - state = 1; - ident = (struct ident *)expr; - continue; - - case 1: /* Constraint */ - state = 2; - constraint = expr ? expr->string->data : ""; - continue; - - case 2: /* Expression */ - state = 0; - add_asm_input(ep, insn, expr, constraint, ident); - } + constraint = expr->constraint ? expr->constraint->string->data : ""; + add_asm_input(ep, insn, expr->expr, constraint, expr->name); } END_FOR_EACH_PTR(expr); add_one_insn(ep, insn); /* Assign the outputs */ - state = 0; - ident = NULL; - constraint = NULL; FOR_EACH_PTR(stmt->asm_outputs, expr) { - switch (state) { - case 0: /* Identifier */ - state = 1; - ident = (struct ident *)expr; - continue; - - case 1: /* Constraint */ - state = 2; - constraint = expr ? expr->string->data : ""; - continue; - - case 2: - state = 0; - add_asm_output(ep, insn, expr, constraint, ident); - } + constraint = expr->constraint ? expr->constraint->string->data : ""; + add_asm_output(ep, insn, expr->expr, constraint, expr->name); } END_FOR_EACH_PTR(expr); return VOID; diff --git a/parse.c b/parse.c index 02a55a745..8407eb855 100644 --- a/parse.c +++ b/parse.c @@ -1929,24 +1929,20 @@ static struct token *expression_statement(struct token *token, struct expression static struct token *parse_asm_operands(struct token *token, struct statement *stmt, struct expression_list **inout) { - struct expression *expr; - /* Allow empty operands */ if (match_op(token->next, ':') || match_op(token->next, ')')) return token->next; do { - struct ident *ident = NULL; + struct expression *op = alloc_expression(token->pos, EXPR_ASM_OPERAND); if (match_op(token->next, '[') && token_type(token->next->next) == TOKEN_IDENT && match_op(token->next->next->next, ']')) { - ident = token->next->next->ident; + op->name = token->next->next->ident; token = token->next->next->next; } - add_expression(inout, (struct expression *)ident); /* UGGLEE!!! */ - token = primary_expression(token->next, &expr); - add_expression(inout, expr); - token = parens_expression(token, &expr, "in asm parameter"); - add_expression(inout, expr); + token = primary_expression(token->next, &op->constraint); + token = parens_expression(token, &op->expr, "in asm parameter"); + add_expression(inout, op); } while (match_op(token, ',')); return token; } diff --git a/show-parse.c b/show-parse.c index d365d737f..f97619e69 100644 --- a/show-parse.c +++ b/show-parse.c @@ -1169,6 +1169,9 @@ int show_expression(struct expression *expr) case EXPR_TYPE: warning(expr->pos, "unable to show type expression"); return 0; + case EXPR_ASM_OPERAND: + warning(expr->pos, "unable to show asm operand expression"); + return 0; } return 0; }