aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorseyko <seyko2@gmail.com>2016-05-01 22:38:38 +0300
committerseyko <seyko2@gmail.com>2016-05-01 22:38:38 +0300
commit6afe668ec7a11736a9418a46370af89a8c657ee8 (patch)
tree754e61e7f4d077df6e89e5d82dc0e3638474c6ed
parent09a78412f071d189f52caed0866d02a608eb2d56 (diff)
downloadtinycc-6afe668ec7a11736a9418a46370af89a8c657ee8.tar.gz
tinycc-6afe668ec7a11736a9418a46370af89a8c657ee8.tar.bz2
__asm__() outside function
gcc/pcc allow __asm__() outside a function body: extern void vide(void); __asm__("vide: ret"); There is many such code in the Linux kernels.
-rw-r--r--tccasm.c10
-rw-r--r--tests/tests2/85-asm-outside-function.c7
-rw-r--r--tests/tests2/85-asm-outside-function.expect0
3 files changed, 17 insertions, 0 deletions
diff --git a/tccasm.c b/tccasm.c
index 72121e4..3fd69f7 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -824,6 +824,16 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
opcode = tok;
next();
if (tok == ':') {
+ /* handle "extern void vide(void); __asm__("vide: ret");" as
+ "__asm__("globl vide\nvide: ret");" */
+ Sym *sym = sym_find(opcode);
+ if (sym && (sym->type.t & VT_EXTERN) && nocode_wanted) {
+ sym = label_find(opcode);
+ if (!sym) {
+ sym = label_push(&s1->asm_labels, opcode, 0);
+ sym->type.t = VT_VOID;
+ }
+ }
/* new label */
asm_new_label(s1, opcode, 0);
next();
diff --git a/tests/tests2/85-asm-outside-function.c b/tests/tests2/85-asm-outside-function.c
new file mode 100644
index 0000000..0aa7e33
--- /dev/null
+++ b/tests/tests2/85-asm-outside-function.c
@@ -0,0 +1,7 @@
+extern void vide(void);
+__asm__("vide: ret");
+
+int main() {
+ vide();
+ return 0;
+}
diff --git a/tests/tests2/85-asm-outside-function.expect b/tests/tests2/85-asm-outside-function.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/tests2/85-asm-outside-function.expect