/* This document is meant for developers */ Implementation details of "builtin" functions in SDCC. Built in functions are target/port specific and are defined in src//main.c. Here is a layout of the builtin structure (port.h). Front-End --------- #define MAX_BUILTIN_ARGS 16 /* definition of builtin functions */ typedef struct builtins { char *name ; /* name of builtin function */ char *rtype; /* return type as string : see typefromStr */ int nParms; /* number of parms : max 8 */ char *parm_types[MAX_BUILTIN_ARGS]; /* each parm type as string : see typeFromStr */ } builtins ; The port structure contains a pointer to a table of the builtin functions. Example of the builtin function table. static builtins __ds390_builtins[] = { { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */ { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code char *,int) */ { NULL , NULL,0, {NULL}} /* mark end of table */ }; Here the function names are prefixed with "__builtin" this is not a requirement, standard C library functions can also be defined in this table by a particular port to generate more efficient code . Function "initBuiltIns" in SDCCsymt.c is invoked to initialize the symbol table with the builtin functions. The return type & the parameter types are specified as encoded strings. Function "typeFromStr" parses this encoded string and translates them into sym_link . /*-----------------------------------------------------------------*/ /* typeFromStr - create a typechain from an encoded string */ /* basic types - 'c' - char */ /* 's' - short */ /* 'i' - int */ /* 'l' - long */ /* 'f' - float */ /* 'v' - void */ /* '*' - pointer - default (GPOINTER) */ /* modifiers - 'u' - unsigned */ /* pointer modifiers - 'g' - generic */ /* 'x' - xdata */ /* 'p' - code */ /* 'd' - data */ /* 'F' - FUNCTION */ /* examples : "ig*" - generic int * */ /* "cx*" - char xdata * */ /* "ui" - unsigned int */ /*-----------------------------------------------------------------*/ So much for the front-end issues. iCode - implications. --------------------- Intermediate code (iCode) will ALWAYS generate a SEND for parameters of a builtin function with a special flag (ic->builtinSEND) set. This eliminates the need for special processing for different memory models and --stack-auto option. All optimizations remain untouched. Example of intermediate code generated for builtin void memcpy(xdata char *d,xdata char *s) { __builtin_memcpy_x2x(d,s+10,10); } iTemp0 [k2 lr3:12 so:0]{ ia0 re1 rm0 nos0 ru0}{xdata char xdata * }{ sir@ _memcpy_d_1_1}[_memcpy_d_1_1] = recv iTemp2 [k7 lr4:12 so:0]{ ia0 re0 rm0 nos0 ru0}{xdata char xdata * }[r5 r6 r7 ] := _memcpy_PARM_2 [k6 lr0:0 so:0]{ ia0 re0 rm0 nos0 ru0}{xdata char xdata * } iTemp3 [k8 lr5:8 so:0]{ ia0 re0 rm0 nos0 ru0}{xdata char xdata * }[r0 r1 r2 ] = iTemp2 [k7 lr4:12 so:0]{ ia0 re0 rm0 nos0 ru0}{xdata char xdata * }[r5 r6 r7 ] + 0xa {literal unsigned char} send iTemp0 [k2 lr3:12 so:0]{ ia0 re1 rm0 nos0 ru0}{xdata char xdata * }{ sir@ _memcpy_d_1_1}[_memcpy_d_1_1] send iTemp3 [k8 lr5:8 so:0]{ ia0 re0 rm0 nos0 ru0}{xdata char xdata * }[r0 r1 r2 ] send 0xa {literal int} iTemp4 [k9 lr9:9 so:0]{ ia0 re0 rm0 nos0 ru1}{void} = call ___builtin_memcpy_x2x [k4 lr0:0 so:0]{ ia0 re0 rm0 nos0 ru0}{void function __builtin__} Backend/Code generation for builtin functions. ---------------------------------------------- When a SEND icode with the ic->builtinSEND flag is detected by the code generator, it should go into builtin function processing mode. E.g. case SEND: if (ic->builtinSEND) genBuiltIn(ic); else addSet (&_G.sendSet, ic); break; SDCCicode.c contains a port/target independent routine (getBuiltinParms) which goes thru the iCodes (starting from the first SEND (with builtinSEND set)) and returns the parameters and number of parameters in an array, example. NOTE the function "getBuiltinParms" also marks the iCodes as "generated" . /*-----------------------------------------------------------------*/ /* genBuiltIn - calls the appropriate function to generating code */ /* for a built in function */ /*-----------------------------------------------------------------*/ static void genBuiltIn (iCode *ic) { operand *bi_parms[MAX_BUILTIN_ARGS]; int nbi_parms; iCode *bi_iCode; symbol *bif; /* get all the arguments for a built in function */ bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms); /* which function is it */ bif = OP_SYMBOL(IC_LEFT(bi_iCode)); if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) { genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0); } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) { genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1); } else { werror(E_INTERNAL_ERROR,"unknown builtin function encountered\n"); return ; } return ; }