aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tcc.h4
-rw-r--r--tccasm.c87
-rw-r--r--tccpp.c12
-rw-r--r--tcctok.h57
-rw-r--r--tests/Makefile6
-rw-r--r--tests/pp/12.S8
-rw-r--r--tests/pp/12.expect2
-rw-r--r--tests/pp/Makefile12
8 files changed, 115 insertions, 73 deletions
diff --git a/tcc.h b/tcc.h
index 0200207..2e1e32f 100644
--- a/tcc.h
+++ b/tcc.h
@@ -957,7 +957,9 @@ struct TCCState {
#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
#define TOK_ASM_int TOK_INT
-#define TOK_ASM_weak TOK_WEAK1
+#define DEF_ASMDIR(x) DEF(TOK_ASMDIR_ ## x, "." #x)
+#define TOK_ASMDIR_FIRST TOK_ASMDIR_byte
+#define TOK_ASMDIR_LAST TOK_ASMDIR_section
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
/* only used for i386 asm opcodes definitions */
diff --git a/tccasm.c b/tccasm.c
index 28e07fd..fade2d1 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -331,24 +331,23 @@ static void asm_parse_directive(TCCState *s1)
uint8_t *ptr;
/* assembler directive */
- next();
sec = cur_text_section;
switch(tok) {
- case TOK_ASM_align:
- case TOK_ASM_p2align:
- case TOK_ASM_skip:
- case TOK_ASM_space:
+ case TOK_ASMDIR_align:
+ case TOK_ASMDIR_p2align:
+ case TOK_ASMDIR_skip:
+ case TOK_ASMDIR_space:
tok1 = tok;
next();
n = asm_int_expr(s1);
- if (tok1 == TOK_ASM_p2align)
+ if (tok1 == TOK_ASMDIR_p2align)
{
if (n < 0 || n > 30)
tcc_error("invalid p2align, must be between 0 and 30");
n = 1 << n;
- tok1 = TOK_ASM_align;
+ tok1 = TOK_ASMDIR_align;
}
- if (tok1 == TOK_ASM_align) {
+ if (tok1 == TOK_ASMDIR_align) {
if (n < 0 || (n & (n-1)) != 0)
tcc_error("alignment must be a positive power of two");
offset = (ind + n - 1) & -n;
@@ -372,7 +371,7 @@ static void asm_parse_directive(TCCState *s1)
}
ind += size;
break;
- case TOK_ASM_quad:
+ case TOK_ASMDIR_quad:
next();
for(;;) {
uint64_t vl;
@@ -399,15 +398,15 @@ static void asm_parse_directive(TCCState *s1)
next();
}
break;
- case TOK_ASM_byte:
+ case TOK_ASMDIR_byte:
size = 1;
goto asm_data;
- case TOK_ASM_word:
- case TOK_SHORT:
+ case TOK_ASMDIR_word:
+ case TOK_ASMDIR_short:
size = 2;
goto asm_data;
- case TOK_LONG:
- case TOK_INT:
+ case TOK_ASMDIR_long:
+ case TOK_ASMDIR_int:
size = 4;
asm_data:
next();
@@ -433,7 +432,7 @@ static void asm_parse_directive(TCCState *s1)
next();
}
break;
- case TOK_ASM_fill:
+ case TOK_ASMDIR_fill:
{
int repeat, size, val, i, j;
uint8_t repeat_buf[8];
@@ -475,7 +474,7 @@ static void asm_parse_directive(TCCState *s1)
}
}
break;
- case TOK_ASM_org:
+ case TOK_ASMDIR_org:
{
unsigned long n;
next();
@@ -488,10 +487,10 @@ static void asm_parse_directive(TCCState *s1)
goto zero_pad;
}
break;
- case TOK_ASM_globl:
- case TOK_ASM_global:
- case TOK_ASM_weak:
- case TOK_ASM_hidden:
+ case TOK_ASMDIR_globl:
+ case TOK_ASMDIR_global:
+ case TOK_ASMDIR_weak:
+ case TOK_ASMDIR_hidden:
tok1 = tok;
do {
Sym *sym;
@@ -502,18 +501,18 @@ static void asm_parse_directive(TCCState *s1)
sym = label_push(&s1->asm_labels, tok, 0);
sym->type.t = VT_VOID;
}
- if (tok1 != TOK_ASM_hidden)
+ if (tok1 != TOK_ASMDIR_hidden)
sym->type.t &= ~VT_STATIC;
- if (tok1 == TOK_ASM_weak)
+ if (tok1 == TOK_ASMDIR_weak)
sym->type.t |= VT_WEAK;
- else if (tok1 == TOK_ASM_hidden)
+ else if (tok1 == TOK_ASMDIR_hidden)
sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT;
next();
} while (tok == ',');
break;
- case TOK_ASM_string:
- case TOK_ASM_ascii:
- case TOK_ASM_asciz:
+ case TOK_ASMDIR_string:
+ case TOK_ASMDIR_ascii:
+ case TOK_ASMDIR_asciz:
{
const uint8_t *p;
int i, size, t;
@@ -525,7 +524,7 @@ static void asm_parse_directive(TCCState *s1)
expect("string constant");
p = tokc.str.data;
size = tokc.str.size;
- if (t == TOK_ASM_ascii && size > 0)
+ if (t == TOK_ASMDIR_ascii && size > 0)
size--;
for(i = 0; i < size; i++)
g(p[i]);
@@ -538,9 +537,9 @@ static void asm_parse_directive(TCCState *s1)
}
}
break;
- case TOK_ASM_text:
- case TOK_ASM_data:
- case TOK_ASM_bss:
+ case TOK_ASMDIR_text:
+ case TOK_ASMDIR_data:
+ case TOK_ASMDIR_bss:
{
char sname[64];
tok1 = tok;
@@ -557,7 +556,7 @@ static void asm_parse_directive(TCCState *s1)
use_section(s1, sname);
}
break;
- case TOK_ASM_file:
+ case TOK_ASMDIR_file:
{
char filename[512];
@@ -575,7 +574,7 @@ static void asm_parse_directive(TCCState *s1)
next();
}
break;
- case TOK_ASM_ident:
+ case TOK_ASMDIR_ident:
{
char ident[256];
@@ -593,7 +592,7 @@ static void asm_parse_directive(TCCState *s1)
next();
}
break;
- case TOK_ASM_size:
+ case TOK_ASMDIR_size:
{
Sym *sym;
@@ -614,7 +613,7 @@ static void asm_parse_directive(TCCState *s1)
}
}
break;
- case TOK_ASM_type:
+ case TOK_ASMDIR_type:
{
Sym *sym;
const char *newtype;
@@ -632,7 +631,7 @@ static void asm_parse_directive(TCCState *s1)
newtype = tokc.str.data;
} else {
if (tok == '@' || tok == '%')
- skip(tok);
+ next();
newtype = get_tok_str(tok, NULL);
}
@@ -646,7 +645,7 @@ static void asm_parse_directive(TCCState *s1)
next();
}
break;
- case TOK_SECTION1:
+ case TOK_ASMDIR_section:
{
char sname[256];
@@ -666,12 +665,18 @@ static void asm_parse_directive(TCCState *s1)
if (tok != TOK_STR)
expect("string constant");
next();
+ if (tok == ',') {
+ next();
+ if (tok == '@' || tok == '%')
+ next();
+ next();
+ }
}
last_text_section = cur_text_section;
use_section(s1, sname);
}
break;
- case TOK_ASM_previous:
+ case TOK_ASMDIR_previous:
{
Section *sec;
next();
@@ -683,13 +688,13 @@ static void asm_parse_directive(TCCState *s1)
}
break;
#ifdef TCC_TARGET_I386
- case TOK_ASM_code16:
+ case TOK_ASMDIR_code16:
{
next();
s1->seg_size = 16;
}
break;
- case TOK_ASM_code32:
+ case TOK_ASMDIR_code32:
{
next();
s1->seg_size = 32;
@@ -698,7 +703,7 @@ static void asm_parse_directive(TCCState *s1)
#endif
#ifdef TCC_TARGET_X86_64
/* added for compatibility with GAS */
- case TOK_ASM_code64:
+ case TOK_ASMDIR_code64:
next();
break;
#endif
@@ -763,7 +768,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
/* horrible gas comment */
while (tok != TOK_LINEFEED)
next();
- } else if (tok == '.') {
+ } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
asm_parse_directive(s1);
} else if (tok == TOK_PPNUM) {
const char *p;
diff --git a/tccpp.c b/tccpp.c
index 64c4919..cbc3707 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -1328,6 +1328,8 @@ ST_FUNC void parse_define(void)
parse_flags |= PARSE_FLAG_SPACES;
next_nomacro_spc();
if (tok == '(') {
+ /* must be able to parse TOK_DOTS (in asm mode '.' can be part of identifier) */
+ parse_flags &= ~PARSE_FLAG_ASM_FILE;
next_nomacro();
ps = &first;
if (tok != ')') for (;;) {
@@ -1355,6 +1357,7 @@ ST_FUNC void parse_define(void)
}
next_nomacro_spc();
t = MACRO_FUNC;
+ parse_flags |= (saved_parse_flags & PARSE_FLAG_ASM_FILE);
}
tok_str_new(&str);
spc = 2;
@@ -2460,7 +2463,8 @@ maybe_newline:
p1 = p;
h = TOK_HASH_INIT;
h = TOK_HASH_FUNC(h, c);
- while (c = *++p, isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
+ while (c = *++p, (isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
+ || (c == '.' && (parse_flags & PARSE_FLAG_ASM_FILE)))
h = TOK_HASH_FUNC(h, c);
if (c != '\\') {
TokenSym **pts;
@@ -2492,7 +2496,9 @@ maybe_newline:
p--;
PEEKC(c, p);
parse_ident_slow:
- while (isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM)) {
+ while ((isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
+ || (c == '.' && (parse_flags & PARSE_FLAG_ASM_FILE)))
+ {
cstr_ccat(&tokcstr, c);
PEEKC(c, p);
}
@@ -2551,7 +2557,7 @@ maybe_newline:
cstr_reset(&tokcstr);
cstr_ccat(&tokcstr, '.');
goto parse_num;
- } else if ((isidnum_table['.' - CH_EOF] & IS_ID) != 0) { /* asm mode */
+ } else if (parse_flags & PARSE_FLAG_ASM_FILE) {
*--p = c = '.';
goto parse_ident_fast;
} else if (c == '.') {
diff --git a/tcctok.h b/tcctok.h
index 31b6dae..b2fbebf 100644
--- a/tcctok.h
+++ b/tcctok.h
@@ -301,35 +301,40 @@
#endif
/* Tiny Assembler */
- DEF_ASM(byte)
- DEF_ASM(word)
- DEF_ASM(align)
- DEF_ASM(p2align)
- DEF_ASM(skip)
- DEF_ASM(space)
- DEF_ASM(string)
- DEF_ASM(asciz)
- DEF_ASM(ascii)
- DEF_ASM(file)
- DEF_ASM(globl)
- DEF_ASM(global)
- DEF_ASM(hidden)
- DEF_ASM(ident)
- DEF_ASM(size)
- DEF_ASM(type)
- DEF_ASM(text)
- DEF_ASM(data)
- DEF_ASM(bss)
- DEF_ASM(previous)
- DEF_ASM(fill)
- DEF_ASM(org)
- DEF_ASM(quad)
+ DEF_ASMDIR(byte) /* must be first directive */
+ DEF_ASMDIR(word)
+ DEF_ASMDIR(align)
+ DEF_ASMDIR(p2align)
+ DEF_ASMDIR(skip)
+ DEF_ASMDIR(space)
+ DEF_ASMDIR(string)
+ DEF_ASMDIR(asciz)
+ DEF_ASMDIR(ascii)
+ DEF_ASMDIR(file)
+ DEF_ASMDIR(globl)
+ DEF_ASMDIR(global)
+ DEF_ASMDIR(weak)
+ DEF_ASMDIR(hidden)
+ DEF_ASMDIR(ident)
+ DEF_ASMDIR(size)
+ DEF_ASMDIR(type)
+ DEF_ASMDIR(text)
+ DEF_ASMDIR(data)
+ DEF_ASMDIR(bss)
+ DEF_ASMDIR(previous)
+ DEF_ASMDIR(fill)
+ DEF_ASMDIR(org)
+ DEF_ASMDIR(quad)
#if defined(TCC_TARGET_I386)
- DEF_ASM(code16)
- DEF_ASM(code32)
+ DEF_ASMDIR(code16)
+ DEF_ASMDIR(code32)
#elif defined(TCC_TARGET_X86_64)
- DEF_ASM(code64)
+ DEF_ASMDIR(code64)
#endif
+ DEF_ASMDIR(short)
+ DEF_ASMDIR(long)
+ DEF_ASMDIR(int)
+ DEF_ASMDIR(section) /* must be last directive */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
#include "i386-tok.h"
diff --git a/tests/Makefile b/tests/Makefile
index 04390c7..f556cc5 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -73,7 +73,11 @@ DISAS = objdump -d
# libtcc test
ifdef LIBTCC1
- LIBTCC1:=$(TOP)/$(LIBTCC1)
+ ifdef CONFIG_WIN32
+ LIBTCC1:=$(TOP)/win32/libtcc/libtcc.a
+ else
+ LIBTCC1:=$(TOP)/$(LIBTCC1)
+ endif
endif
all test : $(TESTS)
diff --git a/tests/pp/12.S b/tests/pp/12.S
new file mode 100644
index 0000000..597ccb4
--- /dev/null
+++ b/tests/pp/12.S
@@ -0,0 +1,8 @@
+#define SRC(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6001f ; \
+ // .previous
+
+ SRC(1: movw (%esi), %bx)
+6001:
diff --git a/tests/pp/12.expect b/tests/pp/12.expect
new file mode 100644
index 0000000..17a861c
--- /dev/null
+++ b/tests/pp/12.expect
@@ -0,0 +1,2 @@
+ 9999: 1: movw (%esi), %bx; .section __ex_table, "a"; .long 9999b, 6001f ;
+6001:
diff --git a/tests/pp/Makefile b/tests/pp/Makefile
index cb8bfea..d55699c 100644
--- a/tests/pp/Makefile
+++ b/tests/pp/Makefile
@@ -7,6 +7,7 @@ include $(TOP)/Makefile
TCC = $(TOP)/tcc
TESTS = $(patsubst %.c,%.test,$(wildcard *.c))
+TESTS += $(patsubst %.S,%.test,$(wildcard *.S))
ifdef CONFIG_WIN32
TCC = $(top_srcdir)/win32/tcc
@@ -20,10 +21,19 @@ all test : $(TESTS)
diff -Nu -b -B -I "^#" $(EXTRA_DIFF_OPTS) $*.expect $*.output \
&& rm -f $*.output
+%.test: %.S %.expect
+ @echo PPTest $* ...
+ @$(TCC) -E -P $< >$*.output 2>&1 ; \
+ diff -Nu -b -B -I "^#" $(EXTRA_DIFF_OPTS) $*.expect $*.output \
+ && rm -f $*.output
+
# automatically generate .expect files with gcc:
-%.expect :
+%.expect: %.c
gcc -E -P $*.c >$*.expect 2>&1
+%.expect: %.S
+ gcc -E -P $*.S >$*.expect 2>&1
+
# tell make not to delete
.PRECIOUS: %.expect