mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-30 23:23:07 +00:00 
			
		
		
		
	Merge updates.
This commit is contained in:
		| @@ -266,7 +266,7 @@ value." | ||||
|                                    subloop | ||||
|                                    (tuple ':= bindings (tuple + bindings inc))))) | ||||
|             :keys (do | ||||
|                     (def $dict (gensym "dict")) | ||||
|                     (def $dict (gensym)) | ||||
|                     (def preds @['and (tuple not= nil bindings)]) | ||||
|                     (def subloop (doone (+ i 3) preds)) | ||||
|                     (tuple 'do | ||||
| @@ -276,9 +276,9 @@ value." | ||||
|                                   subloop | ||||
|                                   (tuple ':= bindings (tuple next $dict bindings))))) | ||||
|             :in (do | ||||
|                   (def $len (gensym "len")) | ||||
|                   (def $i (gensym "i")) | ||||
|                   (def $indexed (gensym "indexed")) | ||||
|                   (def $len (gensym)) | ||||
|                   (def $i (gensym)) | ||||
|                   (def $indexed (gensym)) | ||||
|                   (def preds @['and (tuple < $i $len)]) | ||||
|                   (def subloop (doone (+ i 3) preds)) | ||||
|                   (tuple 'do | ||||
| @@ -295,7 +295,7 @@ value." | ||||
| (defmacro for | ||||
|   "Similar to loop, but accumulates the loop body into an array and returns that." | ||||
|   [head & body] | ||||
|   (def $accum (gensym "accum")) | ||||
|   (def $accum (gensym)) | ||||
|   (tuple 'do | ||||
|          (tuple 'def $accum @[]) | ||||
|          (tuple 'loop head | ||||
| @@ -1059,8 +1059,8 @@ onvalue." | ||||
|      (do | ||||
|        (file.write stdout " [" source "]") | ||||
|        (if source-line (file.write stdout " on line " | ||||
|          (string source-line) ", column " (string source-col)))) | ||||
|      (if pc (file.write stdout " at (pc=" (string pc) ")"))) | ||||
|          (string source-line) ", column " (string source-col))))) | ||||
|    (if pc (file.write stdout " (pc=" (string pc) ")")) | ||||
|    (when tail (file.write stdout " (tailcall)")) | ||||
|    (file.write stdout "\n")))) | ||||
|  | ||||
|   | ||||
| @@ -101,7 +101,7 @@ DstSlot dstc_cslot(Dst x) { | ||||
| DstSlot dstc_nearslot(DstCompiler *c, DstcRegisterTemp tag) { | ||||
|     DstSlot ret; | ||||
|     ret.flags = DST_SLOTTYPE_ANY; | ||||
|     ret.index = dstc_getreg_temp(c, tag); | ||||
|     ret.index = dstc_allocnear(c, tag); | ||||
|     ret.constant = dst_wrap_nil(); | ||||
|     ret.envindex = -1; | ||||
|     return ret; | ||||
| @@ -111,7 +111,7 @@ DstSlot dstc_nearslot(DstCompiler *c, DstcRegisterTemp tag) { | ||||
| DstSlot dstc_farslot(DstCompiler *c) { | ||||
|     DstSlot ret; | ||||
|     ret.flags = DST_SLOTTYPE_ANY; | ||||
|     ret.index = dstc_getreg(c); | ||||
|     ret.index = dstc_allocfar(c); | ||||
|     ret.constant = dst_wrap_nil(); | ||||
|     ret.envindex = -1; | ||||
|     return ret; | ||||
| @@ -314,7 +314,7 @@ DstSlot dstc_gettarget(DstFopts opts) { | ||||
|         slot.envindex = -1; | ||||
|         slot.constant = dst_wrap_nil(); | ||||
|         slot.flags = 0; | ||||
|         slot.index = dstc_getreg_temp(opts.compiler, DSTC_REGTEMP_3); | ||||
|         slot.index = dstc_allocnear(opts.compiler, DSTC_REGTEMP_3); | ||||
|     } | ||||
|     return slot; | ||||
| } | ||||
| @@ -403,7 +403,7 @@ static DstSlot dstc_call(DstFopts opts, DstSlot *slots, DstSlot fun) { | ||||
|             retslot.flags = DST_SLOT_RETURNED; | ||||
|         } else { | ||||
|             retslot = dstc_gettarget(opts); | ||||
|             int32_t fun_register = dstc_to_tempreg(c, fun, DSTC_REGTEMP_0); | ||||
|             int32_t fun_register = dstc_regnear(c, fun, DSTC_REGTEMP_0); | ||||
|             dstc_emit(c, DOP_CALL | | ||||
|                     (retslot.index << 8) | | ||||
|                     (fun_register << 16)); | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
| #include "emit.h" | ||||
|  | ||||
| /* Get a register */ | ||||
| int32_t dstc_getreg(DstCompiler *c) { | ||||
| int32_t dstc_allocfar(DstCompiler *c) { | ||||
|     int32_t reg = dstc_regalloc_1(&c->scope->ra); | ||||
|     if (reg > 0xFFFF) { | ||||
|         dstc_cerror(c, "ran out of internal registers"); | ||||
| @@ -34,7 +34,7 @@ int32_t dstc_getreg(DstCompiler *c) { | ||||
| } | ||||
|  | ||||
| /* Get a register less than 256 */ | ||||
| int32_t dstc_getreg_temp(DstCompiler *c, DstcRegisterTemp tag) { | ||||
| int32_t dstc_allocnear(DstCompiler *c, DstcRegisterTemp tag) { | ||||
|     return dstc_regalloc_temp(&c->scope->ra, tag); | ||||
| } | ||||
|  | ||||
| @@ -107,10 +107,10 @@ static void dstc_loadconst(DstCompiler *c, Dst k, int32_t reg) { | ||||
| } | ||||
|  | ||||
| /* Convert a slot to a two byte register */ | ||||
| int32_t dstc_to_reg(DstCompiler *c, DstSlot s) { | ||||
| int32_t dstc_regfar(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) { | ||||
|     int32_t reg; | ||||
|     if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) { | ||||
|         reg = dstc_getreg(c); | ||||
|         reg = dstc_allocnear(c, tag); | ||||
|         dstc_loadconst(c, s.constant, reg); | ||||
|         /* If we also are a reference, deref the one element array */ | ||||
|         if (s.flags & DST_SLOT_REF) { | ||||
| @@ -119,8 +119,8 @@ int32_t dstc_to_reg(DstCompiler *c, DstSlot s) { | ||||
|                     (reg << 8) | | ||||
|                     DOP_GET_INDEX); | ||||
|         } | ||||
|     } else if (s.envindex >= 0 || s.index > 0xFF) { | ||||
|         reg = dstc_getreg(c); | ||||
|     } else if (s.envindex >= 0) { | ||||
|         reg = dstc_allocnear(c, tag); | ||||
|         dstc_emit(c, | ||||
|                 ((uint32_t)(s.index) << 24) | | ||||
|                 ((uint32_t)(s.envindex) << 16) | | ||||
| @@ -134,10 +134,10 @@ int32_t dstc_to_reg(DstCompiler *c, DstSlot s) { | ||||
| } | ||||
|  | ||||
| /* Convert a slot to a temporary 1 byte register */ | ||||
| int32_t dstc_to_tempreg(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) { | ||||
| int32_t dstc_regnear(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) { | ||||
|     int32_t reg; | ||||
|     if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) { | ||||
|         reg = dstc_getreg_temp(c, tag); | ||||
|         reg = dstc_allocnear(c, tag); | ||||
|         dstc_loadconst(c, s.constant, reg); | ||||
|         /* If we also are a reference, deref the one element array */ | ||||
|         if (s.flags & DST_SLOT_REF) { | ||||
| @@ -146,15 +146,15 @@ int32_t dstc_to_tempreg(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) { | ||||
|                     (reg << 8) | | ||||
|                     DOP_GET_INDEX); | ||||
|         } | ||||
|     } else if (s.envindex >= 0 || s.index > 0xFF) { | ||||
|         reg = dstc_getreg_temp(c, tag); | ||||
|     } else if (s.envindex >= 0) { | ||||
|         reg = dstc_allocnear(c, tag); | ||||
|         dstc_emit(c, | ||||
|                 ((uint32_t)(s.index) << 24) | | ||||
|                 ((uint32_t)(s.envindex) << 16) | | ||||
|                 ((uint32_t)(reg) << 8) | | ||||
|                 DOP_LOAD_UPVALUE); | ||||
|     } else if (s.index > 0xFF) { | ||||
|         reg = dstc_getreg_temp(c, tag); | ||||
|         reg = dstc_allocnear(c, tag); | ||||
|         dstc_emit(c, | ||||
|                 ((uint32_t)(s.index) << 16) | | ||||
|                 ((uint32_t)(reg) << 8) | | ||||
| @@ -175,7 +175,7 @@ void dstc_free_reg(DstCompiler *c, DstSlot s, int32_t reg) { | ||||
| } | ||||
|  | ||||
| /* Check if two slots are equal */ | ||||
| int dstc_sequal(DstSlot lhs, DstSlot rhs) { | ||||
| static int dstc_sequal(DstSlot lhs, DstSlot rhs) { | ||||
|     if (lhs.flags == rhs.flags && | ||||
|             lhs.index == rhs.index && | ||||
|             lhs.envindex == rhs.envindex) { | ||||
| @@ -190,7 +190,7 @@ int dstc_sequal(DstSlot lhs, DstSlot rhs) { | ||||
|  | ||||
| /* Move values from one slot to another. The destination must | ||||
|  * be writeable (not a literal). */ | ||||
| int dstc_copy( | ||||
| void dstc_copy( | ||||
|         DstCompiler *c, | ||||
|         DstSlot dest, | ||||
|         DstSlot src) { | ||||
| @@ -202,11 +202,11 @@ int dstc_copy( | ||||
|     /* Can't write to constants */ | ||||
|     if (dest.flags & DST_SLOT_CONSTANT) { | ||||
|         dstc_cerror(c, "cannot write to constant"); | ||||
|         return 0; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /* Short circuit if dest and source are equal */ | ||||
|     if (dstc_sequal(dest, src)) return 0; | ||||
|     if (dstc_sequal(dest, src)) return; | ||||
|  | ||||
|     /* Types of slots - src */ | ||||
|     /* constants */ | ||||
| @@ -243,19 +243,19 @@ int dstc_copy( | ||||
|                     (dest.index << 8) | | ||||
|                     DOP_MOVE_NEAR); | ||||
|         } | ||||
|         return 1; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /* Process: src -> srclocal -> destlocal -> dest */ | ||||
|  | ||||
|     /* src -> srclocal */ | ||||
|     srclocal = dstc_to_tempreg(c, src, DSTC_REGTEMP_0); | ||||
|     srclocal = dstc_regnear(c, src, DSTC_REGTEMP_0); | ||||
|  | ||||
|     /* Pull down dest (find destlocal) */ | ||||
|     if (dest.flags & DST_SLOT_REF) { | ||||
|         writeback = 1; | ||||
|         destlocal = srclocal; | ||||
|         reflocal = dstc_getreg_temp(c, DSTC_REGTEMP_1); | ||||
|         reflocal = dstc_allocnear(c, DSTC_REGTEMP_1); | ||||
|         dstc_emit(c, | ||||
|                 (dstc_const(c, dest.constant) << 16) | | ||||
|                 (reflocal << 8) | | ||||
| @@ -302,13 +302,12 @@ int dstc_copy( | ||||
|         dstc_regalloc_free(&c->scope->ra, reflocal); | ||||
|     } | ||||
|     dstc_free_reg(c, src, srclocal); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| /* Instruction templated emitters */ | ||||
|  | ||||
| static int32_t emit1s(DstCompiler *c, uint8_t op, DstSlot s, int32_t rest) { | ||||
|     int32_t reg = dstc_to_tempreg(c, s, DSTC_REGTEMP_0); | ||||
|     int32_t reg = dstc_regnear(c, s, DSTC_REGTEMP_0); | ||||
|     int32_t label = dst_v_count(c->buffer); | ||||
|     dstc_emit(c, op | (reg << 8) | (rest << 16)); | ||||
|     dstc_free_reg(c, s, reg); | ||||
| @@ -316,7 +315,7 @@ static int32_t emit1s(DstCompiler *c, uint8_t op, DstSlot s, int32_t rest) { | ||||
| } | ||||
|  | ||||
| int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s) { | ||||
|     int32_t reg = dstc_to_reg(c, s); | ||||
|     int32_t reg = dstc_regfar(c, s, DSTC_REGTEMP_0); | ||||
|     int32_t label = dst_v_count(c->buffer); | ||||
|     dstc_emit(c, op | (reg << 8)); | ||||
|     dstc_free_reg(c, s, reg); | ||||
| @@ -345,8 +344,8 @@ int32_t dstc_emit_su(DstCompiler *c, uint8_t op, DstSlot s, uint16_t immediate) | ||||
| } | ||||
|  | ||||
| static int32_t emit2s(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int32_t rest) { | ||||
|     int32_t reg1 = dstc_to_tempreg(c, s1, DSTC_REGTEMP_0); | ||||
|     int32_t reg2 = dstc_to_tempreg(c, s2, DSTC_REGTEMP_1); | ||||
|     int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0); | ||||
|     int32_t reg2 = dstc_regnear(c, s2, DSTC_REGTEMP_1); | ||||
|     int32_t label = dst_v_count(c->buffer); | ||||
|     dstc_emit(c, op | (reg1 << 8) | (reg2 << 16) | (rest << 24)); | ||||
|     dstc_free_reg(c, s1, reg1); | ||||
| @@ -355,8 +354,8 @@ static int32_t emit2s(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int32_ | ||||
| } | ||||
|  | ||||
| int32_t dstc_emit_ss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2) { | ||||
|     int32_t reg1 = dstc_to_tempreg(c, s1, DSTC_REGTEMP_0); | ||||
|     int32_t reg2 = dstc_to_reg(c, s2); | ||||
|     int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0); | ||||
|     int32_t reg2 = dstc_regfar(c, s2, DSTC_REGTEMP_1); | ||||
|     int32_t label = dst_v_count(c->buffer); | ||||
|     dstc_emit(c, op | (reg1 << 8) | (reg2 << 16)); | ||||
|     dstc_free_reg(c, s1, reg1); | ||||
| @@ -373,9 +372,9 @@ int32_t dstc_emit_ssu(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, uint8_ | ||||
| } | ||||
|  | ||||
| int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3) { | ||||
|     int32_t reg1 = dstc_to_tempreg(c, s1, DSTC_REGTEMP_0); | ||||
|     int32_t reg2 = dstc_to_tempreg(c, s2, DSTC_REGTEMP_1); | ||||
|     int32_t reg3 = dstc_to_tempreg(c, s3, DSTC_REGTEMP_2); | ||||
|     int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0); | ||||
|     int32_t reg2 = dstc_regnear(c, s2, DSTC_REGTEMP_1); | ||||
|     int32_t reg3 = dstc_regnear(c, s3, DSTC_REGTEMP_2); | ||||
|     int32_t label = dst_v_count(c->buffer); | ||||
|     dstc_emit(c, op | (reg1 << 8) | (reg2 << 16) | (reg3 << 24)); | ||||
|     dstc_free_reg(c, s1, reg1); | ||||
|   | ||||
| @@ -27,11 +27,11 @@ | ||||
|  | ||||
| void dstc_emit(DstCompiler *c, uint32_t instr); | ||||
|  | ||||
| int32_t dstc_getreg(DstCompiler *c); | ||||
| int32_t dstc_getreg_temp(DstCompiler *c, DstcRegisterTemp); | ||||
| int32_t dstc_allocfar(DstCompiler *c); | ||||
| int32_t dstc_allocnear(DstCompiler *c, DstcRegisterTemp); | ||||
|  | ||||
| int32_t dstc_to_reg(DstCompiler *c, DstSlot s); | ||||
| int32_t dstc_to_tempreg(DstCompiler *c, DstSlot s, DstcRegisterTemp tag); | ||||
| int32_t dstc_regfar(DstCompiler *c, DstSlot s, DstcRegisterTemp tag); | ||||
| int32_t dstc_regnear(DstCompiler *c, DstSlot s, DstcRegisterTemp tag); | ||||
| void dstc_free_reg(DstCompiler *c, DstSlot s, int32_t reg); | ||||
|  | ||||
| int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s); | ||||
| @@ -45,6 +45,6 @@ int32_t dstc_emit_ssu(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, uint8_ | ||||
| int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3); | ||||
|  | ||||
| /* Move value from one slot to another. Cannot copy to constant slots. */ | ||||
| int dstc_copy(DstCompiler *c, DstSlot dest, DstSlot src); | ||||
| void dstc_copy(DstCompiler *c, DstSlot dest, DstSlot src); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -29,6 +29,7 @@ void dstc_regalloc_init(DstcRegisterAllocator *ra) { | ||||
|     ra->count = 0; | ||||
|     ra->capacity = 0; | ||||
|     ra->max = 0; | ||||
|     ra->regtemps = 0; | ||||
| } | ||||
|  | ||||
| void dstc_regalloc_deinit(DstcRegisterAllocator *ra) { | ||||
| @@ -126,9 +127,16 @@ int32_t dstc_regalloc_1(DstcRegisterAllocator *ra) { | ||||
|  * without being freed. */ | ||||
| void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg) { | ||||
|     /* We cannot free reserved slots */ | ||||
|     if (reg < 0 || (reg >= 240 && reg <= 255)) | ||||
|     if (reg < 0) | ||||
|         return; | ||||
|     if (reg >= 0xF0 && reg <= 0xFF) { | ||||
|         ra->regtemps &= ~(1 << (reg - 0xF0)); | ||||
|         return; | ||||
|     } | ||||
|     int32_t chunk = reg >> 5; | ||||
|     /* Outside normal chunk range */ | ||||
|     if (chunk >= ra->count) | ||||
|         return; | ||||
|     int32_t bit = reg & 0x1F; | ||||
|     ra->chunks[chunk] &= ~ithbit(bit); | ||||
| } | ||||
| @@ -139,6 +147,8 @@ void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg) { | ||||
| int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth) { | ||||
|     int32_t oldmax = ra->max; | ||||
|     int32_t reg = dstc_regalloc_1(ra); | ||||
|     dst_assert(~(ra->regtemps & (1 << nth)), "regtemp already allocated"); | ||||
|     ra->regtemps |= 1 << nth; | ||||
|     if (reg > 0xFF) { | ||||
|         reg = 0xF0 + nth; | ||||
|         ra->max = (reg > oldmax) ? reg : oldmax; | ||||
| @@ -146,8 +156,9 @@ int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth) { | ||||
|     return reg; | ||||
| } | ||||
|  | ||||
| /* Check if a range is free. Returns the next index to check if not free, | ||||
|  * -1 if free. */ | ||||
| /* Disable multi-slot allocation for now. */ | ||||
|  | ||||
| /* | ||||
| static int32_t checkrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) { | ||||
|     int32_t startchunk = start / 32; | ||||
|     int32_t endchunk = end / 32; | ||||
| @@ -161,7 +172,6 @@ static int32_t checkrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) | ||||
|         uint32_t block = ra->chunks[chunk]; | ||||
|         uint32_t masking = mask & block; | ||||
|         if (masking) { | ||||
|             /* If block is full, skip it completely. */ | ||||
|             int32_t nextbit = (block == 0xFFFFFFFF) | ||||
|                 ? 32 | ||||
|                 : count_trailing_zeros(masking) + 1; | ||||
| @@ -171,7 +181,6 @@ static int32_t checkrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| /* Mark a range */ | ||||
| static void markrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) { | ||||
|     int32_t startchunk = start / 32; | ||||
|     int32_t endchunk = end / 32; | ||||
| @@ -185,7 +194,6 @@ static void markrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Free a range of registers. */ | ||||
| void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t start, int32_t n) { | ||||
|     int32_t end = start + n - 1; | ||||
|     int32_t startchunk = start / 32; | ||||
| @@ -200,8 +208,6 @@ void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t start, int32_t n | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Allocate n contiguous registers. Returns the first register | ||||
|  * in the range allocated. */ | ||||
| int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n) { | ||||
|     int32_t start = 0, end = 0, next = 0; | ||||
|     while (next >= 0) { | ||||
| @@ -210,15 +216,11 @@ int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n) { | ||||
|         next = checkrange(ra, start, end); | ||||
|     } | ||||
|     markrange(ra, start, end); | ||||
|     /* Set max */ | ||||
|     if (end > ra->max) | ||||
|         ra->max = end; | ||||
|     return start; | ||||
| } | ||||
|  | ||||
| /* Allocates registers for a function call. Tries to not move the callee, | ||||
|  * but will find nargs + 1 other contiguous registers if there is not enough | ||||
|  * space after the callee. */ | ||||
| int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t nargs) { | ||||
|     if (checkrange(ra, callee, callee + nargs) < 0) { | ||||
|         markrange(ra, callee + 1, callee + nargs); | ||||
| @@ -227,3 +229,4 @@ int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t na | ||||
|     return dstc_regalloc_n(ra, nargs + 1); | ||||
| } | ||||
|  | ||||
| */ | ||||
|   | ||||
| @@ -44,6 +44,7 @@ typedef struct { | ||||
|     int32_t count; /* number of chunks in chunks */ | ||||
|     int32_t capacity; /* amount allocated for chunks */ | ||||
|     int32_t max; /* The maximum allocated register so far */ | ||||
|     int32_t regtemps; /* Hold which tempregistered are alloced. */ | ||||
| } DstcRegisterAllocator; | ||||
|  | ||||
| void dstc_regalloc_init(DstcRegisterAllocator *ra); | ||||
| @@ -51,56 +52,15 @@ void dstc_regalloc_deinit(DstcRegisterAllocator *ra); | ||||
|  | ||||
| int32_t dstc_regalloc_1(DstcRegisterAllocator *ra); | ||||
| void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg); | ||||
| void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t regstart, int32_t n); | ||||
| int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth); | ||||
| int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n); | ||||
| int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t nargs); | ||||
| void dstc_regalloc_clone(DstcRegisterAllocator *dest, DstcRegisterAllocator *src); | ||||
| void dstc_regalloc_touch(DstcRegisterAllocator *ra, int32_t reg); | ||||
|  | ||||
| /* Test code */ | ||||
| /* Mutli-slot allocation disabled */ | ||||
| /* | ||||
| #include <stdio.h> | ||||
| static void printreg(DstcRegisterAllocator *ra) { | ||||
|     printf("count=%d, cap=%d, max=%d\n", ra->count, ra->capacity, ra->max); | ||||
|     for (int row = 0; row < ra->count; row++) { | ||||
|         uint32_t chunk = ra->chunks[row]; | ||||
|         putc('[', stdout); | ||||
|         for (int i = 0; i < 32; i++) { | ||||
|             putc( | ||||
|                 (chunk & (1 << i)) | ||||
|                     ? '*' | ||||
|                     : '.', stdout); | ||||
|         } | ||||
|         putc(']', stdout); | ||||
|         putc('\n', stdout); | ||||
|     } | ||||
|     putc('\n', stdout); | ||||
| } | ||||
|  | ||||
| static void runtest(void) { | ||||
|     DstcRegisterAllocator ra, rb; | ||||
|     dstc_regalloc_init(&ra); | ||||
|     int32_t a = dstc_regalloc_1(&ra); | ||||
|     int32_t b = dstc_regalloc_1(&ra); | ||||
|     int32_t c = dstc_regalloc_1(&ra); | ||||
|     int32_t d = dstc_regalloc_1(&ra); | ||||
|     int32_t e = dstc_regalloc_1(&ra); | ||||
|     printreg(&ra); | ||||
|     dstc_regalloc_free(&ra, b); | ||||
|     dstc_regalloc_free(&ra, d); | ||||
|     printreg(&ra); | ||||
|     int32_t x = dstc_regalloc_n(&ra, 32); | ||||
|     printreg(&ra); | ||||
|     dstc_regalloc_1(&ra); | ||||
|     printreg(&ra); | ||||
|     int32_t y = dstc_regalloc_n(&ra, 101); | ||||
|     printreg(&ra); | ||||
|     dstc_regalloc_clone(&rb, &ra); | ||||
|     printreg(&rb); | ||||
|     dstc_regalloc_deinit(&ra); | ||||
|     dstc_regalloc_deinit(&rb); | ||||
| } | ||||
| int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n); | ||||
| int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t nargs); | ||||
| void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t regstart, int32_t n); | ||||
| */ | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -63,8 +63,8 @@ static void destructure(DstCompiler *c, | ||||
|                 for (i = 0; i < len; i++) { | ||||
|                     DstSlot nextright; | ||||
|                     Dst subval = values[i]; | ||||
|                     right_register = dstc_to_tempreg(c, right, DSTC_REGTEMP_0); | ||||
|                     subval_register = dstc_getreg_temp(c, DSTC_REGTEMP_1); | ||||
|                     right_register = dstc_regnear(c, right, DSTC_REGTEMP_0); | ||||
|                     subval_register = dstc_allocnear(c, DSTC_REGTEMP_1); | ||||
|                     if (i < 0x100) { | ||||
|                         dstc_emit(c, DOP_GET_INDEX | | ||||
|                                 (subval_register << 8) | | ||||
| @@ -72,7 +72,7 @@ static void destructure(DstCompiler *c, | ||||
|                                 (i << 24)); | ||||
|                     } else { | ||||
|                         DstSlot islot = dstc_cslot(dst_wrap_integer(i)); | ||||
|                         int32_t i_register = dstc_to_tempreg(c, islot, DSTC_REGTEMP_2); | ||||
|                         int32_t i_register = dstc_regnear(c, islot, DSTC_REGTEMP_2); | ||||
|                         dstc_emit(c, DOP_GET_INDEX | | ||||
|                                 (subval_register << 8) | | ||||
|                                 (right_register << 16) | | ||||
| @@ -88,8 +88,6 @@ static void destructure(DstCompiler *c, | ||||
|                     dstc_free_reg(c, right, right_register); | ||||
|                 } | ||||
|             } | ||||
|             /* Free right */ | ||||
|             dstc_freeslot(c, right); | ||||
|             break; | ||||
|         case DST_TABLE: | ||||
|         case DST_STRUCT: | ||||
| @@ -100,9 +98,9 @@ static void destructure(DstCompiler *c, | ||||
|                     DstSlot nextright; | ||||
|                     DstSlot kslot = dstc_value(dstc_fopts_default(c), kv->key); | ||||
|  | ||||
|                     right_register = dstc_to_tempreg(c, right, DSTC_REGTEMP_0); | ||||
|                     subval_register = dstc_getreg_temp(c, DSTC_REGTEMP_1); | ||||
|                     k_register = dstc_to_tempreg(c, kslot, DSTC_REGTEMP_2); | ||||
|                     right_register = dstc_regnear(c, right, DSTC_REGTEMP_0); | ||||
|                     subval_register = dstc_allocnear(c, DSTC_REGTEMP_1); | ||||
|                     k_register = dstc_regnear(c, kslot, DSTC_REGTEMP_2); | ||||
|                     dstc_emit(c, DOP_GET | | ||||
|                             (subval_register << 8) | | ||||
|                             (right_register << 16) | | ||||
| @@ -117,11 +115,8 @@ static void destructure(DstCompiler *c, | ||||
|                     dstc_free_reg(c, right, right_register); | ||||
|                 } | ||||
|             } | ||||
|             /* Free right */ | ||||
|             dstc_freeslot(c, right); | ||||
|             break; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| DstSlot dstc_varset(DstFopts opts, int32_t argn, const Dst *argv) { | ||||
| @@ -193,7 +188,7 @@ static DstSlot namelocal(DstCompiler *c, Dst head, int32_t flags, DstSlot ret) { | ||||
|             ret.index > 0xFF) { | ||||
|         /* Slot is not able to be named */ | ||||
|         DstSlot localslot; | ||||
|         localslot.index = dstc_getreg(c); | ||||
|         localslot.index = dstc_allocfar(c); | ||||
|         /* infer type? */ | ||||
|         localslot.flags = flags; | ||||
|         localslot.envindex = -1; | ||||
|   | ||||
| @@ -169,15 +169,8 @@ int dst_core_struct(DstArgs args) { | ||||
| } | ||||
|  | ||||
| int dst_core_gensym(DstArgs args) { | ||||
|     DST_MAXARITY(args, 1); | ||||
|     if (args.n == 0) { | ||||
|         DST_RETURN_SYMBOL(args, dst_symbol_gen(NULL, 0)); | ||||
|     } else { | ||||
|         const uint8_t *s; | ||||
|         int32_t len; | ||||
|         DST_ARG_BYTES(s, len, args, 0); | ||||
|         DST_RETURN_SYMBOL(args, dst_symbol_gen(s, len)); | ||||
|     } | ||||
|     DST_FIXARITY(args, 0); | ||||
|     DST_RETURN_SYMBOL(args, dst_symbol_gen()); | ||||
| } | ||||
|  | ||||
| int dst_core_gccollect(DstArgs args) { | ||||
|   | ||||
| @@ -201,48 +201,52 @@ const uint8_t *dst_symbol_from_string(const uint8_t *str) { | ||||
|     return str; | ||||
| } | ||||
|  | ||||
| /* Helper for creating a unique string. Increment an integer | ||||
|  * represented as an array of integer digits. */ | ||||
| static void inc_counter(uint8_t *digits, int base, int len) { | ||||
|     int i; | ||||
|     uint8_t carry = 1; | ||||
|     for (i = len - 1; i >= 0; --i) { | ||||
|         digits[i] += carry; | ||||
|         carry = 0; | ||||
|         if (digits[i] == base) { | ||||
|             digits[i] = 0; | ||||
|             carry = 1; | ||||
| /* Store counter for genysm to avoid quadratic behavior */ | ||||
| DST_THREAD_LOCAL uint8_t gensym_counter[8] = {'_', '0', '0', '0', '0', '0', '0', 0}; | ||||
|  | ||||
| /* Increment the gensym buffer */ | ||||
| static void inc_gensym(void) { | ||||
|     for (int i = sizeof(gensym_counter) - 2; i; i--) { | ||||
|         if (gensym_counter[i] == '9') { | ||||
|             gensym_counter[i] = 'a'; | ||||
|         } else if (gensym_counter[i] == 'z') { | ||||
|             gensym_counter[i] = 'A'; | ||||
|         } else if (gensym_counter[i] == 'Z') { | ||||
|             gensym_counter[i] = '0'; | ||||
|         } else { | ||||
|             gensym_counter[i]++; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Generate a unique symbol. This is used in the library function gensym. The | ||||
|  * symbol will be of the format prefix_XXXXXX, where X is a base64 digit, and | ||||
|  * prefix is the argument passed.  */ | ||||
| const uint8_t *dst_symbol_gen(const uint8_t *buf, int32_t len) { | ||||
|  * symbol will be of the format _XXXXXX, where X is a base64 digit, and | ||||
|  * prefix is the argument passed. No prefix for speed. */ | ||||
| const uint8_t *dst_symbol_gen(void) { | ||||
|     const uint8_t **bucket = NULL; | ||||
|     uint8_t *sym; | ||||
|     int32_t hash = 0; | ||||
|     uint8_t counter[6] = {63, 63, 63, 63, 63, 63}; | ||||
|     int status; | ||||
|     /* Leave spaces for 6 base 64 digits and two dashes. That means 64^6 possible suffixes, which | ||||
|      * is enough for resolving collisions. */ | ||||
|     int32_t newlen = len + 7; | ||||
|     int32_t newbufsize = newlen + 2 * sizeof(int32_t) + 1; | ||||
|     uint8_t *str = (uint8_t *)dst_gcalloc(DST_MEMORY_SYMBOL, newbufsize) + 2 * sizeof(int32_t); | ||||
|     dst_string_length(str) = newlen; | ||||
|     memcpy(str, buf, len); | ||||
|     str[len] = '_'; | ||||
|     str[newlen] = 0; | ||||
|     uint8_t *saltbuf = str + len + 1; | ||||
|     int status = 1; | ||||
|     while (status) { | ||||
|         int i; | ||||
|         inc_counter(counter, 64, 6); | ||||
|         for (i = 0; i < 6; ++i) | ||||
|             saltbuf[i] = dst_base64[counter[i]]; | ||||
|         hash = dst_string_calchash(str, newlen); | ||||
|         bucket = dst_symcache_findmem(str, newlen, hash, &status); | ||||
|     } | ||||
|     dst_string_hash(str) = hash; | ||||
|     dst_symcache_put((const uint8_t *)str, bucket); | ||||
|     return (const uint8_t *)str; | ||||
|     do { | ||||
|         hash = dst_string_calchash( | ||||
|                 gensym_counter,  | ||||
|                 sizeof(gensym_counter) - 1); | ||||
|         bucket = dst_symcache_findmem( | ||||
|                 gensym_counter,  | ||||
|                 sizeof(gensym_counter) - 1, | ||||
|                 hash, | ||||
|                 &status); | ||||
|     } while (status && (inc_gensym(), 1)); | ||||
|     sym = (uint8_t *) dst_gcalloc( | ||||
|             DST_MEMORY_SYMBOL,  | ||||
|             2 * sizeof(int32_t) + sizeof(gensym_counter)) + | ||||
|         (2 * sizeof(int32_t)); | ||||
|     memcpy(sym, gensym_counter, sizeof(gensym_counter)); | ||||
|     dst_string_length(sym) = sizeof(gensym_counter) - 1; | ||||
|     dst_string_hash(sym) = hash; | ||||
|     dst_symcache_put((const uint8_t *)sym, bucket); | ||||
|     return (const uint8_t *)sym; | ||||
| } | ||||
|   | ||||
| @@ -129,7 +129,7 @@ void dst_puts(const uint8_t *str); | ||||
| const uint8_t *dst_symbol(const uint8_t *str, int32_t len); | ||||
| const uint8_t *dst_symbol_from_string(const uint8_t *str); | ||||
| const uint8_t *dst_csymbol(const char *str); | ||||
| const uint8_t *dst_symbol_gen(const uint8_t *buf, int32_t len); | ||||
| const uint8_t *dst_symbol_gen(); | ||||
| #define dst_symbolv(str, len) dst_wrap_symbol(dst_symbol((str), (len))) | ||||
| #define dst_csymbolv(cstr) dst_wrap_symbol(dst_csymbol(cstr)) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose