Commits

Anonymous committed 54b2db7

implemented at_beginning and at_end

  • Participants
  • Parent commits 2761f14

Comments (0)

Files changed (1)

File llvmre.patch

 diff -r 37ecb109fa41 Lib/llvmre.py
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/Lib/llvmre.py	Thu May 27 07:54:42 2010 +0200
-@@ -0,0 +1,50 @@
++++ b/Lib/llvmre.py	Mon May 31 07:49:43 2010 +0200
+@@ -0,0 +1,48 @@
 +import sys
 +import sre_compile
 +
 +    def __init__(self, pattern, flags):
 +        self.flags = flags
 +        self.unicode = self.flags & U
-+        if not self.unicode:
-+            raise error("Not implemented.")
 +
 +        from sre_parse import parse
 +        self.__parsed = parse(pattern, flags)
 +        if self.unicode:
 +            string = unicode(string)
 +        else:
-+            raise error("Not implemented.")
++            string = str(string)
 +
 +        if self.__re.match(string, pos, endpos):
 +            return MatchObject()
 +    return RegexObject(pattern, flags)
 diff -r 37ecb109fa41 Modules/Setup.dist
 --- a/Modules/Setup.dist	Mon May 03 18:00:25 2010 +0200
-+++ b/Modules/Setup.dist	Thu May 27 07:54:42 2010 +0200
++++ b/Modules/Setup.dist	Mon May 31 07:49:43 2010 +0200
 @@ -117,6 +117,8 @@
  pwd pwdmodule.c			# this is needed to find out the user's home dir
  				# if $HOME is not set
  # The zipimport module is always imported at startup. Having it as a
 diff -r 37ecb109fa41 Modules/_llvmre/llvmre.cc
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/Modules/_llvmre/llvmre.cc	Thu May 27 07:54:42 2010 +0200
-@@ -0,0 +1,1048 @@
++++ b/Modules/_llvmre/llvmre.cc	Mon May 31 07:49:43 2010 +0200
+@@ -0,0 +1,1135 @@
 +#include "Python.h"
 +
 +#include "JIT/global_llvm_data.h"
 +}
 +
 +static const llvm::FunctionType *
-+get_function_type(llvm::Module *module, bool recursive)
++get_function_type(llvm::Module *module, const llvm::Type* char_type)
 +{
 +    std::vector<const llvm::Type*> args;
-+    args.push_back(PyTypeBuilder<Py_UNICODE *>::get(module->getContext()));
-+    args.push_back(PyTypeBuilder<Py_UNICODE *>::get(module->getContext()));
-+    //    args.push_back(PyTypeBuilder<int *>::get(module->getContext()));
-+
++    args.push_back(llvm::PointerType::getUnqual(char_type));
++    args.push_back(llvm::PointerType::getUnqual(char_type));
++    args.push_back(llvm::PointerType::getUnqual(char_type));
++
++    // get_recursive_type may destroy Type's so call it last
 +    args.push_back(llvm::PointerType::getUnqual(get_recursive_type(module)));
 +
 +    return llvm::FunctionType::get(
 +// *****************************************
 +
 +RegExBuilder::RegExBuilder(RegularExpression *regex, llvm::Function *cont)
-+    : func_(new RegExFunction(regex, false)),
++    : func_(new RegExFunction(regex)),
 +      llvm_data_(PyGlobalLlvmData::Get()),
 +      context_(this->llvm_data_->context()),
 +      continue_func_(cont)
 +                result = false;
 +            }
 +        }
++        else if (strcmp(op_str, "at") == 0) {
++            RegExOpcodeAt at(this);
++            if (!at.EmitAt(arg)) {
++                result = false;
++            }
++        }
 +        else {
 +            PyErr_Format(PyExc_ValueError,
 +                         "Unsupported SRE code '%s'", op_str);
 +            ConstantInt::get(PyTypeBuilder<char>::get(this->context_), true));
 +    }
 +    else {
-+        llvm::CallInst *result = this->func_->builder().CreateCall3(
++        llvm::CallInst *result = this->func_->builder().CreateCall4(
 +            this->continue_func_,
++            this->func_->StartPosition(),
 +            this->func_->CurrentPosition(),
 +            this->func_->EndPosition(),
 +            this->func_->rec_stats_addr(),
 +    // Accept anything but '\n'.
 +    // TODO: check table from sre
 +    llvm::Value *c = this->func_->LoadCharacter();
-+    Value *lit_value = ConstantInt::get(
-+        PyTypeBuilder<Py_UNICODE>::get(this->context_), '\n');
++    Value *lit_value = ConstantInt::get(this->func_->GetCharType(), '\n');
 +    llvm::Value *equal = builder.CreateICmpEQ(c, lit_value);
 +    llvm::BasicBlock *cont_block =
 +        this->func_->CreateBasicBlock("any_continue");
 +    this->func_->CheckEnd();
 +
 +    llvm::Value *c = this->func_->LoadCharacter();
-+    Value *lit_value = ConstantInt::get(
-+        PyTypeBuilder<Py_UNICODE>::get(this->context_), literal);
++    Value *lit_value = ConstantInt::get(this->func_->GetCharType(), literal);
 +    llvm::Value *equal = builder.CreateICmpEQ(c, lit_value);
 +    llvm::BasicBlock *equal_block =
 +        this->func_->CreateBasicBlock("literal_equal");
 +        return false;
 +    }
 +
-+    RegExFunction *cont = new RegExFunction(this->func_->regex(), false);
++    RegExFunction *cont = new RegExFunction(this->func_->regex());
 +
 +    llvm::BasicBlock *success =
 +        this->func_->CreateBasicBlock("branch_success");
 +        }
 +
 +        llvm::Value *call =
-+            irbuilder.CreateCall3(
++            irbuilder.CreateCall4(
 +                entry,
++                this->func_->StartPosition(),
 +                this->func_->CurrentPosition(),
 +                this->func_->EndPosition(),
 +                this->func_->rec_stats_addr(),
 +        return false;
 +    }
 +
-+    RegExFunction *cont = new RegExFunction(this->func_->regex(), false);
++    RegExFunction *cont = new RegExFunction(this->func_->regex());
 +
 +    RegExBuilder builder(this->func_->regex(), cont->function());
 +    llvm::Function *entry = builder.function()->function();
 +    }
 +
 +    llvm::Value *call =
-+        this->func_->builder().CreateCall3(
++        this->func_->builder().CreateCall4(
 +            entry,
++            this->func_->StartPosition(),
 +            this->func_->CurrentPosition(),
 +            this->func_->EndPosition(),
 +            this->func_->rec_stats_addr(),
 +RegExBuilder::EmitMaxRepeatPartMax(long min_repeat, long max_repeat,
 +                               PyObject *repeat)
 +{
-+    RegExFunction *rest = new RegExFunction(this->func_->regex(), false);
-+    RegExFunction *recurse = new RegExFunction(this->func_->regex(), false);
-+    RegExFunction *cont = new RegExFunction(this->func_->regex(), false);
++    RegExFunction *rest = new RegExFunction(this->func_->regex());
++    RegExFunction *recurse = new RegExFunction(this->func_->regex());
++    RegExFunction *cont = new RegExFunction(this->func_->regex());
 +
 +    RegExBuilder builder(this->func_->regex(), cont->function());
 +    llvm::Function *entry = builder.function()->function();
 +        irbuilder.CreateStore(this->func_->rec_stats_addr(), old_stats_addr_);
 +
 +        Value *call =
-+            irbuilder.CreateCall3(recurse->function(),
++            irbuilder.CreateCall4(recurse->function(),
++                                  this->func_->StartPosition(),
 +                                  this->func_->CurrentPosition(),
 +                                  this->func_->EndPosition(),
 +                                  stat,
 +        // Handle end of recursion (either fail or count)
 +        irbuilder.SetInsertPoint(recurse_done);
 +        Value *call_continue =
-+            irbuilder.CreateCall3(rest->function(),
++            irbuilder.CreateCall4(rest->function(),
++                                  recurse->StartPosition(),
 +                                  recurse->CurrentPosition(),
 +                                  recurse->EndPosition(),
 +                                  irbuilder.CreateLoad(old_stats_addr_),
 +
 +        // entry matches the subpattern, which calls cont, which calls recurse
 +        Value *rec_result =
-+          irbuilder.CreateCall3(entry,
++          irbuilder.CreateCall4(entry,
++                                recurse->StartPosition(),
 +                                recurse->CurrentPosition(),
 +                                recurse->EndPosition(),
 +                                stats,
 +        RegExFunction::BuilderT &irbuilder = cont->builder();
 +        Value *stats = cont->rec_stats_addr();
 +        Value *call_continue =
-+            irbuilder.CreateCall3(recurse->function(),
++            irbuilder.CreateCall4(recurse->function(),
++                                  cont->StartPosition(),
 +                                  cont->CurrentPosition(),
 +                                  cont->EndPosition(),
 +                                  stats,
 +RegExBuilder::EmitMaxRepeatPartMin(long min_repeat, long max_repeat,
 +                                   PyObject *repeat)
 +{
-+    RegExFunction *rest = new RegExFunction(this->func_->regex(), false);
-+    RegExFunction *recurse = new RegExFunction(this->func_->regex(), false);
-+    RegExFunction *cont = new RegExFunction(this->func_->regex(), false);
++    RegExFunction *rest = new RegExFunction(this->func_->regex());
++    RegExFunction *recurse = new RegExFunction(this->func_->regex());
++    RegExFunction *cont = new RegExFunction(this->func_->regex());
 +
 +    RegExBuilder builder(this->func_->regex(), cont->function());
 +    llvm::Function *entry = builder.function()->function();
 +
 +
 +        Value *call =
-+            irbuilder.CreateCall3(recurse->function(),
++            irbuilder.CreateCall4(recurse->function(),
++                                  this->func_->StartPosition(),
 +                                  this->func_->CurrentPosition(),
 +                                  this->func_->EndPosition(),
 +                                  stat,
 +        RegExFunction::BuilderT &irbuilder = cont->builder();
 +        Value *stats = cont->rec_stats_addr();
 +        Value *call_continue =
-+            irbuilder.CreateCall3(recurse->function(),
++            irbuilder.CreateCall4(recurse->function(),
++                                  cont->StartPosition(),
 +                                  cont->CurrentPosition(),
 +                                  cont->EndPosition(),
 +                                  stats,
 +        // Handle end of recursion (either fail or count)
 +        irbuilder.SetInsertPoint(recurse_done);
 +        Value *call_continue =
-+            irbuilder.CreateCall3(rest->function(),
++            irbuilder.CreateCall4(rest->function(),
++                                  recurse->StartPosition(),
 +                                  recurse->CurrentPosition(),
 +                                  recurse->EndPosition(),
 +                                  irbuilder.CreateLoad(old_stats_addr_),
 +
 +        // entry matches the subpattern, which calls cont, which calls recurse
 +        Value *rec_result =
-+          irbuilder.CreateCall3(entry,
++          irbuilder.CreateCall4(entry,
++                                recurse->StartPosition(),
 +                                recurse->CurrentPosition(),
 +                                recurse->EndPosition(),
 +                                stats,
 +
 +// *****************************************
 +
-+RegExFunction::RegExFunction(RegularExpression *regex, bool recursive)
++RegExFunction::RegExFunction(RegularExpression *regex)
 +    : regex_(regex),
 +      llvm_data_(PyGlobalLlvmData::Get()),
 +      context_(this->llvm_data_->context()),
 +      builder_(this->context_,
 +               llvm::TargetFolder(
-+                   this->llvm_data_->getExecutionEngine()->getTargetData())),
-+      recursive_(recursive)
-+
++                   this->llvm_data_->getExecutionEngine()->getTargetData()))
 +{
 +    llvm::Module *module = regex_->module();
 +
-+    this->func_ = llvm::Function::Create(get_function_type(module, recursive),
++    this->func_ = llvm::Function::Create(get_function_type(module,
++                                                           this->GetCharType()),
 +                                         llvm::GlobalValue::InternalLinkage,
 +                                         "#re#function",
 +                                         module);
 +    this->InitializeFunction();
 +}
 +
++const llvm::Type *
++RegExFunction::GetCharType()
++{
++    if (this->regex_->unicode()) {
++        return PyTypeBuilder<Py_UNICODE>::get(this->context_);
++    }
++    else {
++        return PyTypeBuilder<char>::get(this->context_);
++    }
++}
++
++
 +void
 +RegExFunction::InitializeFunction()
 +{
 +    Function::arg_iterator args = this->func_->arg_begin();
 +    this->start_position_ = args++;
 +    this->start_position_->setName("start_position");
++    llvm::Value *current_position = args++;
++    current_position->setName("current_position");
 +    this->end_position_ = args++;
 +    this->end_position_->setName("end_position");
 +    this->rec_stats_addr_ = args++;
 +    assert(args == this->func_->arg_end() && "Unexpected number of arguments");
 +
 +    this->position_addr_ = this->builder_.CreateAlloca(
-+        PyTypeBuilder<Py_UNICODE *>::get(this->context_),
++        llvm::PointerType::getUnqual(this->GetCharType()),
 +        NULL, "position_addr");
-+    this->builder_.CreateStore(this->start_position_, this->position_addr_);
++    this->builder_.CreateStore(current_position, this->position_addr_);
 +
 +    this->fail_block_ = this->CreateBasicBlock("fail_block");
 +    this->builder_.SetInsertPoint(this->fail_block_);
 +}
 +
 +llvm::Value *
++RegExFunction::StartPosition()
++{
++    return this->start_position_;
++}
++
++llvm::Value *
 +RegExFunction::CurrentPosition()
 +{
 +    return this->builder_.CreateLoad(this->position_addr_);
 +// *****************************************
 +
 +RegularExpression::RegularExpression()
-+    : module_(NULL)
++    : unicode_(false),
++      multiline_(false),
++      module_(NULL)
++      
 +{
 +    this->module_ =
 +        new llvm::Module("regex", PyGlobalLlvmData::Get()->context());
 +    this->flags_ = flags;
 +    this->groups_ = groups;
 +
++    if (flags & 32)
++        this->unicode_ = true;
++
++    if (flags & 8)
++        this->multiline_ = true;
++
 +    RegExBuilder builder(this, NULL);
 +    if (!builder.Compile(seq, flags, groups)) {
 +        return false;
 +    }
 +    regex_module->Optimize(this->module_);
 +
-+    this->entry_ =
-+        (RegExNativeFunction)regex_module->Compile(this->functions_[0]);
++    void *func = regex_module->Compile(this->functions_[0]);
++    if (this->unicode_)
++        this->unicode_entry_ = (RegExUnicodeFunction)func;
++    else
++        this->char_entry_ = (RegExCharFunction)func;
++
 +    return true;
 +}
 +
 +{
 +    if (end < length)
 +        length = end;
-+    
-+    unsigned char result = this->entry_(str + pos, str + length);
++
++    if (pos > length)
++        return false;
++
++    unsigned char result = this->unicode_entry_(str,
++                                                str + pos,
++                                                str + length,
++                                                NULL);
++    return result != 0;
++}
++
++bool
++RegularExpression::Match(char *str, Py_ssize_t length,
++                         Py_ssize_t pos, Py_ssize_t end)
++{
++    if (end < length)
++        length = end;
++
++    if (pos > length)
++        return false;
++
++    unsigned char result = this->char_entry_(str,
++                                             str + pos,
++                                             str + length,
++                                             NULL);
 +    return result != 0;
 +}
 +
 +}
 +
 +static PyObject *
-+RegEx_match(RegEx* self, PyObject* args)
-+{
-+    Py_UNICODE* characters;
++RegEx_match(RegEx *self, PyObject *args)
++{
++    if (self->re == NULL) {
++        _PyErr_SetString(PyExc_SystemError, "Uninitialized RegEx.");
++        return NULL;
++    }
++    Py_UNICODE *unicode_str;
++    char *char_str;
 +    Py_ssize_t length, pos, end;
-+    if (!PyArg_ParseTuple(args, "u#nn", &characters, &length, &pos, &end)) {
-+        return NULL;
-+    }
-+
-+    if (self->re) {
-+        if (self->re->Match(characters, length, pos, end)) {
++    if (self->re->unicode()) {
++        if (!PyArg_ParseTuple(args, "u#nn", &unicode_str,
++                              &length, &pos, &end)) {
++            return NULL;
++        }
++
++        if (self->re->Match(unicode_str, length, pos, end)) {
 +            Py_RETURN_TRUE;
 +        }
 +        else {
 +            Py_RETURN_FALSE;
 +        }
-+    } else {
-+        return NULL;
++    }
++    else {
++        if (!PyArg_ParseTuple(args, "s#nn", &char_str, &length, &pos, &end)) {
++            return NULL;
++        }
++
++        if (self->re->Match(char_str, length, pos, end)) {
++            Py_RETURN_TRUE;
++        }
++        else {
++            Py_RETURN_FALSE;
++        }
 +    }
 +}
 +
 +static PyObject *
-+RegEx_dump(RegEx* self, PyObject* args)
++RegEx_dump(RegEx *self, PyObject *args)
 +{
 +    self->re->Print();
 +    Py_RETURN_NONE;
 +
 diff -r 37ecb109fa41 Modules/_llvmre/llvmre.h
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/Modules/_llvmre/llvmre.h	Thu May 27 07:54:42 2010 +0200
-@@ -0,0 +1,145 @@
++++ b/Modules/_llvmre/llvmre.h	Mon May 31 07:49:43 2010 +0200
+@@ -0,0 +1,178 @@
 +// -*- C++ -*-
 +#ifndef MODULES_LLVMRE_H
 +#define MODULES_LLVMRE_H
 +#include "llvm/Support/IRBuilder.h"
 +#include "llvm/Support/TargetFolder.h"
 +
-+typedef unsigned char (*RegExNativeFunction)(Py_UNICODE *, Py_UNICODE *);
++typedef unsigned char (*RegExUnicodeFunction)(Py_UNICODE *,
++                                              Py_UNICODE *,
++                                              Py_UNICODE *,
++                                              void *);
++
++typedef unsigned char (*RegExCharFunction)(char *, char *, char *, void *);
 +
 +class RegularExpression {
 +public:
 +    void AddFunction(llvm::Function *func);
 +
 +    bool Match(Py_UNICODE *str, Py_ssize_t length,
-+			   Py_ssize_t pos, Py_ssize_t end);
++               Py_ssize_t pos, Py_ssize_t end);
++    bool Match(char *str, Py_ssize_t length,
++               Py_ssize_t pos, Py_ssize_t end);
 +
 +    void Print();
 +
++    bool unicode() { return this->unicode_; }
++    bool multiline() { return this->multiline_; }
++
 +private:
 +    int flags_;
 +    int groups_;
 +
-+    RegExNativeFunction entry_;
++    bool unicode_;
++    bool multiline_;
++
++    RegExUnicodeFunction unicode_entry_;
++    RegExCharFunction char_entry_;
++
 +    std::vector<llvm::Function *> functions_;
 +    llvm::Module *module_;
 +};
 +
 +class RegExFunction {
 +public:
-+    RegExFunction(RegularExpression *regex, bool recursive);
++    RegExFunction(RegularExpression *regex);
 +
 +    RegularExpression *regex() { return this->regex_; }
 +    llvm::Function *function() { return this->func_; }
 +        llvm::Value *array_size,
 +        const char *name);
 +
++    const llvm::Type *GetCharType();
++
 +    llvm::Value *LoadCharacter();
 +    void Advance();
 +    void CheckEnd();
 +
++    llvm::Value *StartPosition();
 +    llvm::Value *CurrentPosition();
 +    llvm::Value *EndPosition();
 +    llvm::Value *rec_stats_addr() const { return rec_stats_addr_; }
 +
 +    BuilderT builder_;
 +
-+    bool recursive_;
-+
 +    llvm::Value *start_position_;
 +    llvm::Value *end_position_;
 +    llvm::Value *position_addr_;
 +
 +};
 +
++class RegExOpcodeAt {
++public:
++    RegExOpcodeAt(RegExBuilder *builder);
++    bool EmitAt(PyObject *arg);
++
++private:
++    bool EmitAtBeginning();
++    bool EmitAtEnd();
++
++    RegExFunction *func_;
++    RegExBuilder *builder_;
++    RegularExpression *regex_;
++
++    PyGlobalLlvmData *const llvm_data_;
++    llvm::LLVMContext &context_;
++};
++
 +#endif /* MODULES_LLVMRE_H */
 diff -r 37ecb109fa41 Modules/_llvmre/re_opcodes.cc
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/Modules/_llvmre/re_opcodes.cc	Thu May 27 07:54:42 2010 +0200
-@@ -0,0 +1,153 @@
++++ b/Modules/_llvmre/re_opcodes.cc	Mon May 31 07:49:43 2010 +0200
+@@ -0,0 +1,275 @@
 +#include "Python.h"
 +
 +#include "JIT/global_llvm_data.h"
 +    }
 +
 +    long arg_value = PyInt_AsLong(arg);
-+    llvm::ConstantInt *literal = 
-+        ConstantInt::get(PyTypeBuilder<Py_UNICODE>::get(this->context_), 
-+                         arg_value);
++    ConstantInt *literal = llvm::dyn_cast<ConstantInt>(
++        ConstantInt::get(this->func_->GetCharType(), arg_value));
++
++    if (literal == NULL) {
++        _PyErr_SetString(PyExc_SystemError, "Could not emit literal into set");
++    }
 +
 +    this->literals_->addCase(literal, this->literals_match_block_);
 +
 +    return true;
 +}
++
++
++
++RegExOpcodeAt::RegExOpcodeAt(RegExBuilder *builder)
++    : func_(builder->function()),
++      builder_(builder),
++      regex_(func_->regex()),
++      llvm_data_(PyGlobalLlvmData::Get()),
++      context_(this->llvm_data_->context())
++{
++}
++
++bool
++RegExOpcodeAt::EmitAt(PyObject *arg)
++{
++    if (!PyString_Check(arg)) {
++        _PyErr_SetString(PyExc_TypeError, "Expected a string");
++        return false;
++    }
++
++    const char *op_str = PyString_AsString(arg);
++    bool result = true;
++
++    if (strcmp(op_str, "at_beginning") == 0) {
++        if (!this->EmitAtBeginning()) {
++            result = false;
++        }
++    }
++    else if (strcmp(op_str, "at_end") == 0) {
++        if (!this->EmitAtEnd()) {
++            result = false;
++        }
++    }
++    else {
++        PyErr_Format(PyExc_ValueError,
++                     "Unsupported state '%s' in at", op_str);
++        result = false;
++    }
++
++    if (!result) {
++        return false;
++    }
++
++    return true;
++}
++
++bool
++RegExOpcodeAt::EmitAtBeginning()
++{
++    RegExFunction::BuilderT &irbuilder = this->func_->builder();
++
++    Value *start_pos = this->func_->StartPosition();
++    Value *current_pos = this->func_->CurrentPosition();
++
++    Value *at_beginning =
++        irbuilder.CreateICmpEQ(start_pos, current_pos, "beginning");
++
++    BasicBlock *cont_block = this->func_->CreateBasicBlock("at_begin_cont");
++    BasicBlock *fail_block = this->func_->CreateBasicBlock("at_begin_fail");
++    irbuilder.CreateCondBr(at_beginning, cont_block, fail_block);
++    irbuilder.SetInsertPoint(fail_block);
++
++    if (this->func_->regex()->multiline()) {
++        Value *one =
++            ConstantInt::get(PyTypeBuilder<int>::get(this->context_), -1);
++        llvm::Value *prev =
++            irbuilder.CreateGEP(current_pos, one, "prev_position");
++
++        llvm::Constant *literal = 
++            ConstantInt::get(this->func_->GetCharType(), '\n');
++        llvm::Value *prev_val = irbuilder.CreateLoad(prev);
++
++        llvm::Value *after_newline = irbuilder.CreateICmpEQ(prev_val, literal);
++        irbuilder.CreateCondBr(after_newline, cont_block,
++                               this->func_->fail_block());
++    }
++    else {
++        irbuilder.CreateBr(this->func_->fail_block());
++    }
++
++    irbuilder.SetInsertPoint(cont_block);
++    return true;
++}
++
++bool
++RegExOpcodeAt::EmitAtEnd()
++{
++    RegExFunction::BuilderT &irbuilder = this->func_->builder();
++
++    Value *end_pos = this->func_->EndPosition();
++    Value *current_pos = this->func_->CurrentPosition();
++
++    Value *at_end = irbuilder.CreateICmpEQ(end_pos, current_pos, "end");
++
++    BasicBlock *cont_block = this->func_->CreateBasicBlock("at_end_cont");
++    BasicBlock *fail_block = this->func_->CreateBasicBlock("at_end_fail");
++    irbuilder.CreateCondBr(at_end, cont_block, fail_block);
++    irbuilder.SetInsertPoint(fail_block);
++
++    if (this->func_->regex()->multiline()) {
++        Value *one =
++            ConstantInt::get(PyTypeBuilder<int>::get(this->context_), 1);
++        llvm::Value *next =
++            irbuilder.CreateGEP(current_pos, one, "next_position");
++
++        llvm::Constant *literal = 
++            ConstantInt::get(this->func_->GetCharType(), '\n');
++        llvm::Value *next_val = irbuilder.CreateLoad(next);
++
++        llvm::Value *before_newline = irbuilder.CreateICmpEQ(next_val, literal);
++        irbuilder.CreateCondBr(before_newline, cont_block,
++                               this->func_->fail_block());
++    }
++    else {
++        irbuilder.CreateBr(this->func_->fail_block());
++    }
++    irbuilder.SetInsertPoint(cont_block);
++    return true;
++}
 diff -r 37ecb109fa41 configure
 --- a/configure	Mon May 03 18:00:25 2010 +0200
-+++ b/configure	Thu May 27 07:54:42 2010 +0200
++++ b/configure	Mon May 31 07:49:43 2010 +0200
 @@ -1,63 +1,86 @@
  #! /bin/sh
  # From configure.in Revision: 75132 .
    See PEP 11 for the gory details.
 diff -r 37ecb109fa41 configure.in
 --- a/configure.in	Mon May 03 18:00:25 2010 +0200
-+++ b/configure.in	Thu May 27 07:54:42 2010 +0200
++++ b/configure.in	Mon May 31 07:49:43 2010 +0200
 @@ -509,9 +509,9 @@
  
      LLVM_INC_DIR=`$LLVM_CONFIG --includedir`
          [], [AC_MSG_ERROR([Did not find clang in $LLVM_BIN_DIR])])
 diff -r 37ecb109fa41 proto.py
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/proto.py	Thu May 27 07:54:42 2010 +0200
++++ b/proto.py	Mon May 31 07:49:43 2010 +0200
 @@ -0,0 +1,132 @@
 +from sre_parse import parse
 +
 +    _main()
 diff -r 37ecb109fa41 pyconfig.h.in
 --- a/pyconfig.h.in	Mon May 03 18:00:25 2010 +0200
-+++ b/pyconfig.h.in	Thu May 27 07:54:42 2010 +0200
++++ b/pyconfig.h.in	Mon May 31 07:49:43 2010 +0200
 @@ -5,6 +5,9 @@
  #define Py_PYCONFIG_H
  
  
 diff -r 37ecb109fa41 recompile.py
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/recompile.py	Thu May 27 07:54:42 2010 +0200
++++ b/recompile.py	Mon May 31 07:49:43 2010 +0200
 @@ -0,0 +1,51 @@
 +import pickle
 +import llvmre
 +def eval_flags():
 +    import re
 +    print "I", re.I, "L", re.L, "M", re.M, "S", re.S, "U", re.U, "X", re.X
-+    return re.I | re.L | re.M | re.S | re.X, re.U
++    return re.I | re.L | re.M | re.S | re.X, 0
 +
 +def _main():
 +    with open("regexes.pickle", "r") as infile:
 +                continue
 +            if re[1] & unsupported_flags > 0:
 +                raise ValueError("Unsupported Flags %d" % re[1])
-+            if re[1] & must_flags == 0:
++            if re[1] & must_flags != must_flags:
 +                raise ValueError("Must Flags not set %d" % re[1])
 +            llvmre.compile(*re)
 +            compiled += 1
 +    _main()
 diff -r 37ecb109fa41 regex.py
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/regex.py	Thu May 27 07:54:42 2010 +0200
++++ b/regex.py	Mon May 31 07:49:43 2010 +0200
 @@ -0,0 +1,21 @@
 +import llvmre
 +from sre_parse import parse
 +import re
 +
-+pattern = "(\\s+e|\\s+o[0-9]+)"
++pattern = "a$"
 +
 +print parse(pattern)
 +
-+obj = llvmre.compile(pattern)
++obj = llvmre.compile(pattern, llvmre.M)
 +obj.dump()
 +
 +print obj
 +print obj.match("aacc")
 +print obj.match("bbcaacc")
 +print obj.match("aaaa")
-+print obj.match("d")
++print obj.match("a")
 +
 diff -r 37ecb109fa41 regexes.pickle
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/regexes.pickle	Thu May 27 07:54:42 2010 +0200
++++ b/regexes.pickle	Mon May 31 07:49:43 2010 +0200
 @@ -0,0 +1,1112 @@
 +(lp0
 +(S'\\bnpgvingr\\b'
 \ No newline at end of file
 diff -r 37ecb109fa41 tests.py
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/tests.py	Thu May 27 07:54:42 2010 +0200
-@@ -0,0 +1,78 @@
++++ b/tests.py	Mon May 31 07:49:43 2010 +0200
+@@ -0,0 +1,109 @@
 +import unittest
++import functools
 +
 +import llvmre as re
 +
++def with_flags(func):
++    flags = [0, re.U]
++    @functools.wraps(func)
++    def result(self):
++        for f in flags:
++            func(self, f)
++    return result
++
 +class TestSimpleRegEx(unittest.TestCase):
-+    def test_literals(self):
-+        ex = re.compile("aa")
++    @with_flags
++    def test_literals(self, flags):
++        ex = re.compile("aa", flags)
 +        self.assertTrue(ex.match("aa"))
 +        self.assertFalse(ex.match("a"))
 +        self.assertTrue(ex.match("aaaa"))
 +        self.assertFalse(ex.match("bb"))
 +
-+    def test_branch(self):
-+        ex = re.compile("aa|bb")
++    @with_flags
++    def test_branch(self, flags):
++        ex = re.compile("aa|bb", flags)
 +        self.assertTrue(ex.match("aa"))
 +        self.assertTrue(ex.match("aaa"))
 +        self.assertTrue(ex.match("bb"))
 +        self.assertFalse(ex.match("c"))
 +        self.assertFalse(ex.match("cccc"))
 +
-+    def test_subpattern(self):
-+        ex = re.compile("(aa|bb)")
++    @with_flags
++    def test_subpattern(self, flags):
++        ex = re.compile("(aa|bb)", flags)
 +        self.assertTrue(ex.match("aa"))
 +        self.assertTrue(ex.match("aaa"))
 +        self.assertTrue(ex.match("bb"))
 +        self.assertFalse(ex.match("c"))
 +        self.assertFalse(ex.match("cccc"))
 +
-+    def test_repeat_simple(self):
-+        ex = re.compile("a*b")
++    @with_flags
++    def test_repeat_simple(self, flags):
++        ex = re.compile("a*b", flags)
 +        self.assertTrue(ex.match("b"))
 +        self.assertTrue(ex.match("ab"))
 +        self.assertTrue(ex.match("aab"))
 +        self.assertFalse(ex.match("cb"))
 +        self.assertTrue(ex.match("aaaaabc"))
 +
-+    def test_repeat_max_limit(self):
-+        ex = re.compile("a?b")
++    @with_flags
++    def test_repeat_max_limit(self, flags):
++        ex = re.compile("a?b", flags)
 +        self.assertTrue(ex.match("b"))
 +        self.assertTrue(ex.match("ab"))
 +        self.assertFalse(ex.match("aab"))
 +        self.assertFalse(ex.match("cb"))
 +
-+    def test_repeat(self):
-+        ex = re.compile("(aa|bb)*c")
++    @with_flags
++    def test_repeat(self, flags):
++        ex = re.compile("(aa|bb)*c", flags)
 +        self.assertTrue(ex.match("aac"))
 +        self.assertTrue(ex.match("bbbbc"))
 +        self.assertFalse(ex.match("bbbc"))
 +        self.assertTrue(ex.match("aabbc"))
 +        self.assertFalse(ex.match("aabc"))
 +
-+        ex = re.compile("((aa|bb)*c)*d")
++        ex = re.compile("((aa|bb)*c)*d", flags)
 +        self.assertTrue(ex.match("aacd"))
 +        self.assertTrue(ex.match("bbbbcd"))
 +        self.assertFalse(ex.match("bbbcd"))
 +        self.assertFalse(ex.match("aabcd"))
 +        self.assertTrue(ex.match("aacbbcaacd"))
 +
-+    def test_min_repeat(self):
-+        ex = re.compile("(aa|bb){2,3}c")
++    @with_flags
++    def test_min_repeat(self, flags):
++        ex = re.compile("(aa|bb){2,3}c", flags)
 +        self.assertFalse(ex.match("aac"))
 +        self.assertTrue(ex.match("aabbc"))
 +        self.assertTrue(ex.match("aabbaac"))
 +        self.assertFalse(ex.match("aabbaabbc"))
 +        self.assertFalse(ex.match("aaddaac"))
 +
-+    def test_any(self):
-+        ex = re.compile("a.b")
++    @with_flags
++    def test_any(self, flags):
++        ex = re.compile("a.b", flags)
 +        self.assertTrue(ex.match("axb"))
 +        self.assertTrue(ex.match("ayb"))
 +        self.assertFalse(ex.match("a\nb"))
 +
++    @with_flags
++    def test_at_beginning(self, flags):
++        ex = re.compile("^a", flags)
++        self.assertTrue(ex.match("aa"))
++        self.assertFalse(ex.match("ba"))
++        self.assertFalse(ex.match("aa", 1))
++        self.assertFalse(ex.match("ba", 1))
++
++        ex = re.compile("^a", flags | re.M)
++        self.assertTrue(ex.match("aa"))
++        self.assertFalse(ex.match("ba"))
++        self.assertTrue(ex.match("a\na", 2))
++        self.assertTrue(ex.match("b\na", 2))
++
 +
 +if __name__ == '__main__':
 +    unittest.main()