[svn r82] Fixed: Fall-through switch cases were broken.

This commit is contained in:
Tomas Lindquist Olsen
2007-10-31 20:50:21 +01:00
parent 0979d55d26
commit d8f021d63f
7 changed files with 75 additions and 29 deletions

View File

@@ -1,6 +1,5 @@
module qd;
/*
import std.c.time: sleep;
void main() {
screen(640, 480);
@@ -18,7 +17,6 @@ void main() {
pset(10, 10);
sleep(5);
}
*/
extern(C) {
struct SDL_Rect {
@@ -308,8 +306,13 @@ void line(T...)(int x0, int y0, int x1, int y1, T p) {
}
}
import llvm.intrinsic;
alias llvm_sqrt sqrt;
pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f32") {
float sqrt(float val);
}
pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f64") {
double sqrt(double val);
real sqrt(real val);
}
template circle_bresenham_pass(bool first) {
const string xy=(first?"x":"y");

View File

@@ -255,6 +255,7 @@ void WhileStatement::toIR(IRState* p)
// create while blocks
llvm::BasicBlock* oldend = gIR->scopeend();
llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend);
llvm::BasicBlock* whilebodybb = new llvm::BasicBlock("whilebody", gIR->topfunc(), oldend);
llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend);
// move into the while block
@@ -269,11 +270,8 @@ void WhileStatement::toIR(IRState* p)
llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue());
delete cond_e;
// while body block
llvm::BasicBlock* whilebodybb = new llvm::BasicBlock("whilebody", gIR->topfunc(), endbb);
// conditional branch
llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, whilebb);
llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb());
// rewrite scope
gIR->scope() = IRScope(whilebodybb,endbb);
@@ -580,7 +578,7 @@ void SwitchStatement::toIR(IRState* p)
p->loopbbs.pop_back();
llvm::BasicBlock* curbb = p->scopebb();
if (!curbb->empty() && !curbb->back().isTerminator())
if (curbb->empty() || !curbb->back().isTerminator())
{
new llvm::BranchInst(nextbb, curbb);
}
@@ -591,11 +589,12 @@ void SwitchStatement::toIR(IRState* p)
{
p->scope() = IRScope(defbb,endbb);
p->loopbbs.push_back(IRScope(defbb,endbb));
Logger::println("doing default statement");
sdefault->statement->toIR(p);
p->loopbbs.pop_back();
llvm::BasicBlock* curbb = p->scopebb();
if (!curbb->empty() && !curbb->back().isTerminator())
if (curbb->empty() || !curbb->back().isTerminator())
{
new llvm::BranchInst(endbb, curbb);
}

View File

@@ -1445,6 +1445,7 @@ elem* SymOffExp::toElem(IRState* p)
llvm::Value* llvalue = vd->nestedref ? LLVM_DtoNestedVariable(vd) : vd->llvmValue;
if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
Logger::println("struct");
TypeStruct* vdt = (TypeStruct*)vdtype;
assert(vdt->sym);
e = new elem;
@@ -1455,26 +1456,12 @@ elem* SymOffExp::toElem(IRState* p)
else {
std::vector<unsigned> dst;
e->mem = LLVM_DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
/*size_t fo = vdt->sym->offsetToIndex(tnext, offset, dst);
llvm::Value* ptr = llvalue;
assert(ptr);
e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
if (e->mem->getType() != llt) {
e->mem = p->ir->CreateBitCast(e->mem, llt, "tmp");
}
if (fo == (size_t)-1) {
size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
assert(offset % llt_sz == 0);
e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(offset / llt_sz), "tmp", p->scopebb());
}
else if (fo) {
e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(fo), "tmp", p->scopebb());
}*/
}
e->type = elem::VAL;
e->field = true;
}
else if (vdtype->ty == Tsarray) {
Logger::println("sarray");
e = new elem;
assert(llvalue);
e->arg = llvalue;
@@ -1496,6 +1483,7 @@ elem* SymOffExp::toElem(IRState* p)
}
}
else if (offset == 0) {
Logger::println("normal symoff");
e = new elem;
e->type = elem::VAL;
assert(llvalue);

View File

@@ -1241,12 +1241,20 @@ llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expr
}
}
if (fnarg && paramtype && retval->getType() != paramtype) {
// this is unfortunately needed with the way SymOffExp is overused
// and static arrays can end up being a pointer to their element type
if (arg->field) {
retval = gIR->ir->CreateBitCast(retval, paramtype, "tmp");
}
else {
Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
assert(0 && "parameter type that was actually passed is invalid");
}
}
delete arg;
if (fnarg && paramtype && retval->getType() != paramtype) {
Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
assert(0 && "parameter type that was actually passed is invalid");
}
return retval;
}

10
test/bug42.d Normal file
View File

@@ -0,0 +1,10 @@
module bug42;
void main() {
int i = 2;
switch (i) {
case 0:
case 1:
default:
}
}

16
test/bug43.d Normal file
View File

@@ -0,0 +1,16 @@
module bug43;
struct S
{
ubyte[3] vals;
}
void func(ubyte[3] v)
{
}
void main()
{
S s;
func(s.vals);
}

22
test/union6.d Normal file
View File

@@ -0,0 +1,22 @@
module union6;
pragma(LLVM_internal, "notypeinfo") {
struct S
{
byte a;
byte b;
}
union U
{
byte a;
byte b;
S c;
}
}
void main()
{
U u;
auto a = u.c.b;
//auto c = u.s.l;
}