summaryrefslogtreecommitdiff
path: root/includes/mkDerivedConstants.c
diff options
context:
space:
mode:
Diffstat (limited to 'includes/mkDerivedConstants.c')
-rw-r--r--includes/mkDerivedConstants.c426
1 files changed, 332 insertions, 94 deletions
diff --git a/includes/mkDerivedConstants.c b/includes/mkDerivedConstants.c
index 3fcf12849f..558d709f94 100644
--- a/includes/mkDerivedConstants.c
+++ b/includes/mkDerivedConstants.c
@@ -26,7 +26,11 @@
#include "Stable.h"
#include "Capability.h"
+#include <inttypes.h>
#include <stdio.h>
+#include <string.h>
+
+enum Mode { Gen_Haskell_Type, Gen_Haskell_Value, Gen_Haskell_Wrappers, Gen_Haskell_Exports, Gen_Header } mode;
#define str(a,b) #a "_" #b
@@ -36,38 +40,69 @@
#pragma GCC poison sizeof
-#if defined(GEN_HASKELL)
-#define def_offset(str, offset) \
- printf("oFFSET_" str " :: Int\n"); \
- printf("oFFSET_" str " = %" FMT_SizeT "\n", (size_t)offset);
-#else
-#define def_offset(str, offset) \
- printf("#define OFFSET_" str " %" FMT_SizeT "\n", (size_t)offset);
-#endif
+#define def_offset(str, offset) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ printf(" , pc_OFFSET_" str " :: Int\n"); \
+ break; \
+ case Gen_Haskell_Value: \
+ printf(" , pc_OFFSET_" str " = %" PRIdPTR "\n", (intptr_t)offset); \
+ break; \
+ case Gen_Haskell_Wrappers: \
+ printf("oFFSET_" str " :: DynFlags -> Int\n"); \
+ printf("oFFSET_" str " dflags = pc_OFFSET_" str " (sPlatformConstants (settings dflags))\n"); \
+ break; \
+ case Gen_Haskell_Exports: \
+ printf(" oFFSET_" str ",\n"); \
+ break; \
+ case Gen_Header: \
+ printf("#define OFFSET_" str " %" PRIdPTR "\n", (intptr_t)offset); \
+ break; \
+ }
+
+#define ctype(type) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define SIZEOF_" #type " %" FMT_SizeT "\n", \
+ (size_t)TYPE_SIZE(type)); \
+ break; \
+ }
-#if defined(GEN_HASKELL)
-#define ctype(type) /* nothing */
-#else
-#define ctype(type) \
- printf("#define SIZEOF_" #type " %" FMT_SizeT "\n", (size_t)TYPE_SIZE(type));
-#endif
-
-#if defined(GEN_HASKELL)
-#define field_type_(str, s_type, field) /* nothing */
-#define field_type_gcptr_(str, s_type, field) /* nothing */
-#else
/* Defining REP_x to be b32 etc
These are both the C-- types used in a load
e.g. b32[addr]
and the names of the CmmTypes in the compiler
b32 :: CmmType
*/
-#define field_type_(str, s_type, field) \
- printf("#define REP_" str " b"); \
- printf("%" FMT_SizeT "\n", FIELD_SIZE(s_type, field) * 8);
-#define field_type_gcptr_(str, s_type, field) \
- printf("#define REP_" str " gcptr\n");
-#endif
+#define field_type_(str, s_type, field) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define REP_" str " b"); \
+ printf("%" FMT_SizeT "\n", FIELD_SIZE(s_type, field) * 8); \
+ break; \
+ }
+
+#define field_type_gcptr_(str, s_type, field) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define REP_" str " gcptr\n"); \
+ break; \
+ }
#define field_type(s_type, field) \
field_type_(str(s_type,field),s_type,field);
@@ -79,12 +114,17 @@
field_offset_(str(s_type,field),s_type,field);
/* An access macro for use in C-- sources. */
-#if defined(GEN_HASKELL)
-#define struct_field_macro(str) /* nothing */
-#else
-#define struct_field_macro(str) \
- printf("#define " str "(__ptr__) REP_" str "[__ptr__+OFFSET_" str "]\n");
-#endif
+#define struct_field_macro(str) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define " str "(__ptr__) REP_" str "[__ptr__+OFFSET_" str "]\n"); \
+ break; \
+ }
/* Outputs the byte offset and MachRep for a field */
#define struct_field(s_type, field) \
@@ -97,21 +137,37 @@
field_type_(str, s_type, field); \
struct_field_macro(str)
-#if defined(GEN_HASKELL)
-#define def_size(str, size) \
- printf("sIZEOF_" str " :: Int\n"); \
- printf("sIZEOF_" str " = %" FMT_SizeT "\n", (size_t)size);
-#else
-#define def_size(str, size) \
- printf("#define SIZEOF_" str " %" FMT_SizeT "\n", (size_t)size);
-#endif
-
-#if defined(GEN_HASKELL)
-#define def_closure_size(str, size) /* nothing */
-#else
-#define def_closure_size(str, size) \
- printf("#define SIZEOF_" str " (SIZEOF_StgHeader+%" FMT_SizeT ")\n", (size_t)size);
-#endif
+#define def_size(str, size) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ printf(" , pc_SIZEOF_" str " :: Int\n"); \
+ break; \
+ case Gen_Haskell_Value: \
+ printf(" , pc_SIZEOF_" str " = %" FMT_SizeT "\n", (size_t)size); \
+ break; \
+ case Gen_Haskell_Wrappers: \
+ printf("sIZEOF_" str " :: DynFlags -> Int\n"); \
+ printf("sIZEOF_" str " dflags = pc_SIZEOF_" str " (sPlatformConstants (settings dflags))\n"); \
+ break; \
+ case Gen_Haskell_Exports: \
+ printf(" sIZEOF_" str ",\n"); \
+ break; \
+ case Gen_Header: \
+ printf("#define SIZEOF_" str " %" FMT_SizeT "\n", (size_t)size); \
+ break; \
+ }
+
+#define def_closure_size(str, size) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define SIZEOF_" str " (SIZEOF_StgHeader+%" FMT_SizeT ")\n", (size_t)size); \
+ break; \
+ }
#define struct_size(s_type) \
def_size(#s_type, TYPE_SIZE(s_type));
@@ -129,12 +185,17 @@
closure_size(s_type)
/* An access macro for use in C-- sources. */
-#if defined(GEN_HASKELL)
-#define closure_field_macro(str) /* nothing */
-#else
-#define closure_field_macro(str) \
- printf("#define " str "(__ptr__) REP_" str "[__ptr__+SIZEOF_StgHeader+OFFSET_" str "]\n");
-#endif
+#define closure_field_macro(str) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define " str "(__ptr__) REP_" str "[__ptr__+SIZEOF_StgHeader+OFFSET_" str "]\n"); \
+ break; \
+ }
#define closure_field_offset_(str, s_type,field) \
def_offset(str, OFFSET(s_type,field) - TYPE_SIZE(StgHeader));
@@ -142,12 +203,17 @@
#define closure_field_offset(s_type,field) \
closure_field_offset_(str(s_type,field),s_type,field)
-#if defined(GEN_HASKELL)
-#define closure_payload_macro(str) /* nothing */
-#else
-#define closure_payload_macro(str) \
- printf("#define " str "(__ptr__,__ix__) W_[__ptr__+SIZEOF_StgHeader+OFFSET_" str " + WDS(__ix__)]\n");
-#endif
+#define closure_payload_macro(str) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define " str "(__ptr__,__ix__) W_[__ptr__+SIZEOF_StgHeader+OFFSET_" str " + WDS(__ix__)]\n"); \
+ break; \
+ }
#define closure_payload(s_type,field) \
closure_field_offset_(str(s_type,field),s_type,field); \
@@ -176,60 +242,161 @@
def_offset(str(s_type,field), OFFSET(s_type,field) - TYPE_SIZE(StgHeader) - TYPE_SIZE(StgTSOProfInfo));
/* Full byte offset for a TSO field, for use from Cmm */
-#if defined(GEN_HASKELL)
-#define tso_field_offset_macro(str) /* nothing */
-#else
-#define tso_field_offset_macro(str) \
- printf("#define TSO_OFFSET_" str " (SIZEOF_StgHeader+SIZEOF_OPT_StgTSOProfInfo+OFFSET_" str ")\n");
-#endif
+#define tso_field_offset_macro(str) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define TSO_OFFSET_" str " (SIZEOF_StgHeader+SIZEOF_OPT_StgTSOProfInfo+OFFSET_" str ")\n"); \
+ break; \
+ }
#define tso_field_offset(s_type, field) \
tso_payload_offset(s_type, field); \
tso_field_offset_macro(str(s_type,field));
-#if defined(GEN_HASKELL)
-#define tso_field_macro(str) /* nothing */
-#else
-#define tso_field_macro(str) \
- printf("#define " str "(__ptr__) REP_" str "[__ptr__+TSO_OFFSET_" str "]\n")
-#endif
+#define tso_field_macro(str) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#define " str "(__ptr__) REP_" str "[__ptr__+TSO_OFFSET_" str "]\n") \
+ break; \
+ }
#define tso_field(s_type, field) \
field_type(s_type, field); \
tso_field_offset(s_type,field); \
tso_field_macro(str(s_type,field))
-#if defined(GEN_HASKELL)
-#define opt_struct_size(s_type, option) /* nothing */
-#else
-#define opt_struct_size(s_type, option) \
- printf("#ifdef " #option "\n"); \
- printf("#define SIZEOF_OPT_" #s_type " SIZEOF_" #s_type "\n"); \
- printf("#else\n"); \
- printf("#define SIZEOF_OPT_" #s_type " 0\n"); \
- printf("#endif\n\n");
-#endif
+#define opt_struct_size(s_type, option) \
+ switch (mode) { \
+ case Gen_Haskell_Type: \
+ case Gen_Haskell_Value: \
+ case Gen_Haskell_Wrappers: \
+ case Gen_Haskell_Exports: \
+ break; \
+ case Gen_Header: \
+ printf("#ifdef " #option "\n"); \
+ printf("#define SIZEOF_OPT_" #s_type " SIZEOF_" #s_type "\n"); \
+ printf("#else\n"); \
+ printf("#define SIZEOF_OPT_" #s_type " 0\n"); \
+ printf("#endif\n\n"); \
+ break; \
+ }
#define FUN_OFFSET(sym) (OFFSET(Capability,f.sym) - OFFSET(Capability,r))
+void constantIntC(char *cName, char *haskellName, intptr_t val) {
+ /* If the value is larger than 2^28 or smaller than -2^28, then fail.
+ This test is a bit conservative, but if any constants are roughly
+ maxBoun or minBound then we probably need them to be Integer
+ rather than Int so that cross-compiling between 32bit and 64bit
+ platforms works. */
+ if (val > 268435456) {
+ printf("Value too large for constantInt: %" PRIdPTR "\n", val);
+ exit(1);
+ }
+ if (val < -268435456) {
+ printf("Value too small for constantInt: %" PRIdPTR "\n", val);
+ exit(1);
+ }
+
+ switch (mode) {
+ case Gen_Haskell_Type:
+ printf(" , pc_%s :: Int\n", haskellName);
+ break;
+ case Gen_Haskell_Value:
+ printf(" , pc_%s = %" PRIdPTR "\n", haskellName, val);
+ break;
+ case Gen_Haskell_Wrappers:
+ printf("%s :: DynFlags -> Int\n", haskellName);
+ printf("%s dflags = pc_%s (sPlatformConstants (settings dflags))\n",
+ haskellName, haskellName);
+ break;
+ case Gen_Haskell_Exports:
+ printf(" %s,\n", haskellName);
+ break;
+ case Gen_Header:
+ if (cName != NULL) {
+ printf("#define %s %" PRIdPTR "\n", cName, val);
+ }
+ break;
+ }
+}
+
+void constantInt(char *name, intptr_t val) {
+ constantIntC (NULL, name, val);
+}
int
main(int argc, char *argv[])
{
-#ifndef GEN_HASKELL
- printf("/* This file is created automatically. Do not edit by hand.*/\n\n");
-
- printf("#define STD_HDR_SIZE %" FMT_SizeT "\n", (size_t)sizeofW(StgHeader) - sizeofW(StgProfHeader));
+ if (argc == 1) {
+ mode = Gen_Header;
+ }
+ else if (argc == 2) {
+ if (0 == strcmp("--gen-haskell-type", argv[1])) {
+ mode = Gen_Haskell_Type;
+ }
+ else if (0 == strcmp("--gen-haskell-value", argv[1])) {
+ mode = Gen_Haskell_Value;
+ }
+ else if (0 == strcmp("--gen-haskell-wrappers", argv[1])) {
+ mode = Gen_Haskell_Wrappers;
+ }
+ else if (0 == strcmp("--gen-haskell-exports", argv[1])) {
+ mode = Gen_Haskell_Exports;
+ }
+ else {
+ printf("Bad args\n");
+ exit(1);
+ }
+ }
+ else {
+ printf("Bad args\n");
+ exit(1);
+ }
+
+ switch (mode) {
+ case Gen_Haskell_Type:
+ printf("data PlatformConstants = PlatformConstants {\n");
+ /* Now a kludge that allows the real entries to all start with a
+ comma, which makes life a little easier */
+ printf(" pc_platformConstants :: ()\n");
+ break;
+ case Gen_Haskell_Value:
+ printf("PlatformConstants {\n");
+ printf(" pc_platformConstants = ()\n");
+ break;
+ case Gen_Haskell_Wrappers:
+ case Gen_Haskell_Exports:
+ break;
+ case Gen_Header:
+ printf("/* This file is created automatically. Do not edit by hand.*/\n\n");
+
+ break;
+ }
+
+ // Closure header sizes.
+ constantIntC("STD_HDR_SIZE", "sTD_HDR_SIZE",
+ sizeofW(StgHeader) - sizeofW(StgProfHeader));
/* grrr.. PROFILING is on so we need to subtract sizeofW(StgProfHeader) */
- printf("#define PROF_HDR_SIZE %" FMT_SizeT "\n", (size_t)sizeofW(StgProfHeader));
+ constantIntC("PROF_HDR_SIZE", "pROF_HDR_SIZE", sizeofW(StgProfHeader));
- printf("#define BLOCK_SIZE %u\n", BLOCK_SIZE);
- printf("#define MBLOCK_SIZE %u\n", MBLOCK_SIZE);
- printf("#define BLOCKS_PER_MBLOCK %" FMT_SizeT "\n", (lnat)BLOCKS_PER_MBLOCK);
+ // Size of a storage manager block (in bytes).
+ constantIntC("BLOCK_SIZE", "bLOCK_SIZE", BLOCK_SIZE);
+ constantIntC("MBLOCK_SIZE", "mBLOCK_SIZE", MBLOCK_SIZE);
+ // blocks that fit in an MBlock, leaving space for the block descriptors
+ constantIntC("BLOCKS_PER_MBLOCK", "bLOCKS_PER_MBLOCK", BLOCKS_PER_MBLOCK);
// could be derived, but better to save doing the calculation twice
- printf("\n\n");
-#endif
field_offset(StgRegTable, rR1);
field_offset(StgRegTable, rR2);
@@ -469,11 +636,82 @@ main(int argc, char *argv[])
struct_field(snEntry,addr);
#ifdef mingw32_HOST_OS
- struct_size(StgAsyncIOResult);
- struct_field(StgAsyncIOResult, reqID);
- struct_field(StgAsyncIOResult, len);
- struct_field(StgAsyncIOResult, errCode);
+ /* Note that this conditional part only affects the C headers.
+ That's important, as it means we get the same PlatformConstants
+ type on all platforms. */
+ if (mode == Gen_Header) {
+ struct_size(StgAsyncIOResult);
+ struct_field(StgAsyncIOResult, reqID);
+ struct_field(StgAsyncIOResult, len);
+ struct_field(StgAsyncIOResult, errCode);
+ }
#endif
+ // pre-compiled thunk types
+ constantInt("mAX_SPEC_SELECTEE_SIZE", MAX_SPEC_SELECTEE_SIZE);
+ constantInt("mAX_SPEC_AP_SIZE", MAX_SPEC_AP_SIZE);
+
+ // closure sizes: these do NOT include the header (see below for
+ // header sizes)
+ constantInt("mIN_PAYLOAD_SIZE", MIN_PAYLOAD_SIZE);
+
+ constantInt("mIN_INTLIKE", MIN_INTLIKE);
+ constantInt("mAX_INTLIKE", MAX_INTLIKE);
+
+ constantInt("mIN_CHARLIKE", MIN_CHARLIKE);
+ constantInt("mAX_CHARLIKE", MAX_CHARLIKE);
+
+ constantInt("mUT_ARR_PTRS_CARD_BITS", MUT_ARR_PTRS_CARD_BITS);
+
+ // A section of code-generator-related MAGIC CONSTANTS.
+ constantInt("mAX_Vanilla_REG", MAX_VANILLA_REG);
+ constantInt("mAX_Float_REG", MAX_FLOAT_REG);
+ constantInt("mAX_Double_REG", MAX_DOUBLE_REG);
+ constantInt("mAX_Long_REG", MAX_LONG_REG);
+ constantInt("mAX_Real_Vanilla_REG", MAX_REAL_VANILLA_REG);
+ constantInt("mAX_Real_Float_REG", MAX_REAL_FLOAT_REG);
+ constantInt("mAX_Real_Double_REG", MAX_REAL_DOUBLE_REG);
+ constantInt("mAX_Real_Long_REG", MAX_REAL_LONG_REG);
+
+ // This tells the native code generator the size of the spill
+ // area is has available.
+ constantInt("rESERVED_C_STACK_BYTES", RESERVED_C_STACK_BYTES);
+ // The amount of (Haskell) stack to leave free for saving registers when
+ // returning to the scheduler.
+ constantInt("rESERVED_STACK_WORDS", RESERVED_STACK_WORDS);
+ // Continuations that need more than this amount of stack should do their
+ // own stack check (see bug #1466).
+ constantInt("aP_STACK_SPLIM", AP_STACK_SPLIM);
+
+ // Size of a word, in bytes
+ constantInt("wORD_SIZE", SIZEOF_HSWORD);
+
+ // Size of a double in StgWords.
+ constantInt("dOUBLE_SIZE", SIZEOF_DOUBLE);
+
+ // Size of a C int, in bytes. May be smaller than wORD_SIZE.
+ constantInt("cINT_SIZE", SIZEOF_INT);
+ constantInt("cLONG_SIZE", SIZEOF_LONG);
+ constantInt("cLONG_LONG_SIZE", SIZEOF_LONG_LONG);
+
+ // Number of bits to shift a bitfield left by in an info table.
+ constantInt("bITMAP_BITS_SHIFT", BITMAP_BITS_SHIFT);
+
+ // Amount of pointer bits used for semi-tagging constructor closures
+ constantInt("tAG_BITS", TAG_BITS);
+
+ switch (mode) {
+ case Gen_Haskell_Type:
+ printf(" } deriving (Read, Show)\n");
+ break;
+ case Gen_Haskell_Value:
+ printf(" }\n");
+ break;
+ case Gen_Haskell_Wrappers:
+ case Gen_Haskell_Exports:
+ case Gen_Header:
+ break;
+ }
+
return 0;
}