diff options
Diffstat (limited to 'lib/CodeGen/StringHandler.cc')
| -rw-r--r-- | lib/CodeGen/StringHandler.cc | 206 |
1 files changed, 0 insertions, 206 deletions
diff --git a/lib/CodeGen/StringHandler.cc b/lib/CodeGen/StringHandler.cc deleted file mode 100644 index f91539c..0000000 --- a/lib/CodeGen/StringHandler.cc +++ /dev/null @@ -1,206 +0,0 @@ -#include "cps/StringHandler.h" -#include "cps/Lexer.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Constants.h" - -using namespace llvm; -using namespace cps; - -StringHandler::StringHandler(LLVMContext &Ctx, IRBuilder<> &B, llvm::Module &M) - : Context(Ctx), Builder(B), Module(M) { - setupExternalFunctions(); -} - -void StringHandler::setupExternalFunctions() { - FunctionType *MallocType = FunctionType::get(PointerType::getUnqual(Context), {Type::getInt64Ty(Context)}, false); - MallocFunc = Module.getOrInsertFunction("malloc", MallocType); - - FunctionType *StrLenType = FunctionType::get(Type::getInt64Ty(Context), {PointerType::getUnqual(Context)}, false); - StrLenFunc = Module.getOrInsertFunction("strlen", StrLenType); - - std::vector<Type*> MemCpyArgs = {PointerType::getUnqual(Context), PointerType::getUnqual(Context), Type::getInt64Ty(Context)}; - FunctionType *MemCpyType = FunctionType::get(PointerType::getUnqual(Context), MemCpyArgs, false); - MemCpyFunc = Module.getOrInsertFunction("memcpy", MemCpyType); - - FunctionType *StrCpyType = FunctionType::get(PointerType::getUnqual(Context), - {PointerType::getUnqual(Context), PointerType::getUnqual(Context)}, - false); - StrCpyFunc = Module.getOrInsertFunction("strcpy", StrCpyType); - StrCatFunc = Module.getOrInsertFunction("strcat", StrCpyType); - StrCmpFunc = Module.getOrInsertFunction("strcmp", - FunctionType::get(Type::getInt32Ty(Context), - {PointerType::getUnqual(Context), PointerType::getUnqual(Context)}, false)); - - FunctionType *CharCaseType = FunctionType::get(Type::getInt32Ty(Context), {Type::getInt32Ty(Context)}, false); - ToUpperFunc = Module.getOrInsertFunction("toupper", CharCaseType); - ToLowerFunc = Module.getOrInsertFunction("tolower", CharCaseType); -} - -Value *StringHandler::createLiteral(const std::string &Val) { - return Builder.CreateGlobalString(Val); -} - -Value *StringHandler::emitLength(Value *Str) { - if (!Str) return nullptr; - return Builder.CreateCall(StrLenFunc, Str, "len"); -} - -Value *StringHandler::emitConcat(Value *LHS, Value *RHS) { - if (!LHS || !RHS) return nullptr; - - Value *LLen = Builder.CreateCall(StrLenFunc, {LHS}, "llen"); - Value *RLen = Builder.CreateCall(StrLenFunc, {RHS}, "rlen"); - Value *TotalLen = Builder.CreateAdd(LLen, RLen, "totallen"); - Value *AllocSize = Builder.CreateAdd(TotalLen, ConstantInt::get(Type::getInt64Ty(Context), 1), "allocsize"); - - Value *NewStr = Builder.CreateCall(MallocFunc, {AllocSize}, "concat_str"); - - Builder.CreateCall(StrCpyFunc, {NewStr, LHS}); - Builder.CreateCall(StrCatFunc, {NewStr, RHS}); - - return NewStr; -} - -Value *StringHandler::emitCompare(int Op, Value *LHS, Value *RHS) { - if (!LHS || !RHS) return nullptr; - - CmpInst::Predicate Pred; - switch (Op) { - case tok_eq: Pred = CmpInst::ICMP_EQ; break; - case tok_ne: Pred = CmpInst::ICMP_NE; break; - case '<': Pred = CmpInst::ICMP_SLT; break; - case '>': Pred = CmpInst::ICMP_SGT; break; - case tok_le: Pred = CmpInst::ICMP_SLE; break; - case tok_ge: Pred = CmpInst::ICMP_SGE; break; - default: return nullptr; - } - - Value *Cmp = Builder.CreateCall(StrCmpFunc, {LHS, RHS}, "strcmp_result"); - return Builder.CreateICmp(Pred, Cmp, ConstantInt::get(Type::getInt32Ty(Context), 0), "str_compare"); -} - -// 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)); - Value *Zero = ConstantInt::get(Context, APInt(64, 0)); - Value *StartZeroBased = Builder.CreateSub(Start, One, "start_idx"); - - Value *IsNeg = Builder.CreateICmpSLT(StartZeroBased, Zero); - StartZeroBased = Builder.CreateSelect(IsNeg, Zero, StartZeroBased); - - Value *IsTooBig = Builder.CreateICmpSGT(StartZeroBased, FullLen); - StartZeroBased = Builder.CreateSelect(IsTooBig, FullLen, StartZeroBased); - - Value *RemLen = Builder.CreateSub(FullLen, StartZeroBased); - - Value *IsLenTooBig = Builder.CreateICmpSGT(Len, RemLen); - Value *ActualLen = Builder.CreateSelect(IsLenTooBig, RemLen, Len); - - Value *IsLenNeg = Builder.CreateICmpSLT(ActualLen, Zero); - ActualLen = Builder.CreateSelect(IsLenNeg, Zero, ActualLen); - - return allocCopySubstring(Str, StartZeroBased, ActualLen); -} - -Value *StringHandler::emitRight(Value *Str, Value *Len) { - Value *FullLen = emitLength(Str); - - Value *StartIdx = Builder.CreateSub(FullLen, Len, "right_start"); - - Value *Zero = ConstantInt::get(Context, APInt(64, 0)); - Value *IsNeg = Builder.CreateICmpSLT(StartIdx, Zero); - StartIdx = Builder.CreateSelect(IsNeg, Zero, StartIdx); - - Value *ActualLen = Builder.CreateSub(FullLen, StartIdx); - - return allocCopySubstring(Str, StartIdx, ActualLen); -} - -Value *StringHandler::emitLeft(Value *Str, Value *Len) { - Value *FullLen = emitLength(Str); - - Value *Zero = ConstantInt::get(Context, APInt(64, 0)); - Value *IsNeg = Builder.CreateICmpSLT(Len, Zero); - Value *SafeLen = Builder.CreateSelect(IsNeg, Zero, Len); - - Value *IsTooBig = Builder.CreateICmpSGT(SafeLen, FullLen); - Value *ActualLen = Builder.CreateSelect(IsTooBig, FullLen, SafeLen); - - return allocCopySubstring(Str, Zero, ActualLen); -} - -// 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) { - if (!Str) return nullptr; - Value *Len = emitLength(Str); - Value *One = ConstantInt::get(Context, APInt(64, 1)); - Value *AllocSize = Builder.CreateAdd(Len, One); - Value *NewStr = Builder.CreateCall(MallocFunc, AllocSize, "case_str"); - - Function *TheFunction = Builder.GetInsertBlock()->getParent(); - BasicBlock *LoopBB = BasicBlock::Create(Context, "loop", TheFunction); - BasicBlock *AfterBB = BasicBlock::Create(Context, "afterloop", TheFunction); - - 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 *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); - - 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::emitLCase(Value *Str) { - return emitCaseConvert(Str, ToLowerFunc); -} - -Value *StringHandler::emitUCase(Value *Str) { - return emitCaseConvert(Str, ToUpperFunc); -} |
