Implementation of swi attribute for ARM

2012-02-20 Thread Barracuda
Hello!
I'm new to GCC internals, but I'm using GCC for couple of years.
Yesterday I found that GCC does not support calling SWI routines from C/C++
code.
For example, in other ARM-targeted compiliers developer can use such syntax
for function prototype:
In ARM IAR:
#pragma swi_number=0x15
int some_call(int, int);
In RVDS:
__swi(0x15) int some_call(int, int);
And then just call function as usual:
a = some_call(5, 8);
GCC lacks this feauture, so I've decided to go on Free Software way - if your
need something, implement it yourself =)
I can't write any testsuite, because I don't know how to do it, sorry. I
tested some programs written for IAR, they compiled and launched successfully.
I've also tested some programs with functions that don't use this attribute -
they was unaffected by this patch. So I decided to send it to this mailing
list.
Changelog and patch included in attachment.
I tested cross-compiling, host=i686-pc-linux-gnu and host=x86_64-pc-linux-gnu,
target=arm-linux-gnueabi. Works stable and fine.

Barracudadiff -aur sources/gcc-4.5.1/gcc/config/arm//arm.c gcc-4.5.1/gcc/config/arm//arm.c
--- sources/gcc-4.5.1/gcc/config/arm//arm.c	2010-07-12 20:05:41.0 +0600
+++ gcc-4.5.1/gcc/config/arm//arm.c	2012-02-21 04:24:13.295235261 +0600
@@ -225,6 +225,7 @@
 static void arm_trampoline_init (rtx, tree, rtx);
 static rtx arm_trampoline_adjust_address (rtx);
 
+static tree arm_handle_swi_attribute (tree *, tree, tree, int, bool *);
 
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -243,6 +246,7 @@
   { "isr",  0, 1, false, false, false, arm_handle_isr_attribute },
   { "interrupt",0, 1, false, false, false, arm_handle_isr_attribute },
   { "naked",0, 0, true,  false, false, arm_handle_fndecl_attribute },
+  { "swi",  1, 1, false, false, false, arm_handle_swi_attribute },
 #ifdef ARM_PE
   /* ARM/PE has three new attributes:
  interfacearm - ?
@@ -4595,6 +4601,47 @@
   return NULL_TREE;
 }
 
+static tree
+arm_handle_swi_attribute (tree *node, tree name, tree args, int flags,
+			  bool *no_add_attrs)
+{
+  if (DECL_P (*node))
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+	{
+	  warning (OPT_Wattributes, "%qE attribute only applies to functions",
+		   name);
+	  *no_add_attrs = true;
+	} else {
+  tree cst = TREE_VALUE (args);
+  if (TREE_CODE (cst) != INTEGER_CST)
+{
+  error ("%qE attribute requires an integer constant argument",
+ name);
+  *no_add_attrs = true;
+}
+  else if (TARGET_ARM && (compare_tree_int (cst, 0xFF) > 0))
+{
+  error ("argument to %qE attribute larger than 0xFF",
+ name);
+  *no_add_attrs = true;
+}
+  else if (TARGET_THUMB && (compare_tree_int (cst, 0xFF) > 0))
+{
+  error ("argument to %qE attribute larger than 0xFF",
+ name);
+  *no_add_attrs = true;
+}
+}
+} else {
+  warning (OPT_Wattributes,
+   "%qE attribute can be applied only to function prototype");
+  *no_add_attrs = true;
+}
+
+  return NULL_TREE;
+}
+
 /* Handle a "pcs" attribute; arguments as in struct
attribute_spec.handler.  */
 static tree
@@ -4768,6 +4821,52 @@
   return TARGET_LONG_CALLS;
 }
 
+bool
+arm_is_swicall (tree decl)
+{
+  tree attrs;
+  tree a;
+
+  if (!decl)
+  {
+return false;
+  }
+
+  attrs = DECL_ATTRIBUTES ( decl);
+  a = lookup_attribute ("swi", attrs);
+  if (a == NULL_TREE)
+  {
+return false;
+  }
+
+  return true;
+}
+
+const char *
+output_swicall (tree decl)
+{
+  tree attrs;
+  tree a;
+  tree cst;
+  int value;
+  char *buf = ggc_alloc_cleared (32);
+
+  attrs = DECL_ATTRIBUTES (decl);
+  a = lookup_attribute ("swi", attrs);
+  if (TREE_VALUE (a) == NULL_TREE)
+return "ERROR";
+
+  cst = TREE_VALUE (TREE_VALUE (a));
+  if (TREE_CODE (cst) != INTEGER_CST)
+return "ERROR1";
+
+  value = TREE_INT_CST_LOW (cst);
+
+  snprintf (buf, 32, "swi%%?\t%d", value);
+
+  return buf;
+}
+
 /* Return nonzero if it is ok to make a tail-call to DECL.  */
 static bool
 arm_function_ok_for_sibcall (tree decl, tree exp)
diff -aur sources/gcc-4.5.1/gcc/config/arm//arm.md gcc-4.5.1/gcc/config/arm//arm.md
--- sources/gcc-4.5.1/gcc/config/arm//arm.md	2010-07-31 04:35:40.0 +0600
+++ gcc-4.5.1/gcc/config/arm//arm.md	2012-02-21 04:20:46.846224042 +0600
@@ -8646,7 +8646,11 @@
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
   "*
   {
-return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
+bool is_swi = arm_is_swicall (SYMBOL_REF_DECL (operands[1]));
+if (is_swi)
+  return output_swicall (SYMBOL_REF_DECL (operands[1]));
+else
+  return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
   }"
   [(set_attr "type" "call")]
 )
@@ -8673,7 +8678,14 @@
   "TARGET_THUMB
&&

Re[2]: Implementation of swi attribute for ARM

2012-02-21 Thread Barracuda
1) No, I don't. I think I should read FAQ about this then work will be 
completed =) I'm not interested in "copyrighting" this, just want to share it 
with other people.
2) Probably most hard part for me, but I'll try to do this.
I've never used testsuites before, but now it's time to begin.
3) What type of documentation I must provide? Brief annotation (as for other 
attributes)? Yes, I've just use standart calling convention - first 4 args 
resides in r0-r3, others in stack.
4,5,6,7,8,10 - thanks for help, I made some corrections and improvements - 
wrote comments, tidy up the style, add more range and null-pointer checks. 
Also, as you suggested, in addition to "svc" I've implemented "smc" attribute 
and dummy "hvc" attribute - can't find documentation for hvc, I've just noted 
it's Hypervisor Call. Then code will be completed, I'll made patch for trunk, 
for now I can't checkout it, sorry.
And, of course, thanks for reply