Skip to content

Commit

Permalink
Allow string arguments in inline assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
positively-charged committed May 24, 2017
1 parent 9e4a461 commit 973aee8
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 18 deletions.
2 changes: 2 additions & 0 deletions doc/grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -596,9 +596,11 @@ inline-asm:
inline-asm-args:
<number>
<id>
<string>
( <expr )
<inline-asm-args> , <number>
<inline-asm-args> , <id>
<inline-asm-args> , <string>
<inline-asm-args> , ( <expr> )

empty-statement:
Expand Down
12 changes: 12 additions & 0 deletions src/codegen/asm.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "phase.h"

static void write_arg( struct codegen* codegen, struct inline_asm_arg* arg );
static void write_string_arg( struct codegen* codegen,
struct inline_asm_arg* arg );
static void write_expr_arg( struct codegen* codegen,
struct inline_asm_arg* arg );

Expand All @@ -20,6 +22,9 @@ static void write_arg( struct codegen* codegen, struct inline_asm_arg* arg ) {
case INLINE_ASM_ARG_NUMBER:
c_arg( codegen, arg->value.number );
break;
case INLINE_ASM_ARG_STRING:
write_string_arg( codegen, arg );
break;
case INLINE_ASM_ARG_LABEL:
if ( ! arg->value.label->point ) {
arg->value.label->point = c_create_point( codegen );
Expand Down Expand Up @@ -47,9 +52,16 @@ static void write_arg( struct codegen* codegen, struct inline_asm_arg* arg ) {
break;
default:
UNREACHABLE();
c_bail( codegen );
}
}

static void write_string_arg( struct codegen* codegen,
struct inline_asm_arg* arg ) {
c_append_string( codegen, arg->value.string );
c_arg( codegen, arg->value.string->index_runtime );
}

static void write_expr_arg( struct codegen* codegen,
struct inline_asm_arg* arg ) {
struct indexed_string* string = NULL;
Expand Down
39 changes: 21 additions & 18 deletions src/codegen/pcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
enum { VARIABLE_ARGC = -1 };

// n -- number
// s -- string literal
// l -- label
// a -- array
// g -- global
Expand All @@ -23,7 +24,7 @@ static struct pcode pcode_info[] = {
{ PCD_NONE, 0, "" },
{ PCD_TERMINATE, 0, "" },
{ PCD_SUSPEND, 0, "" },
{ PCD_PUSHNUMBER, 1, "ne" },
{ PCD_PUSHNUMBER, 1, "nse" },
{ PCD_LSPEC1, 1, "ne" },
{ PCD_LSPEC2, 1, "ne" },
{ PCD_LSPEC3, 1, "ne" },
Expand Down Expand Up @@ -86,9 +87,9 @@ static struct pcode pcode_info[] = {
{ PCD_POLYWAIT, 0, "" },
{ PCD_POLYWAITDIRECT, 1, "ne" },
{ PCD_CHANGEFLOOR, 0, "" },
{ PCD_CHANGEFLOORDIRECT, 2, "ne,ne" },
{ PCD_CHANGEFLOORDIRECT, 2, "ne,nse" },
{ PCD_CHANGECEILING, 0, "" },
{ PCD_CHANGECEILINGDIRECT, 2, "ne,ne" },
{ PCD_CHANGECEILINGDIRECT, 2, "ne,nse" },
{ PCD_RESTART, 0, "" },
{ PCD_ANDLOGICAL, 0, "" },
{ PCD_ORLOGICAL, 0, "" },
Expand Down Expand Up @@ -153,7 +154,7 @@ static struct pcode pcode_info[] = {
{ PCD_GETINVASIONSTATE, 0, "" },
{ PCD_PRINTNAME, 0, "" },
{ PCD_MUSICCHANGE, 0, "" },
{ PCD_CONSOLECOMMANDDIRECT, 3, "ne,n,n" },
{ PCD_CONSOLECOMMANDDIRECT, 3, "nse,n,n" },
{ PCD_CONSOLECOMMAND, 0, "" },
{ PCD_SINGLEPLAYER, 0, "" },
{ PCD_FIXEDMUL, 0, "" },
Expand All @@ -164,19 +165,19 @@ static struct pcode pcode_info[] = {
{ PCD_SETAIRCONTROLDIRECT, 1, "ne" },
{ PCD_CLEARINVENTORY, 0, "" },
{ PCD_GIVEINVENTORY, 0, "" },
{ PCD_GIVEINVENTORYDIRECT, 2, "ne,ne" },
{ PCD_GIVEINVENTORYDIRECT, 2, "nse,ne" },
{ PCD_TAKEINVENTORY, 0, "" },
{ PCD_TAKEINVENTORYDIRECT, 2, "ne,ne" },
{ PCD_TAKEINVENTORYDIRECT, 2, "nse,ne" },
{ PCD_CHECKINVENTORY, 0, "" },
{ PCD_CHECKINVENTORYDIRECT, 1, "ne" },
{ PCD_CHECKINVENTORYDIRECT, 1, "nse" },
{ PCD_SPAWN, 0, "" },
{ PCD_SPAWNDIRECT, 6, "ne,ne,ne,ne,ne,ne" },
{ PCD_SPAWNDIRECT, 6, "nse,ne,ne,ne,ne,ne" },
{ PCD_SPAWNSPOT, 0, "" },
{ PCD_SPAWNSPOTDIRECT, 4, "ne,ne,ne,ne" },
{ PCD_SPAWNSPOTDIRECT, 4, "nse,ne,ne,ne" },
{ PCD_SETMUSIC, 0, "" },
{ PCD_SETMUSICDIRECT, 3, "ne,ne,ne" },
{ PCD_SETMUSICDIRECT, 3, "nse,ne,ne" },
{ PCD_LOCALSETMUSIC, 0, "" },
{ PCD_LOCALSETMUSICDIRECT, 3, "ne,ne,ne" },
{ PCD_LOCALSETMUSICDIRECT, 3, "nse,ne,ne" },
{ PCD_PRINTFIXED, 0, "" },
{ PCD_PRINTLOCALIZED, 0, "" },
{ PCD_MOREHUDMESSAGE, 0, "" },
Expand All @@ -186,20 +187,22 @@ static struct pcode pcode_info[] = {
{ PCD_SETSTYLE, 0, "" },
{ PCD_SETSTYLEDIRECT, 0, "" },
{ PCD_SETFONT, 0, "" },
{ PCD_SETFONTDIRECT, 1, "ne" },
{ PCD_PUSHBYTE, 1, "ne" },
{ PCD_SETFONTDIRECT, 1, "nse" },
{ PCD_PUSHBYTE, 1, "nse" },
{ PCD_LSPEC1DIRECTB, 2, "ne,ne" },
{ PCD_LSPEC2DIRECTB, 3, "ne,ne,ne" },
{ PCD_LSPEC3DIRECTB, 4, "ne,ne,ne,ne" },
{ PCD_LSPEC4DIRECTB, 5, "ne,ne,ne,ne,ne" },
{ PCD_LSPEC5DIRECTB, 6, "ne,ne,ne,ne,ne,ne" },
{ PCD_DELAYDIRECTB, 1, "ne" },
{ PCD_RANDOMDIRECTB, 2, "ne,ne" },
{ PCD_PUSHBYTES, VARIABLE_ARGC, "+ne" },
{ PCD_PUSH2BYTES, 2, "ne,ne" },
{ PCD_PUSH3BYTES, 3, "ne,ne,ne" },
{ PCD_PUSH4BYTES, 4, "ne,ne,ne,ne" },
{ PCD_PUSH5BYTES, 5, "ne,ne,ne,ne,ne" },
// FIXME: This argument specification requests at least two arguments, but
// the pushbytes should be able to take at least one argument, a zero.
{ PCD_PUSHBYTES, VARIABLE_ARGC, "ne,+nse" },
{ PCD_PUSH2BYTES, 2, "nse,nse" },
{ PCD_PUSH3BYTES, 3, "nse,nse,nse" },
{ PCD_PUSH4BYTES, 4, "nse,nse,nse,nse" },
{ PCD_PUSH5BYTES, 5, "nse,nse,nse,nse,nse" },
{ PCD_SETTHINGSPECIAL, 0, "" },
{ PCD_ASSIGNGLOBALVAR, 1, "nvge" },
{ PCD_PUSHGLOBALVAR, 1, "nvge" },
Expand Down
9 changes: 9 additions & 0 deletions src/parse/asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ static void read_arg( struct parse* parse, struct inline_asm* inline_asm ) {
arg->value.number = p_extract_literal_value( parse );
p_read_tk( parse );
}
// FIXME: missing maximum string length check.
else if ( parse->tk == TK_LIT_STRING ) {
arg->type = INLINE_ASM_ARG_STRING;
struct indexed_string* string = t_intern_string( parse->task,
parse->tk_text, parse->tk_length );
string->in_source_code = true;
arg->value.string = string;
p_read_tk( parse );
}
else if ( parse->tk == TK_ID ) {
arg->type = INLINE_ASM_ARG_ID;
arg->value.id = parse->tk_text;
Expand Down
2 changes: 2 additions & 0 deletions src/semantic/asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ static void test_arg( struct semantic* semantic, struct test* test,
bool unknown = false;
switch ( *test->format ) {
case 'n': match = ( arg->type == INLINE_ASM_ARG_NUMBER ); break;
case 's': match = ( arg->type == INLINE_ASM_ARG_STRING ); break;
case 'l': match = ( arg->type == INLINE_ASM_ARG_ID ); break;
case 'v': match = ( arg->type == INLINE_ASM_ARG_ID ); break;
case 'a': match = ( arg->type == INLINE_ASM_ARG_ID ); break;
Expand Down Expand Up @@ -506,6 +507,7 @@ static void test_arg( struct semantic* semantic, struct test* test,
test_expr_arg( semantic, arg );
break;
case 'n':
case 's':
break;
default:
s_diag( semantic, DIAG_POS_ERR, &arg->pos,
Expand Down
2 changes: 2 additions & 0 deletions src/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,7 @@ struct inline_asm_arg {
enum {
INLINE_ASM_ARG_NUMBER,
INLINE_ASM_ARG_ID,
INLINE_ASM_ARG_STRING,
INLINE_ASM_ARG_EXPR,
INLINE_ASM_ARG_LABEL,
INLINE_ASM_ARG_VAR,
Expand All @@ -1088,6 +1089,7 @@ struct inline_asm_arg {
union {
int number;
const char* id;
struct indexed_string* string;
struct expr* expr;
struct label* label;
struct var* var;
Expand Down

0 comments on commit 973aee8

Please sign in to comment.