Using C pragmas in library interfaces

948 views
Skip to first unread message

Brandon Barker

unread,
Feb 15, 2014, 1:11:42 PM2/15/14
to ats-lan...@googlegroups.com
I realize it is an unusual feature (I did not see any examples). Should pragmas be placed in .cats or .dats (using %{ ... %} for .dats)? 

I tried .cats since I don't really like using %{ %} mainly due to its effect on ats-mode in emacs:


#define atscntrb_openmp_omp_parallel_private(thread_id) \
  _Pragma(STRINGIFY( omp parallel private (thread_id) ))

// It is generated correctly by gcc -E in a simple test case
#pragma omp parallel private (17)

//Generated C code related to actual example:
//...
__patsflab_main_void_0:
# 168 "hello_dats.c"

# 168 "hello_dats.c"
#pragma omp parallel private (tmpref1)
# 168 "hello_dats.c"
 ;




(tmp4 = omp_get_thread_num()) ;
//...


Though the ATS version compiles, it is not run in parallel as the same example in the c version, which makes me think the pragmas are somehow not being used correctly.

Or maybe it is something more subtle.

Code at:



gmhwxi

unread,
Feb 16, 2014, 4:10:06 PM2/16/14
to ats-lan...@googlegroups.com
The generated pragma does not seem to be correct.

In general, pragma code should be done in C directly.
If I translate the following code into ATS, I would only write in ATS functions like 'printf'; the '#pragma ...'
part stays in C.

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {

int nthreads, tid;

/* Fork a team of threads giving them their own copies of variables */
#pragma omp parallel private(nthreads, tid)
 
{

 
/* Obtain thread number */
 tid
= omp_get_thread_num();
 printf
("Hello World from thread = %d\n", tid);

 
/* Only master thread does this */
 
if (tid == 0)
 
{
 nthreads
= omp_get_num_threads();
 printf
("Number of threads = %d\n", nthreads);
 
}

 
} /* All threads join master thread and disband */

}


Brandon Barker

unread,
May 4, 2014, 9:01:08 PM5/4/14
to ats-lan...@googlegroups.com
Just showing a different attempt, which may still be more ATS and less C than you were suggesting:

//
// OpenMP hello world
//


staload _
= "prelude/DATS/integer.dats"


(* ****** ****** *)


staload
"./../SATS/omp.sats"


(* ****** ****** *)


implement
main0
() = {
 
var th_id: int?
 
var nthreads: int?
 
//val () = omp_parallel_private(th_id)
 
%{
   
#pragma omp parallel private(th_id)
   
{
 
%}
  val
() = th_id := omp_get_thread_num()
 
//val () = th_id := 0
  val
() = println!(th_id)
  val
() = if th_id = 0
 
then
   
(nthreads := omp_get_num_threads();
     println
! (nthreads))
 
else
   
()
  val
() = println! ("Hello world!") // English
 
%{
   
}
 
%}
} // end of [main0]


(* ****** ****** *)


(* end of [hello.dats] *)



This results in errors along the lines of:

/home/brand_000/ATS-Postiats/contrib/libats-bbarker/OpenMP/TEST/hello.dats: 255(line=19, offs=5) -- 262(line=19, offs=12): error(parsing): the keyword '}' is needed.
/home/brand_000/ATS-Postiats/contrib/libats-bbarker/OpenMP/TEST/hello.dats: 249(line=18, offs=4) -- 250(line=18, offs=5): error(parsing): the keyword '}' is needed.

Brandon Barker

unread,
May 6, 2014, 12:58:49 PM5/6/14
to ats-lan...@googlegroups.com
The delimiters for C code inclusion (e.g. %{ and %} appear to need to be at the beginning of their line. I don't think this currently emphasized in the book. That taken care of, back to the problem at hand:

For comparison, here is the c code (from wikipedia) I based this very simple test on, which compiles for me with gcc -fopenmp:

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>


int main (int argc, char *argv[]) {

 
int th_id, nthreads;
#pragma omp parallel private(th_id)
 
{
    th_id
= omp_get_thread_num();
    printf
("Hello World from thread %d\n", th_id);
   
#pragma omp barrier
   
if ( th_id == 0 ) {
      nthreads
= omp_get_num_threads();
      printf
("There are %d threads\n",nthreads);
   
}
 
}
 
return EXIT_SUCCESS;
}


Trying again to compile the ATS example results in some gcc errors:

hello_dats.c:132:9: error: expected declaration specifiers before ‘#pragma’
 #pragma omp parallel private(th_id)
         ^
hello_dats.c:133:1: error: expected identifier or ‘(’ before ‘{’ token
 {
 ^

This is no surprise when we look at the code around the #pragma:

#pragma omp parallel private(th_id)
{
/*
/home/brand_000/ATS-Postiats/contrib/libats-bbarker/OpenMP/TEST/hello.dats: 543(line=32, offs=1) -- 5\
50(line=34, offs=3)
*/

}
#if(0)
ATSglobaldec()
atsvoid_t0ype
mainats_void_0
() ;
#endif // end of [QUALIFIED]
//...


A closing brace is inserted. However, if we leave out the open brace in our C code, no braces at all (opening or closing) are inserted, and we only get the first error about "expected declaration specifiers" (though I don't think ultimately we could leave out the braces if we want the #pragma to work correctly.

A closer look seems to suggest that the inserted c code is not in the right place, which to be fair, the book did warn about the c code being placed in an arbitrary location. 

Any suggestions on what to try next?




gmhwxi

unread,
May 6, 2014, 1:22:29 PM5/6/14
to ats-lan...@googlegroups.com
I suggest that you try the following style:

%{^
#define a_pragma_macro_beg() {
#define a_pragma_macro_end() }
%}
extern
fun a_pragma_macro_beg
(): void = "mac#"
extern
fun a_pragma_macro_end
(): void = "mac#"

#include
"share/atspre_staload.hats"

fun foo
 
(x: int): int = res where
{
  val
() = a_pragma_macro_beg ()
  val res
= x + x
  val
() = a_pragma_macro_end ()
}

implement
main0
() = println! ("foo(10) = ", foo(10))


gmhwxi

unread,
May 6, 2014, 1:44:38 PM5/6/14
to ats-lan...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages