diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-14 03:31:47 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-14 03:31:47 +0000 |
| commit | 2147449f4d6f37b4624990ff26bce58ebf3cfb4b (patch) | |
| tree | bbf09cea539b8ea01ee3d392ec828067552fa4b7 /lib/CodeGen | |
| parent | 699e18b65b07af73ccd14b28f83572b1843c7d37 (diff) | |
feat(parser): add explicit parenthesized type casts
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen')
| -rw-r--r-- | lib/CodeGen/CTypeGen.cc | 79 | ||||
| -rw-r--r-- | lib/CodeGen/CodeGen.cc | 19 | ||||
| -rw-r--r-- | lib/CodeGen/Designator.cc | 3 |
3 files changed, 100 insertions, 1 deletions
diff --git a/lib/CodeGen/CTypeGen.cc b/lib/CodeGen/CTypeGen.cc new file mode 100644 index 0000000..03f398f --- /dev/null +++ b/lib/CodeGen/CTypeGen.cc @@ -0,0 +1,79 @@ +#include "cps/CodeGen.h" +#include "cps/TypeAST.h" + +using namespace llvm; +using namespace cps; + +namespace { + +bool isScalar(const TypeInfo *Info) { + if (!Info || Info->isVoid()) return false; + return Info->Kind == TypeKind::CScalar || Info->Kind == TypeKind::Integer || + Info->Kind == TypeKind::Real || Info->Kind == TypeKind::Boolean || + Info->Kind == TypeKind::Char; +} + +bool isSigned(const TypeInfo *Info) { + return Info->isC() ? Info->CSigned : Info->Kind == TypeKind::Integer; +} + +} // namespace + +// Source type identity is essential: native signed char and pseudocode CHAR +// can share i8 while requiring different extensions and FP conversions. +Value *CodeGen::convertNumericValue(Value *Val, const TypeInfo *Source, const TypeInfo *Target) { + if (!Val || !isScalar(Source) || !isScalar(Target)) return nullptr; + Type *From = Val->getType(); + Type *To = Target->LLVMType; + if (From == To) return Val; + if (To->isIntegerTy(1)) { + if (From->isIntegerTy()) + return Builder->CreateICmpNE(Val, Constant::getNullValue(From), "cast_bool"); + return Builder->CreateFCmpUNE(Val, ConstantFP::get(From, 0.0), "cast_bool"); + } + if (From->isIntegerTy() && To->isIntegerTy()) + return Builder->CreateIntCast(Val, To, isSigned(Source), "cast_int"); + if (From->isIntegerTy() && To->isFloatingPointTy()) + return isSigned(Source) ? Builder->CreateSIToFP(Val, To, "cast_fp") + : Builder->CreateUIToFP(Val, To, "cast_fp"); + if (From->isFloatingPointTy() && To->isIntegerTy()) + return isSigned(Target) ? Builder->CreateFPToSI(Val, To, "cast_int") + : Builder->CreateFPToUI(Val, To, "cast_int"); + return Builder->CreateFPCast(Val, To, "cast_fp"); +} + +Value *CodeGen::emitCast(CastExprAST *Cast) { + const TypeInfo *Target = resolveType(Cast->getTypeName()); + ExprAST *Operand = Cast->getOperand(); + if (!Target || Target->isVoid()) { + reportError("Invalid cast target %s", Cast->getTypeName().c_str()); + return nullptr; + } + if (isWholeArrayVar(Operand)) { + reportError("Cannot cast a whole array; index it"); + return nullptr; + } + if (auto *Address = dynamic_cast<AddrOfExprAST*>(Operand)) { + LValueInfo LV; + if (!emitLValue(Address->getTarget(), LV)) return nullptr; + const TypeInfo *Pointee = resolveType(LV.TypeName); + if (Target->Kind == TypeKind::CPointer && Pointee && Pointee->isC()) return LV.Addr; + reportError("Address casts require a C pointee and C pointer target"); + return nullptr; + } + const TypeInfo *Source = getExprTypeInfo(Operand); + if (!Source || Source->isVoid() || Source->isUserKind() || Target->isUserKind()) { + reportError("Unsupported operand or target for cast to %s", Target->Name.c_str()); + return nullptr; + } + if (isScalar(Source) && isScalar(Target)) + return convertNumericValue(emitExpr(Operand), Source, Target); + if (Source->Kind == TypeKind::CPointer && Target->Kind == TypeKind::CPointer) + return emitExpr(Operand); + if (Source->isString() && Target->CIdentity == "char*") return emitExpr(Operand); + if (Source->CIdentity == "char*" && Target->isString()) + return emitStringNullGuard(emitExpr(Operand)); + if (Source->isString() && Target->isString()) return emitExpr(Operand); + reportError("Cannot cast %s to %s", Source->Name.c_str(), Target->Name.c_str()); + return nullptr; +} diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index 8c01972..ce34ebc 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -185,6 +185,8 @@ const TypeInfo *CodeGen::getExprTypeInfo(ExprAST *Expr) const { if (dynamic_cast<BooleanExprAST*>(Expr)) return resolveType("BOOLEAN"); if (dynamic_cast<CharExprAST*>(Expr)) return resolveType("CHAR"); if (dynamic_cast<StringExprAST*>(Expr)) return resolveType("STRING"); + if (auto *Cast = dynamic_cast<CastExprAST*>(Expr)) + return resolveType(Cast->getTypeName()); if (auto *Var = dynamic_cast<VariableExprAST*>(Expr)) { const SymbolInfo *Info = getSymbolInfo(Var->getName()); @@ -240,7 +242,10 @@ const TypeInfo *CodeGen::getExprTypeInfo(ExprAST *Expr) const { if (Unary->getOp() == tok_not) { return resolveType("BOOLEAN"); } - return getExprTypeInfo(Unary->getOperand()); + const TypeInfo *Operand = getExprTypeInfo(Unary->getOperand()); + if (Operand && !Operand->isC() && !Operand->isUserKind()) + return Operand->isReal() ? resolveType("REAL") : resolveType("INTEGER"); + return nullptr; } if (auto *Bin = dynamic_cast<BinaryExprAST*>(Expr)) { @@ -572,6 +577,7 @@ void CodeGen::print(raw_ostream &Output) { } Value *CodeGen::emitExpr(ExprAST *Expr) { + if (auto *Cast = dynamic_cast<CastExprAST*>(Expr)) return emitCast(Cast); if (!Expr) return nullptr; if (auto *Num = dynamic_cast<IntegerExprAST*>(Expr)) { @@ -632,6 +638,17 @@ Value *CodeGen::emitExpr(ExprAST *Expr) { if (!Operand) return nullptr; return Builder->CreateNot(Operand, "nottmp"); } + if (Unary->getOp() == '-') { + const TypeInfo *Info = getExprTypeInfo(Unary->getOperand()); + if (!Info || Info->isC() || Info->isUserKind() || Info->isString() || Info->isVoid()) { + reportError("Unary '-' requires a supported numeric operand"); + return nullptr; + } + Value *Operand = emitExpr(Unary->getOperand()); + if (!Operand) return nullptr; + return ArithHandler->emitBinaryOp('-', ConstantInt::get(Type::getInt64Ty(*TheContext), 0), + Operand, 0); + } return nullptr; } diff --git a/lib/CodeGen/Designator.cc b/lib/CodeGen/Designator.cc index c7d0796..019c19e 100644 --- a/lib/CodeGen/Designator.cc +++ b/lib/CodeGen/Designator.cc @@ -231,6 +231,9 @@ Value *CodeGen::emitCoercedExpr(ExprAST *E, const TypeInfo *Target) { return nullptr; } if (Src && Src->sameType(Target) && !Target->isVoid()) return emitExpr(E); + if (Src && Src->Kind == TypeKind::CScalar && Target->Kind == TypeKind::CScalar && + !Src->isVoid() && !Target->isVoid()) + return convertNumericValue(emitExpr(E), Src, Target); reportError("Cannot implicitly convert %s to %s; use an explicit cast", Src ? Src->Name.c_str() : "expression", Target->Name.c_str()); return nullptr; |
