1/*
2 *  abi.h
3 *
4 *  @copyright
5 *  Copyright (C) 2009-2013, Intel Corporation
6 *  All rights reserved.
7 *
8 *  @copyright
9 *  Redistribution and use in source and binary forms, with or without
10 *  modification, are permitted provided that the following conditions
11 *  are met:
12 *
13 *    * Redistributions of source code must retain the above copyright
14 *      notice, this list of conditions and the following disclaimer.
15 *    * Redistributions in binary form must reproduce the above copyright
16 *      notice, this list of conditions and the following disclaimer in
17 *      the documentation and/or other materials provided with the
18 *      distribution.
19 *    * Neither the name of Intel Corporation nor the names of its
20 *      contributors may be used to endorse or promote products derived
21 *      from this software without specific prior written permission.
22 *
23 *  @copyright
24 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
31 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 *  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
34 *  WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 *  POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38
39/**
40 * @file abi.h
41 *
42 * @brief Defines the application binary interface between the compiler and
43 * the Intel Cilk Plus runtime.
44 */
45
46#ifndef CILK_INTERNAL_ABI_H
47#define CILK_INTERNAL_ABI_H
48
49
50#include <cilk/common.h>
51#include <stddef.h>  // Needed to define size_t
52
53/**
54 * Jump buffers are OS and architecture dependent
55 */
56#if ! defined(_MSC_VER)
57/* Non-Windows - only need 5 registers for the jump buffer for both IA32 and Intel64 */
58typedef void *__CILK_JUMP_BUFFER[5];
59
60/** OS-specific implementation of setjmp */
61#   define CILK_SETJMP(X) __builtin_setjmp(X)
62/** OS-specific implementation of longjmp */
63#   define CILK_LONGJMP(X) __builtin_longjmp(X,1)
64#else
65/* Windows - things are a little more complicated */
66#   if defined(_M_X64)
67/* Intel64 - Use an OS-defined jump buffer */
68#       include <setjmp.h>
69typedef jmp_buf __CILK_JUMP_BUFFER;
70
71#       define CILK_SETJMP(X) setjmp(X)
72#       define CILK_LONGJMP(X) longjmp(X, 1)
73#   elif defined(_M_IX86)
74/**
75 * Windows x86 - Use a simplified version of the Windows jump buffer for x86
76 * setjmp is provided by __cilkrts_setjmp which passes jump buffer in EAX and
77 * destination in EDX longjmp is provided by an internal routine which uses
78 * this structure
79 */
80typedef struct
81{
82    unsigned long Ebp;
83    unsigned long Ebx;
84    unsigned long Edi;
85    unsigned long Esi;
86    unsigned long Esp;
87    unsigned long Eip;
88    unsigned long Registration;
89    unsigned long TryLevel;
90} __CILK_JUMP_BUFFER;
91
92#    else
93#    error Unexpected architecture - Need to define __CILK_JUMP_BUFFER
94#    endif  /* _M_X64 */
95
96#endif  /* defined(_MSC_VER) */
97
98/* struct tags */
99typedef struct __cilkrts_stack_frame __cilkrts_stack_frame; ///< struct tag for stack frame
100
101// Forwarded declarations
102typedef struct global_state_t        global_state_t;  ///< Forwarded declaration for global state
103typedef struct local_state           local_state;     ///< Forwarded declaration for local state
104typedef struct cilkred_map           cilkred_map;     ///< Forward declaration for reducer map
105
106/// Forwarded declaration for system-dependent worker state
107typedef struct __cilkrts_worker_sysdep_state
108                                     __cilkrts_worker_sysdep_state;
109
110/**
111 * The worker struct contains per-worker information that needs to be
112 * visible to the compiler, or rooted here.
113 *
114 * For 32-bit Windows we need to be aligning the structures on 4-byte
115 * boundaries to match where ICL is allocating the birthrank and rank
116 * in the __cilkrts_stack_frame.  It's 4-byte aligned instead of 8-byte
117 * aligned.  This is OK because the compiler is dealing with the 64-bit
118 * quantities as two 32-bit values.  So change the packing to be on
119 * 4-byte boundaries.
120 *
121 * The fields of the worker struct can be classified as either local
122 * or shared.
123 *
124 *  Local: This field is only accessed by the thread bound to this
125 *    worker struct.  Local fields can be freely accessed without
126 *    acquiring locks.
127 *
128 *  Shared: This field may be accessed by multiple worker threads.
129 *    Accesses to shared fields usually requires locks, except in
130 *    special situations where one can prove that locks are
131 *    unnecessary.
132 *
133 * The fields of the worker struct can also be classified as
134 * "read-only" if the field does not change after it is initialized.
135 * Otherwise, the field is "read/write".  Read-only fields do not
136 * require locks to access (ignoring the synchronization that might be
137 * needed for initialization if this can occur in parallel).
138 *
139 * Finally, we explicitly classify some fields as "synchronization"
140 * fields if they are used as part of a synchronization protocol in
141 * the runtime.  These variables are generally shared and read/write.
142 * Mostly, this category includes lock variables and other variables
143 * that are involved in synchronization protocols (i.e., the THE
144 * protocol).
145 */
146#if defined(_MSC_VER) && defined(_M_IX86)
147#pragma pack(push, 4)
148#endif
149
150struct __cilkrts_worker {
151    /**
152     * T, H, and E pointers in the THE protocol See "The implementation of
153     * the Cilk-5 multithreaded language", PLDI 1998:
154     * http://portal.acm.org/citation.cfm?doid=277652.277725
155     *
156     * Synchronization fields.  [shared read/write]
157     */
158    __cilkrts_stack_frame *volatile *volatile tail;
159    __cilkrts_stack_frame *volatile *volatile head;  /**< @copydoc tail */
160    __cilkrts_stack_frame *volatile *volatile exc;   /**< @copydoc tail */
161
162    /**
163     * Addition to the THE protocol to allow us to protect some set of
164     * entries in the tail queue from stealing.  Normally, this is set
165     * beyond the end of the task queue, indicating that all entries are
166     * available for stealing.  During exception handling, protected_tail
167     * may be set to the first entry in the task queue, indicating that
168     * stealing is not allowed.
169     *
170     * Synchronization field.
171     */
172    __cilkrts_stack_frame *volatile *volatile protected_tail;
173
174    /**
175     * Limit of the Lazy Task Queue, to detect queue overflow
176     * [local read-only]
177     */
178    __cilkrts_stack_frame *volatile *ltq_limit;
179
180    /**
181     * Worker id.
182     * [local read-only]
183     */
184    int32_t self;
185
186    /**
187     * Global state of the runtime system, opaque to the client.
188     * [local read-only]
189     */
190    global_state_t *g;
191
192    /**
193     * Additional per-worker state of the runtime system that we want
194     * to maintain hidden from the client.
195     * [shared read-only]
196     */
197    local_state *l;
198
199    /**
200     * Map from reducer names to reducer values.
201     * [local read/write]
202     */
203    cilkred_map *reducer_map;
204
205    /**
206     * A slot that points to the currently executing Cilk frame.
207     * [local read/write]
208     */
209    __cilkrts_stack_frame *current_stack_frame;
210
211    /**
212     * Reserved space for a pointer.
213     * Used to be __cilkrts_stack_frame *volatile *volatile saved_protected_tail;
214     */
215    void* reserved;
216
217    /**
218     * System-dependent part of the worker state
219     * [local read-only]
220     */
221    __cilkrts_worker_sysdep_state *sysdep;
222
223#if __CILKRTS_ABI_VERSION >= 1
224    /**
225     * Per-worker pedigree information used to support scheduling-independent
226     * pseudo-random numbers.
227     * [local read/write]
228     */
229    __cilkrts_pedigree   pedigree;
230#endif  /* __CILKRTS_ABI_VERSION >= 1 */
231};
232
233
234/**
235 * Every spawning function has a frame descriptor.  A spawning function
236 * is a function that spawns or detaches.  Only spawning functions
237 * are visible to the Cilk runtime.
238 */
239struct __cilkrts_stack_frame
240{
241    /**
242     * flags is an integer with values defined below.  Client code
243     * initializes flags to CILK_FRAME_VERSION before the first Cilk
244     * operation.
245     *
246     * The low 24-bits of the 'flags' field are the flags, proper.  The high
247     * 8-bits are the version number.
248     *
249     * IMPORTANT: bits in this word are set and read by the PARENT ONLY,
250     * not by a spawned child.  In particular, the STOLEN and UNSYNCHED
251     * bits are set on a steal and are read before a sync.  Since there
252     * is no synchronization (locking) on this word, any attempt to set
253     * or read these bits asynchronously in a child would result in a race.
254     */
255    uint32_t flags;
256
257    /** Not currently used.  Not initialized by Intel compiler. */
258    int32_t size;
259
260    /**
261     * call_parent points to the __cilkrts_stack_frame of the closest
262     * ancestor spawning function, including spawn helpers, of this frame.
263     * It forms a linked list ending at the first stolen frame.
264     */
265    __cilkrts_stack_frame *call_parent;
266
267    /**
268     * The client copies the worker from TLS here when initializing
269     * the structure.  The runtime ensures that the field always points
270     * to the __cilkrts_worker which currently "owns" the frame.
271     */
272    __cilkrts_worker *worker;
273
274    /**
275     * Unix: Pending exception after sync.  The sync continuation
276     * must call __cilkrts_rethrow to handle the pending exception.
277     *
278     * Windows: the handler that _would_ have been registered if our
279     * handler were not there.  We maintain this for unwinding purposes.
280     * Win32: the value of this field is only defined in spawn helper
281     * functions
282     *
283     * Win64: except_data must be filled in  for all functions with a
284     * __cilkrts_stack_frame
285     */
286    void *except_data;
287
288    /**
289     * Before every spawn and nontrivial sync the client function
290     * saves its continuation here.
291     */
292    __CILK_JUMP_BUFFER ctx;
293
294#if __CILKRTS_ABI_VERSION >= 1
295    /**
296     * Architecture-specific floating point state.  mxcsr and fpcsr should be
297     * set when CILK_SETJMP is called in client code.  Note that the Win64
298     * jmpbuf for the Intel64 architecture already contains this information
299     * so there is no need to use these fields on that OS/architecture.
300     */
301    uint32_t mxcsr;
302    uint16_t fpcsr;         /**< @copydoc mxcsr */
303
304
305    /**
306     * reserved is not used at this time.  Client code should initialize it
307     * to 0 before the first Cilk operation
308     */
309    uint16_t reserved;
310
311    /**
312     * Pedigree information to support scheduling-independent pseudo-random
313     * numbers.  There are two views of this information.  The copy in a
314     * spawning function is used to stack the rank and communicate to the
315     * runtime on a steal or continuation.  The copy in a spawn helper is
316     * immutable once the function is detached and is a node in the pedigree.
317     * The union is used to make clear which view we're using.
318     *
319     * In the detach sequence Client code should:
320     *    - copy the worker pedigree into the spawn helper's pedigree
321     *    - copy the worker pedigree into the call parent's pedigree
322     *    - set the worker's rank to 0
323     *    - set the worker's pedigree.next to the spawn helper's pedigree
324     */
325    union
326    {
327        __cilkrts_pedigree spawn_helper_pedigree; /* Used in spawn helpers */
328        __cilkrts_pedigree parent_pedigree;       /* Used in spawning funcs */
329    };
330#endif  /* __CILKRTS_ABI_VERSION >= 1 */
331};
332
333/*
334 * Restore previous structure packing for 32-bit Windows
335 */
336#if defined(_MSC_VER) && defined(_M_IX86)
337#pragma pack(pop)
338#endif
339
340/* Values of the flags bitfield */
341/** CILK_FRAME_STOLEN is set if the frame has ever been stolen. */
342#define CILK_FRAME_STOLEN    0x01
343
344/**
345 * CILK_FRAME_UNSYNCHED is set if the frame has been stolen and
346 * is has not yet executed _Cilk_sync.  It is technically a misnomer in that a
347 * frame can have this flag set even if all children have returned.
348 */
349#define CILK_FRAME_UNSYNCHED 0x02
350
351/**
352 * Is this frame detached (spawned)?  If so the runtime needs
353 * to undo-detach in the slow path epilogue.
354 */
355#define CILK_FRAME_DETACHED  0x04
356
357/**
358 * CILK_FRAME_EXCEPTION_PROBED is set if the frame has been probed in the
359 * exception handler first pass
360 */
361#define CILK_FRAME_EXCEPTION_PROBED 0x08
362
363/** Is this frame receiving an exception after sync? */
364#define CILK_FRAME_EXCEPTING 0x10
365
366/**
367 * Is the pedigree unsynched?  That is, has a synch occurred that is not
368 * yet represented in the pedigree?
369 */
370#define CILK_FRAME_SF_PEDIGREE_UNSYNCHED 0x20
371
372/** Is this the last (oldest) Cilk frame? */
373#define CILK_FRAME_LAST	     0x80
374
375/**
376 * Is this frame in the epilogue, or more generally after the last
377 * sync when it can no longer do any Cilk operations?
378 */
379#define CILK_FRAME_EXITING   0x0100
380
381/** Is this frame suspended? (used for debugging) */
382#define CILK_FRAME_SUSPENDED 0x8000
383
384/** Used by Windows exception handling to indicate that __cilkrts_leave_frame should do nothing */
385#define CILK_FRAME_UNWINDING 0x10000
386
387/*
388 * The low 24-bits of the 'flags' field are the flags, proper.  The high 8-bits
389 * are the version number.
390 */
391
392/** ABI version left shifted to the high byte */
393#define CILK_FRAME_VERSION (__CILKRTS_ABI_VERSION << 24)
394
395/** Mask for the flags field to isolate the version bits */
396#define CILK_FRAME_VERSION_MASK  0xFF000000
397
398/** Mask for the flags field to isolate the flag bits */
399#define CILK_FRAME_FLAGS_MASK    0x00FFFFFF
400
401/** Convenience macro to provide access the version portion of the flags field */
402#define CILK_FRAME_VERSION_VALUE(_flags) (((_flags) & CILK_FRAME_VERSION_MASK) >> 24)
403
404/** Any undefined bits are reserved and must be zero ("MBZ" = "Must Be Zero") */
405#define CILK_FRAME_MBZ  (~ (CILK_FRAME_STOLEN | \
406                            CILK_FRAME_UNSYNCHED | \
407                            CILK_FRAME_DETACHED | \
408                            CILK_FRAME_EXCEPTION_PROBED | \
409                            CILK_FRAME_EXCEPTING | \
410                            CILK_FRAME_SF_PEDIGREE_UNSYNCHED | \
411                            CILK_FRAME_LAST | \
412                            CILK_FRAME_EXITING | \
413                            CILK_FRAME_SUSPENDED | \
414                            CILK_FRAME_UNWINDING | \
415                            CILK_FRAME_VERSION_MASK))
416
417__CILKRTS_BEGIN_EXTERN_C
418
419/**
420 * Call __cilkrts_enter_frame to initialize an ABI 0 frame descriptor.
421 * Initialize the frame descriptor before spawn or detach.  A function that
422 * conditionally does Cilk operations need not initialize the frame descriptor
423 * in a code path that never uses it.
424 *
425 * @param sf The __cilkrts_stack_frame that is to be initialized.
426 */
427CILK_ABI(void) __cilkrts_enter_frame(__cilkrts_stack_frame* sf);
428
429/**
430 * Call __cilkrts_enter_frame to initialize an ABI 1 frame descriptor.
431 * Initialize the frame descriptor before spawn or detach.  A function that
432 * conditionally does Cilk operations need not initialize the frame descriptor
433 * in a code path that never uses it.
434 *
435 * @param sf The __cilkrts_stack_frame that is to be initialized.
436 */
437CILK_ABI(void) __cilkrts_enter_frame_1(__cilkrts_stack_frame* sf);
438
439/**
440 * __cilkrts_enter_frame_fast is the same as __cilkrts_enter_frame, except it
441 * assumes that the thread has already been bound to a worker.
442 *
443 * @param sf The __cilkrts_stack_frame that is to be initialized.
444 */
445CILK_ABI(void) __cilkrts_enter_frame_fast(__cilkrts_stack_frame *sf);
446
447/**
448 * __cilkrts_enter_frame_fast_1 is the same as __cilkrts_enter_frame_1,
449 * except it assumes that the thread has already been bound to a worker.
450 *
451 * @param sf The __cilkrts_stack_frame that is to be initialized.
452 */
453CILK_ABI(void) __cilkrts_enter_frame_fast_1(__cilkrts_stack_frame *sf);
454
455/**
456 * Call leave_frame before leaving a frame, after sync.  This function
457 * returns except in a spawn wrapper where the parent has been stolen.
458 *
459 * @param sf The __cilkrts_stack_frame that is to be left.
460 */
461CILK_ABI(void) __cilkrts_leave_frame(__cilkrts_stack_frame *sf);
462
463/**
464 * Wait for any spawned children of this function to complete before
465 * continuing.  This function will only return when the join counter
466 * has gone to 0.  Other workers will re-enter the scheduling loop to
467 * attempt to steal additional work.
468 *
469 * @param sf The __cilkrts_stack_frame that is to be synched.
470 */
471CILK_ABI(void) __cilkrts_sync(__cilkrts_stack_frame *sf);
472
473/**
474 * Called when an exception is escaping a spawn * wrapper.
475 * The stack frame's except_data field is the C++ runtime
476 * exception object.  If NULL (temporary workaround) the
477 * currently caught exception should be rethrown.  If this
478 * function returns normal exit functions must be called;
479 * undo-detach will have been done.
480 *
481 * @param sf The __cilkrts_stack_frame for the function that
482 * is raising an exception.
483 */
484CILK_ABI_THROWS(void)
485    __cilkrts_return_exception(__cilkrts_stack_frame *sf);
486
487/**
488 * Called to re-raise an exception.
489 *
490 * @param sf The __cilkrts_stack_frame for the function that
491 * is raising an exception.
492 */
493CILK_ABI_THROWS(void) __cilkrts_rethrow(__cilkrts_stack_frame *sf);
494
495/**
496 * Called at the beginning of a spawning function to get the worker
497 * that this function is running on.  This worker will be used to
498 * initialize the __cilkrts_stack_frame.
499 *
500 * @return The __cilkrts_worker that the function is running on.
501 * @return NULL if this thread is not yet bound to a worker.
502 */
503CILK_ABI(__cilkrts_worker_ptr) __cilkrts_get_tls_worker(void);
504
505/**
506 * Similar to __cilkrts_get_tls_worker, but assumes that TLS has been
507 * initialized.
508 *
509 * @return The __cilkrts_worker that the function is running on.
510 * @return NULL if this thread is not yet bound to a worker.
511 */
512CILK_ABI(__cilkrts_worker_ptr) __cilkrts_get_tls_worker_fast(void);
513
514/**
515 * Binds a thread to the runtime by associating a __cilkrts_worker with
516 * it.  Called if __cilkrts_get_tls_worker returns NULL.  This function will
517 * initialize the runtime the first time it is called.
518 *
519 * This function is versioned by the ABI version number.  The runtime
520 * will export all previous versions.  This prevents using an application
521 * built with a newer compiler against an old runtime.
522 *
523 * @return The __cilkrts_worker bound to the thread the function is running
524 * on.
525 */
526CILK_ABI(__cilkrts_worker_ptr) __cilkrts_bind_thread_1(void);
527
528typedef uint32_t cilk32_t;  /**< 32-bit unsigned type for cilk_for loop indicies */
529
530typedef uint64_t cilk64_t;  /**< 64-bit unsigned type for cilk_for loop indicies */
531
532/**
533 * Signature for the lambda function generated for the body of a cilk_for loop
534 * which uses 32-bit indicies
535 */
536typedef void (*__cilk_abi_f32_t)(void *data, cilk32_t low, cilk32_t high);
537
538/**
539 * Signature for the lambda function generated for the body of a cilk_for lop
540 * which uses 64-bit indicies
541 */
542typedef void (*__cilk_abi_f64_t)(void *data, cilk64_t low, cilk64_t high);
543
544/**
545 * @brief cilk_for implementation for 32-bit indexes.
546 *
547 * @param body The lambda function for the body of the cilk_for.  The lambda
548 * function will be called to execute each grain of work.
549 * @param data Data passed by the compiler into the lambda function.  Provides
550 * access to data outside the cilk_for body.
551 * @param count Number of steps in the loop.
552 * @param grain This parameter allows the compiler to pass a value from a
553 * \#pragam(grainsize) statement to allow the user to control the grainsize.  If
554 * there isn't a \#pragma(grainsize) immediately preceeding cilk_for loop, Pass
555 * 0 to specify that the runtime should calculate the grainsize using its own
556 * hueristicts.
557 */
558CILK_ABI_THROWS(void) __cilkrts_cilk_for_32(__cilk_abi_f32_t body,
559                                            void *data,
560                                            cilk32_t count,
561                                            int grain);
562
563/**
564 * @brief cilk_for implementation for 64-bit indexes.
565 *
566 * @copydetails __cilkrts_cilk_for_32
567 */
568CILK_ABI_THROWS(void) __cilkrts_cilk_for_64(__cilk_abi_f64_t body,
569                                            void *data,
570                                            cilk64_t count,
571                                            int grain);
572
573/**
574 * @brief Allocate memory for variable length arrays. If the frame is
575 * sync'd, the memory will be allocated on the stack, otherwise it will
576 * be allocated from the heap.
577 *
578 * @param sf The __cilkrts_stack_frame for the function allocating the
579 * memory.
580 * @param size The number of bytes requested.
581 * @param distance_from_sp_to_alloca_area ?.
582 * @param align Alignment required.  Always >= minimum stack alignment,
583 * >= ptr_size, and always a power of 2.
584 * @param needs_tag Non-zero if the pointer being returned needs to be
585 * tagged
586 *
587 * @return The address of the memory block allocated.
588 */
589
590CILK_ABI(__cilkrts_void_ptr)
591__cilkrts_stack_alloc(__cilkrts_stack_frame *sf,
592                      size_t size,
593                      size_t distance_from_sp_to_alloca_area,
594                      uint32_t align,
595                      uint32_t needs_tag);
596
597/**
598 * @brief Free memory allocated by _cilkrts_stack_alloc() for variable length
599 * arrays.
600 *
601 * @param sf The __cilkrts_stack_frame for the function allocating the
602 * memory.
603 * @param p Pointer to the memory block to be freed.
604 * @param size The number of bytes requested.
605 * @param distance_from_sp_to_alloca_area ?.
606 * @param align Alignment required.  Always >= minimum stack alignment,
607 * >= ptr_size, and always a power of 2.
608 * @param know_from_stack Non-zero if the pointer is known to have been
609 * allocated on the stack and has no tag.
610 */
611CILK_ABI(void)
612__cilkrts_stack_free(__cilkrts_stack_frame *sf,
613                     void *p,
614                     size_t size,
615                     size_t distance_from_sp_to_alloca_area,
616                     uint32_t align,
617                     uint32_t known_from_stack);
618
619/**
620 * @brief System-dependent code to save floating point control information
621 * to an ABI 1 or higher @c __cilkrts_stack_frame.  If possible (and necessary)
622 * the code to save the floating point control information should be inlined.
623 *
624 * Note that this function does *not* save the current floating point
625 * registers.  It saves the floating point control words that control
626 * precision and rounding and stuff like that.
627 *
628 * This function will be a noop for architectures that don't have warts
629 * like the floating point control words, or where the information is
630 * already being saved by the setjmp.
631 *
632 * @param sf  @c __cilkrts_stack_frame for the frame we're saving the
633 * floating point control information in.
634 */
635CILK_ABI(void)
636__cilkrts_save_fp_ctrl_state(__cilkrts_stack_frame *sf);
637
638__CILKRTS_END_EXTERN_C
639#endif /* include guard */
640