diff options
| author | _ov4 <ov4@ov4.org> | 2026-07-26 12:17:20 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-07-26 12:17:20 +0000 |
| commit | 9164871fe4982bdd12866eb28ebded68ca3dacd1 (patch) | |
| tree | 7cfd061e731958071f833d0a8932cc45c51ad455 /lib/CodeGen/StringHandler.cc | |
| parent | 1749b2b4a3e55db7c9bed95376f99b7f07932b49 (diff) | |
refactor: dedupe StringHandler case-convert and substring-copy code
emitLCase/emitUCase were a 45-line verbatim pair differing only in the
libc callee; both now delegate to emitCaseConvert(Str, CaseFn). The
malloc+memcpy+NUL tail duplicated across emitMid/emitRight/emitLeft
moves into allocCopySubstring; each function keeps its own clamp logic,
which is intentionally different.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen/StringHandler.cc')
| -rw-r--r-- | lib/CodeGen/StringHandler.cc | 129 |
1 files changed, 36 insertions, 93 deletions
diff --git a/lib/CodeGen/StringHandler.cc b/lib/CodeGen/StringHandler.cc index 463bf96..783f8e5 100644 --- a/lib/CodeGen/StringHandler.cc +++ b/lib/CodeGen/StringHandler.cc @@ -58,8 +58,23 @@ Value *StringHandler::emitConcat(Value *LHS, Value *RHS) { return NewStr; } +// malloc(Len + 1), copy Len bytes from Src + StartIdx, NUL-terminate. +// Clamping is each caller's business — MID/RIGHT/LEFT clamp different things. +Value *StringHandler::allocCopySubstring(Value *Src, Value *StartIdx, Value *Len) { + Value *One = ConstantInt::get(Context, APInt(64, 1)); + Value *AllocSize = Builder.CreateAdd(Len, One); + Value *NewStr = Builder.CreateCall(MallocFunc, AllocSize, "substr_mem"); + + Value *SrcPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), Src, StartIdx); + Builder.CreateCall(MemCpyFunc, {NewStr, SrcPtr, Len}); + + Value *NullTermPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), NewStr, Len); + Builder.CreateStore(ConstantInt::get(Type::getInt8Ty(Context), 0), NullTermPtr); + + return NewStr; +} + Value *StringHandler::emitMid(Value *Str, Value *Start, Value *Len) { - Value *FullLen = emitLength(Str); Value *One = ConstantInt::get(Context, APInt(64, 1)); @@ -80,18 +95,7 @@ Value *StringHandler::emitMid(Value *Str, Value *Start, Value *Len) { Value *IsLenNeg = Builder.CreateICmpSLT(ActualLen, Zero); ActualLen = Builder.CreateSelect(IsLenNeg, Zero, ActualLen); - Value *AllocSize = Builder.CreateAdd(ActualLen, One); - Value *NewStrMem = Builder.CreateCall(MallocFunc, AllocSize, "mid_str_mem"); - - Value *SrcPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), Str, StartZeroBased); - - std::vector<Value*> Args = {NewStrMem, SrcPtr, ActualLen}; - Builder.CreateCall(MemCpyFunc, Args); - - Value *NullTermPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), NewStrMem, ActualLen); - Builder.CreateStore(ConstantInt::get(Type::getInt8Ty(Context), 0), NullTermPtr); - - return NewStrMem; + return allocCopySubstring(Str, StartZeroBased, ActualLen); } Value *StringHandler::emitRight(Value *Str, Value *Len) { @@ -105,19 +109,7 @@ Value *StringHandler::emitRight(Value *Str, Value *Len) { Value *ActualLen = Builder.CreateSub(FullLen, StartIdx); - Value *One = ConstantInt::get(Context, APInt(64, 1)); - Value *AllocSize = Builder.CreateAdd(ActualLen, One); - Value *NewStrMem = Builder.CreateCall(MallocFunc, AllocSize, "right_str_mem"); - - Value *SrcPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), Str, StartIdx); - - std::vector<Value*> Args = {NewStrMem, SrcPtr, ActualLen}; - Builder.CreateCall(MemCpyFunc, Args); - - Value *NullTermPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), NewStrMem, ActualLen); - Builder.CreateStore(ConstantInt::get(Type::getInt8Ty(Context), 0), NullTermPtr); - - return NewStrMem; + return allocCopySubstring(Str, StartIdx, ActualLen); } Value *StringHandler::emitLeft(Value *Str, Value *Len) { @@ -130,24 +122,16 @@ Value *StringHandler::emitLeft(Value *Str, Value *Len) { Value *IsTooBig = Builder.CreateICmpSGT(SafeLen, FullLen); Value *ActualLen = Builder.CreateSelect(IsTooBig, FullLen, SafeLen); - Value *One = ConstantInt::get(Context, APInt(64, 1)); - Value *AllocSize = Builder.CreateAdd(ActualLen, One); - Value *NewStrMem = Builder.CreateCall(MallocFunc, AllocSize, "left_str_mem"); - - std::vector<Value*> Args = {NewStrMem, Str, ActualLen}; - Builder.CreateCall(MemCpyFunc, Args); - - Value *NullTermPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), NewStrMem, ActualLen); - Builder.CreateStore(ConstantInt::get(Type::getInt8Ty(Context), 0), NullTermPtr); - - return NewStrMem; + return allocCopySubstring(Str, Zero, ActualLen); } -Value *StringHandler::emitLCase(Value *Str) { +// Shared loop for LCASE/UCASE: malloc a copy of Str with every byte run +// through CaseFn (tolower/toupper). +Value *StringHandler::emitCaseConvert(Value *Str, FunctionCallee CaseFn) { Value *Len = emitLength(Str); Value *One = ConstantInt::get(Context, APInt(64, 1)); Value *AllocSize = Builder.CreateAdd(Len, One); - Value *NewStr = Builder.CreateCall(MallocFunc, AllocSize, "lcase_str"); + Value *NewStr = Builder.CreateCall(MallocFunc, AllocSize, "case_str"); Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *LoopBB = BasicBlock::Create(Context, "loop", TheFunction); @@ -156,24 +140,24 @@ Value *StringHandler::emitLCase(Value *Str) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); AllocaInst *IdxVar = TmpB.CreateAlloca(Type::getInt64Ty(Context), nullptr, "idx"); Builder.CreateStore(ConstantInt::get(Context, APInt(64, 0)), IdxVar); - + Builder.CreateBr(LoopBB); Builder.SetInsertPoint(LoopBB); - + Value *CurIdx = Builder.CreateLoad(Type::getInt64Ty(Context), IdxVar); Value *Cond = Builder.CreateICmpSLT(CurIdx, Len); - + BasicBlock *BodyBB = BasicBlock::Create(Context, "body", TheFunction); Builder.CreateCondBr(Cond, BodyBB, AfterBB); - + Builder.SetInsertPoint(BodyBB); Value *SrcPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), Str, CurIdx); Value *CharVal = Builder.CreateLoad(Type::getInt8Ty(Context), SrcPtr); Value *ExtChar = Builder.CreateSExt(CharVal, Type::getInt32Ty(Context)); - Value *LowerChar = Builder.CreateCall(ToLowerFunc, ExtChar); - Value *TruncChar = Builder.CreateTrunc(LowerChar, Type::getInt8Ty(Context)); + Value *ConvChar = Builder.CreateCall(CaseFn, ExtChar); + Value *TruncChar = Builder.CreateTrunc(ConvChar, Type::getInt8Ty(Context)); Value *DestPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), NewStr, CurIdx); Builder.CreateStore(TruncChar, DestPtr); @@ -181,60 +165,19 @@ Value *StringHandler::emitLCase(Value *Str) { Value *NextIdx = Builder.CreateAdd(CurIdx, One); Builder.CreateStore(NextIdx, IdxVar); Builder.CreateBr(LoopBB); - + Builder.SetInsertPoint(AfterBB); Value *NullPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), NewStr, Len); Builder.CreateStore(ConstantInt::get(Type::getInt8Ty(Context), 0), NullPtr); - + return NewStr; } -Value *StringHandler::emitUCase(Value *Str) { - Value *Len = emitLength(Str); - Value *One = ConstantInt::get(Context, APInt(64, 1)); - Value *AllocSize = Builder.CreateAdd(Len, One); - Value *NewStr = Builder.CreateCall(MallocFunc, AllocSize, "ucase_str"); - - // Loop - Function *TheFunction = Builder.GetInsertBlock()->getParent(); - BasicBlock *LoopBB = BasicBlock::Create(Context, "loop", TheFunction); - BasicBlock *AfterBB = BasicBlock::Create(Context, "afterloop", TheFunction); - - // Init i = 0 - IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - AllocaInst *IdxVar = TmpB.CreateAlloca(Type::getInt64Ty(Context), nullptr, "idx"); - Builder.CreateStore(ConstantInt::get(Context, APInt(64, 0)), IdxVar); - - Builder.CreateBr(LoopBB); - Builder.SetInsertPoint(LoopBB); - - Value *CurIdx = Builder.CreateLoad(Type::getInt64Ty(Context), IdxVar); - Value *Cond = Builder.CreateICmpSLT(CurIdx, Len); - - BasicBlock *BodyBB = BasicBlock::Create(Context, "body", TheFunction); - Builder.CreateCondBr(Cond, BodyBB, AfterBB); - - Builder.SetInsertPoint(BodyBB); - - Value *SrcPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), Str, CurIdx); - Value *CharVal = Builder.CreateLoad(Type::getInt8Ty(Context), SrcPtr); - - Value *ExtChar = Builder.CreateSExt(CharVal, Type::getInt32Ty(Context)); - Value *UpperChar = Builder.CreateCall(ToUpperFunc, ExtChar); - Value *TruncChar = Builder.CreateTrunc(UpperChar, Type::getInt8Ty(Context)); - - Value *DestPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), NewStr, CurIdx); - Builder.CreateStore(TruncChar, DestPtr); - - Value *NextIdx = Builder.CreateAdd(CurIdx, One); - Builder.CreateStore(NextIdx, IdxVar); - Builder.CreateBr(LoopBB); - - Builder.SetInsertPoint(AfterBB); +Value *StringHandler::emitLCase(Value *Str) { + return emitCaseConvert(Str, ToLowerFunc); +} - Value *NullPtr = Builder.CreateInBoundsGEP(Type::getInt8Ty(Context), NewStr, Len); - Builder.CreateStore(ConstantInt::get(Type::getInt8Ty(Context), 0), NullPtr); - - return NewStr; +Value *StringHandler::emitUCase(Value *Str) { + return emitCaseConvert(Str, ToUpperFunc); } |
