1-- C->Haskell Compiler: information about the C implementation 2-- 3-- Author : Manuel M T Chakravarty 4-- Created: 5 February 01 5-- 6-- Version $Revision: 1.2 $ from $Date: 2005/01/16 21:31:21 $ 7-- 8-- Copyright (c) 2001 Manuel M T Chakravarty 9-- 10-- This file is free software; you can redistribute it and/or modify 11-- it under the terms of the GNU General Public License as published by 12-- the Free Software Foundation; either version 2 of the License, or 13-- (at your option) any later version. 14-- 15-- This file is distributed in the hope that it will be useful, 16-- but WITHOUT ANY WARRANTY; without even the implied warranty of 17-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18-- GNU General Public License for more details. 19-- 20--- DESCRIPTION --------------------------------------------------------------- 21-- 22-- This module provide some information about the specific implementation of 23-- C that we are dealing with. 24-- 25--- DOCU ---------------------------------------------------------------------- 26-- 27-- language: Haskell 98 28-- 29-- Bit fields 30-- ~~~~~~~~~~ 31-- Bit fields in C can be signed and unsigned. According to K&R A8.3, they 32-- can only be formed from `int', `signed int', and `unsigned int', where for 33-- `int' it is implementation dependent whether the field is signed or 34-- unsigned. Moreover, the following parameters are implementation 35-- dependent: 36-- 37-- * the direction of packing bits into storage units, 38-- * the size of storage units, and 39-- * whether when a field that doesn't fit a partially filled storage unit 40-- is split across units or the partially filled unit is padded. 41-- 42-- Generally, unnamed fields (those without an identifier) with a width of 0 43-- are guaranteed to forces the above padding. Note that in `CPrimType' we 44-- only represent 0 width fields *if* they imply padding. In other words, 45-- whenever they are unnamed, they are represented by a `CPrimType', and if 46-- they are named, they are represented by a `CPrimType' only if that 47-- targeted C compiler chooses to let them introduce padding. If a field 48-- does not have any effect, it is dropped during the conversion of a C type 49-- into a `CPrimType'-based representation. 50-- 51-- In the code, we assume that the alignment of a bitfield (as determined by 52-- `bitfieldAlignment') is independent of the size of the bitfield. 53-- 54--- TODO ---------------------------------------------------------------------- 55-- 56 57module CInfo ( 58 CPrimType(..), size, alignment, 59 bitfieldDirection, bitfieldPadding, bitfieldIntSigned, bitfieldAlignment 60) where 61 62import Foreign.C 63 64-- we can't rely on the compiler used to compile c2hs already having the new 65-- FFI, so this is system dependent 66-- 67import C2HSConfig (Ptr, FunPtr, 68 bitfieldDirection, bitfieldPadding, bitfieldIntSigned, 69 bitfieldAlignment) 70import qualified 71 C2HSConfig as Storable 72 (Storable(sizeOf, alignment)) 73 74 75-- calibration of C's primitive types 76-- ---------------------------------- 77 78-- C's primitive types (EXPORTED) 79-- 80-- * `CFunPtrPT' doesn't occur in Haskell representations of C types, but we 81-- need to know their size, which may be different from `CPtrPT' 82-- 83data CPrimType = CPtrPT -- void * 84 | CFunPtrPT -- void *() 85 | CCharPT -- char 86 | CUCharPT -- unsigned char 87 | CSCharPT -- signed char 88 | CIntPT -- int 89 | CShortPT -- short int 90 | CLongPT -- long int 91 | CLLongPT -- long long int 92 | CUIntPT -- unsigned int 93 | CUShortPT -- unsigned short int 94 | CULongPT -- unsigned long int 95 | CULLongPT -- unsigned long long int 96 | CFloatPT -- float 97 | CDoublePT -- double 98 | CLDoublePT -- long double 99 | CSFieldPT Int -- signed bit field 100 | CUFieldPT Int -- unsigned bit field 101 deriving (Eq) 102 103-- size of primitive type of C (EXPORTED) 104-- 105-- * negative size implies that it is a bit, not an octet size 106-- 107size :: CPrimType -> Int 108size CPtrPT = Storable.sizeOf (undefined :: Ptr ()) 109size CFunPtrPT = Storable.sizeOf (undefined :: FunPtr ()) 110size CCharPT = 1 111size CUCharPT = 1 112size CSCharPT = 1 113size CIntPT = Storable.sizeOf (undefined :: CInt) 114size CShortPT = Storable.sizeOf (undefined :: CShort) 115size CLongPT = Storable.sizeOf (undefined :: CLong) 116size CLLongPT = Storable.sizeOf (undefined :: CLLong) 117size CUIntPT = Storable.sizeOf (undefined :: CUInt) 118size CUShortPT = Storable.sizeOf (undefined :: CUShort) 119size CULongPT = Storable.sizeOf (undefined :: CULong) 120size CULLongPT = Storable.sizeOf (undefined :: CLLong) 121size CFloatPT = Storable.sizeOf (undefined :: CFloat) 122size CDoublePT = Storable.sizeOf (undefined :: CDouble) 123--size CLDoublePT = Storable.sizeOf (undefined :: CLDouble) 124size (CSFieldPT bs) = -bs 125size (CUFieldPT bs) = -bs 126 127-- alignment of C's primitive types (EXPORTED) 128-- 129-- * more precisely, the padding put before the type's member starts when the 130-- preceding component is a char 131-- 132alignment :: CPrimType -> Int 133alignment CPtrPT = Storable.alignment (undefined :: Ptr ()) 134alignment CFunPtrPT = Storable.alignment (undefined :: FunPtr ()) 135alignment CCharPT = 1 136alignment CUCharPT = 1 137alignment CSCharPT = 1 138alignment CIntPT = Storable.alignment (undefined :: CInt) 139alignment CShortPT = Storable.alignment (undefined :: CShort) 140alignment CLongPT = Storable.alignment (undefined :: CLong) 141alignment CLLongPT = Storable.alignment (undefined :: CLLong) 142alignment CUIntPT = Storable.alignment (undefined :: CUInt) 143alignment CUShortPT = Storable.alignment (undefined :: CUShort) 144alignment CULongPT = Storable.alignment (undefined :: CULong) 145alignment CULLongPT = Storable.alignment (undefined :: CULLong) 146alignment CFloatPT = Storable.alignment (undefined :: CFloat) 147alignment CDoublePT = Storable.alignment (undefined :: CDouble) 148--alignment CLDoublePT = Storable.alignment (undefined :: CLDouble) 149alignment (CSFieldPT bs) = fieldAlignment bs 150alignment (CUFieldPT bs) = fieldAlignment bs 151 152-- alignment constraint for a C bitfield 153-- 154-- * gets the bitfield size (in bits) as an argument 155-- 156-- * alignments constraints smaller or equal to zero are reserved for bitfield 157-- alignments 158-- 159-- * bitfields of size 0 always trigger padding; thus, they get the maximal 160-- size 161-- 162-- * if bitfields whose size exceeds the space that is still available in a 163-- partially filled storage unit trigger padding, the size of a storage unit 164-- is provided as the alignment constraint; otherwise, it is 0 (meaning it 165-- definitely starts at the current position) 166-- 167-- * here, alignment constraint /= 0 are somewhat subtle; they mean that is 168-- the given number of bits doesn't fit in what's left in the current 169-- storage unit, alignment to the start of the next storage unit has to be 170-- triggered 171-- 172fieldAlignment :: Int -> Int 173fieldAlignment 0 = - (size CIntPT - 1) 174fieldAlignment bs | bitfieldPadding = - bs 175 | otherwise = 0 176